aboutsummaryrefslogtreecommitdiffstats
path: root/cmake
diff options
context:
space:
mode:
authortobigun <tobigun@b956fd51-792f-4845-bead-9b4dfca2ff2c>2010-05-23 09:07:15 +0000
committertobigun <tobigun@b956fd51-792f-4845-bead-9b4dfca2ff2c>2010-05-23 09:07:15 +0000
commit678cc132f942ff4d84a803550eedf96acc543bca (patch)
treeeb195abafaf69d55fa0f4b77323e517fcd2263cd /cmake
parent7e677fd5ebe60c3dd9df8954e1ed28c4afdf8660 (diff)
downloadusdx-678cc132f942ff4d84a803550eedf96acc543bca.tar.gz
usdx-678cc132f942ff4d84a803550eedf96acc543bca.tar.xz
usdx-678cc132f942ff4d84a803550eedf96acc543bca.zip
update to trunk rev. 2391
git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/branches/experimental@2401 b956fd51-792f-4845-bead-9b4dfca2ff2c
Diffstat (limited to 'cmake')
-rw-r--r--cmake/.gitignore22
-rw-r--r--cmake/AUTHORS.txt1
-rw-r--r--cmake/BuildBot.trigger2
-rw-r--r--cmake/COPYRIGHT.txt57
-rw-r--r--cmake/ChangeLog.GERMAN.txt538
-rw-r--r--cmake/ChangeLog.txt142
-rw-r--r--cmake/DisplayChanges.patch14
-rw-r--r--cmake/RELEASEBLOCKERS.txt61
-rw-r--r--cmake/artwork/.PLACEHOLDER2
-rw-r--r--cmake/build/.gitignore1
-rw-r--r--cmake/build/delphi-win/.gitignore1
-rw-r--r--cmake/dists/delphi2005/readme.txt10
-rw-r--r--cmake/dists/delphi7/readme.txt10
-rw-r--r--cmake/dists/gentoo/readme.txt2
-rw-r--r--cmake/dists/gentoo/ultrastardx-1.1_beta.ebuild81
-rwxr-xr-xcmake/dists/lazarus/readme.txt30
-rw-r--r--cmake/dists/lazarus/ultrastardx-unix.lpi248
-rw-r--r--cmake/dists/lazarus/ultrastardx-win.lpi58
-rw-r--r--cmake/game/.gitignore8
-rw-r--r--cmake/game/LuaCommands.odtbin0 -> 17530 bytes
-rw-r--r--cmake/game/fonts/DejaVu/AUTHORS44
-rw-r--r--cmake/game/fonts/DejaVu/DejaVuSans-Bold.ttfbin0 -> 561576 bytes
-rw-r--r--cmake/game/fonts/DejaVu/DejaVuSans.ttfbin0 -> 611552 bytes
-rw-r--r--cmake/game/fonts/DejaVu/LICENSE99
-rw-r--r--cmake/game/fonts/DejaVu/README59
-rw-r--r--cmake/game/fonts/FreeSans/AUTHORS191
-rw-r--r--cmake/game/fonts/FreeSans/COPYING341
-rw-r--r--cmake/game/fonts/FreeSans/CREDITS506
-rw-r--r--cmake/game/fonts/FreeSans/FreeSans.ttf (renamed from cmake/game/fonts/FreeSans.ttf)bin770828 -> 770828 bytes
-rw-r--r--cmake/game/fonts/FreeSans/FreeSansBold.ttf (renamed from cmake/game/fonts/FreeSansBold.ttf)bin250228 -> 250228 bytes
-rw-r--r--cmake/game/fonts/FreeSans/README108
-rw-r--r--cmake/game/fonts/Vera.ttfbin65932 -> 0 bytes
-rw-r--r--cmake/game/fonts/VeraBd.ttfbin58716 -> 0 bytes
-rw-r--r--cmake/game/fonts/bold/eurostar_regular_bold.datbin256 -> 0 bytes
-rw-r--r--cmake/game/fonts/bold/eurostar_regular_bold.pngbin84067 -> 0 bytes
-rwxr-xr-xcmake/game/fonts/fonts.ini67
-rw-r--r--cmake/game/fonts/fontsTTF.ini11
-rw-r--r--cmake/game/fonts/normal/eurostar_regular.datbin256 -> 0 bytes
-rw-r--r--cmake/game/fonts/normal/eurostar_regular.pngbin59609 -> 0 bytes
-rw-r--r--cmake/game/fonts/outline1/outline1.datbin256 -> 0 bytes
-rw-r--r--cmake/game/fonts/outline1/outline1.pngbin74739 -> 0 bytes
-rw-r--r--cmake/game/fonts/outline2/outline2.datbin256 -> 0 bytes
-rw-r--r--cmake/game/fonts/outline2/outline2.pngbin106020 -> 0 bytes
-rw-r--r--cmake/game/fonts/wqy-microhei/AUTHORS.txt12774
-rw-r--r--cmake/game/fonts/wqy-microhei/LICENSE_Apache2.txt122
-rw-r--r--cmake/game/fonts/wqy-microhei/LICENSE_GPLv3.txt674
-rw-r--r--cmake/game/fonts/wqy-microhei/README.txt378
-rw-r--r--cmake/game/fonts/wqy-microhei/wqy-microhei.ttcbin0 -> 5177387 bytes
-rw-r--r--cmake/game/languages/Catalan.ini773
-rw-r--r--cmake/game/languages/Croatian.ini794
-rw-r--r--cmake/game/languages/Dutch.ini781
-rw-r--r--cmake/game/languages/English.ini106
-rw-r--r--cmake/game/languages/Euskara.ini127
-rw-r--r--cmake/game/languages/Finnish.ini145
-rw-r--r--cmake/game/languages/French.ini783
-rw-r--r--cmake/game/languages/German.ini214
-rw-r--r--cmake/game/languages/Greek.ini785
-rw-r--r--cmake/game/languages/Icelandic.ini431
-rw-r--r--cmake/game/languages/Italian.ini71
-rw-r--r--cmake/game/languages/Japanese.inibin15902 -> 12999 bytes
-rw-r--r--cmake/game/languages/Luxembourgish.ini402
-rw-r--r--cmake/game/languages/Portuguese.ini781
-rw-r--r--cmake/game/languages/Spanish.ini783
-rw-r--r--cmake/game/languages/Swedish.ini781
-rwxr-xr-xcmake/game/languages/convert.sh43
-rw-r--r--cmake/game/languages/old/Catalan.ini298
-rw-r--r--cmake/game/languages/old/Danish.ini592
-rw-r--r--cmake/game/languages/old/French.ini618
-rw-r--r--cmake/game/languages/old/Norwegian.ini592
-rw-r--r--cmake/game/languages/old/Polish.ini606
-rw-r--r--cmake/game/languages/old/Serbian.ini594
-rw-r--r--cmake/game/languages/old/Slovak.ini602
-rw-r--r--cmake/game/languages/old/Slovenian.ini642
-rw-r--r--cmake/game/languages/old/readme.txt570
-rw-r--r--cmake/game/plugins/5000points.usdx74
-rw-r--r--cmake/game/plugins/PluginDescription.odtbin0 -> 18417 bytes
-rw-r--r--cmake/game/plugins/blind.usdx53
-rw-r--r--cmake/game/plugins/duel.usdx41
-rw-r--r--cmake/game/plugins/hooks.txt5
-rw-r--r--cmake/game/plugins/teamduel.usdx258
-rw-r--r--cmake/game/sounds/Bebeto_-_Loop010-license.txt10
-rw-r--r--cmake/game/themes/Classic.ini11199
-rw-r--r--cmake/game/themes/Classic/Star.ini286
-rw-r--r--cmake/game/themes/Classic/[bg-load]star.jpgbin0 -> 8249 bytes
-rw-r--r--cmake/game/themes/Classic/[bg-main]star.jpgbin0 -> 5928 bytes
-rw-r--r--cmake/game/themes/Classic/[button]13.jpgbin893 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[button]13.pngbin0 -> 935 bytes
-rw-r--r--cmake/game/themes/Classic/[button]alt.jpgbin892 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[button]alt.pngbin0 -> 929 bytes
-rw-r--r--cmake/game/themes/Classic/[button]az.jpgbin900 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[button]az.pngbin0 -> 954 bytes
-rw-r--r--cmake/game/themes/Classic/[button]e.jpgbin883 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[button]e.pngbin0 -> 1103 bytes
-rw-r--r--cmake/game/themes/Classic/[button]enter.jpgbin911 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[button]enter.pngbin0 -> 884 bytes
-rw-r--r--cmake/game/themes/Classic/[button]esc.jpgbin892 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[button]esc.pngbin0 -> 972 bytes
-rw-r--r--cmake/game/themes/Classic/[button]j.jpgbin880 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[button]j.pngbin0 -> 1116 bytes
-rw-r--r--cmake/game/themes/Classic/[button]m.jpgbin889 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[button]m.pngbin0 -> 1148 bytes
-rw-r--r--cmake/game/themes/Classic/[button]navi.jpgbin938 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[button]navi.pngbin0 -> 1294 bytes
-rw-r--r--cmake/game/themes/Classic/[button]p.jpgbin884 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[button]p.pngbin0 -> 1130 bytes
-rw-r--r--cmake/game/themes/Classic/[effect]goldenNoteStar.jpgbin24894 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[effect]goldenNoteStar.pngbin0 -> 24444 bytes
-rw-r--r--cmake/game/themes/Classic/[effect]perfectNoteStar.jpgbin27633 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[effect]perfectNoteStar.pngbin0 -> 40783 bytes
-rw-r--r--cmake/game/themes/Classic/[helper]buttonFade.pngbin0 -> 337 bytes
-rw-r--r--cmake/game/themes/Classic/[helper]rectangle.jpgbin604 -> 353 bytes
-rw-r--r--cmake/game/themes/Classic/[icon]Star.jpgbin942 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[icon]Star.pngbin0 -> 463 bytes
-rw-r--r--cmake/game/themes/Classic/[icon]cd.pngbin0 -> 777 bytes
-rw-r--r--cmake/game/themes/Classic/[icon]error.jpgbin1407 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[icon]error.pngbin0 -> 694 bytes
-rw-r--r--cmake/game/themes/Classic/[icon]main.pngbin0 -> 803 bytes
-rw-r--r--cmake/game/themes/Classic/[icon]options.pngbin0 -> 954 bytes
-rw-r--r--cmake/game/themes/Classic/[icon]party.pngbin0 -> 694 bytes
-rw-r--r--cmake/game/themes/Classic/[icon]question.jpgbin1695 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[icon]question.pngbin0 -> 747 bytes
-rw-r--r--cmake/game/themes/Classic/[icon]score.pngbin0 -> 794 bytes
-rw-r--r--cmake/game/themes/Classic/[icon]song_menu.png (renamed from cmake/game/themes/Deluxe/icon/song_menu.png)bin724 -> 724 bytes
-rw-r--r--cmake/game/themes/Classic/[icon]song_search.png (renamed from cmake/game/themes/Deluxe/icon/song_search.png)bin960 -> 960 bytes
-rw-r--r--cmake/game/themes/Classic/[icon]song_video.pngbin0 -> 864 bytes
-rw-r--r--cmake/game/themes/Classic/[icon]stats.jpgbin1010 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[icon]stats.pngbin0 -> 676 bytes
-rw-r--r--cmake/game/themes/Classic/[icon]video.jpgbin2608 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[icon]video.pngbin0 -> 3002 bytes
-rw-r--r--cmake/game/themes/Classic/[interface]cursor.pngbin0 -> 5635 bytes
-rw-r--r--cmake/game/themes/Classic/[interface]cursor_pressed.png (renamed from cmake/game/themes/Deluxe/interface/cursor_pressed.png)bin3756 -> 4086 bytes
-rw-r--r--cmake/game/themes/Classic/[interface]dialog_background.pngbin0 -> 887 bytes
-rw-r--r--cmake/game/themes/Classic/[interface]select_arrow_left.png (renamed from cmake/game/themes/Deluxe/interface/select_arrow_left.png)bin485 -> 485 bytes
-rw-r--r--cmake/game/themes/Classic/[interface]select_arrow_right.png (renamed from cmake/game/themes/Deluxe/interface/select_arrow_right.png)bin485 -> 485 bytes
-rw-r--r--cmake/game/themes/Classic/[interface]selectbg_search.png (renamed from cmake/game/themes/Deluxe/interface/selectbg_search.png)bin477 -> 477 bytes
-rw-r--r--cmake/game/themes/Classic/[main]Bar.jpgbin3689 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[main]Bar1.jpgbin2115 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[main]Button.jpgbin1377 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[main]Button2.jpgbin2506 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[main]Button3.jpgbin3068 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[main]ButtonEditor.jpgbin5112 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[main]Logo.jpgbin19821 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[main]button.pngbin0 -> 929 bytes
-rw-r--r--cmake/game/themes/Classic/[main]buttonf.jpgbin0 -> 17717 bytes
-rw-r--r--cmake/game/themes/Classic/[main]logo.pngbin0 -> 7327 bytes
-rw-r--r--cmake/game/themes/Classic/[main]mainBar.pngbin0 -> 304 bytes
-rw-r--r--cmake/game/themes/Classic/[main]playerNumberBox.pngbin0 -> 2267 bytes
-rw-r--r--cmake/game/themes/Classic/[main]selectbg.pngbin0 -> 285 bytes
-rw-r--r--cmake/game/themes/Classic/[main]songCover.jpgbin30254 -> 15045 bytes
-rw-r--r--cmake/game/themes/Classic/[main]square.jpgbin1574 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[mainbutton]Exit.jpgbin3065 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[mainbutton]Exit.pngbin0 -> 1688 bytes
-rw-r--r--cmake/game/themes/Classic/[mainbutton]Multi.jpgbin2965 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[mainbutton]Multi.pngbin0 -> 1678 bytes
-rw-r--r--cmake/game/themes/Classic/[mainbutton]Options.jpgbin2875 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[mainbutton]Options.pngbin0 -> 1778 bytes
-rw-r--r--cmake/game/themes/Classic/[mainbutton]Solo.jpgbin3070 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[mainbutton]Solo.pngbin0 -> 1684 bytes
-rw-r--r--cmake/game/themes/Classic/[mainbutton]Stats.jpgbin3246 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[mainbutton]Stats.pngbin0 -> 1774 bytes
-rw-r--r--cmake/game/themes/Classic/[menu]PopUpBg.JPGbin4013 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[menu]PopUpFg.JPGbin4151 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[menu]PopUpFg.pngbin0 -> 912 bytes
-rw-r--r--cmake/game/themes/Classic/[menu]jumpToBg.jpgbin885 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[menu]jumpToBg.pngbin0 -> 18921 bytes
-rw-r--r--cmake/game/themes/Classic/[menu]songMenuBg.jpgbin1327 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[menu]songMenuBg.pngbin0 -> 18529 bytes
-rw-r--r--cmake/game/themes/Classic/[menu]songMenuBorder.jpgbin2076 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[menu]songMenuButtonBG.jpgbin720 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[menu]songMenuSelectBG.jpgbin889 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[menu]songMenuSelectBg.pngbin0 -> 4707 bytes
-rw-r--r--cmake/game/themes/Classic/[party]Joker.jpgbin2334 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[party]Joker.pngbin0 -> 1343 bytes
-rw-r--r--cmake/game/themes/Classic/[party]playerButton.jpgbin1519 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[party]playerButton.pngbin0 -> 1346 bytes
-rw-r--r--cmake/game/themes/Classic/[party]playerTeamButton.jpgbin2428 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[party]playerTeamButton.pngbin0 -> 529 bytes
-rw-r--r--cmake/game/themes/Classic/[party]playerselectbg.pngbin0 -> 200 bytes
-rw-r--r--cmake/game/themes/Classic/[party]pointer.bmpbin6198 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[party]pointer.pngbin0 -> 362 bytes
-rw-r--r--cmake/game/themes/Classic/[party]roundBG1.jpgbin1043 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[party]roundBG1.pngbin0 -> 1073 bytes
-rw-r--r--cmake/game/themes/Classic/[party]roundBG2.jpgbin978 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[party]roundBG2.pngbin0 -> 1049 bytes
-rw-r--r--cmake/game/themes/Classic/[party]roundBG3.jpgbin1251 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[party]roundBG3.pngbin0 -> 1135 bytes
-rw-r--r--cmake/game/themes/Classic/[party]roundBG4.jpgbin1229 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[party]roundBG4.pngbin0 -> 1229 bytes
-rw-r--r--cmake/game/themes/Classic/[party]roundTeamButton.jpgbin2887 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[party]roundTeamButton.pngbin0 -> 1207 bytes
-rw-r--r--cmake/game/themes/Classic/[party]scoreBG1.jpgbin1226 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[party]scoreBG1.pngbin0 -> 529 bytes
-rw-r--r--cmake/game/themes/Classic/[party]scoreBG2.jpgbin653 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[party]scoreBG2.pngbin0 -> 300 bytes
-rw-r--r--cmake/game/themes/Classic/[party]scoreDecoration.jpgbin6179 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[party]scoreDecoration.pngbin0 -> 9140 bytes
-rw-r--r--cmake/game/themes/Classic/[party]teamPoints.jpgbin729 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[party]teamPoints.pngbin0 -> 1195 bytes
-rw-r--r--cmake/game/themes/Classic/[party]winDecoration.jpgbin3878 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[party]winDecoration.pngbin0 -> 4292 bytes
-rw-r--r--cmake/game/themes/Classic/[party]winTeamButton1.jpgbin1925 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[party]winTeamButton1.pngbin0 -> 516 bytes
-rw-r--r--cmake/game/themes/Classic/[party]winTeamButton2.jpgbin1783 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[party]winTeamButton2.pngbin0 -> 419 bytes
-rw-r--r--cmake/game/themes/Classic/[party]winTeamButton3.jpgbin1458 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[party]winTeamButton3.pngbin0 -> 378 bytes
-rw-r--r--cmake/game/themes/Classic/[score]Line.pngbin0 -> 2825 bytes
-rw-r--r--cmake/game/themes/Classic/[score]bar_box_dark.pngbin0 -> 496 bytes
-rw-r--r--cmake/game/themes/Classic/[score]bar_box_light.pngbin0 -> 490 bytes
-rw-r--r--cmake/game/themes/Classic/[score]bar_box_lightest.pngbin0 -> 484 bytes
-rw-r--r--cmake/game/themes/Classic/[score]box.jpgbin690 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[score]box.pngbin0 -> 307 bytes
-rw-r--r--cmake/game/themes/Classic/[score]endcap.pngbin0 -> 2275 bytes
-rw-r--r--cmake/game/themes/Classic/[score]glass_box.pngbin0 -> 3581 bytes
-rw-r--r--cmake/game/themes/Classic/[score]level.jpgbin1245 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[score]level.pngbin0 -> 266 bytes
-rw-r--r--cmake/game/themes/Classic/[score]levelRound.pngbin0 -> 524 bytes
-rw-r--r--cmake/game/themes/Classic/[score]level_dark.pngbin0 -> 213 bytes
-rw-r--r--cmake/game/themes/Classic/[score]level_dark_round.pngbin0 -> 410 bytes
-rw-r--r--cmake/game/themes/Classic/[score]level_light.pngbin0 -> 209 bytes
-rw-r--r--cmake/game/themes/Classic/[score]level_light_round.pngbin0 -> 445 bytes
-rw-r--r--cmake/game/themes/Classic/[score]level_lightest.pngbin0 -> 209 bytes
-rw-r--r--cmake/game/themes/Classic/[score]level_lightest_round.pngbin0 -> 467 bytes
-rw-r--r--cmake/game/themes/Classic/[score]levelround.jpgbin616 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[score]line.jpgbin730 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[score]rating_0.pngbin0 -> 7412 bytes
-rw-r--r--cmake/game/themes/Classic/[score]rating_1.pngbin0 -> 8206 bytes
-rw-r--r--cmake/game/themes/Classic/[score]rating_2.pngbin0 -> 9681 bytes
-rw-r--r--cmake/game/themes/Classic/[score]rating_3.pngbin0 -> 8363 bytes
-rw-r--r--cmake/game/themes/Classic/[score]rating_4.pngbin0 -> 8231 bytes
-rw-r--r--cmake/game/themes/Classic/[score]rating_5.pngbin0 -> 8720 bytes
-rw-r--r--cmake/game/themes/Classic/[score]rating_6.pngbin0 -> 8162 bytes
-rw-r--r--cmake/game/themes/Classic/[score]rating_7.pngbin0 -> 9573 bytes
-rw-r--r--cmake/game/themes/Classic/[sing.player1]lyric_active.pngbin0 -> 884 bytes
-rw-r--r--cmake/game/themes/Classic/[sing.player1]lyric_inactive.pngbin0 -> 862 bytes
-rw-r--r--cmake/game/themes/Classic/[sing.player2]lyric_active.pngbin0 -> 1034 bytes
-rw-r--r--cmake/game/themes/Classic/[sing.player2]lyric_inactive.pngbin0 -> 948 bytes
-rw-r--r--cmake/game/themes/Classic/[sing.player3]lyric_active.pngbin0 -> 988 bytes
-rw-r--r--cmake/game/themes/Classic/[sing.player3]lyric_inactive.pngbin0 -> 911 bytes
-rw-r--r--cmake/game/themes/Classic/[sing.player4]lyric_active.pngbin0 -> 966 bytes
-rw-r--r--cmake/game/themes/Classic/[sing.player4]lyric_inactive.pngbin0 -> 861 bytes
-rw-r--r--cmake/game/themes/Classic/[sing.player5]lyric_active.pngbin0 -> 959 bytes
-rw-r--r--cmake/game/themes/Classic/[sing.player5]lyric_inactive.pngbin0 -> 877 bytes
-rw-r--r--cmake/game/themes/Classic/[sing.player6]lyric_active.pngbin0 -> 960 bytes
-rw-r--r--cmake/game/themes/Classic/[sing.player6]lyric_inactive.pngbin0 -> 872 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]lineBonusPopUp.jpgbin2356 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]lineBonusPopUp.pngbin0 -> 237 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]lyricsHelpBar.bmpbin3126 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]lyricsHelpBar.pngbin0 -> 340 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]notesBgLeft.bmpbin1590 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]notesBgLeft.pngbin0 -> 292 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]notesBgMid.bmpbin1590 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]notesBgMid.pngbin0 -> 144 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]notesBgRight.bmpbin1590 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]notesBgRight.pngbin0 -> 280 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]notesLeft.bmpbin822 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]notesLeft.pngbin0 -> 671 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]notesMid.bmpbin3126 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]notesMid.pngbin0 -> 236 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]notesPlainLeft.pngbin0 -> 681 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]notesPlainMid.pngbin0 -> 151 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]notesPlainRight.pngbin0 -> 690 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]notesRight.bmpbin822 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]notesRight.pngbin0 -> 728 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]p.jpgbin1487 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]p.pngbin0 -> 192 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]pause.pngbin0 -> 13261 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]scoreBg.jpgbin2005 -> 680 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]scoreBg.pngbin0 -> 289 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]singBarBack.jpgbin388 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]singBarBack.pngbin0 -> 203 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]singBarBar.pngbin0 -> 183 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]singBarFront.jpgbin549 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]singBarFront.pngbin0 -> 199 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]textBar.jpgbin1558 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]textBar.pngbin0 -> 9671 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]timeBar.jpgbin0 -> 317 bytes
-rw-r--r--cmake/game/themes/Classic/[sing]timeBarBG.pngbin0 -> 4121 bytes
-rw-r--r--cmake/game/themes/Classic/[song]selection.jpgbin3418 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[song]selection.pngbin0 -> 1482 bytes
-rw-r--r--cmake/game/themes/Classic/[songs]bg.pngbin0 -> 610 bytes
-rw-r--r--cmake/game/themes/Classic/[special]bar1.pngbin0 -> 381 bytes
-rw-r--r--cmake/game/themes/Classic/[special]bar2.pngbin0 -> 410 bytes
-rw-r--r--cmake/game/themes/Classic/[special]bg_fade.pngbin0 -> 32518 bytes
-rw-r--r--cmake/game/themes/Classic/[stat]detailBG1.jpgbin653 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[stat]detailBG1.pngbin0 -> 282 bytes
-rw-r--r--cmake/game/themes/Classic/[stat]mainBG1.jpgbin652 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[stat]mainBG1.pngbin0 -> 269 bytes
-rw-r--r--cmake/game/themes/Classic/[stat]mainBG2.jpgbin2942 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[stat]mainBG2.pngbin0 -> 1093 bytes
-rw-r--r--cmake/game/themes/Classic/[stat]mainBG3.jpgbin747 -> 0 bytes
-rw-r--r--cmake/game/themes/Classic/[stat]mainBG3.pngbin0 -> 251 bytes
-rw-r--r--cmake/game/themes/Deluxe.ini1528
-rw-r--r--cmake/game/themes/Deluxe/Blue.ini23
-rw-r--r--cmake/game/themes/Deluxe/Fall.ini23
-rw-r--r--cmake/game/themes/Deluxe/Ocean.ini27
-rw-r--r--cmake/game/themes/Deluxe/Ribbon.ini462
-rw-r--r--cmake/game/themes/Deluxe/Summer.ini25
-rw-r--r--cmake/game/themes/Deluxe/Winter.ini23
-rw-r--r--cmake/game/themes/Deluxe/[icon]song_menu.pngbin0 -> 724 bytes
-rw-r--r--cmake/game/themes/Deluxe/[icon]song_search.pngbin0 -> 960 bytes
-rw-r--r--cmake/game/themes/Deluxe/[icon]song_video.png (renamed from cmake/game/themes/Deluxe/icon/song_video.png)bin629 -> 629 bytes
-rw-r--r--cmake/game/themes/Deluxe/[interface]cursor.pngbin0 -> 5635 bytes
-rw-r--r--cmake/game/themes/Deluxe/[interface]cursor_pressed.png (renamed from cmake/game/themes/Deluxe/interface/cursor.png)bin4111 -> 4086 bytes
-rw-r--r--cmake/game/themes/Deluxe/[interface]dialog_background.png (renamed from cmake/game/themes/Deluxe/interface/dialog_background.png)bin4063 -> 4063 bytes
-rw-r--r--cmake/game/themes/Deluxe/[interface]select_arrow_left.pngbin0 -> 485 bytes
-rw-r--r--cmake/game/themes/Deluxe/[interface]select_arrow_right.pngbin0 -> 485 bytes
-rw-r--r--cmake/game/themes/Deluxe/[interface]selectbg_search.pngbin0 -> 477 bytes
-rw-r--r--cmake/game/themes/Deluxe/[party]playerselectbg.pngbin0 -> 2910 bytes
-rw-r--r--cmake/game/visuals/.gitignore2
-rw-r--r--cmake/icons/rccompile-fpc.bat4
-rw-r--r--cmake/icons/ultrastardx-icon.rc1
-rw-r--r--cmake/installer/UltraStar Deluxe.nsi1326
-rw-r--r--cmake/installer/dependencies/dll/put game dlls here0
-rw-r--r--cmake/installer/dependencies/documents/documentation.pdf (renamed from cmake/installerdependencies/documents/documentation.pdf)bin575306 -> 575306 bytes
-rw-r--r--cmake/installer/dependencies/documents/license.txt (renamed from cmake/installerdependencies/documents/license.txt)250
-rw-r--r--cmake/installer/dependencies/images/header.bmp (renamed from cmake/installerdependencies/images/header.bmp)bin25820 -> 25820 bytes
-rw-r--r--cmake/installer/dependencies/images/side.bmp (renamed from cmake/installerdependencies/images/side.bmp)bin618008 -> 618008 bytes
-rw-r--r--cmake/installer/dependencies/loop.wavbin0 -> 1228860 bytes
-rw-r--r--cmake/installer/dependencies/plugins/NSISdl.dll (renamed from cmake/installerdependencies/plugins/NSISdl.dll)bin14848 -> 14848 bytes
-rw-r--r--cmake/installer/dependencies/plugins/ZipDLL.dll (renamed from cmake/installerdependencies/plugins/ZipDLL.dll)bin167424 -> 167424 bytes
-rw-r--r--cmake/installer/dependencies/plugins/nsProcess.dll (renamed from cmake/installerdependencies/plugins/nsProcess.dll)bin4096 -> 4096 bytes
-rw-r--r--cmake/installer/install.icobin0 -> 17542 bytes
-rw-r--r--cmake/installer/languages/English.nsh119
-rw-r--r--cmake/installer/languages/German.nsh138
-rw-r--r--cmake/installer/languages/Hungarian.nsh133
-rw-r--r--cmake/installer/languages/translations.txt16
-rw-r--r--cmake/installer/settings/GameExplorer.nsh198
-rw-r--r--cmake/installer/settings/files_main_install.nsh90
-rw-r--r--cmake/installer/settings/files_main_uninstall.nsh71
-rw-r--r--cmake/installer/settings/files_opt_songs.nsh931
-rw-r--r--cmake/installer/settings/functions.nsh153
-rw-r--r--cmake/installer/settings/settings-1031.ini197
-rw-r--r--cmake/installer/settings/settings-1033.ini201
-rw-r--r--cmake/installer/settings/settings-1038.ini161
-rw-r--r--cmake/installer/settings/variables.nsh22
-rw-r--r--cmake/installer/uninstall.ico (renamed from cmake/installerdependencies/images/uninstall.ico)bin22486 -> 22486 bytes
-rw-r--r--cmake/installerdependencies/images/install.icobin72374 -> 0 bytes
-rw-r--r--cmake/installerdependencies/plugins/gdf.dllbin126976 -> 0 bytes
-rw-r--r--cmake/plugins/5000Points/CMakeLists.txt4
-rw-r--r--cmake/plugins/5000Points/Until5000.dpr104
-rw-r--r--cmake/plugins/Blind/Blind.dpr112
-rw-r--r--cmake/plugins/Blind/CMakeLists.txt4
-rw-r--r--cmake/plugins/CMakeLists.txt18
-rw-r--r--cmake/plugins/Dont_Get_Worse/CMakeLists.txt8
-rw-r--r--cmake/plugins/Dont_Get_Worse/Hold_The_Line.bdsproj175
-rw-r--r--cmake/plugins/Dont_Get_Worse/Hold_The_Line.dpr227
-rw-r--r--cmake/plugins/Dont_Get_Worse/Hold_The_Line.lpi108
-rw-r--r--cmake/plugins/Dont_Get_Worse/dismissed.mp3bin5433 -> 0 bytes
-rw-r--r--cmake/plugins/Duell/CMakeLists.txt4
-rw-r--r--cmake/plugins/Duell/Duell.dpr106
-rw-r--r--cmake/plugins/README(Plugins Status).txt12
-rw-r--r--cmake/plugins/SDK/ModiSDK.pas164
-rw-r--r--cmake/plugins/SDK/USDXStrUtils.pas79
-rw-r--r--cmake/plugins/Team_Duell/CMakeLists.txt8
-rw-r--r--cmake/plugins/Team_Duell/TeamDuell.dpr274
-rw-r--r--cmake/res/rccompile-delphi.bat (renamed from cmake/icons/rccompile-delphi.bat)4
-rw-r--r--cmake/res/rccompile-fpc.bat4
-rw-r--r--cmake/res/ultrastardx.exe.manifest12
-rw-r--r--cmake/res/ultrastardx.rc4
-rw-r--r--cmake/res/ultrastardx.res (renamed from cmake/icons/ultrastardx-icon.res)bin22748 -> 23352 bytes
-rw-r--r--cmake/src/.gitignore8
-rw-r--r--cmake/src/base/TextGL.pas393
-rw-r--r--cmake/src/base/TextGLFreetype.pas222
-rw-r--r--cmake/src/base/UBeatTimer.pas459
-rw-r--r--cmake/src/base/UCatCovers.pas131
-rw-r--r--cmake/src/base/UCommandLine.pas25
-rw-r--r--cmake/src/base/UCommon.pas346
-rw-r--r--cmake/src/base/UConfig.pas30
-rw-r--r--cmake/src/base/UCovers.pas56
-rw-r--r--cmake/src/base/UDLLManager.pas292
-rw-r--r--cmake/src/base/UDataBase.pas458
-rw-r--r--cmake/src/base/UDraw.pas374
-rw-r--r--cmake/src/base/UEditorLyrics.pas4
-rw-r--r--cmake/src/base/UFiles.pas221
-rw-r--r--cmake/src/base/UFilesystem.pas692
-rw-r--r--cmake/src/base/UFont.pas849
-rw-r--r--cmake/src/base/UGraphic.pas186
-rw-r--r--cmake/src/base/UImage.pas194
-rw-r--r--cmake/src/base/UIni.pas451
-rw-r--r--cmake/src/base/ULanguage.pas220
-rw-r--r--cmake/src/base/ULog.pas44
-rw-r--r--cmake/src/base/ULyrics.pas4
-rw-r--r--cmake/src/base/UMain.pas302
-rw-r--r--cmake/src/base/UMusic.pas178
-rw-r--r--cmake/src/base/UNote.pas9
-rw-r--r--cmake/src/base/UParty.pas1057
-rw-r--r--cmake/src/base/UPath.pas1615
-rw-r--r--cmake/src/base/UPathUtils.pas196
-rw-r--r--cmake/src/base/UPlatform.pas95
-rw-r--r--cmake/src/base/UPlatformLinux.pas102
-rw-r--r--cmake/src/base/UPlatformMacOSX.pas198
-rw-r--r--cmake/src/base/UPlatformWindows.pas232
-rw-r--r--cmake/src/base/UPlaylist.pas261
-rw-r--r--cmake/src/base/URecord.pas67
-rw-r--r--cmake/src/base/USingScores.pas175
-rw-r--r--cmake/src/base/USkins.pas145
-rw-r--r--cmake/src/base/USong.pas1101
-rw-r--r--cmake/src/base/USongs.pas455
-rw-r--r--cmake/src/base/UTextEncoding.pas279
-rw-r--r--cmake/src/base/UTexture.pas50
-rw-r--r--cmake/src/base/UThemes.pas227
-rw-r--r--cmake/src/base/UTime.pas158
-rw-r--r--cmake/src/base/UUnicodeUtils.pas670
-rw-r--r--cmake/src/base/UXMLSong.pas97
-rw-r--r--cmake/src/config-win.inc29
-rw-r--r--cmake/src/config.inc.in5
-rw-r--r--cmake/src/encoding/Auto.inc137
-rw-r--r--cmake/src/encoding/CP1250.inc236
-rw-r--r--cmake/src/encoding/CP1252.inc122
-rw-r--r--cmake/src/encoding/Locale.inc55
-rw-r--r--cmake/src/encoding/UTF8.inc70
-rw-r--r--cmake/src/lib/FreeImage/FreeBitmap.pas2
-rw-r--r--cmake/src/lib/JEDI-SDL/OpenGL/Pas/glext.pas19
-rw-r--r--cmake/src/lib/JEDI-SDL/SDL/Pas/jedi-sdl.inc8
-rw-r--r--cmake/src/lib/JEDI-SDL/SDL/Pas/moduleloader.pas2
-rw-r--r--cmake/src/lib/JEDI-SDL/SDL/Pas/sdl.pas2
-rw-r--r--cmake/src/lib/Lua/ULua.pas1086
-rw-r--r--cmake/src/lib/SQLite/SQLite3.pas2
-rw-r--r--cmake/src/lib/SQLite/SQLiteTable3.pas21
-rw-r--r--cmake/src/lib/TntUnicodeControls/License.txt11
-rw-r--r--cmake/src/lib/TntUnicodeControls/Readme.txt53
-rw-r--r--cmake/src/lib/TntUnicodeControls/TntClasses.pas1806
-rw-r--r--cmake/src/lib/TntUnicodeControls/TntCompilers.inc378
-rw-r--r--cmake/src/lib/TntUnicodeControls/TntFormatStrUtils.pas521
-rw-r--r--cmake/src/lib/TntUnicodeControls/TntSysUtils.pas1753
-rw-r--r--cmake/src/lib/TntUnicodeControls/TntSystem.pas1427
-rw-r--r--cmake/src/lib/TntUnicodeControls/TntWideStrUtils.pas455
-rw-r--r--cmake/src/lib/TntUnicodeControls/TntWideStrings.pas846
-rw-r--r--cmake/src/lib/TntUnicodeControls/TntWindows.pas1501
-rw-r--r--cmake/src/lib/bass/bass.chmbin210668 -> 217294 bytes
-rw-r--r--cmake/src/lib/bass/bass.txt94
-rw-r--r--cmake/src/lib/bass/delphi/bass.pas115
-rw-r--r--cmake/src/lib/ctypes/ctypes.pas144
-rw-r--r--cmake/src/lib/ffmpeg/avcodec.pas730
-rw-r--r--cmake/src/lib/ffmpeg/avformat.pas315
-rw-r--r--cmake/src/lib/ffmpeg/avio.pas204
-rw-r--r--cmake/src/lib/ffmpeg/avutil.pas140
-rw-r--r--cmake/src/lib/ffmpeg/error.pas113
-rw-r--r--cmake/src/lib/ffmpeg/mathematics.pas30
-rw-r--r--cmake/src/lib/ffmpeg/opt.pas59
-rw-r--r--cmake/src/lib/ffmpeg/rational.pas4
-rw-r--r--cmake/src/lib/ffmpeg/src/MacOSX/MacOSXReadMe.txt24
-rwxr-xr-xcmake/src/lib/ffmpeg/src/MacOSX/build_ffmpeg.sh6
-rwxr-xr-xcmake/src/lib/ffmpeg/src/MacOSX/copy_and_patch_dylibs.sh23
-rw-r--r--cmake/src/lib/ffmpeg/swscale.pas92
-rw-r--r--cmake/src/lib/fft/UFFT.pas2
-rw-r--r--cmake/src/lib/freetype/demo/engine-test.bdsproj14
-rw-r--r--cmake/src/lib/freetype/demo/engine-test.dpr16
-rw-r--r--cmake/src/lib/freetype/demo/engine-test.lpi39
-rw-r--r--cmake/src/lib/freetype/freetype.pas989
-rw-r--r--cmake/src/lib/freetype/ftconfig.inc35
-rw-r--r--cmake/src/lib/freetype/ftglyph.inc435
-rw-r--r--cmake/src/lib/freetype/ftimage.inc849
-rw-r--r--cmake/src/lib/freetype/ftoutln.inc497
-rw-r--r--cmake/src/lib/freetype/ftstroke.inc711
-rw-r--r--cmake/src/lib/freetype/fttypes.inc311
-rw-r--r--cmake/src/lib/lib-info.txt118
-rw-r--r--cmake/src/lib/midi/CIRCBUF.PAS2
-rw-r--r--cmake/src/lib/midi/DELPHMCB.PAS2
-rw-r--r--cmake/src/lib/midi/MIDIDEFS.PAS2
-rw-r--r--cmake/src/lib/midi/MIDITYPE.PAS2
-rw-r--r--cmake/src/lib/midi/MidiFile.pas28
-rw-r--r--cmake/src/lib/midi/MidiScope.pas2
-rw-r--r--cmake/src/lib/midi/Midicons.pas2
-rw-r--r--cmake/src/lib/midi/Midiin.pas11
-rw-r--r--cmake/src/lib/midi/Midiout.pas11
-rw-r--r--cmake/src/lib/other/DirWatch.pas2
-rw-r--r--cmake/src/lib/pcre/pcre.pas852
-rw-r--r--cmake/src/lib/portaudio/portaudio.pas4
-rw-r--r--cmake/src/lib/projectM/cwrapper/projectM-cwrapper.h3
-rw-r--r--cmake/src/lib/projectM/projectM.pas2
-rw-r--r--cmake/src/lib/zlib/zlib.pas2
-rw-r--r--cmake/src/lua/UHookableEvent.pas380
-rw-r--r--cmake/src/lua/ULuaCore.pas1021
-rw-r--r--cmake/src/lua/ULuaGl.pas1513
-rw-r--r--cmake/src/lua/ULuaLog.pas167
-rw-r--r--cmake/src/lua/ULuaParty.pas391
-rw-r--r--cmake/src/lua/ULuaScreenSing.pas489
-rw-r--r--cmake/src/lua/ULuaTextGL.pas148
-rw-r--r--cmake/src/lua/ULuaTexture.pas63
-rw-r--r--cmake/src/lua/ULuaUsdx.pas145
-rw-r--r--cmake/src/lua/ULuaUtils.pas186
-rw-r--r--cmake/src/media/UAudioCore_Bass.pas29
-rw-r--r--cmake/src/media/UAudioCore_Portaudio.pas88
-rw-r--r--cmake/src/media/UAudioDecoder_Bass.pas21
-rw-r--r--cmake/src/media/UAudioDecoder_FFmpeg.pas96
-rw-r--r--cmake/src/media/UAudioInput_Bass.pas19
-rw-r--r--cmake/src/media/UAudioInput_Portaudio.pas188
-rw-r--r--cmake/src/media/UAudioPlaybackBase.pas24
-rw-r--r--cmake/src/media/UAudioPlayback_Bass.pas6
-rw-r--r--cmake/src/media/UAudioPlayback_Portaudio.pas22
-rw-r--r--cmake/src/media/UAudioPlayback_SoftMixer.pas94
-rw-r--r--cmake/src/media/UMediaCore_FFmpeg.pas146
-rw-r--r--cmake/src/media/UMedia_dummy.pas210
-rw-r--r--cmake/src/media/UVideo.pas377
-rw-r--r--cmake/src/media/UVisualizer.pas231
-rw-r--r--cmake/src/menu/UDisplay.pas389
-rw-r--r--cmake/src/menu/UMenu.pas508
-rw-r--r--cmake/src/menu/UMenuBackground.pas166
-rw-r--r--cmake/src/menu/UMenuBackgroundColor.pas144
-rw-r--r--cmake/src/menu/UMenuBackgroundFade.pas352
-rw-r--r--cmake/src/menu/UMenuBackgroundNone.pas138
-rw-r--r--cmake/src/menu/UMenuBackgroundTexture.pas251
-rw-r--r--cmake/src/menu/UMenuBackgroundVideo.pas415
-rw-r--r--cmake/src/menu/UMenuButton.pas48
-rw-r--r--cmake/src/menu/UMenuInteract.pas9
-rw-r--r--cmake/src/menu/UMenuSelectSlide.pas217
-rw-r--r--cmake/src/menu/UMenuText.pas57
-rw-r--r--cmake/src/screens/UScreenCredits.pas97
-rw-r--r--cmake/src/screens/UScreenEdit.pas15
-rw-r--r--cmake/src/screens/UScreenEditConvert.pas678
-rw-r--r--cmake/src/screens/UScreenEditHeader.pas110
-rw-r--r--cmake/src/screens/UScreenEditSub.pas579
-rw-r--r--cmake/src/screens/UScreenLevel.pas25
-rw-r--r--cmake/src/screens/UScreenLoading.pas11
-rw-r--r--cmake/src/screens/UScreenMain.pas68
-rw-r--r--cmake/src/screens/UScreenName.pas20
-rw-r--r--cmake/src/screens/UScreenOpen.pas99
-rw-r--r--cmake/src/screens/UScreenOptions.pas19
-rw-r--r--cmake/src/screens/UScreenOptionsAdvanced.pas22
-rw-r--r--cmake/src/screens/UScreenOptionsGame.pas31
-rw-r--r--cmake/src/screens/UScreenOptionsGraphics.pas28
-rw-r--r--cmake/src/screens/UScreenOptionsLyrics.pas18
-rw-r--r--cmake/src/screens/UScreenOptionsRecord.pas57
-rw-r--r--cmake/src/screens/UScreenOptionsSound.pas19
-rw-r--r--cmake/src/screens/UScreenOptionsThemes.pas46
-rw-r--r--cmake/src/screens/UScreenPartyNewRound.pas318
-rw-r--r--cmake/src/screens/UScreenPartyOptions.pas113
-rw-r--r--cmake/src/screens/UScreenPartyPlayer.pas306
-rw-r--r--cmake/src/screens/UScreenPartyRounds.pas233
-rw-r--r--cmake/src/screens/UScreenPartyScore.pas193
-rw-r--r--cmake/src/screens/UScreenPartyWin.pas155
-rw-r--r--cmake/src/screens/UScreenPopup.pas148
-rw-r--r--cmake/src/screens/UScreenScore.pas807
-rw-r--r--cmake/src/screens/UScreenSing.pas339
-rw-r--r--cmake/src/screens/UScreenSingModi.pas580
-rw-r--r--cmake/src/screens/UScreenSong.pas568
-rw-r--r--cmake/src/screens/UScreenSongJumpto.pas97
-rw-r--r--cmake/src/screens/UScreenSongMenu.pas58
-rw-r--r--cmake/src/screens/UScreenStatDetail.pas21
-rw-r--r--cmake/src/screens/UScreenStatMain.pas42
-rw-r--r--cmake/src/screens/UScreenTop5.pas114
-rw-r--r--cmake/src/screens/UScreenWelcome.pas164
-rw-r--r--cmake/src/switches.inc28
-rw-r--r--cmake/src/ultrastardx.dpr66
-rw-r--r--cmake/test/TestPortAudioDevice.pas528
-rw-r--r--cmake/test/TestSignAlgorithm.pas58
548 files changed, 68784 insertions, 26810 deletions
diff --git a/cmake/.gitignore b/cmake/.gitignore
new file mode 100644
index 00000000..2223ac43
--- /dev/null
+++ b/cmake/.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/cmake/AUTHORS.txt b/cmake/AUTHORS.txt
index 3f9a0f63..21f2c27a 100644
--- a/cmake/AUTHORS.txt
+++ b/cmake/AUTHORS.txt
@@ -8,6 +8,7 @@ This modification was continued at Sourceforge.net by the Ultrastar Deluxe Team:
Mischi
Mog
Whiteshark
+ brunzel
~=[ Retired project developers / admins ]=~
Alex
diff --git a/cmake/BuildBot.trigger b/cmake/BuildBot.trigger
index 56a6051c..be162472 100644
--- a/cmake/BuildBot.trigger
+++ b/cmake/BuildBot.trigger
@@ -1 +1 @@
-1 \ No newline at end of file
+4 \ No newline at end of file
diff --git a/cmake/COPYRIGHT.txt b/cmake/COPYRIGHT.txt
index 2dbd2616..f2a8e249 100644
--- a/cmake/COPYRIGHT.txt
+++ b/cmake/COPYRIGHT.txt
@@ -1,29 +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"
-"eddie-0815"
-Mike Gränz "mog"
-Tobias Gunkel "tobigun"
-"mota"
-"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"
+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/cmake/ChangeLog.GERMAN.txt b/cmake/ChangeLog.GERMAN.txt
index cf9b3391..a20873b7 100644
--- a/cmake/ChangeLog.GERMAN.txt
+++ b/cmake/ChangeLog.GERMAN.txt
@@ -1,202 +1,336 @@
-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
+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 Max 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
+
+--------------
+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
+
+--------------
+Song Dateien
+--------------
+Upd: Unterstützung für UTF8
+Upd: #Encoding Tag
+ - CP1250: Mittel-/Osteuropäische Kodierung; wird standardmäßig von Corvus Ultrastar benutzt
+ - CP1252: Westeuropäische Kodierung; wurde standardmäßig von Ultrastar Deluxe vor 1.1 benutzt
+ - Locale: Benutzt die Systemkodierung (sollte für neue Dateien nicht verwendet werden)
+ - UTF8: Textdatei ist in UTF8 kodiert (empfohlen)
+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
diff --git a/cmake/ChangeLog.txt b/cmake/ChangeLog.txt
index 9b4bbfea..d6987489 100644
--- a/cmake/ChangeLog.txt
+++ b/cmake/ChangeLog.txt
@@ -1,3 +1,137 @@
+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: Max 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)
+
+--------------
+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
+
+--------------
+song files
+--------------
+upd: UTF8 support
+upd: #Encoding tag
+ - CP1250: Central/Eastern european encoding
+ - CP1252: Western european encoding; was used as default before 1.1
+ - Locale: uses system encoding (should not be used for new files!)
+ - UTF8: text file is encoded in UTF8 (recommended)
+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)
-----------------------------
@@ -14,7 +148,7 @@ 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
--------------
@@ -58,7 +192,7 @@ 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:
+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.
@@ -131,7 +265,7 @@ 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
@@ -192,4 +326,4 @@ UltraStar 0.5.0 mota patch (Release by Mota)
UltraStar 0.5.0 (by Corvus5)
--------------------------
-- Original Code \ No newline at end of file
+- Original Code
diff --git a/cmake/DisplayChanges.patch b/cmake/DisplayChanges.patch
index c22be897..9cb00a18 100644
--- a/cmake/DisplayChanges.patch
+++ b/cmake/DisplayChanges.patch
@@ -1,8 +1,8 @@
-Index: src/menu/UDisplay.pas
-===================================================================
---- src/menu/UDisplay.pas (revision 1702)
-+++ src/menu/UDisplay.pas (working copy)
-@@ -42,8 +42,65 @@
+Index: src/menu/UDisplay.pas
+===================================================================
+--- src/menu/UDisplay.pas (revision 1702)
++++ src/menu/UDisplay.pas (working copy)
+@@ -42,8 +42,65 @@
SysUtils;
type
@@ -68,7 +68,7 @@ Index: src/menu/UDisplay.pas
//fade-to-black-hack
BlackScreen: boolean;
-@@ -53,7 +110,7 @@
+@@ -53,7 +110,7 @@
LastFadeTime: cardinal; // last fade update time
FadeTex: array[1..2] of GLuint;
@@ -77,7 +77,7 @@ Index: src/menu/UDisplay.pas
FPSCounter: cardinal;
LastFPS: cardinal;
NextFPSSwap: cardinal;
-@@ -78,7 +135,7 @@
+@@ -78,7 +135,7 @@
procedure SaveScreenShot;
function Draw: boolean;
diff --git a/cmake/RELEASEBLOCKERS.txt b/cmake/RELEASEBLOCKERS.txt
index 54d7342e..bcac2887 100644
--- a/cmake/RELEASEBLOCKERS.txt
+++ b/cmake/RELEASEBLOCKERS.txt
@@ -1,31 +1,32 @@
-Blockers for the outstanding 1.1 release
-if you want to help us then start at this tasks
-
-Missing party mode (contact whiteshark to get further information on how to help)
-- finishing new one (partymode branch)
- pro: should be easy to port to all supported platforms
- it should be easy to extended w/ lua support
- basic plugin support, not only party modes
- con: work!
- modes has to be adapted
- work!
-- merge the old one
- pro: less work
- it is known to work and there are many existing modis
- con: may be difficult to port to other platforms than windows
-
-Unicode support (contact tobigun to get further information on how to help)
-- there is a unicode branch
-- seems to work except for some glitches
-
-Microfone playback
-- 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
-
-Theme changes
-- there are some problems w/ theme-object positions mainly in the option-screens
-
-There are also assembla tickets that need to be fixed
+Blockers for the outstanding 1.1 release
+if you want to help us then start at this tasks
+
+Missing party mode (contact whiteshark to get further information on how to help)
+- finishing new one (partymode branch)
+ pro: should be easy to port to all supported platforms
+ it should be easy to extended w/ lua support
+ basic plugin support, not only party modes
+ con: work!
+ modes has to be adapted
+ work!
+- merge the old one
+ pro: less work
+ it is known to work and there are many existing modis
+ con: may be difficult to port to other platforms than windows
+
+Unicode support (contact tobigun to get further information on how to help)
+- should work now but needs some testing
+- report bugs specific to the unicode branch (cross-check the trunk) at
+ our forum (http://ultrastardeluxe.xtremeweb-hosting.net/)
+
+Microfone playback
+- 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
+
+Theme changes
+- there are some problems w/ theme-object positions mainly in the option-screens
+
+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/cmake/artwork/.PLACEHOLDER b/cmake/artwork/.PLACEHOLDER
deleted file mode 100644
index e6e5ed81..00000000
--- a/cmake/artwork/.PLACEHOLDER
+++ /dev/null
@@ -1,2 +0,0 @@
-Placeholder for empty directories that might be ignored by "make package_source" otherwise.
-
diff --git a/cmake/build/.gitignore b/cmake/build/.gitignore
new file mode 100644
index 00000000..caf367b0
--- /dev/null
+++ b/cmake/build/.gitignore
@@ -0,0 +1 @@
+*.res
diff --git a/cmake/build/delphi-win/.gitignore b/cmake/build/delphi-win/.gitignore
new file mode 100644
index 00000000..59424db9
--- /dev/null
+++ b/cmake/build/delphi-win/.gitignore
@@ -0,0 +1 @@
+# don't delete this file as it prevents git from removing this directory
diff --git a/cmake/dists/delphi2005/readme.txt b/cmake/dists/delphi2005/readme.txt
index 2901b48a..64168d3c 100644
--- a/cmake/dists/delphi2005/readme.txt
+++ b/cmake/dists/delphi2005/readme.txt
@@ -1,5 +1,5 @@
-(Turbo-)Delphi 2005/2006 Project file
---------------------------------------
-1. Copy ultrastardx.bdsproj to <ultrastardx>/src
-2. Double-click <ultrastardx>/src/ultrastardx.bdsproj
-
+(Turbo-)Delphi 2005/2006 Project file
+--------------------------------------
+1. Copy ultrastardx.bdsproj to <ultrastardx>/src
+2. Double-click <ultrastardx>/src/ultrastardx.bdsproj
+
diff --git a/cmake/dists/delphi7/readme.txt b/cmake/dists/delphi7/readme.txt
index 1ede3162..fa77699b 100644
--- a/cmake/dists/delphi7/readme.txt
+++ b/cmake/dists/delphi7/readme.txt
@@ -1,5 +1,5 @@
-Delphi 7 Project file
---------------------------------------
-1. Copy ultrastardx.dof to <ultrastardx>/src
-2. Double-click <ultrastardx>/src/ultrastardx.dpr
-
+Delphi 7 Project file
+--------------------------------------
+1. Copy ultrastardx.dof to <ultrastardx>/src
+2. Double-click <ultrastardx>/src/ultrastardx.dpr
+
diff --git a/cmake/dists/gentoo/readme.txt b/cmake/dists/gentoo/readme.txt
index cf6dfcc1..982d42c9 100644
--- a/cmake/dists/gentoo/readme.txt
+++ b/cmake/dists/gentoo/readme.txt
@@ -3,7 +3,7 @@
---------------------------------------
This directory contains two ebuilds for UltraStar Deluxe
- ultrastardx-9999.ebuild: a live ebuild using SVN sources
-- ultrastardx-1.1_alpha.ebuild: a snapshot ebuild that might be appended to the official portage someday (Note: at the moment there is no source snapshot for USDX so this will not work)
+- ultrastardx-1.1_beta.ebuild: a snapshot ebuild that might be appended to the official portage someday (Note: at the moment there is no source snapshot for USDX so this will not work)
---------------------------------------
2. Create a portage overlay
diff --git a/cmake/dists/gentoo/ultrastardx-1.1_beta.ebuild b/cmake/dists/gentoo/ultrastardx-1.1_beta.ebuild
new file mode 100644
index 00000000..efb52a54
--- /dev/null
+++ b/cmake/dists/gentoo/ultrastardx-1.1_beta.ebuild
@@ -0,0 +1,81 @@
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header $
+
+inherit cmake-utils 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.2"
+
+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() {
+ # set build-type as the "Gentoo" build-type does not work with
+ # Pascal (no optimization, etc.)
+ if use debug ; then
+ CMAKE_BUILD_TYPE="Debug"
+ else
+ CMAKE_BUILD_TYPE="Release"
+ fi
+
+ # set PREFIX so that CMAKE_INSTALL_PREFIX will be set to GAMES_PREFIX
+ PREFIX="${GAMES_PREFIX}"
+
+ # configure flags
+ local mycmakeargs="$(cmake-utils_use_enable projectm PROJECTM) \
+ $(cmake-utils_use_build plugins PLUGINS) \
+ -DBINDIR=${GAMES_BINDIR} \
+ -DDATADIR=${GAMES_DATADIR}/${PN}"
+
+ cmake-utils_src_compile
+}
+
+src_install() {
+ cmake-utils_src_install
+
+ 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/cmake/dists/lazarus/readme.txt b/cmake/dists/lazarus/readme.txt
index c828266b..012ee37a 100755
--- a/cmake/dists/lazarus/readme.txt
+++ b/cmake/dists/lazarus/readme.txt
@@ -1,15 +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"
+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/cmake/dists/lazarus/ultrastardx-unix.lpi b/cmake/dists/lazarus/ultrastardx-unix.lpi
index 0fab8fcd..4160f850 100644
--- a/cmake/dists/lazarus/ultrastardx-unix.lpi
+++ b/cmake/dists/lazarus/ultrastardx-unix.lpi
@@ -2,15 +2,15 @@
<CONFIG>
<ProjectOptions>
<PathDelim Value="/"/>
- <Version Value="6"/>
+ <Version Value="7"/>
<General>
<Flags>
<MainUnitHasCreateFormStatements Value="False"/>
<MainUnitHasTitleStatement Value="False"/>
+ <LRSInOutputDirectory Value="False"/>
</Flags>
<SessionStorage Value="InProjectDir"/>
<MainUnit Value="0"/>
- <IconPath Value="./"/>
<TargetFileExt Value=""/>
<Title Value="ultrastardx"/>
</General>
@@ -29,7 +29,7 @@
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
</local>
</RunParams>
- <Units Count="118">
+ <Units Count="127">
<Unit0>
<Filename Value="ultrastardx.dpr"/>
<IsPartOfProject Value="True"/>
@@ -130,381 +130,431 @@
<Unit24>
<Filename Value="base/UMain.pas"/>
<IsPartOfProject Value="True"/>
+ <UnitName Value="UMain"/>
</Unit24>
<Unit25>
- <Filename Value="base/UModules.pas"/>
+ <Filename Value="base/UMusic.pas"/>
<IsPartOfProject Value="True"/>
</Unit25>
<Unit26>
- <Filename Value="base/UMusic.pas"/>
+ <Filename Value="base/UParty.pas"/>
<IsPartOfProject Value="True"/>
</Unit26>
<Unit27>
- <Filename Value="base/UParty.pas"/>
+ <Filename Value="base/UPlatform.pas"/>
<IsPartOfProject Value="True"/>
</Unit27>
<Unit28>
- <Filename Value="base/UPlatform.pas"/>
+ <Filename Value="base/UPlatformLinux.pas"/>
<IsPartOfProject Value="True"/>
</Unit28>
<Unit29>
- <Filename Value="base/UPlatformLinux.pas"/>
+ <Filename Value="base/UPlatformMacOSX.pas"/>
<IsPartOfProject Value="True"/>
</Unit29>
<Unit30>
- <Filename Value="base/UPlatformMacOSX.pas"/>
+ <Filename Value="base/UPlatformWindows.pas"/>
<IsPartOfProject Value="True"/>
</Unit30>
<Unit31>
- <Filename Value="base/UPlatformWindows.pas"/>
+ <Filename Value="base/UPlaylist.pas"/>
<IsPartOfProject Value="True"/>
</Unit31>
<Unit32>
- <Filename Value="base/UPlaylist.pas"/>
+ <Filename Value="base/UPluginInterface.pas"/>
<IsPartOfProject Value="True"/>
</Unit32>
<Unit33>
- <Filename Value="base/UPluginInterface.pas"/>
+ <Filename Value="base/UPluginLoader.pas"/>
<IsPartOfProject Value="True"/>
</Unit33>
<Unit34>
- <Filename Value="base/UPluginLoader.pas"/>
+ <Filename Value="base/URecord.pas"/>
<IsPartOfProject Value="True"/>
</Unit34>
<Unit35>
- <Filename Value="base/URecord.pas"/>
+ <Filename Value="base/URingBuffer.pas"/>
<IsPartOfProject Value="True"/>
</Unit35>
<Unit36>
- <Filename Value="base/URingBuffer.pas"/>
+ <Filename Value="base/UServices.pas"/>
<IsPartOfProject Value="True"/>
</Unit36>
<Unit37>
- <Filename Value="base/UServices.pas"/>
+ <Filename Value="base/USingNotes.pas"/>
<IsPartOfProject Value="True"/>
</Unit37>
<Unit38>
- <Filename Value="base/USingNotes.pas"/>
+ <Filename Value="base/USingScores.pas"/>
<IsPartOfProject Value="True"/>
</Unit38>
<Unit39>
- <Filename Value="base/USingScores.pas"/>
+ <Filename Value="base/USkins.pas"/>
<IsPartOfProject Value="True"/>
</Unit39>
<Unit40>
- <Filename Value="base/USkins.pas"/>
+ <Filename Value="base/USong.pas"/>
<IsPartOfProject Value="True"/>
</Unit40>
<Unit41>
- <Filename Value="base/USong.pas"/>
+ <Filename Value="base/USongs.pas"/>
<IsPartOfProject Value="True"/>
</Unit41>
<Unit42>
- <Filename Value="base/USongs.pas"/>
+ <Filename Value="base/UTextClasses.pas"/>
<IsPartOfProject Value="True"/>
</Unit42>
<Unit43>
- <Filename Value="base/UTextClasses.pas"/>
+ <Filename Value="base/UTexture.pas"/>
<IsPartOfProject Value="True"/>
</Unit43>
<Unit44>
- <Filename Value="base/UTexture.pas"/>
+ <Filename Value="base/UThemes.pas"/>
<IsPartOfProject Value="True"/>
+ <UnitName Value="UThemes"/>
</Unit44>
<Unit45>
- <Filename Value="base/UThemes.pas"/>
+ <Filename Value="base/UTime.pas"/>
<IsPartOfProject Value="True"/>
- <UnitName Value="UThemes"/>
+ <UnitName Value="UTime"/>
</Unit45>
<Unit46>
- <Filename Value="base/UTime.pas"/>
+ <Filename Value="base/UXMLSong.pas"/>
<IsPartOfProject Value="True"/>
</Unit46>
<Unit47>
- <Filename Value="base/UXMLSong.pas"/>
+ <Filename Value="menu/UDisplay.pas"/>
<IsPartOfProject Value="True"/>
</Unit47>
<Unit48>
- <Filename Value="menu/UDisplay.pas"/>
+ <Filename Value="menu/UDrawTexture.pas"/>
<IsPartOfProject Value="True"/>
</Unit48>
<Unit49>
- <Filename Value="menu/UDrawTexture.pas"/>
+ <Filename Value="menu/UMenu.pas"/>
<IsPartOfProject Value="True"/>
</Unit49>
<Unit50>
- <Filename Value="menu/UMenu.pas"/>
+ <Filename Value="menu/UMenuBackground.pas"/>
<IsPartOfProject Value="True"/>
</Unit50>
<Unit51>
- <Filename Value="menu/UMenuBackground.pas"/>
+ <Filename Value="menu/UMenuBackgroundColor.pas"/>
<IsPartOfProject Value="True"/>
</Unit51>
<Unit52>
- <Filename Value="menu/UMenuBackgroundColor.pas"/>
+ <Filename Value="menu/UMenuBackgroundFade.pas"/>
<IsPartOfProject Value="True"/>
</Unit52>
<Unit53>
- <Filename Value="menu/UMenuBackgroundFade.pas"/>
+ <Filename Value="menu/UMenuBackgroundNone.pas"/>
<IsPartOfProject Value="True"/>
</Unit53>
<Unit54>
- <Filename Value="menu/UMenuBackgroundNone.pas"/>
+ <Filename Value="menu/UMenuBackgroundTexture.pas"/>
<IsPartOfProject Value="True"/>
</Unit54>
<Unit55>
- <Filename Value="menu/UMenuBackgroundTexture.pas"/>
+ <Filename Value="menu/UMenuBackgroundVideo.pas"/>
<IsPartOfProject Value="True"/>
</Unit55>
<Unit56>
- <Filename Value="menu/UMenuBackgroundVideo.pas"/>
+ <Filename Value="menu/UMenuButton.pas"/>
<IsPartOfProject Value="True"/>
</Unit56>
<Unit57>
- <Filename Value="menu/UMenuButton.pas"/>
+ <Filename Value="menu/UMenuButtonCollection.pas"/>
<IsPartOfProject Value="True"/>
</Unit57>
<Unit58>
- <Filename Value="menu/UMenuButtonCollection.pas"/>
+ <Filename Value="menu/UMenuEqualizer.pas"/>
<IsPartOfProject Value="True"/>
</Unit58>
<Unit59>
- <Filename Value="menu/UMenuEqualizer.pas"/>
+ <Filename Value="menu/UMenuInteract.pas"/>
<IsPartOfProject Value="True"/>
</Unit59>
<Unit60>
- <Filename Value="menu/UMenuInteract.pas"/>
+ <Filename Value="menu/UMenuSelectSlide.pas"/>
<IsPartOfProject Value="True"/>
</Unit60>
<Unit61>
- <Filename Value="menu/UMenuSelectSlide.pas"/>
+ <Filename Value="menu/UMenuStatic.pas"/>
<IsPartOfProject Value="True"/>
</Unit61>
<Unit62>
- <Filename Value="menu/UMenuStatic.pas"/>
+ <Filename Value="menu/UMenuText.pas"/>
<IsPartOfProject Value="True"/>
</Unit62>
<Unit63>
- <Filename Value="menu/UMenuText.pas"/>
+ <Filename Value="screens/UScreenCredits.pas"/>
<IsPartOfProject Value="True"/>
+ <UnitName Value="UScreenCredits"/>
</Unit63>
<Unit64>
- <Filename Value="screens/UScreenCredits.pas"/>
+ <Filename Value="screens/UScreenEdit.pas"/>
<IsPartOfProject Value="True"/>
- <UnitName Value="UScreenCredits"/>
</Unit64>
<Unit65>
- <Filename Value="screens/UScreenEdit.pas"/>
+ <Filename Value="screens/UScreenEditConvert.pas"/>
<IsPartOfProject Value="True"/>
</Unit65>
<Unit66>
- <Filename Value="screens/UScreenEditConvert.pas"/>
+ <Filename Value="screens/UScreenEditHeader.pas"/>
<IsPartOfProject Value="True"/>
</Unit66>
<Unit67>
- <Filename Value="screens/UScreenEditHeader.pas"/>
+ <Filename Value="screens/UScreenEditSub.pas"/>
<IsPartOfProject Value="True"/>
</Unit67>
<Unit68>
- <Filename Value="screens/UScreenEditSub.pas"/>
+ <Filename Value="screens/UScreenLevel.pas"/>
<IsPartOfProject Value="True"/>
</Unit68>
<Unit69>
- <Filename Value="screens/UScreenLevel.pas"/>
+ <Filename Value="screens/UScreenLoading.pas"/>
<IsPartOfProject Value="True"/>
</Unit69>
<Unit70>
- <Filename Value="screens/UScreenLoading.pas"/>
+ <Filename Value="screens/UScreenMain.pas"/>
<IsPartOfProject Value="True"/>
</Unit70>
<Unit71>
- <Filename Value="screens/UScreenMain.pas"/>
+ <Filename Value="screens/UScreenName.pas"/>
<IsPartOfProject Value="True"/>
</Unit71>
<Unit72>
- <Filename Value="screens/UScreenName.pas"/>
+ <Filename Value="screens/UScreenOpen.pas"/>
<IsPartOfProject Value="True"/>
</Unit72>
<Unit73>
- <Filename Value="screens/UScreenOpen.pas"/>
+ <Filename Value="screens/UScreenOptions.pas"/>
<IsPartOfProject Value="True"/>
</Unit73>
<Unit74>
- <Filename Value="screens/UScreenOptions.pas"/>
+ <Filename Value="screens/UScreenOptionsAdvanced.pas"/>
<IsPartOfProject Value="True"/>
</Unit74>
<Unit75>
- <Filename Value="screens/UScreenOptionsAdvanced.pas"/>
+ <Filename Value="screens/UScreenOptionsGame.pas"/>
<IsPartOfProject Value="True"/>
</Unit75>
<Unit76>
- <Filename Value="screens/UScreenOptionsGame.pas"/>
+ <Filename Value="screens/UScreenOptionsGraphics.pas"/>
<IsPartOfProject Value="True"/>
</Unit76>
<Unit77>
- <Filename Value="screens/UScreenOptionsGraphics.pas"/>
+ <Filename Value="screens/UScreenOptionsLyrics.pas"/>
<IsPartOfProject Value="True"/>
</Unit77>
<Unit78>
- <Filename Value="screens/UScreenOptionsLyrics.pas"/>
+ <Filename Value="screens/UScreenOptionsRecord.pas"/>
<IsPartOfProject Value="True"/>
</Unit78>
<Unit79>
- <Filename Value="screens/UScreenOptionsRecord.pas"/>
+ <Filename Value="screens/UScreenOptionsSound.pas"/>
<IsPartOfProject Value="True"/>
</Unit79>
<Unit80>
- <Filename Value="screens/UScreenOptionsSound.pas"/>
+ <Filename Value="screens/UScreenOptionsThemes.pas"/>
<IsPartOfProject Value="True"/>
</Unit80>
<Unit81>
- <Filename Value="screens/UScreenOptionsThemes.pas"/>
+ <Filename Value="screens/UScreenPartyNewRound.pas"/>
<IsPartOfProject Value="True"/>
</Unit81>
<Unit82>
- <Filename Value="screens/UScreenPartyNewRound.pas"/>
+ <Filename Value="screens/UScreenPartyOptions.pas"/>
<IsPartOfProject Value="True"/>
</Unit82>
<Unit83>
- <Filename Value="screens/UScreenPartyOptions.pas"/>
+ <Filename Value="screens/UScreenPartyPlayer.pas"/>
<IsPartOfProject Value="True"/>
</Unit83>
<Unit84>
- <Filename Value="screens/UScreenPartyPlayer.pas"/>
+ <Filename Value="screens/UScreenPartyScore.pas"/>
<IsPartOfProject Value="True"/>
</Unit84>
<Unit85>
- <Filename Value="screens/UScreenPartyScore.pas"/>
+ <Filename Value="screens/UScreenPartyWin.pas"/>
<IsPartOfProject Value="True"/>
</Unit85>
<Unit86>
- <Filename Value="screens/UScreenPartyWin.pas"/>
+ <Filename Value="screens/UScreenPopup.pas"/>
<IsPartOfProject Value="True"/>
</Unit86>
<Unit87>
- <Filename Value="screens/UScreenPopup.pas"/>
+ <Filename Value="screens/UScreenScore.pas"/>
<IsPartOfProject Value="True"/>
</Unit87>
<Unit88>
- <Filename Value="screens/UScreenScore.pas"/>
+ <Filename Value="screens/UScreenSing.pas"/>
<IsPartOfProject Value="True"/>
</Unit88>
<Unit89>
- <Filename Value="screens/UScreenSing.pas"/>
+ <Filename Value="screens/UScreenSingModi.pas"/>
<IsPartOfProject Value="True"/>
</Unit89>
<Unit90>
- <Filename Value="screens/UScreenSingModi.pas"/>
+ <Filename Value="screens/UScreenSong.pas"/>
<IsPartOfProject Value="True"/>
</Unit90>
<Unit91>
- <Filename Value="screens/UScreenSong.pas"/>
+ <Filename Value="screens/UScreenSongJumpto.pas"/>
<IsPartOfProject Value="True"/>
</Unit91>
<Unit92>
- <Filename Value="screens/UScreenSongJumpto.pas"/>
+ <Filename Value="screens/UScreenSongMenu.pas"/>
<IsPartOfProject Value="True"/>
</Unit92>
<Unit93>
- <Filename Value="screens/UScreenSongMenu.pas"/>
+ <Filename Value="screens/UScreenStatDetail.pas"/>
<IsPartOfProject Value="True"/>
</Unit93>
<Unit94>
- <Filename Value="screens/UScreenStatDetail.pas"/>
+ <Filename Value="screens/UScreenStatMain.pas"/>
<IsPartOfProject Value="True"/>
</Unit94>
<Unit95>
- <Filename Value="screens/UScreenStatMain.pas"/>
+ <Filename Value="screens/UScreenTop5.pas"/>
<IsPartOfProject Value="True"/>
</Unit95>
<Unit96>
- <Filename Value="screens/UScreenTop5.pas"/>
+ <Filename Value="screens/UScreenWelcome.pas"/>
<IsPartOfProject Value="True"/>
</Unit96>
<Unit97>
- <Filename Value="screens/UScreenWelcome.pas"/>
+ <Filename Value="media/UAudioConverter.pas"/>
<IsPartOfProject Value="True"/>
</Unit97>
<Unit98>
- <Filename Value="media/UAudioConverter.pas"/>
+ <Filename Value="media/UAudioCore_Bass.pas"/>
<IsPartOfProject Value="True"/>
</Unit98>
<Unit99>
- <Filename Value="media/UAudioCore_Bass.pas"/>
+ <Filename Value="media/UAudioCore_Portaudio.pas"/>
<IsPartOfProject Value="True"/>
</Unit99>
<Unit100>
- <Filename Value="media/UAudioCore_Portaudio.pas"/>
+ <Filename Value="media/UAudioDecoder_Bass.pas"/>
<IsPartOfProject Value="True"/>
</Unit100>
<Unit101>
- <Filename Value="media/UAudioDecoder_Bass.pas"/>
+ <Filename Value="media/UAudioDecoder_FFmpeg.pas"/>
<IsPartOfProject Value="True"/>
</Unit101>
<Unit102>
- <Filename Value="media/UAudioDecoder_FFmpeg.pas"/>
+ <Filename Value="media/UAudioInput_Bass.pas"/>
<IsPartOfProject Value="True"/>
</Unit102>
<Unit103>
- <Filename Value="media/UAudioInput_Bass.pas"/>
+ <Filename Value="media/UAudioInput_Portaudio.pas"/>
<IsPartOfProject Value="True"/>
</Unit103>
<Unit104>
- <Filename Value="media/UAudioInput_Portaudio.pas"/>
+ <Filename Value="media/UAudioPlaybackBase.pas"/>
<IsPartOfProject Value="True"/>
</Unit104>
<Unit105>
- <Filename Value="media/UAudioPlaybackBase.pas"/>
+ <Filename Value="media/UAudioPlayback_Bass.pas"/>
<IsPartOfProject Value="True"/>
</Unit105>
<Unit106>
- <Filename Value="media/UAudioPlayback_Bass.pas"/>
+ <Filename Value="media/UAudioPlayback_Portaudio.pas"/>
<IsPartOfProject Value="True"/>
</Unit106>
<Unit107>
- <Filename Value="media/UAudioPlayback_Portaudio.pas"/>
+ <Filename Value="media/UAudioPlayback_SDL.pas"/>
<IsPartOfProject Value="True"/>
</Unit107>
<Unit108>
- <Filename Value="media/UAudioPlayback_SDL.pas"/>
+ <Filename Value="media/UAudioPlayback_SoftMixer.pas"/>
<IsPartOfProject Value="True"/>
</Unit108>
<Unit109>
- <Filename Value="media/UAudioPlayback_SoftMixer.pas"/>
+ <Filename Value="media/UMediaCore_FFmpeg.pas"/>
<IsPartOfProject Value="True"/>
</Unit109>
<Unit110>
- <Filename Value="media/UMediaCore_FFmpeg.pas"/>
+ <Filename Value="media/UMediaCore_SDL.pas"/>
<IsPartOfProject Value="True"/>
</Unit110>
<Unit111>
- <Filename Value="media/UMediaCore_SDL.pas"/>
+ <Filename Value="media/UMedia_dummy.pas"/>
<IsPartOfProject Value="True"/>
</Unit111>
<Unit112>
- <Filename Value="media/UMedia_dummy.pas"/>
+ <Filename Value="media/UVideo.pas"/>
<IsPartOfProject Value="True"/>
+ <UnitName Value="UVideo"/>
</Unit112>
<Unit113>
- <Filename Value="media/UVideo.pas"/>
+ <Filename Value="media/UVisualizer.pas"/>
<IsPartOfProject Value="True"/>
+ <UnitName Value="UVisualizer"/>
</Unit113>
<Unit114>
- <Filename Value="media/UVisualizer.pas"/>
+ <Filename Value="config-linux.inc"/>
<IsPartOfProject Value="True"/>
</Unit114>
<Unit115>
- <Filename Value="config-linux.inc"/>
+ <Filename Value="paths.inc"/>
<IsPartOfProject Value="True"/>
</Unit115>
<Unit116>
- <Filename Value="paths.inc"/>
+ <Filename Value="switches.inc"/>
<IsPartOfProject Value="True"/>
</Unit116>
<Unit117>
- <Filename Value="switches.inc"/>
+ <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>
@@ -514,8 +564,8 @@
</Target>
<SearchPaths>
<IncludeFiles Value="lib/JEDI-SDL/SDL/Pas/"/>
+ <OtherUnitFiles Value="base/;menu/;screens/;media/;lib/;lua/"/>
<UnitOutputDirectory Value="../build/fpc-$(TargetCPU)-$(TargetOS)"/>
- <SrcPath Value="base/;menu/;screens/;media/;lib/"/>
</SearchPaths>
<Parsing>
<SyntaxOptions>
diff --git a/cmake/dists/lazarus/ultrastardx-win.lpi b/cmake/dists/lazarus/ultrastardx-win.lpi
index a049cd10..acce323b 100644
--- a/cmake/dists/lazarus/ultrastardx-win.lpi
+++ b/cmake/dists/lazarus/ultrastardx-win.lpi
@@ -2,16 +2,16 @@
<CONFIG>
<ProjectOptions>
<PathDelim Value="\"/>
- <Version Value="6"/>
+ <Version Value="7"/>
<General>
<Flags>
<MainUnitHasCreateFormStatements Value="False"/>
<MainUnitHasTitleStatement Value="False"/>
<AlwaysBuild Value="False"/>
+ <LRSInOutputDirectory Value="False"/>
</Flags>
<SessionStorage Value="InProjectDir"/>
<MainUnit Value="0"/>
- <IconPath Value="./"/>
<TargetFileExt Value=".exe"/>
<Title Value="ultrastardx"/>
</General>
@@ -30,7 +30,7 @@
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
</local>
</RunParams>
- <Units Count="117">
+ <Units Count="127">
<Unit0>
<Filename Value="ultrastardx.dpr"/>
<IsPartOfProject Value="True"/>
@@ -500,6 +500,56 @@
<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>
@@ -510,8 +560,8 @@
</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)"/>
- <SrcPath Value="base\;menu\;screens\;media\;lib\JEDI-SDL\SDL\Pas\;lib\JEDI-SDL\SDL_Image\Pas\;lib\JEDI-SDL\OpenGL\Pas\;lib\portaudio\;lib\ffmpeg\;lib\SQLite\;lib\other\"/>
</SearchPaths>
<Parsing>
<SyntaxOptions>
diff --git a/cmake/game/.gitignore b/cmake/game/.gitignore
new file mode 100644
index 00000000..487210c1
--- /dev/null
+++ b/cmake/game/.gitignore
@@ -0,0 +1,8 @@
+playlists
+screenshots
+songs
+config.ini
+cover.db
+ultrastardx
+Ultrastar.db
+Error.log
diff --git a/cmake/game/LuaCommands.odt b/cmake/game/LuaCommands.odt
new file mode 100644
index 00000000..223df235
--- /dev/null
+++ b/cmake/game/LuaCommands.odt
Binary files differ
diff --git a/cmake/game/fonts/DejaVu/AUTHORS b/cmake/game/fonts/DejaVu/AUTHORS
new file mode 100644
index 00000000..66b7e445
--- /dev/null
+++ b/cmake/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/cmake/game/fonts/DejaVu/DejaVuSans-Bold.ttf b/cmake/game/fonts/DejaVu/DejaVuSans-Bold.ttf
new file mode 100644
index 00000000..29da1369
--- /dev/null
+++ b/cmake/game/fonts/DejaVu/DejaVuSans-Bold.ttf
Binary files differ
diff --git a/cmake/game/fonts/DejaVu/DejaVuSans.ttf b/cmake/game/fonts/DejaVu/DejaVuSans.ttf
new file mode 100644
index 00000000..e0699fec
--- /dev/null
+++ b/cmake/game/fonts/DejaVu/DejaVuSans.ttf
Binary files differ
diff --git a/cmake/game/fonts/DejaVu/LICENSE b/cmake/game/fonts/DejaVu/LICENSE
new file mode 100644
index 00000000..254e2cc4
--- /dev/null
+++ b/cmake/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/cmake/game/fonts/DejaVu/README b/cmake/game/fonts/DejaVu/README
new file mode 100644
index 00000000..6882268b
--- /dev/null
+++ b/cmake/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/cmake/game/fonts/FreeSans/AUTHORS b/cmake/game/fonts/FreeSans/AUTHORS
new file mode 100644
index 00000000..fbb0e990
--- /dev/null
+++ b/cmake/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/cmake/game/fonts/FreeSans/COPYING b/cmake/game/fonts/FreeSans/COPYING
new file mode 100644
index 00000000..7f1c9b60
--- /dev/null
+++ b/cmake/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/cmake/game/fonts/FreeSans/CREDITS b/cmake/game/fonts/FreeSans/CREDITS
new file mode 100644
index 00000000..0cc30949
--- /dev/null
+++ b/cmake/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/cmake/game/fonts/FreeSans.ttf b/cmake/game/fonts/FreeSans/FreeSans.ttf
index a4c41697..a4c41697 100644
--- a/cmake/game/fonts/FreeSans.ttf
+++ b/cmake/game/fonts/FreeSans/FreeSans.ttf
Binary files differ
diff --git a/cmake/game/fonts/FreeSansBold.ttf b/cmake/game/fonts/FreeSans/FreeSansBold.ttf
index 15511674..15511674 100644
--- a/cmake/game/fonts/FreeSansBold.ttf
+++ b/cmake/game/fonts/FreeSans/FreeSansBold.ttf
Binary files differ
diff --git a/cmake/game/fonts/FreeSans/README b/cmake/game/fonts/FreeSans/README
new file mode 100644
index 00000000..96e4a4db
--- /dev/null
+++ b/cmake/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/cmake/game/fonts/Vera.ttf b/cmake/game/fonts/Vera.ttf
deleted file mode 100644
index 58cd6b5e..00000000
--- a/cmake/game/fonts/Vera.ttf
+++ /dev/null
Binary files differ
diff --git a/cmake/game/fonts/VeraBd.ttf b/cmake/game/fonts/VeraBd.ttf
deleted file mode 100644
index 51d6111d..00000000
--- a/cmake/game/fonts/VeraBd.ttf
+++ /dev/null
Binary files differ
diff --git a/cmake/game/fonts/bold/eurostar_regular_bold.dat b/cmake/game/fonts/bold/eurostar_regular_bold.dat
deleted file mode 100644
index 1b2023e2..00000000
--- a/cmake/game/fonts/bold/eurostar_regular_bold.dat
+++ /dev/null
Binary files differ
diff --git a/cmake/game/fonts/bold/eurostar_regular_bold.png b/cmake/game/fonts/bold/eurostar_regular_bold.png
deleted file mode 100644
index f2732e44..00000000
--- a/cmake/game/fonts/bold/eurostar_regular_bold.png
+++ /dev/null
Binary files differ
diff --git a/cmake/game/fonts/fonts.ini b/cmake/game/fonts/fonts.ini
index 6abd7366..f152852d 100755
--- a/cmake/game/fonts/fonts.ini
+++ b/cmake/game/fonts/fonts.ini
@@ -1,11 +1,56 @@
-[Normal]
-File=normal/eurostar_regular.png
-
-[Bold]
-File=bold/eurostar_regular_bold.png
-
-[Outline1]
-File=outline1/outline1.png
-
-[Outline2]
-File=outline2/outline2.png
+;+++++++++++++++++++++++++++++++++++++++++++++++++
+; 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/cmake/game/fonts/fontsTTF.ini b/cmake/game/fonts/fontsTTF.ini
deleted file mode 100644
index 839258b2..00000000
--- a/cmake/game/fonts/fontsTTF.ini
+++ /dev/null
@@ -1,11 +0,0 @@
-[Normal]
-File=FreeSans.ttf
-
-[Bold]
-File=FreeSansBold.ttf
-
-[Outline1]
-File=FreeSansBold.ttf
-
-[Outline2]
-File=Vera.ttf
diff --git a/cmake/game/fonts/normal/eurostar_regular.dat b/cmake/game/fonts/normal/eurostar_regular.dat
deleted file mode 100644
index f44ae7d8..00000000
--- a/cmake/game/fonts/normal/eurostar_regular.dat
+++ /dev/null
Binary files differ
diff --git a/cmake/game/fonts/normal/eurostar_regular.png b/cmake/game/fonts/normal/eurostar_regular.png
deleted file mode 100644
index 21ef5ac4..00000000
--- a/cmake/game/fonts/normal/eurostar_regular.png
+++ /dev/null
Binary files differ
diff --git a/cmake/game/fonts/outline1/outline1.dat b/cmake/game/fonts/outline1/outline1.dat
deleted file mode 100644
index ea9f2484..00000000
--- a/cmake/game/fonts/outline1/outline1.dat
+++ /dev/null
Binary files differ
diff --git a/cmake/game/fonts/outline1/outline1.png b/cmake/game/fonts/outline1/outline1.png
deleted file mode 100644
index a1af3cd2..00000000
--- a/cmake/game/fonts/outline1/outline1.png
+++ /dev/null
Binary files differ
diff --git a/cmake/game/fonts/outline2/outline2.dat b/cmake/game/fonts/outline2/outline2.dat
deleted file mode 100644
index 062f1629..00000000
--- a/cmake/game/fonts/outline2/outline2.dat
+++ /dev/null
Binary files differ
diff --git a/cmake/game/fonts/outline2/outline2.png b/cmake/game/fonts/outline2/outline2.png
deleted file mode 100644
index 9677d379..00000000
--- a/cmake/game/fonts/outline2/outline2.png
+++ /dev/null
Binary files differ
diff --git a/cmake/game/fonts/wqy-microhei/AUTHORS.txt b/cmake/game/fonts/wqy-microhei/AUTHORS.txt
new file mode 100644
index 00000000..d19d4cad
--- /dev/null
+++ b/cmake/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/cmake/game/fonts/wqy-microhei/LICENSE_Apache2.txt b/cmake/game/fonts/wqy-microhei/LICENSE_Apache2.txt
new file mode 100644
index 00000000..79fd69c9
--- /dev/null
+++ b/cmake/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/cmake/game/fonts/wqy-microhei/LICENSE_GPLv3.txt b/cmake/game/fonts/wqy-microhei/LICENSE_GPLv3.txt
new file mode 100644
index 00000000..94a9ed02
--- /dev/null
+++ b/cmake/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/cmake/game/fonts/wqy-microhei/README.txt b/cmake/game/fonts/wqy-microhei/README.txt
new file mode 100644
index 00000000..16b8ac24
--- /dev/null
+++ b/cmake/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/cmake/game/fonts/wqy-microhei/wqy-microhei.ttc b/cmake/game/fonts/wqy-microhei/wqy-microhei.ttc
new file mode 100644
index 00000000..2c9bc2d4
--- /dev/null
+++ b/cmake/game/fonts/wqy-microhei/wqy-microhei.ttc
Binary files differ
diff --git a/cmake/game/languages/Catalan.ini b/cmake/game/languages/Catalan.ini
index 5e3c0a5c..de9f9852 100644
--- a/cmake/game/languages/Catalan.ini
+++ b/cmake/game/languages/Catalan.ini
@@ -1,377 +1,396 @@
-[Text]
-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_BALCK=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=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_COUNT_HOW_OFTEN_SUNG=Quantes vegades cantada
-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çó
-
-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_ROUNDS=Rondes
-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
-PARTY_PLAYER_LEGEND_CONTINUE=iniciar festa
-
-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!
-
-PLUGIN_HDL_NAME=Aguantar la línia
-PLUGIN_HDL_DESC=No baixis de la fletxa a la barra de qualitat
-
-PLUGIN_UNTIL5000_NAME=Fins a 5000
-PLUGIN_UNTIL5000_DESC=El primer a arribar a 5000 punts guanya
-
-PLUGIN_DUELL_NAME=Duel
-PLUGIN_DUELL_DESC=Cantar un duela fins a 10000 punts
-
-PLUGIN_BLIND_NAME=Mode cec
-PLUGIN_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_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] \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
-
-MSG_ERROR_TITLE=Error
-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
-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
+[Text]
+OPTION_VALUE_CATALAN=Catalan
+OPTION_VALUE_CROATIAN=Croatian
+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_ITALIAN=Italian
+OPTION_VALUE_JAPANESE=Japanese
+OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+OPTION_VALUE_PORTUGUESE=Portuguese
+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=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_COUNT_HOW_OFTEN_SUNG=Quantes vegades cantada
+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_ROUNDS=Rondes
+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
+PARTY_PLAYER_LEGEND_CONTINUE=iniciar festa
+
+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!
+
+PLUGIN_HDL_NAME=Aguantar la línia
+PLUGIN_HDL_DESC=No baixis de la fletxa a la barra de qualitat
+
+PLUGIN_UNTIL5000_NAME=Fins a 5000
+PLUGIN_UNTIL5000_DESC=El primer a arribar a 5000 punts guanya
+
+PLUGIN_DUELL_NAME=Duel
+PLUGIN_DUELL_DESC=Cantar un duela fins a 10000 punts
+
+PLUGIN_BLIND_NAME=Mode cec
+PLUGIN_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
+
+MSG_ERROR_TITLE=Error
+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
+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 \ No newline at end of file
diff --git a/cmake/game/languages/Croatian.ini b/cmake/game/languages/Croatian.ini
index 38fbffb9..9da8796e 100644
--- a/cmake/game/languages/Croatian.ini
+++ b/cmake/game/languages/Croatian.ini
@@ -1,388 +1,406 @@
-[Text]
-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_BALCK=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=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_OSCILLOSCOPE=Osciloskop
-SING_OPTIONS_GRAPHICS_LINEBONUS=Bonus linije
-SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Velièina videa
-SING_OPTIONS_GRAPHICS_VISUALIZER=Vizualizacije
-
-SING_OPTIONS_SOUND_WHEREAMI=Opcije Zvuka
-SING_OPTIONS_SOUND_DESC=postavke zvuka
-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_SOUND_VOICEPASSTHROUGH=Microphone Playback
-SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Pozadinska glazba
-
-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_COUNT_HOW_OFTEN_SUNG=Zapamti broj pjev.
-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_RISING_STAR=Zvijezda u usponu
-SING_SCORE_LEAD_SINGER=Vodeæi pjevaè
-SING_SCORE_HIT_ARTIST=Hit Artist
-SING_SCORE_SUPERSTAR=Superstar
-SING_SCORE_ULTRASTAR=Ultrastar
-SING_SCORE_WANNABE=Wannabe
-SING_SCORE_HOPEFUL=Pun nade
-
-SING_TOP_5_CHARTS=top 5 Igraèa
-SING_TOP_5_CHARTS_WHEREAMI=top 5
-SING_TOP_5_CHARTS_CONTINUE=odabir pjesme
-
-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
-
-SONG_MENU_NAME_PLAYLIST_DEL=Stvarno obrisati?
-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=Obriši Playlistu?
-
-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_ROUNDS=Runde
-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
-PARTY_PLAYER_LEGEND_CONTINUE=zapoèni party-igru
-
-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!
-
-PLUGIN_HDL_NAME=Zadrži liniju
-PLUGIN_HDL_DESC=Nemoj biti gori od pokazivaèa na 'rating' baru.
-
-PLUGIN_UNTIL5000_NAME=Do 5000
-PLUGIN_UNTIL5000_DESC=Pobjeðuje onaj tko prvi doðe do 5000 bodova.
-
-PLUGIN_DUELL_NAME=Dvoboj
-PLUGIN_DUELL_DESC=Pjevaj dvoboj do 10000 bodova.
-
-PLUGIN_TEAMDUELL_NAME=Dvoboj timova
-PLUGIN_TEAMDUELL_DESC=Dodaj mikrofon!
-
-PLUGIN_BLIND_NAME=Slijepi naèin
-PLUGIN_BLIND_DESC=Dvoboj bez gledanja nota.
-
-PLUGIN_BLIND_NOSCORE_NAME=Slijepi naèin 2
-PLUGIN_BLIND_NOSCORE_DESC=Dvoboj bez gledanja nota i bodova.
-
-PLUGIN_MORE1000_NAME=1000 Više
-PLUGIN_MORE1000_DESC=Pjevajte dok jedan od igraèa ne skupi 1000 bod više.
-
-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_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] \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
-
-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
-
-MSG_ERROR_TITLE=Greška
-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
-ERROR_CORRUPT_SONG=Pjesma se ne može uèitati. \ No newline at end of file
+[Text]
+OPTION_VALUE_CATALAN=Catalan
+OPTION_VALUE_CROATIAN=Croatian
+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_ITALIAN=Italian
+OPTION_VALUE_JAPANESE=Japanese
+OPTION_VALUE_PORTUGUESE=Portuguese
+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=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_OSCILLOSCOPE=Osciloskop
+SING_OPTIONS_GRAPHICS_LINEBONUS=Bonus linije
+SING_OPTIONS_GRAPHICS_MOVIE_SIZE=VeliÄina videa
+SING_OPTIONS_GRAPHICS_VISUALIZER=Vizualizacije
+
+SING_OPTIONS_SOUND_WHEREAMI=Opcije Zvuka
+SING_OPTIONS_SOUND_DESC=postavke zvuka
+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_SOUND_VOICEPASSTHROUGH=Microphone Playback
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Pozadinska glazba
+
+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_COUNT_HOW_OFTEN_SUNG=Zapamti broj pjev.
+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_RISING_STAR=Zvijezda u usponu
+SING_SCORE_LEAD_SINGER=Vodeći pjevaÄ
+SING_SCORE_HIT_ARTIST=Hit Artist
+SING_SCORE_SUPERSTAR=Superstar
+SING_SCORE_ULTRASTAR=Ultrastar
+SING_SCORE_WANNABE=Wannabe
+SING_SCORE_HOPEFUL=Pun nade
+
+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
+
+SONG_MENU_NAME_PLAYLIST_DEL=Stvarno obrisati?
+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=Obriši Playlistu?
+
+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_ROUNDS=Runde
+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
+PARTY_PLAYER_LEGEND_CONTINUE=zapoÄni party-igru
+
+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!
+
+PLUGIN_HDL_NAME=Zadrži liniju
+PLUGIN_HDL_DESC=Nemoj biti gori od pokazivaÄa na 'rating' baru.
+
+PLUGIN_UNTIL5000_NAME=Do 5000
+PLUGIN_UNTIL5000_DESC=Pobjeđuje onaj tko prvi dođe do 5000 bodova.
+
+PLUGIN_DUELL_NAME=Dvoboj
+PLUGIN_DUELL_DESC=Pjevaj dvoboj do 10000 bodova.
+
+PLUGIN_TEAMDUELL_NAME=Dvoboj timova
+PLUGIN_TEAMDUELL_DESC=Dodaj mikrofon!
+
+PLUGIN_BLIND_NAME=Slijepi naÄin
+PLUGIN_BLIND_DESC=Dvoboj bez gledanja nota.
+
+PLUGIN_BLIND_NOSCORE_NAME=Slijepi naÄin 2
+PLUGIN_BLIND_NOSCORE_DESC=Dvoboj bez gledanja nota i bodova.
+
+PLUGIN_MORE1000_NAME=1000 Više
+PLUGIN_MORE1000_DESC=Pjevajte dok jedan od igraÄa ne skupi 1000 bod viÅ¡e.
+
+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
+
+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
+
+MSG_ERROR_TITLE=Greška
+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
+ERROR_CORRUPT_SONG=Pjesma se ne može uÄitati. \ No newline at end of file
diff --git a/cmake/game/languages/Dutch.ini b/cmake/game/languages/Dutch.ini
index 33dc36e2..703c0751 100644
--- a/cmake/game/languages/Dutch.ini
+++ b/cmake/game/languages/Dutch.ini
@@ -1,382 +1,401 @@
-[Text]
-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_BALCK=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=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_COUNT_HOW_OFTEN_SUNG=Telling
-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
-
-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_ROUNDS=Rondes
-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
-PARTY_PLAYER_LEGEND_CONTINUE=start partyspelletje
-
-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!
-
-PLUGIN_HDL_NAME=Hold the Line
-PLUGIN_HDL_DESC=Zing niet slechter dan het pijltje aangeeft!
-
-PLUGIN_UNTIL5000_NAME=Tot 5000
-PLUGIN_UNTIL5000_DESC=De eerste aan 5000 wint.
-
-PLUGIN_DUELL_NAME=Duel
-PLUGIN_DUELL_DESC=Zing een duel to 10000 punten.
-
-PLUGIN_TEAMDUELL_NAME=Team Duel
-PLUGIN_TEAMDUELL_DESC=Geef de microfoon door!
-
-PLUGIN_BLIND_NAME=Blinde Mode
-PLUGIN_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_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] \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
-
-MSG_ERROR_TITLE=Error
-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
-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
+[Text]
+OPTION_VALUE_CATALAN=Catalan
+OPTION_VALUE_CROATIAN=Croatian
+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_ITALIAN=Italian
+OPTION_VALUE_JAPANESE=Japanese
+OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+OPTION_VALUE_PORTUGUESE=Portuguese
+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=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_COUNT_HOW_OFTEN_SUNG=Telling
+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_ROUNDS=Rondes
+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
+PARTY_PLAYER_LEGEND_CONTINUE=start partyspelletje
+
+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!
+
+PLUGIN_HDL_NAME=Hold the Line
+PLUGIN_HDL_DESC=Zing niet slechter dan het pijltje aangeeft!
+
+PLUGIN_UNTIL5000_NAME=Tot 5000
+PLUGIN_UNTIL5000_DESC=De eerste aan 5000 wint.
+
+PLUGIN_DUELL_NAME=Duel
+PLUGIN_DUELL_DESC=Zing een duel to 10000 punten.
+
+PLUGIN_TEAMDUELL_NAME=Team Duel
+PLUGIN_TEAMDUELL_DESC=Geef de microfoon door!
+
+PLUGIN_BLIND_NAME=Blinde Mode
+PLUGIN_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
+
+MSG_ERROR_TITLE=Error
+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
+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 \ No newline at end of file
diff --git a/cmake/game/languages/English.ini b/cmake/game/languages/English.ini
index 27fd2cf2..5ac41efc 100644
--- a/cmake/game/languages/English.ini
+++ b/cmake/game/languages/English.ini
@@ -1,4 +1,21 @@
-[Text]
+[Text]
+OPTION_VALUE_CATALAN=Catalan
+OPTION_VALUE_CROATIAN=Croatian
+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_ICELANDIC=Icelandic
+OPTION_VALUE_ITALIAN=Italian
+OPTION_VALUE_JAPANESE=Japanese
+OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+OPTION_VALUE_PORTUGUESE=Portuguese
+OPTION_VALUE_SPANISH=Spanish
+OPTION_VALUE_SWEDISH=Swedish
+
OPTION_VALUE_EASY=Easy
OPTION_VALUE_MEDIUM=Medium
OPTION_VALUE_HARD=Hard
@@ -50,7 +67,7 @@ OPTION_VALUE_VIOLET=Violet
OPTION_VALUE_ORANGE=Orange
OPTION_VALUE_YELLOW=Yellow
OPTION_VALUE_BROWN=Brown
-OPTION_VALUE_BALCK=Black
+OPTION_VALUE_BLACK=Black
OPTION_VALUE_SING=Sing
OPTION_VALUE_SELECT_PLAYERS=Select Players
@@ -217,6 +234,7 @@ 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!
@@ -227,8 +245,8 @@ POPUP_BAD=bad!
POPUP_POOR=poor!
POPUP_AWFUL=awful!
-IMPLODE_GLUE1=,
-IMPLODE_GLUE2= and
+IMPLODE_GLUE1=,
+IMPLODE_GLUE2= and
SONG_MENU_NAME_MAIN=song menu
SONG_MENU_PLAY=Sing
@@ -243,7 +261,7 @@ 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 exsiting playlist
+SONG_MENU_PLAYLIST_ADD_EXISTING=to existing playlist
SONG_MENU_PLAYLIST_NOEXISTING=No playlist available
SONG_MENU_NAME_PLAYLIST_NEW=New Playlist
@@ -281,11 +299,10 @@ PARTY_PLAYLIST=Playlist Mode
PARTY_PLAYLIST_ALL=All songs
PARTY_PLAYLIST_CATEGORY=Folder
PARTY_PLAYLIST_PLAYLIST=Playlist
-PARTY_ROUNDS=Rounds
-PARTY_TEAMS=Teams
-PARTY_TEAMS_PLAYER1=Player Team1
-PARTY_TEAMS_PLAYER2=Player Team2
-PARTY_TEAMS_PLAYER3=Player Team3
+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
@@ -295,14 +312,26 @@ PARTY_OPTIONS_WHEREAMI=Party Options
PARTY_PLAYER_DESC=enter player- and teamnames!
PARTY_PLAYER_WHEREAMI=Party Names
PARTY_PLAYER_ENTER_NAME=enter names
-PARTY_PLAYER_LEGEND_CONTINUE=start party-game
+
+
+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_WHEREAMI=Party Song-Selection
+PARTY_SONG_LEGEND_CONTINUE=sing
PARTY_SONG_MENU=party menu
PARTY_SCORE_DESC=score of the last round
@@ -319,23 +348,26 @@ PARTY_NOBODY=nobody
NEXT_ROUND=Next round:
PARTY_DISMISSED=Dismissed!
-PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS=%s
PARTY_SCORE_WINS2=wins!
-PLUGIN_HDL_NAME=Hold the Line
-PLUGIN_HDL_DESC=Don't get worse than the pointer at the rating bar shows you.
+MODE_RANDOM_NAME=Random Mode
+MODE_RANDOM_DESC=One mode will be choosen randomly
-PLUGIN_UNTIL5000_NAME=Until 5000
-PLUGIN_UNTIL5000_DESC=Who gets 5000 points first wins the match.
+MODE_HDL_NAME=Hold the Line
+MODE_HDL_DESC=Don't get worse than the pointer at the rating bar shows you.
-PLUGIN_DUELL_NAME=Duel
-PLUGIN_DUELL_DESC=Sing a duel until 10000 points.
+MODE_5000POINTS_NAME=Until 5000
+MODE_5000POINTS_DESC=Who gets 5000 points first wins the match.
-PLUGIN_TEAMDUELL_NAME=Team Duell
-PLUGIN_TEAMDUELL_DESC=Pass The Mic!
+MODE_DUEL_NAME=Duel
+MODE_DUEL_DESC=Sing a duel until 10000 points.
-PLUGIN_BLIND_NAME=Blind Mode
-PLUGIN_BLIND_DESC=Duel without seeing the notes.
+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
@@ -345,17 +377,19 @@ 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=Seite %0:d of %1:d Pages\n (%2:d of %3:d Entrys)
+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] \n (%3:s - %4:s)
+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
@@ -369,14 +403,30 @@ 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 end Party Mode?
+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 \ No newline at end of file
+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 was assigned to multiple microphones. Please check your record options
diff --git a/cmake/game/languages/Euskara.ini b/cmake/game/languages/Euskara.ini
index a38254a7..8665d91f 100644
--- a/cmake/game/languages/Euskara.ini
+++ b/cmake/game/languages/Euskara.ini
@@ -1,63 +1,79 @@
-[Text]
-OPTION_VALUE_EASY=Easy
-OPTION_VALUE_MEDIUM=Medium
-OPTION_VALUE_HARD=Hard
+[Text]
+OPTION_VALUE_CATALAN=Katalana
+OPTION_VALUE_CROATIAN=Kroaziera
+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_ITALIAN=Italianoa
+OPTION_VALUE_JAPANESE=Japoniera
+OPTION_VALUE_LUXEMBOURGISH=Luxenburgera
+OPTION_VALUE_PORTUGUESE=Portuguesa
+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=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_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=When No Video
+OPTION_VALUE_WHENNOVIDEO=Bideorik ez badago
-OPTION_VALUE_SMALL=Small
-OPTION_VALUE_BIG=Big
+OPTION_VALUE_SMALL=Txikia
+OPTION_VALUE_BIG=Handia
-OPTION_VALUE_HALF=Half
-OPTION_VALUE_FULL_VID=Full (Video)
-OPTION_VALUE_FULL_VID_BG=Full (BG & Video)
+OPTION_VALUE_HALF=Erdia
+OPTION_VALUE_FULL_VID=Osoa (Bideoa)
+OPTION_VALUE_FULL_VID_BG=Osoa (BG eta bideoa)
-OPTION_VALUE_AUTO=Auto
-OPTION_VALUE_SEC=Second
-OPTION_VALUE_SECS=Seconds
+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=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_BALCK=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
+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...
@@ -217,6 +233,7 @@ 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!
@@ -227,8 +244,8 @@ POPUP_BAD=Gaizki!
POPUP_POOR=Eskas!
POPUP_AWFUL=Penagarri!
-IMPLODE_GLUE1=,
-IMPLODE_GLUE2= eta
+IMPLODE_GLUE1=,
+IMPLODE_GLUE2= eta
SONG_MENU_NAME_MAIN=Menua
SONG_MENU_PLAY=Abestu
@@ -302,7 +319,7 @@ PARTY_ROUND_WHEREAMI=Hurrengo erronda
PARTY_ROUND_LEGEND_CONTINUE=Erronda hasi
PARTY_SONG_WHEREAMI=Talde Abestia aukeratu
-PARTY_SONG_LEGEND_CONTINUE=Abestu
+PARTY_SONG_LEGEND_CONTINUE=Abestu
PARTY_SONG_MENU=Talde menua
PARTY_SCORE_DESC=Azken Errondako puntuazioa
@@ -316,10 +333,10 @@ PARTY_ROUND=Erronda
PARTY_ROUND_WINNER=Irabazlea
PARTY_NOTPLAYEDYET=Jokatu gabe
PARTY_NOBODY=Inor
-NEXT_ROUND=Hurrengo erronda:
+NEXT_ROUND=Hurrengo erronda:
PARTY_DISMISSED=Galdu duzu!
-PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS=%s
PARTY_SCORE_WINS2=irabazi du!
PLUGIN_HDL_NAME=Eutsi goiari
@@ -345,6 +362,8 @@ STAT_OVERVIEW_INTRO=%0:s estatistikak. \n Azken aldiz ezabatutak %3:dko %2:.2da
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
@@ -355,14 +374,14 @@ 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] \n (%3:s - %4:s)
+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_DESC_SONGS_REVERSED=Abesti ez ospetsuak
STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx aldiz abestuta
STAT_DESC_BANDS=Talde ospetsuak
diff --git a/cmake/game/languages/Finnish.ini b/cmake/game/languages/Finnish.ini
index dd4bd2e5..76f0a6ca 100644
--- a/cmake/game/languages/Finnish.ini
+++ b/cmake/game/languages/Finnish.ini
@@ -1,4 +1,20 @@
-[Text]
+[Text]
+OPTION_VALUE_CATALAN=Catalan
+OPTION_VALUE_CROATIAN=Croatian
+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_ITALIAN=Italian
+OPTION_VALUE_JAPANESE=Japanese
+OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+OPTION_VALUE_PORTUGUESE=Portuguese
+OPTION_VALUE_SPANISH=Spanish
+OPTION_VALUE_SWEDISH=Swedish
+
OPTION_VALUE_EASY=Easy
OPTION_VALUE_MEDIUM=Medium
OPTION_VALUE_HARD=Hard
@@ -50,7 +66,7 @@ OPTION_VALUE_VIOLET=Violet
OPTION_VALUE_ORANGE=Orange
OPTION_VALUE_YELLOW=Yellow
OPTION_VALUE_BROWN=Brown
-OPTION_VALUE_BALCK=Black
+OPTION_VALUE_BLACK=Black
OPTION_VALUE_SING=Sing
OPTION_VALUE_SELECT_PLAYERS=Select Players
@@ -71,7 +87,7 @@ SING_MULTI_DESC=Oletko valmis joukkuetaistoon?
SING_TOOLS=asetukset
SING_STATS=tilastot
-SING_STATS_DESC=näytä tilastot
+SING_STATS_DESC=näytä tilastot
SING_EDITOR=kappale-editori
SING_EDITOR_DESC=luo omia kappaleita
@@ -88,11 +104,11 @@ SING_OPTIONS_WHEREAMI=Asetukset
SING_OPTIONS_GAME=peli
SING_OPTIONS_GRAPHICS=grafiikka
-SING_OPTIONS_SOUND=ääni
+SING_OPTIONS_SOUND=ääni
SING_OPTIONS_LYRICS=lyriikat
SING_OPTIONS_THEMES=ulkoasut
-SING_OPTIONS_RECORD=äänitys
-SING_OPTIONS_ADVANCED=lisäasetukset
+SING_OPTIONS_RECORD=äänitys
+SING_OPTIONS_ADVANCED=lisäasetukset
SING_OPTIONS_EXIT=takaisin
SING_OPTIONS_GAME_WHEREAMI=Peliasetukset
@@ -108,15 +124,15 @@ SING_OPTIONS_GRAPHICS_WHEREAMI=Grafiikka-asetukset
SING_OPTIONS_GRAPHICS_DESC=grafiikka-asetukset
SING_OPTIONS_GRAPHICS_RESOLUTION=Resoluutio
SING_OPTIONS_GRAPHICS_FULLSCREEN=Koko ruutu
-SING_OPTIONS_GRAPHICS_DEPTH=Värisyvyys
+SING_OPTIONS_GRAPHICS_DEPTH=Värisyvyys
SING_OPTIONS_GRAPHICS_VISUALIZER=Visualisointi
-SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Värähtelijä
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Värähtelijä
SING_OPTIONS_GRAPHICS_LINEBONUS=Viivabonukset
SING_OPTIONS_GRAPHICS_MOVIE_SIZE=Videon koko
-SING_OPTIONS_SOUND_WHEREAMI=Ääniasetukset
-SING_OPTIONS_SOUND_DESC=ääniasetukset
-SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Oma ääni kuuluvissa
+SING_OPTIONS_SOUND_WHEREAMI=Ääniasetukset
+SING_OPTIONS_SOUND_DESC=ääniasetukset
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Oma ääni kuuluvissa
SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Taustamusiikki
SING_OPTIONS_SOUND_MIC_BOOST=Mikin voimakkuus
SING_OPTIONS_SOUND_CLICK_ASSIST=Klikkausapu
@@ -137,23 +153,23 @@ SING_OPTIONS_THEMES_WHEREAMI=Ulkoasu-asetukset
SING_OPTIONS_THEMES_DESC=ulkoasu-asetukset
SING_OPTIONS_THEMES_THEME=Ulkoasu
SING_OPTIONS_THEMES_SKIN=Tausta
-SING_OPTIONS_THEMES_COLOR=Väri
+SING_OPTIONS_THEMES_COLOR=Väri
-SING_OPTIONS_RECORD_WHEREAMI=Äänitys-asetukset
+SING_OPTIONS_RECORD_WHEREAMI=Äänitys-asetukset
SING_OPTIONS_RECORD_DESC=mikrofonin asetukset
-SING_OPTIONS_RECORD_CARD=Äänikortti
-SING_OPTIONS_RECORD_INPUT=Sisääntulo
+SING_OPTIONS_RECORD_CARD=Äänikortti
+SING_OPTIONS_RECORD_INPUT=Sisääntulo
SING_OPTIONS_RECORD_CHANNEL=Kanava
-SING_OPTIONS_ADVANCED_WHEREAMI=Lisäasetukset
-SING_OPTIONS_ADVANCED_DESC=lisäasetukset
+SING_OPTIONS_ADVANCED_WHEREAMI=Lisäasetukset
+SING_OPTIONS_ADVANCED_DESC=lisäasetukset
SING_OPTIONS_ADVANCED_EFFECTSING=Kappaletehosteet
SING_OPTIONS_ADVANCED_SCREENFADE=Ruudun feidaus
SING_OPTIONS_ADVANCED_LOADANIMATION=Latausanimaatio
SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Poiston vahvistus
SING_OPTIONS_ADVANCED_LINEBONUS=Rivibonus
SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG=
-SING_OPTIONS_ADVANCED_ONSONGCLICK=Kappaleen jälkeen
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Kappaleen jälkeen
SING_OPTIONS_ADVANCED_PARTYPOPUP=Autom. bilevalikko
SING_EDIT=kappale-editori
@@ -173,9 +189,9 @@ SING_LEGEND_NAVIGATE=liiku
SING_LEGEND_CONTINUE=jatka
SING_LEGEND_ESC=takaisin
-SING_PLAYER_DESC=syötä pelaajan nimi
+SING_PLAYER_DESC=syötä pelaajan nimi
SING_PLAYER_WHEREAMI=Pelaajien nimet
-SING_PLAYER_ENTER_NAME=syötä nimi
+SING_PLAYER_ENTER_NAME=syötä nimi
SING_DIFFICULTY_DESC=valitse vaikeustaso
SING_DIFFICULTY_WHEREAMI=Vaikeustaso
@@ -194,41 +210,42 @@ SING_SONGS_IN_CAT=kappaletta
PLAYLIST_CATTEXT=Soittolista: %s
SING_TIME=KESTO
-SING_TOTAL=yhteensä
+SING_TOTAL=yhteensä
SING_MODE=laula soolo
SING_NOTES=nuotit
SING_GOLDEN_NOTES=kultanuotit
SING_PHRASE_BONUS=rivibonus
-SING_MENU=Päävalikko
+SING_MENU=Päävalikko
SONG_SCORE=kappaleen pisteet
SONG_SCORE_WHEREAMI=Pisteet
-SING_SCORE_TONE_DEAF=Sävelkorvaton
-SING_SCORE_AMATEUR=Amatööri
+SING_SCORE_TONE_DEAF=Sävelkorvaton
+SING_SCORE_AMATEUR=Amatööri
SING_SCORE_WANNABE=Wannabe
-SING_SCORE_HOPEFUL=Toiveita herättävä
-SING_SCORE_RISING_STAR=Nouseva tähti
-SING_SCORE_LEAD_SINGER=Päälaulaja
-SING_SCORE_SUPERSTAR=Supertähti
-SING_SCORE_ULTRASTAR=Ultratähti
+SING_SCORE_HOPEFUL=Toiveita herättävä
+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=top 5 pelaajat
SING_TOP_5_CHARTS_WHEREAMI=top 5
SING_TOP_5_CHARTS_CONTINUE=kappalevalintaan
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=switch difficulty
-POPUP_PERFECT=täydellistä!
+POPUP_PERFECT=täydellistä!
POPUP_AWESOME=loistavaa!
POPUP_GREAT=mahtavaa!
-POPUP_GOOD=hyvä!
+POPUP_GOOD=hyvä!
POPUP_NOTBAD=menettelee!
POPUP_BAD=huonoa!
POPUP_POOR=heikkoa!
POPUP_AWFUL=kauheaa!
-IMPLODE_GLUE1=,
-IMPLODE_GLUE2= ja
+IMPLODE_GLUE1=,
+IMPLODE_GLUE2= ja
SONG_MENU_NAME_MAIN=kappalevalikko
SONG_MENU_PLAY=Laula
@@ -238,20 +255,20 @@ SONG_MENU_MODI=Laula muunneltu kappale
SONG_MENU_CANCEL=Peruuta
SONG_MENU_NAME_PLAYLIST=Kappalevalikko
-SONG_MENU_PLAYLIST_ADD=Lisää kappale
+SONG_MENU_PLAYLIST_ADD=Lisää kappale
SONG_MENU_PLAYLIST_DEL=Poista kappale
-SONG_MENU_NAME_PLAYLIST_ADD=Lisää kappale
+SONG_MENU_NAME_PLAYLIST_ADD=Lisää kappale
SONG_MENU_PLAYLIST_ADD_NEW=uuteen soittolistaan
SONG_MENU_PLAYLIST_ADD_EXISTING=luotuun soittolistaan
SONG_MENU_PLAYLIST_NOEXISTING=Soittolistaa ei saatavilla
SONG_MENU_NAME_PLAYLIST_NEW=Uusi soittolista
SONG_MENU_PLAYLIST_NEW_CREATE=Luo
-SONG_MENU_PLAYLIST_NEW_UNNAMED=Nimetön
+SONG_MENU_PLAYLIST_NEW_UNNAMED=Nimetön
SONG_MENU_NAME_PLAYLIST_DELITEM=Vahvista poisto?
-SONG_MENU_YES=Kyllä
+SONG_MENU_YES=Kyllä
SONG_MENU_NO=Ei
SONG_MENU_NAME_PLAYLIST_LOAD=Avaa soittolista
@@ -263,16 +280,16 @@ SONG_MENU_NAME_PLAYLIST_DEL=Poista soittolista?
SONG_MENU_NAME_PARTY_MAIN=Bilevalikko
SONG_MENU_JOKER=Jokeri
-SONG_MENU_NAME_PARTY_JOKER=käytä jokeri
+SONG_MENU_NAME_PARTY_JOKER=käytä jokeri
SONG_JUMPTO_DESC=etsi kappale
SONG_JUMPTO_TYPE_DESC=Etsi:
SONG_JUMPTO_TYPE1=Kaikki
SONG_JUMPTO_TYPE2=Nimen mukaan
SONG_JUMPTO_TYPE3=Artistin mukaan
-SONG_JUMPTO_SONGSFOUND=Löytyi %d kappaletta
-SONG_JUMPTO_NOSONGSFOUND=Kappaletta ei löytynyt
-SONG_JUMPTO_HELP=Syötä hakuteksti
+SONG_JUMPTO_SONGSFOUND=Löytyi %d kappaletta
+SONG_JUMPTO_NOSONGSFOUND=Kappaletta ei löytynyt
+SONG_JUMPTO_HELP=Syötä hakuteksti
SONG_JUMPTO_CATTEXT=Etsi: %s
PARTY_MODE=biletila
@@ -292,17 +309,17 @@ PARTY_LEGEND_CONTINUE=jatka
PARTY_OPTIONS_DESC=bilepelin asetukset
PARTY_OPTIONS_WHEREAMI=Bile-asetukset
-PARTY_PLAYER_DESC=Syötä pelaajien ja joukkueiden nimet!
+PARTY_PLAYER_DESC=Syötä pelaajien ja joukkueiden nimet!
PARTY_PLAYER_WHEREAMI=Bilepelaajien nimet
-PARTY_PLAYER_ENTER_NAME=syötä nimet
+PARTY_PLAYER_ENTER_NAME=syötä nimet
PARTY_PLAYER_LEGEND_CONTINUE=aloita bileet
PARTY_ROUND_DESC=seuraavat pelaajat mikkeihin
PARTY_ROUND_WHEREAMI=Seuraava kierros
PARTY_ROUND_LEGEND_CONTINUE=aloita
-PARTY_SONG_WHEREAMI=Bilekappaleen valinta
-PARTY_SONG_LEGEND_CONTINUE=laula
+PARTY_SONG_WHEREAMI=Bilekappaleen valinta
+PARTY_SONG_LEGEND_CONTINUE=laula
PARTY_SONG_MENU=bilevalikko
PARTY_SCORE_DESC=kierroksen pisteet
@@ -310,7 +327,7 @@ PARTY_SCORE_WHEREAMI=Bilepisteet
PARTY_WIN_DESC=bilepelin voittaja
PARTY_WIN_WHEREAMI=Bilepelin voittaja
-PARTY_WIN_LEGEND_CONTINUE=takaisin päävalikkoon
+PARTY_WIN_LEGEND_CONTINUE=takaisin päävalikkoon
PARTY_ROUND=Kierros
PARTY_ROUND_WINNER=Voittaja
@@ -319,31 +336,33 @@ PARTY_NOBODY=ei kukaan
NEXT_ROUND=Seuraava kierros:
PARTY_DISMISSED=Diskattu!
-PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS=%s
PARTY_SCORE_WINS2=voittaa!
-PLUGIN_HDL_NAME=Pidä pintasi!
-PLUGIN_HDL_DESC=Älä putoa palkin alapuolelle.
+PLUGIN_HDL_NAME=Pidä pintasi!
+PLUGIN_HDL_DESC=Älä putoa palkin alapuolelle.
PLUGIN_UNTIL5000_NAME=Viistonnia
-PLUGIN_UNTIL5000_DESC=Ensimmäisenä 5000 pistettä saanut voittaa.
+PLUGIN_UNTIL5000_DESC=Ensimmäisenä 5000 pistettä saanut voittaa.
PLUGIN_DUELL_NAME=Kymppitonni
PLUGIN_DUELL_DESC=Kaksintaistelu 10000 pisteeseen.
PLUGIN_TEAMDUELL_NAME=Mikit kiertoon!
-PLUGIN_TEAMDUELL_DESC=Mikki kiertää joukkueen sisällä... Varaudu siis laulamaan!
+PLUGIN_TEAMDUELL_DESC=Mikki kiertää joukkueen sisällä... Varaudu siis laulamaan!
PLUGIN_BLIND_NAME=Sokkona
-PLUGIN_BLIND_DESC=Et näe nuotteja.
+PLUGIN_BLIND_DESC=Et näe nuotteja.
STAT_MAIN=Tilastot
STAT_MAIN_DESC=Yleiset
STAT_MAIN_WHEREAMI=Tilasto
STAT_OVERVIEW_INTRO=%0:s \n Pelattu viimeksi %1:.2d.%2:.2d.%3:d
-STAT_OVERVIEW_SONG=%0:d kappaletta(%3:d musiikkivideota), joista %1:d pelattu ja %2:d joita ei vielä kokeiltu.\n Suosituin kappale: %4:s :n %5:s
-STAT_OVERVIEW_PLAYER=Viimeksi %0:d eri pelaajaa,\n joista paras oli %1:s keskipisteillä %2:d pistettä.\n %3:s sai korkeimmat pisteet, %4:d pistettä.
+STAT_OVERVIEW_SONG=%0:d kappaletta(%3:d musiikkivideota), joista %1:d pelattu ja %2:d joita ei vielä kokeiltu.\n Suosituin kappale: %4:s :n %5:s
+STAT_OVERVIEW_PLAYER=Viimeksi %0:d eri pelaajaa,\n joista paras oli %1:s keskipisteillä %2:d pistettä.\n %3:s sai korkeimmat pisteet, %4:d pistettä.
+
+STAT_FORMAT_DATE=%1:.2d.%0:.2d.%2:d
STAT_DETAIL=Tilasto
STAT_DETAIL_WHEREAMI=Yksityiskohtainen tilasto
@@ -355,18 +374,18 @@ STAT_PAGE=Sivu %0:d / %1:d\n (%2:d / %3:d)
STAT_DESC_SCORES=Parhaat laulajat
STAT_DESC_SCORES_REVERSED=Huonoimmat laulajat
-STAT_FORMAT_SCORES=%0:s - %1:d [%2:s] \n (%3:s - %4:s)
+STAT_FORMAT_SCORES=%0:s - %1:d [%2:s] %5:s \n (%3:s - %4:s)
STAT_DESC_SINGERS=Parhaat laulajat
STAT_DESC_SINGERS_REVERSED=Huonoimmat laulajat
STAT_FORMAT_SINGERS=%0:s \n Keskipisteet: %1:d
STAT_DESC_SONGS=Suosituimmat biisit
-STAT_DESC_SONGS_REVERSED=Vähiten lauletut biisit
+STAT_DESC_SONGS_REVERSED=Vähiten lauletut biisit
STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx laulettu
-STAT_DESC_BANDS=Suosituimmat bändit
-STAT_DESC_BANDS_REVERSED=Vähiten lauletut bändit
+STAT_DESC_BANDS=Suosituimmat bändit
+STAT_DESC_BANDS_REVERSED=Vähiten lauletut bändit
STAT_FORMAT_BANDS=%0:s \n %1:dx laulettu
MSG_ERROR_TITLE=Virhe
@@ -374,9 +393,9 @@ MSG_QUESTION_TITLE= o_0
MSG_QUIT_USDX=Poistutaanko UltraStarista?
MSG_END_PARTY=Poistutaanko biletilasta?
ERROR_NO_SONGS=Kappaleita ei saatavilla
-ERROR_NO_PLUGINS=Lisäosia ei saatavilla
+ERROR_NO_PLUGINS=Lisäosia ei saatavilla
ERROR_CORRUPT_SONG=Kappaletta ei voi ladata.
-ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Kappaletta ei voi ladata: Tiedostoa ei löytynyt
-ERROR_CORRUPT_SONG_NO_NOTES=Kappaletta ei voi ladata: Nuotteja ei löytynyt
-ERROR_CORRUPT_SONG_NO_BREAKS=Kappaletta ei voi ladata: Rivikatko(j)a ei löytynyt
-ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Kappaletta ei voi ladata: Virhe txt:n rivillä %0:d \ No newline at end of file
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Kappaletta ei voi ladata: Tiedostoa ei löytynyt
+ERROR_CORRUPT_SONG_NO_NOTES=Kappaletta ei voi ladata: Nuotteja ei löytynyt
+ERROR_CORRUPT_SONG_NO_BREAKS=Kappaletta ei voi ladata: Rivikatko(j)a ei löytynyt
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Kappaletta ei voi ladata: Virhe txt:n rivillä %0:d \ No newline at end of file
diff --git a/cmake/game/languages/French.ini b/cmake/game/languages/French.ini
index d79919bf..6c4e6b5b 100644
--- a/cmake/game/languages/French.ini
+++ b/cmake/game/languages/French.ini
@@ -1,382 +1,401 @@
-[Text]
-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_BALCK=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=Chargement...
-
-SING_CHOOSE_MODE=Choisir un mode
-SING_SING=Solo
-SING_SING_DESC=Chanter
-
-SING_MULTI=Multi
-SING_MULTI_DESC=Chanter à plusieurs
-
-SING_TOOLS=Outils
-
-SING_STATS=Statistiques
-SING_STATS_DESC=Consulter les statistiques
-
-SING_EDITOR=Éditeur
-SING_EDITOR_DESC=Créer vos propre chansons
-
-SING_GAME_OPTIONS=Options
-SING_GAME_OPTIONS_DESC=Modifier les paramètres du jeu
-
-SING_EXIT=Quitter
-SING_EXIT_DESC=Quitter le jeu
-
-SING_OPTIONS=Options
-SING_OPTIONS_DESC=Changer 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 de jeu
-SING_OPTIONS_GAME_DESC=Options générales de jeu
-SING_OPTIONS_GAME_PLAYERS=Joueurs
-SING_OPTIONS_GAME_DIFFICULTY=Difficulté
-SING_OPTIONS_GAME_LANGUAGE=Langue
-SING_OPTIONS_GAME_TABS=Dossier
-SING_OPTIONS_GAME_SORTING=Tri
-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=Couleurs
-SING_OPTIONS_GRAPHICS_VISUALIZER=Visualization
-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 de son
-SING_OPTIONS_SOUND_DESC=Paramètres de son
-SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Entendre le micro
-SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Musique de fond
-SING_OPTIONS_SOUND_MIC_BOOST=Amplif. mic.
-SING_OPTIONS_SOUND_CLICK_ASSIST=Clics d'aide
-SING_OPTIONS_SOUND_BEAT_CLICK=Métronome
-SING_OPTIONS_SOUND_THRESHOLD=Suppression bruit
-SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Mode 2 joueurs
-SING_OPTIONS_SOUND_PREVIEWVOLUME=Prévis. volume
-SING_OPTIONS_SOUND_PREVIEWFADING=Prévis. baisse
-
-SING_OPTIONS_LYRICS_WHEREAMI=Options de paroles
-SING_OPTIONS_LYRICS_DESC=Paramètres de 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 sup.
-SING_OPTIONS_ADVANCED_LINEBONUS=Bonus de phrases
-SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG=Compteur de titres chantés
-SING_OPTIONS_ADVANCED_ONSONGCLICK=Choix ap. chanson
-SING_OPTIONS_ADVANCED_PARTYPOPUP=Menu multi auto
-
-SING_EDIT=Éditeur
-SING_EDIT_MENU_DESCRIPTION=Créer vos propre chansons
-
-SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Importer texte à une dossier de midi file
-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=Valider
-SING_LEGEND_ESC=Retour
-
-SING_PLAYER_DESC=Entrer le nom du joueur
-SING_PLAYER_WHEREAMI=Nom du joueur
-SING_PLAYER_ENTER_NAME=Modifier
-
-SING_DIFFICULTY_DESC=Choisir 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=Choisir une chanson
-SING_SONG_SELECTION_WHEREAMI=Sélection du titre
-SING_SONG_SELECTION_GOTO=Atteindre
-SING_SONG_SELECTION=Choix de chanson
-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
-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 chanteur
-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
-
-POPUP_PERFECT=Parfait !
-POPUP_AWESOME=Cool !
-POPUP_GREAT=Grandiose !
-POPUP_GOOD=Bien !
-POPUP_NOTBAD=O.K. !
-POPUP_BAD=Pas terrible !
-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 joueur
-SONG_MENU_EDIT=Éditeur
-SONG_MENU_MODI=Chanter un mode
-SONG_MENU_CANCEL=Annuler
-
-SONG_MENU_NAME_PLAYLIST=Menu
-SONG_MENU_PLAYLIST_ADD=Ajouter une chanson
-SONG_MENU_PLAYLIST_DEL=Supprimer la chanson
-
-SONG_MENU_NAME_PLAYLIST_ADD=Ajouter chanson
-SONG_MENU_PLAYLIST_ADD_NEW=À la nouvelle playlist
-SONG_MENU_PLAYLIST_ADD_EXISTING=Ajouter à la playlist
-SONG_MENU_PLAYLIST_NOEXISTING=Pas de playlist
-
-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_DEL=Supprimer la playlist ?
-
-SONG_MENU_NAME_PLAYLIST_LOAD=Ouvrir une playlist
-SONG_MENU_PLAYLIST_LOAD=Ouvrir
-SONG_MENU_PLAYLIST_DELCURRENT=Supprimer la playlist actuel
-
-SONG_MENU_NAME_PARTY_MAIN=Menu
-SONG_MENU_JOKER=Joker
-
-SONG_MENU_NAME_PARTY_JOKER=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=Entrer le texte à rechercher
-SONG_JUMPTO_CATTEXT=Recherche: %s
-
-PARTY_MODE=Mode multi
-PARTY_DIFFICULTY=Difficulté
-PARTY_PLAYLIST=Playlist
-PARTY_PLAYLIST_ALL=Toutes les chansons
-PARTY_PLAYLIST_CATEGORY=Dossier
-PARTY_PLAYLIST_PLAYLIST=Playlist
-PARTY_ROUNDS=Nbre manches
-PARTY_TEAMS=Nbre équipes
-PARTY_TEAMS_PLAYER1=Joueur(s) équipe 1
-PARTY_TEAMS_PLAYER2=Joueur(s) équipe 2
-PARTY_TEAMS_PLAYER3=Joueur(s) équipe 3
-
-PARTY_LEGEND_CONTINUE=Suivant
-
-PARTY_OPTIONS_DESC=Paramètres du mode multi
-PARTY_OPTIONS_WHEREAMI=Options du mode multi
-
-PARTY_PLAYER_DESC=Entrer le nom des équipes et des joueurs
-PARTY_PLAYER_WHEREAMI=Mode multi: Equipes
-PARTY_PLAYER_ENTER_NAME=Modifier
-PARTY_PLAYER_LEGEND_CONTINUE=Valider
-
-PARTY_ROUND_DESC=Joueurs suivants à vos micros !
-PARTY_ROUND_WHEREAMI=Mode multi: Manche suivante
-PARTY_ROUND_LEGEND_CONTINUE=Commencer
-
-PARTY_SONG_WHEREAMI=Mode multi: Choix de la chanson
-PARTY_SONG_LEGEND_CONTINUE=Chanter
-PARTY_SONG_MENU=Menu
-
-PARTY_SCORE_DESC=Score de la manche
-PARTY_SCORE_WHEREAMI=Mode multi: Score
-
-PARTY_WIN_DESC=Gagnant de la partie
-PARTY_WIN_WHEREAMI=Mode multi: 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 !
-
-PLUGIN_HDL_NAME=Tiens la barre
-PLUGIN_HDL_DESC=Maintiens la jauge dans le secteur indiqué
-
-PLUGIN_UNTIL5000_NAME=A 5000
-PLUGIN_UNTIL5000_DESC=Le 1er qui atteint 5000 points remporte la manche
-
-PLUGIN_DUELL_NAME=Duel
-PLUGIN_DUELL_DESC=Le meilleur score remporte la manche
-
-PLUGIN_TEAMDUELL_NAME=Duel par équipe
-PLUGIN_TEAMDUELL_DESC=Passes le micro!
-
-PLUGIN_BLIND_NAME=A l'aveugle
-PLUGIN_BLIND_DESC=Obtiens le meilleur score sans regarder l'écran.
-
-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=%0:d chansons (%3:d avec vidéo)\n%1:d ont déjà été chantées une fois, %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 Meilleur score, %4:d, atteint par %3:s.
-
-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=Score
-STAT_DESC_SCORES_REVERSED=Pires scores
-STAT_FORMAT_SCORES=%0:s - %1:d [%2:s] \n (%3:s - %4:s)
-
-STAT_DESC_SINGERS=Chanteurs
-STAT_DESC_SINGERS_REVERSED=Pires chanteurs
-STAT_FORMAT_SINGERS=%0:s \n Score moyen: %1:d
-
-STAT_DESC_SONGS=Chansons
-STAT_DESC_SONGS_REVERSED=Chansons impopulaires
-STAT_FORMAT_SONGS=%0:s - %1:s \n Chanté %2:dx
-
-STAT_DESC_BANDS=Artistes
-STAT_DESC_BANDS_REVERSED=Artistes impopulaires
-STAT_FORMAT_BANDS=%0:s \n Chansons chantées: %1:d
-
-MSG_ERROR_TITLE=Erreur
-MSG_QUESTION_TITLE=Confirmation
-MSG_QUIT_USDX=Quitter le jeu ?
-MSG_END_PARTY=Quitter la partie ?
-ERROR_NO_SONGS=Aucune chanson.
-ERROR_NO_PLUGINS=Aucun plugin.
-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 \ No newline at end of file
+[Text]
+OPTION_VALUE_CATALAN=Catalan
+OPTION_VALUE_CROATIAN=Croate
+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_ITALIAN=Italien
+OPTION_VALUE_JAPANESE=Japonais
+OPTION_VALUE_Luxembourgish=Luxembourgeois
+OPTION_VALUE_PORTUGUESE=Portugais
+OPTION_VALUE_SPANISH=Espagnol
+OPTION_VALUE_SWEDISH=Suédois
+
+OPTION_VALUE_EASY=Facile
+OPTION_VALUE_MEDIUM=Moyen
+OPTION_VALUE_HARD=Difficile
+
+OPTION_VALUE_ON=Oui
+OPTION_VALUE_OFF=Non
+
+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=Coupé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=Zoom
+OPTION_VALUE_SLIDE=Phrases
+OPTION_VALUE_BALL=Balle
+OPTION_VALUE_SHIFT=Rebond
+
+OPTION_VALUE_EURO=Euro
+OPTION_VALUE_JAPAN=Japan
+OPTION_VALUE_AMERICAN=American
+
+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=Choisir un mode
+SING_SING=Solo
+SING_SING_DESC=Chanter
+
+SING_MULTI=Multi
+SING_MULTI_DESC=Chanter à plusieurs
+
+SING_TOOLS=Outils
+
+SING_STATS=Statistiques
+SING_STATS_DESC=Consulter les statistiques
+
+SING_EDITOR=Éditeur
+SING_EDITOR_DESC=Créer vos propres chansons
+
+SING_GAME_OPTIONS=Options
+SING_GAME_OPTIONS_DESC=Modifier les paramètres du jeu
+
+SING_EXIT=Quitter
+SING_EXIT_DESC=Quitter le jeu
+
+SING_OPTIONS=Options
+SING_OPTIONS_DESC=Changer 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 de jeu
+SING_OPTIONS_GAME_DESC=Options générales de jeu
+SING_OPTIONS_GAME_PLAYERS=Joueurs
+SING_OPTIONS_GAME_DIFFICULTY=Difficulté
+SING_OPTIONS_GAME_LANGUAGE=Langue
+SING_OPTIONS_GAME_TABS=Dossier
+SING_OPTIONS_GAME_SORTING=Tri
+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=Couleurs
+SING_OPTIONS_GRAPHICS_VISUALIZER=Visualization
+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 de son
+SING_OPTIONS_SOUND_DESC=Paramètres de son
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Entendre le micro
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Musique de fond
+SING_OPTIONS_SOUND_MIC_BOOST=Amplif. micro
+SING_OPTIONS_SOUND_CLICK_ASSIST=Clics d'aide
+SING_OPTIONS_SOUND_BEAT_CLICK=Métronome
+SING_OPTIONS_SOUND_THRESHOLD=Suppression bruit
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Mode 2 joueurs
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Prévis. volume
+SING_OPTIONS_SOUND_PREVIEWFADING=Prévis. baisse
+
+SING_OPTIONS_LYRICS_WHEREAMI=Options de paroles
+SING_OPTIONS_LYRICS_DESC=Paramètres de 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 sup.
+SING_OPTIONS_ADVANCED_LINEBONUS=Bonus de phrases
+SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG=Compteur de titres chantés
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Choix ap. chanson
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Menu multi auto
+
+SING_EDIT=Éditeur
+SING_EDIT_MENU_DESCRIPTION=Créez vos propres chansons !
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Importer 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=Valider
+SING_LEGEND_ESC=Retour
+
+SING_PLAYER_DESC=Entrer le nom du joueur
+SING_PLAYER_WHEREAMI=Nom du joueur
+SING_PLAYER_ENTER_NAME=Modifier
+
+SING_DIFFICULTY_DESC=Choisir 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=Choisir 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
+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 chanteur
+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=switch difficulty
+
+POPUP_PERFECT=Parfait !
+POPUP_AWESOME=Cool !
+POPUP_GREAT=Grandiose !
+POPUP_GOOD=Bien !
+POPUP_NOTBAD=O.K. !
+POPUP_BAD=Pas terrible !
+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 joueur
+SONG_MENU_EDIT=Éditeur
+SONG_MENU_MODI=Chanter un mode
+SONG_MENU_CANCEL=Annuler
+
+SONG_MENU_NAME_PLAYLIST=Menu
+SONG_MENU_PLAYLIST_ADD=Ajouter une chanson
+SONG_MENU_PLAYLIST_DEL=Supprimer la chanson
+
+SONG_MENU_NAME_PLAYLIST_ADD=Ajouter chanson
+SONG_MENU_PLAYLIST_ADD_NEW=É la nouvelle playlist
+SONG_MENU_PLAYLIST_ADD_EXISTING=Ajouter à la playlist
+SONG_MENU_PLAYLIST_NOEXISTING=Pas de playlist
+
+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_DEL=Supprimer la playlist ?
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Ouvrir une playlist
+SONG_MENU_PLAYLIST_LOAD=Ouvrir
+SONG_MENU_PLAYLIST_DELCURRENT=Supprimer la playlist actuelle
+
+SONG_MENU_NAME_PARTY_MAIN=Menu
+SONG_MENU_JOKER=Joker
+
+SONG_MENU_NAME_PARTY_JOKER=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=Entrer le texte à rechercher
+SONG_JUMPTO_CATTEXT=Recherche: %s
+
+PARTY_MODE=Mode multi
+PARTY_DIFFICULTY=Difficulté
+PARTY_PLAYLIST=Playlist
+PARTY_PLAYLIST_ALL=Toutes les chansons
+PARTY_PLAYLIST_CATEGORY=Dossier
+PARTY_PLAYLIST_PLAYLIST=Playlist
+PARTY_ROUNDS=Nbre manches
+PARTY_TEAMS=Nbre équipes
+PARTY_TEAMS_PLAYER1=Joueur(s) équipe 1
+PARTY_TEAMS_PLAYER2=Joueur(s) équipe 2
+PARTY_TEAMS_PLAYER3=Joueur(s) équipe 3
+
+PARTY_LEGEND_CONTINUE=Suivant
+
+PARTY_OPTIONS_DESC=Paramètres du mode multi
+PARTY_OPTIONS_WHEREAMI=Options du mode multi
+
+PARTY_PLAYER_DESC=Entrez le nom des équipes et des joueurs
+PARTY_PLAYER_WHEREAMI=Mode multi: Équipes
+PARTY_PLAYER_ENTER_NAME=Modifier
+PARTY_PLAYER_LEGEND_CONTINUE=Valider
+
+PARTY_ROUND_DESC=Joueurs suivants, à vos micros !
+PARTY_ROUND_WHEREAMI=Mode multi: Manche suivante
+PARTY_ROUND_LEGEND_CONTINUE=Commencer
+
+PARTY_SONG_WHEREAMI=Mode multi: Choix de la chanson
+PARTY_SONG_LEGEND_CONTINUE=Chanter
+PARTY_SONG_MENU=Menu
+
+PARTY_SCORE_DESC=Score de la manche
+PARTY_SCORE_WHEREAMI=Mode multi: Score
+
+PARTY_WIN_DESC=Gagnant de la partie
+PARTY_WIN_WHEREAMI=Mode multi: 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 !
+
+PLUGIN_HDL_NAME=Tiens la barre
+PLUGIN_HDL_DESC=Maintiens la jauge dans le secteur indiqué.
+
+PLUGIN_UNTIL5000_NAME=A 5000
+PLUGIN_UNTIL5000_DESC=Le 1er qui atteint 5000 points remporte la manche.
+
+PLUGIN_DUELL_NAME=Duel
+PLUGIN_DUELL_DESC=Le meilleur score remporte la manche.
+
+PLUGIN_TEAMDUELL_NAME=Duel par équipe
+PLUGIN_TEAMDUELL_DESC=Passe le micro!
+
+PLUGIN_BLIND_NAME=É l'aveugle
+PLUGIN_BLIND_DESC=Obtiens le meilleur score sans regarder l'écran.
+
+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=%0:d chansons (%3:d avec vidéo)\n%1:d ont déjà été chantées une fois, %2:d pas encore. \n\n La chanson la plus chantée est %5:s de %4:s.
+STAT_OVERVIEW_INTRO=Statistiques d'%0:s \n Dernière réinitialisation le %1:.2d.%2:.2d.%3:d
+
+STAT_FORMAT_DATE=%1:.2d.%0:.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=Score
+STAT_DESC_SCORES_REVERSED=Pires scores
+STAT_FORMAT_SCORES=%0:s - %1:d [%2:s] %5:s \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Chanteurs
+STAT_DESC_SINGERS_REVERSED=Pires chanteurs
+STAT_FORMAT_SINGERS=%0:s \n Score moyen: %1:d
+
+STAT_DESC_SONGS=Chansons
+STAT_DESC_SONGS_REVERSED=Chansons impopulaires
+STAT_FORMAT_SONGS=%0:s - %1:s \n Chanté %2:dx
+
+STAT_DESC_BANDS=Artistes
+STAT_DESC_BANDS_REVERSED=Artistes impopulaires
+STAT_FORMAT_BANDS=%0:s \n Chansons chantées: %1:d
+
+MSG_ERROR_TITLE=Erreur
+MSG_QUESTION_TITLE=Confirmation
+MSG_QUIT_USDX=Quitter le jeu ?
+MSG_END_PARTY=Quitter la partie ?
+ERROR_NO_SONGS=Aucune chanson.
+ERROR_NO_PLUGINS=Aucun plugin.
+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
diff --git a/cmake/game/languages/German.ini b/cmake/game/languages/German.ini
index 2dbc32eb..02124805 100644
--- a/cmake/game/languages/German.ini
+++ b/cmake/game/languages/German.ini
@@ -1,4 +1,20 @@
-[Text]
+[Text]
+OPTION_VALUE_CATALAN=Katalanisch
+OPTION_VALUE_CROATIAN=Kroatisch
+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_ITALIAN=Italienisch
+OPTION_VALUE_JAPANESE=Japanisch
+OPTION_VALUE_LUXEMBOURGISH=Luxemburgisch
+OPTION_VALUE_PORTUGUESE=Portugiesisch
+OPTION_VALUE_SPANISH=Spanisch
+OPTION_VALUE_SWEDISH=Schwedisch
+
OPTION_VALUE_EASY=Einfach
OPTION_VALUE_MEDIUM=Mittel
OPTION_VALUE_HARD=Schwierig
@@ -11,9 +27,9 @@ OPTION_VALUE_GENRE=Genre
OPTION_VALUE_LANGUAGE=Sprache
OPTION_VALUE_FOLDER=Ordner
OPTION_VALUE_TITLE=Titel
-OPTION_VALUE_ARTIST=Künstler
+OPTION_VALUE_ARTIST=Künstler
OPTION_VALUE_TITLE2=Titel2
-OPTION_VALUE_ARTIST2=Künstler2
+OPTION_VALUE_ARTIST2=Künstler2
OPTION_VALUE_WHENNOVIDEO=Wenn kein Video
@@ -33,35 +49,35 @@ OPTION_VALUE_OLINE1=OLine1
OPTION_VALUE_OLINE2=OLine2
OPTION_VALUE_SIMPLE=Einfach
-OPTION_VALUE_ZOOM=Vergrössern
+OPTION_VALUE_ZOOM=Vergrössern
OPTION_VALUE_SLIDE=Rutschen
OPTION_VALUE_BALL=Ball
OPTION_VALUE_SHIFT=Schieben
-OPTION_VALUE_EURO=Europäisch
+OPTION_VALUE_EURO=Europäisch
OPTION_VALUE_JAPAN=Japanisch
OPTION_VALUE_AMERICAN=Amerikanisch
OPTION_VALUE_BLUE=Blau
-OPTION_VALUE_GREEN=Grün
+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_BALCK=Schwarz
+OPTION_VALUE_BLACK=Schwarz
OPTION_VALUE_SING=Singen
-OPTION_VALUE_SELECT_PLAYERS=Spieler auswählen
-OPTION_VALUE_OPEN_MENU=Menu öffnen
+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_LOADING=Lädt...
-SING_CHOOSE_MODE=Modus wählen
+SING_CHOOSE_MODE=Modus wählen
SING_SING=Singen
SING_SING_DESC=Singen
@@ -77,13 +93,13 @@ SING_EDITOR=Editor
SING_EDITOR_DESC=Erstelle deinen eigenen Song
SING_GAME_OPTIONS=Spieloptionen
-SING_GAME_OPTIONS_DESC=Verändere die Spieleinstellungen
+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_DESC=Einstellungen verändern
SING_OPTIONS_WHEREAMI=Optionen
SING_OPTIONS_GAME=Spiel
@@ -93,7 +109,7 @@ SING_OPTIONS_LYRICS=Lyrics
SING_OPTIONS_THEMES=Design
SING_OPTIONS_RECORD=Aufnahme
SING_OPTIONS_ADVANCED=Erweitert
-SING_OPTIONS_EXIT=zurück
+SING_OPTIONS_EXIT=zurück
SING_OPTIONS_GAME_WHEREAMI=Spieloptionen
SING_OPTIONS_GAME_DESC=Allgemeine Spieleinstellungen
@@ -106,13 +122,13 @@ SING_OPTIONS_GAME_DEBUG=Debug
SING_OPTIONS_GRAPHICS_WHEREAMI=Grafikoptionen
SING_OPTIONS_GRAPHICS_DESC=Grafikeinstellungen
-SING_OPTIONS_GRAPHICS_RESOLUTION=Auflösung
+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_GRAPHICS_MOVIE_SIZE=Videogröße
SING_OPTIONS_SOUND_WHEREAMI=Soundoptionen
SING_OPTIONS_SOUND_DESC=Soundeinstellungen
@@ -127,7 +143,7 @@ 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_DESC=Einstellungen für die Lyrics
SING_OPTIONS_LYRICS_FONT=Schriftart
SING_OPTIONS_LYRICS_EFFECT=Effekt
SING_OPTIONS_LYRICS_SOLMIZATION=Solmisation
@@ -139,7 +155,7 @@ SING_OPTIONS_THEMES_THEME=Design
SING_OPTIONS_THEMES_SKIN=Skin
SING_OPTIONS_THEMES_COLOR=Farbe
-SING_OPTIONS_RECORD_WHEREAMI=Aufnahmeoptionen
+SING_OPTIONS_RECORD_WHEREAMI=Aufnahmeoptionen
SING_OPTIONS_RECORD_DESC=Mikrofoneinstellungen
SING_OPTIONS_RECORD_CARD=Soundkarte
SING_OPTIONS_RECORD_INPUT=Eingang
@@ -152,43 +168,43 @@ 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_COUNT_HOW_OFTEN_SUNG=Wie oft gesungen mitzählen
+SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG=Wie oft gesungen mitzählen
SING_OPTIONS_ADVANCED_ONSONGCLICK=Nach Songauswahl
-SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto Party-Menü
+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_DESCRIPTION_EXIT=zurück
SING_EDIT_BUTTON_CONVERT=Importieren
-SING_EDIT_BUTTON_EXIT=zurück
+SING_EDIT_BUTTON_EXIT=zurück
SING_EDIT_NAVIGATE=Navigieren
-SING_EDIT_SELECT=Auswählen
-SING_EDIT_EXIT=zurück
+SING_EDIT_SELECT=Auswählen
+SING_EDIT_EXIT=zurück
-SING_LEGEND_SELECT=Auswählen
+SING_LEGEND_SELECT=Auswählen
SING_LEGEND_NAVIGATE=Navigieren
SING_LEGEND_CONTINUE=Weiter
-SING_LEGEND_ESC=zurück
+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_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_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_MENU=Menü
SING_SONG_SELECTION_PLAYLIST=Playlist
SING_SONGS_IN_CAT=Songs
PLAYLIST_CATTEXT=Playlist: %s
@@ -200,23 +216,24 @@ SING_NOTES=Noten
SING_GOLDEN_NOTES=Goldener Ton
SING_PHRASE_BONUS=Phrasenbonus
-SING_MENU=Hauptmenü
+SING_MENU=Hauptmenü
SONG_SCORE=Songpunktzahl
SONG_SCORE_WHEREAMI=Punkte
-SING_SCORE_TONE_DEAF=Nichtskönner
+SING_SCORE_TONE_DEAF=Nichtskönner
SING_SCORE_AMATEUR=Amateur
-SING_SCORE_WANNABE=Möchtegern
+SING_SCORE_WANNABE=Möchtegern
SING_SCORE_HOPEFUL=Fortgeschritten
SING_SCORE_RISING_STAR=Sternchen
-SING_SCORE_LEAD_SINGER=Hit-Künstler
+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!
@@ -227,21 +244,21 @@ POPUP_BAD=Schlecht!
POPUP_POOR=Mies!
POPUP_AWFUL=Grausam!
-IMPLODE_GLUE1=,
-IMPLODE_GLUE2= und
+IMPLODE_GLUE1=,
+IMPLODE_GLUE2= und
-SONG_MENU_NAME_MAIN=Menü
+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=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_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
@@ -250,17 +267,17 @@ 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_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_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_PLAYLIST_DEL=Playlist löschen?
-SONG_MENU_NAME_PARTY_MAIN=Party-Menü
+SONG_MENU_NAME_PARTY_MAIN=Party-Menü
SONG_MENU_JOKER=Joker
SONG_MENU_NAME_PARTY_JOKER=Joker einsetzen
@@ -281,84 +298,99 @@ PARTY_PLAYLIST=Playlist-Modus
PARTY_PLAYLIST_ALL=Alle Lieder
PARTY_PLAYLIST_CATEGORY=Ordner
PARTY_PLAYLIST_PLAYLIST=Playlist
-PARTY_ROUNDS=Runden
-PARTY_TEAMS=Teams
-PARTY_TEAMS_PLAYER1=Spieler Team 1
-PARTY_TEAMS_PLAYER2=Spieler Team 2
-PARTY_TEAMS_PLAYER3=Spieler Team 3
+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_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_PLAYER_LEGEND_CONTINUE=Partyspiel starten
-PARTY_ROUND_DESC=Die nächsten Spieler an die Mikros!
-PARTY_ROUND_WHEREAMI=Party nächste Runde
+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_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_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:
+NEXT_ROUND=Nächste Runde:
PARTY_DISMISSED=Ausgeschieden!
-PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS=%s
PARTY_SCORE_WINS2=hat gewonnen!
-PLUGIN_HDL_NAME=Balken halten
-PLUGIN_HDL_DESC=Halte die Bewertungsanzeige im angezeigten Bereich.
+MODE_RANDOM_NAME = zufälliger Modus
+MODE_RANDOM_DESC = Wählt einen zufälligen Modus aus
+
+MODE_HDL_NAME=Balken halten
+MODE_HDL_DESC=Halte die Bewertungsanzeige im angezeigten Bereich.
-PLUGIN_UNTIL5000_NAME=Bis 5000
-PLUGIN_UNTIL5000_DESC=Wer zuerst 5000 Punkte hat, gewinnt.
+MODE_5000POINTS_NAME=Bis 5000
+MODE_5000POINTS_DESC=Wer zuerst 5000 Punkte hat, gewinnt.
-PLUGIN_DUELL_NAME=Duell
-PLUGIN_DUELL_DESC=Normales Spiel. Höchste Punktzahl gewinnt.
+MODE_DUELL_NAME=Duell
+MODE_DUELL_DESC=Normales Spiel. Höchste Punktzahl gewinnt.
-PLUGIN_TEAMDUELL_NAME=Teamsingen
-PLUGIN_TEAMDUELL_DESC=Gib das Mikro weiter!
+MODE_TEAMDUELL_NAME=Teamsingen
+MODE_TEAMDUELL_DESC=Gib das Mikro weiter!
-PLUGIN_BLIND_NAME=Blind Mode
-PLUGIN_BLIND_DESC=Erreiche blind die höchste Punktzahl.
+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_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_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_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] \n (%3:s - %4:s)
+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_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
@@ -369,14 +401,30 @@ 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_QUESTION_TITLE=Frage
-MSG_QUIT_USDX=UltraStar wirklich verlassen?
-MSG_END_PARTY=Party-Modus beenden?
-ERROR_NO_SONGS=Keine Songs vorhanden.
-ERROR_NO_PLUGINS=Keine Plugins vorhanden.
+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 \ No newline at end of file
+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. \ No newline at end of file
diff --git a/cmake/game/languages/Greek.ini b/cmake/game/languages/Greek.ini
index 317f3475..d612392c 100644
--- a/cmake/game/languages/Greek.ini
+++ b/cmake/game/languages/Greek.ini
@@ -1,383 +1,402 @@
-;Leo 21
-[Text]
-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_BALCK=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=Öüñôùíåé...
-
-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_COUNT_HOW_OFTEN_SUNG=
-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=Óôçí åðéëïãÞ ôñáãïõäéïý
-
-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_DEL=ÄéáãñáöÞ?
-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_ROUNDS=Ãýñïé
-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=ÃñÜøå ïíüìáôá
-PARTY_PLAYER_LEGEND_CONTINUE=Îåêßíá ôï ðáé÷íßäé "ÐÜñôõ"
-
-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=Íßêçóå!
-
-PLUGIN_HDL_NAME=Ìåßíå ðÜíù áðü ôç ìðÜñá!
-PLUGIN_HDL_DESC=Ìåßíå ðÜíù áðü ôç ìðÜñá ðïõ åìöáíßæåôáé
-
-PLUGIN_UNTIL5000_NAME=ÌÝ÷ñé 5000 ðüíôïõò
-PLUGIN_UNTIL5000_DESC=¼ðïéïò öôÜóåé ôïõò 5000 ðüíôïõò êåñäßæåé
-
-PLUGIN_DUELL_NAME=Ìïíïìá÷ßá
-PLUGIN_DUELL_DESC=ÔñáãïõäÞóôå óå ìïíïìá÷ßá ìÝ÷ñé ôïõò 10000 ðüíôïõò
-
-PLUGIN_TEAMDUELL_NAME=Ìïíïìá÷ßá ïìÜäùí
-PLUGIN_TEAMDUELL_DESC=Äþóå ôï ìéêñüöùíï!
-
-PLUGIN_BLIND_NAME=Óôá ôõöëÜ
-PLUGIN_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_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] \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 ôñáãïõäÞèçêáí
-
-MSG_ERROR_TITLE=ÓöÜëìá
-MSG_QUESTION_TITLE=Åñþôçóç
-MSG_QUIT_USDX=¸îïäïò áðü ôï ðáé÷íßäé?
-MSG_END_PARTY=¸îïäïò áðï ôï ðáé÷íßäé "ÐÜñôõ"?
-ERROR_NO_SONGS=Äåí öïñôþèçêáí ôñáãïýäéá
-ERROR_NO_PLUGINS=Äåí öïñôþèçêáí âïçèçôéêÝò åöáñìïãÝò
-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 \ No newline at end of file
+;Leo 21
+[Text]
+OPTION_VALUE_CATALAN=Catalan
+OPTION_VALUE_CROATIAN=Croatian
+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_ITALIAN=Italian
+OPTION_VALUE_JAPANESE=Japanese
+OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+OPTION_VALUE_PORTUGUESE=Portuguese
+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=ΦόÏτωνει...
+
+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_COUNT_HOW_OFTEN_SUNG=
+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=ΧωÏίς όνομα
+
+SONG_MENU_NAME_PLAYLIST_DEL=ΔιαγÏαφή?
+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_ROUNDS=ΓÏÏοι
+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=ΓÏάψε ονόματα
+PARTY_PLAYER_LEGEND_CONTINUE=Ξεκίνα το παιχνίδι "ΠάÏÏ„Ï…"
+
+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=Îίκησε!
+
+PLUGIN_HDL_NAME=Μείνε πάνω από τη μπάÏα!
+PLUGIN_HDL_DESC=Μείνε πάνω από τη μπάÏα που εμφανίζεται
+
+PLUGIN_UNTIL5000_NAME=ΜέχÏι 5000 πόντους
+PLUGIN_UNTIL5000_DESC=Όποιος φτάσει τους 5000 πόντους κεÏδίζει
+
+PLUGIN_DUELL_NAME=Μονομαχία
+PLUGIN_DUELL_DESC=ΤÏαγουδήστε σε μονομαχία μέχÏι τους 10000 πόντους
+
+PLUGIN_TEAMDUELL_NAME=Μονομαχία ομάδων
+PLUGIN_TEAMDUELL_DESC=Δώσε το μικÏόφωνο!
+
+PLUGIN_BLIND_NAME=Στα τυφλά
+PLUGIN_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 Ï„Ïαγουδήθηκαν
+
+MSG_ERROR_TITLE=Σφάλμα
+MSG_QUESTION_TITLE=ΕÏώτηση
+MSG_QUIT_USDX=Έξοδος από το παιχνίδι?
+MSG_END_PARTY=Έξοδος απο το παιχνίδι "ΠάÏÏ„Ï…"?
+ERROR_NO_SONGS=Δεν φοÏτώθηκαν Ï„ÏαγοÏδια
+ERROR_NO_PLUGINS=Δεν φοÏτώθηκαν βοηθητικές εφαÏμογές
+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 \ No newline at end of file
diff --git a/cmake/game/languages/Icelandic.ini b/cmake/game/languages/Icelandic.ini
new file mode 100644
index 00000000..35f912c9
--- /dev/null
+++ b/cmake/game/languages/Icelandic.ini
@@ -0,0 +1,431 @@
+;Hlynur Sigurgíslason
+;Sigrún Huld Skúladóttir
+[Text]
+OPTION_VALUE_CATALAN=katalónska
+OPTION_VALUE_CROATIAN=króatíska
+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_ITALIAN=ítalska
+OPTION_VALUE_ICELANDIC=íslenska
+OPTION_VALUE_JAPANESE=japanska
+OPTION_VALUE_LUXEMBOURGISH=lúxemborgíska
+OPTION_VALUE_PORTUGUESE=portúgalska
+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_COUNT_HOW_OFTEN_SUNG=
+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!
+
+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_HDL_NAME=Haltu þig á strikinu
+MODE_HDL_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 \ No newline at end of file
diff --git a/cmake/game/languages/Italian.ini b/cmake/game/languages/Italian.ini
index e2fe7983..660b9b6f 100644
--- a/cmake/game/languages/Italian.ini
+++ b/cmake/game/languages/Italian.ini
@@ -1,4 +1,20 @@
-[Text]
+[Text]
+OPTION_VALUE_CATALAN=Catalan
+OPTION_VALUE_CROATIAN=Croatian
+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_ITALIAN=Italian
+OPTION_VALUE_JAPANESE=Japanese
+OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+OPTION_VALUE_PORTUGUESE=Portuguese
+OPTION_VALUE_SPANISH=Spanish
+OPTION_VALUE_SWEDISH=Swedish
+
OPTION_VALUE_EASY=Easy
OPTION_VALUE_MEDIUM=Medium
OPTION_VALUE_HARD=Hard
@@ -50,7 +66,7 @@ OPTION_VALUE_VIOLET=Violet
OPTION_VALUE_ORANGE=Orange
OPTION_VALUE_YELLOW=Yellow
OPTION_VALUE_BROWN=Brown
-OPTION_VALUE_BALCK=Black
+OPTION_VALUE_BLACK=Black
OPTION_VALUE_SING=Sing
OPTION_VALUE_SELECT_PLAYERS=Select Players
@@ -61,12 +77,12 @@ OPTION_VALUE_SOFTWARE_CURSOR=Software Cursor
SING_LOADING=Caricamento...
-SING_CHOOSE_MODE=scegli modalità
+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_MULTI_DESC=canta in modalità party
SING_TOOLS=strumenti
@@ -98,7 +114,7 @@ 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_DIFFICULTY=Difficultà
SING_OPTIONS_GAME_LANGUAGE=Lingua
SING_OPTIONS_GAME_TABS=Schede
SING_OPTIONS_GAME_SORTING=Ordinamento
@@ -108,7 +124,7 @@ 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_DEPTH=Profondità
SING_OPTIONS_GRAPHICS_VISUALIZER=Visualizzazioni
SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Oscilloscopio
SING_OPTIONS_GRAPHICS_LINEBONUS=Linee Bonus
@@ -122,7 +138,7 @@ 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_TWO_PLAYERS_MODE=Modalità due giocatori
SING_OPTIONS_SOUND_PREVIEWVOLUME=Volume Anteprima
SING_OPTIONS_SOUND_PREVIEWFADING=Fading Anteprima
@@ -177,8 +193,8 @@ 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_DESC=seleziona difficoltà
+SING_DIFFICULTY_WHEREAMI=Difficultà
SING_DIFFICULTY_CONTINUE=per cantare seleziona
SING_EASY=Facile
SING_MEDIUM=Media
@@ -217,6 +233,7 @@ 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!
@@ -227,8 +244,8 @@ POPUP_BAD=scarso!
POPUP_POOR=pessimo!
POPUP_AWFUL=orribile!
-IMPLODE_GLUE1=,
-IMPLODE_GLUE2= e
+IMPLODE_GLUE1=,
+IMPLODE_GLUE2= e
SONG_MENU_NAME_MAIN=menu canzone
SONG_MENU_PLAY=Canta
@@ -251,7 +268,7 @@ 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_YES=Sì
SONG_MENU_NO=No
SONG_MENU_NAME_PLAYLIST_LOAD=Apri Playlist
@@ -275,9 +292,9 @@ 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_MODE=modalità party
+PARTY_DIFFICULTY=Difficultà
+PARTY_PLAYLIST=Modalità Playlist
PARTY_PLAYLIST_ALL=Tutte le Canzoni
PARTY_PLAYLIST_CATEGORY=Cartella
PARTY_PLAYLIST_PLAYLIST=Playlist
@@ -301,8 +318,8 @@ 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_WHEREAMI=Canzone Party-Seleziona
+PARTY_SONG_LEGEND_CONTINUE=canta
PARTY_SONG_MENU=menu party
PARTY_SCORE_DESC=punteggio dell''ultimo round
@@ -319,7 +336,7 @@ PARTY_NOBODY=nessuno
NEXT_ROUND=Prossimo round:
PARTY_DISMISSED=Respinto!
-PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS=%s
PARTY_SCORE_WINS2=vince!
PLUGIN_HDL_NAME=Tieni la Linea
@@ -334,7 +351,7 @@ PLUGIN_DUELL_DESC=Canta in duello fino a 10000 punti.
PLUGIN_TEAMDUELL_NAME=Duello a Team
PLUGIN_TEAMDUELL_DESC=Passa il Microfono!
-PLUGIN_BLIND_NAME=Modalità Ceca
+PLUGIN_BLIND_NAME=Modalità Ceca
PLUGIN_BLIND_DESC=Duella senza vedere le note.
STAT_MAIN=Statistiche
@@ -342,8 +359,10 @@ 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_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
@@ -355,27 +374,27 @@ 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] \n (%3:s - %4:s)
+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=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=Le Bands più popolari
STAT_DESC_BANDS_REVERSED=Le Bands meno popolari
STAT_FORMAT_BANDS=%0:s \n %1:dx Cantate
MSG_ERROR_TITLE=Errore
MSG_QUESTION_TITLE=Domanda
MSG_QUIT_USDX=Vuoi davvero uscire da UltraStar?
-MSG_END_PARTY=Vuoi davvero terminare la Modalità Party?
+MSG_END_PARTY=Vuoi davvero terminare la Modalità Party?
ERROR_NO_SONGS=Nessuna Canzone caricata
ERROR_NO_PLUGINS=Nessun Plugin caricato
-ERROR_CORRUPT_SONG=La canzone non è stata caricata.
+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
diff --git a/cmake/game/languages/Japanese.ini b/cmake/game/languages/Japanese.ini
index 21e78d4a..b22f92b8 100644
--- a/cmake/game/languages/Japanese.ini
+++ b/cmake/game/languages/Japanese.ini
Binary files differ
diff --git a/cmake/game/languages/Luxembourgish.ini b/cmake/game/languages/Luxembourgish.ini
new file mode 100644
index 00000000..4fc3e2ae
--- /dev/null
+++ b/cmake/game/languages/Luxembourgish.ini
@@ -0,0 +1,402 @@
+;Enaid an Nosde
+[Text]
+OPTION_VALUE_CATALAN=Catalanesch
+OPTION_VALUE_CROATIAN=Croatesch
+OPTION_VALUE_DUTCH=Hollänesch
+OPTION_VALUE_ENGLISH=Englesh
+OPTION_VALUE_EUSKARA=Euskaresch
+OPTION_VALUE_FINNISH=Finnesh
+OPTION_VALUE_FRENCH=Franséisch
+OPTION_VALUE_GERMAN=Däitsch
+OPTION_VALUE_GREEK=Griichesch
+OPTION_VALUE_ITALIAN=Italienesch
+OPTION_VALUE_JAPANESE=Japanesch
+OPTION_VALUE_LUXEMBOURGISH=Lëtzebuergesch
+OPTION_VALUE_PORTUGUESE=Portugisesch
+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ünstler
+OPTION_VALUE_TITLE2=Titel2
+OPTION_VALUE_ARTIST2=Künstler2
+
+OPTION_VALUE_WHENNOVIDEO=Wann keen 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=Plain
+OPTION_VALUE_OLINE1=OLine1
+OPTION_VALUE_OLINE2=OLine2
+
+OPTION_VALUE_SIMPLE=Einfach
+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=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 Cursor
+OPTION_VALUE_SOFTWARE_CURSOR=Software Cursor
+
+SING_LOADING=Luedt...
+
+SING_CHOOSE_MODE=Modus wielen
+SING_SING=Sangen
+SING_SING_DESC=Sangen
+
+SING_MULTI=Party
+SING_MULTI_DESC=Zu puer sangen
+
+SING_TOOLS=Aaner
+
+SING_STATS=Statistiken
+SING_STATS_DESC=Statistiken ukucken
+
+SING_EDITOR=Editor
+SING_EDITOR_DESC=Lidder erstellen
+
+SING_GAME_OPTIONS=Optiounen
+SING_GAME_OPTIONS_DESC=Astellungen fum Spill änneren
+
+SING_EXIT=Verloossen
+SING_EXIT_DESC=Spill verloossen
+
+SING_OPTIONS=Optiounen
+SING_OPTIONS_DESC=Astellungen fum Spill änneren
+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éierung
+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=Mik-Unhiewung
+SING_OPTIONS_SOUND_CLICK_ASSIST=Click-Assistent
+SING_OPTIONS_SOUND_BEAT_CLICK=Beat-Click
+SING_OPTIONS_SOUND_THRESHOLD=Räuschënnerdrë.
+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=Noutenlinien
+
+SING_OPTIONS_THEMES_WHEREAMI=Designoptiounen
+SING_OPTIONS_THEMES_DESC=Design an Skinastellungen
+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-Fade
+SING_OPTIONS_ADVANCED_LOADANIMATION=Lued-Animatioun
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Sécherheetsfro
+SING_OPTIONS_ADVANCED_LINEBONUS=Sazbonus
+SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG=Wéi oft gesongen matzielen
+SING_OPTIONS_ADVANCED_ONSONGCLICK=No Liddauswiel
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto Party-Menü
+
+SING_EDIT=Editor
+SING_EDIT_MENU_DESCRIPTION=Lidder erstellen
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Midi/Kar Datei als Text exportéieren
+SING_EDIT_BUTTON_DESCRIPTION_EXIT=Zeréck
+SING_EDIT_BUTTON_CONVERT=Exporté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=Auswielen
+SING_LEGEND_ESC=Zeréck
+
+SING_PLAYER_DESC=Numm vum Spiller aginn
+SING_PLAYER_WHEREAMI=Numm vum Spiller
+SING_PLAYER_ENTER_NAME=Änneren
+
+SING_DIFFICULTY_DESC=Schwieregkeetsgrad auswielen
+SING_DIFFICULTY_WHEREAMI=Schwieregkeetsgrad
+SING_DIFFICULTY_CONTINUE=Auswielen
+SING_EASY=Einfach
+SING_MEDIUM=Mëttel
+SING_HARD=Schwéier
+
+SING_SONG_SELECTION_DESC=Lidd wielen
+SING_SONG_SELECTION_WHEREAMI=Titel wielen
+SING_SONG_SELECTION_GOTO=Erreechen
+SING_SONG_SELECTION=Auswiel vum Lidd
+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=Total
+SING_MODE=Sangmodus
+SING_NOTES=Nouten
+SING_GOLDEN_NOTES=Goldenen Toun
+SING_PHRASE_BONUS=Sazbonus
+
+SING_MENU=Haaptmenü
+
+SONG_SCORE=Score
+SONG_SCORE_WHEREAMI=Punkten
+
+SING_SCORE_TONE_DEAF=Kachdëppen
+SING_SCORE_AMATEUR=Amateur
+SING_SCORE_WANNABE=Möchtegern
+SING_SCORE_HOPEFUL=Fortgeschritten
+SING_SCORE_RISING_STAR=Stärnchen
+SING_SCORE_LEAD_SINGER=Hit-Künstler
+SING_SCORE_SUPERSTAR=Superstar
+SING_SCORE_ULTRASTAR=Ultrastar
+
+SING_TOP_5_CHARTS=Top-5-Spiller
+SING_TOP_5_CHARTS_WHEREAMI=Beschten Spiller
+SING_TOP_5_CHARTS_CONTINUE=Weider
+SING_TOP_5_CHARTS_SWITCH_DIFFICULTY=switch difficulty
+
+POPUP_PERFECT=Perfekt!
+POPUP_AWESOME=Cool!
+POPUP_GREAT=Toll!
+POPUP_GOOD=Gutt!
+POPUP_NOTBAD=O.K.!
+POPUP_BAD=Schlecht!
+POPUP_POOR=Mies!
+POPUP_AWFUL=Grausam!
+
+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=Een 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 der neier Playlist
+SONG_MENU_PLAYLIST_ADD_EXISTING=Bäifügen bei d'Playlist
+SONG_MENU_PLAYLIST_NOEXISTING=Keng Playlist
+
+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=Läschen?
+SONG_MENU_YES=Jo
+SONG_MENU_NO=Nee
+
+SONG_MENU_NAME_PLAYLIST_DEL=Playlist läschen?
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Playlist opmaachen
+SONG_MENU_PLAYLIST_LOAD=Opmaachen
+SONG_MENU_PLAYLIST_DELCURRENT=Aktuel Playlist läschen
+
+SONG_MENU_NAME_PARTY_MAIN=Menü
+SONG_MENU_JOKER=Joker
+
+SONG_MENU_NAME_PARTY_JOKER=Joker
+
+SONG_JUMPTO_DESC=Sichen
+SONG_JUMPTO_TYPE_DESC=Nosichen:
+SONG_JUMPTO_TYPE1=Alles
+SONG_JUMPTO_TYPE2=Titel
+SONG_JUMPTO_TYPE3=Künstler
+SONG_JUMPTO_SONGSFOUND=%d Lidd(er) fond
+SONG_JUMPTO_NOSONGSFOUND=Keen Lidd fond
+SONG_JUMPTO_HELP=Text aginn, fir en ze sichen
+SONG_JUMPTO_CATTEXT=Nosichen: %s
+
+PARTY_MODE=Party-Modus
+PARTY_DIFFICULTY=Schwieregkeet
+PARTY_PLAYLIST=Playlist-Modus
+PARTY_PLAYLIST_ALL=All Lidder
+PARTY_PLAYLIST_CATEGORY=Ordner
+PARTY_PLAYLIST_PLAYLIST=Playlist
+PARTY_ROUNDS=Ronnen
+PARTY_TEAMS=Team
+PARTY_TEAMS_PLAYER1=Spiller Team 1
+PARTY_TEAMS_PLAYER2=Spiller Team 2
+PARTY_TEAMS_PLAYER3=Spiller Team 3
+
+PARTY_LEGEND_CONTINUE=Weider
+
+PARTY_OPTIONS_DESC=Astellungen fir den Party-Modus
+PARTY_OPTIONS_WHEREAMI=Party-Modus Optiounen
+
+PARTY_PLAYER_DESC=Numm vum Team an vun den Spiller aginn
+PARTY_PLAYER_WHEREAMI=Party-Modus: Team
+PARTY_PLAYER_ENTER_NAME=Änneren
+PARTY_PLAYER_LEGEND_CONTINUE=Partyspill starten
+
+PARTY_ROUND_DESC=Déi nächst Spiller un är Microen!
+PARTY_ROUND_WHEREAMI=Party-Modus: Nächst Ronn
+PARTY_ROUND_LEGEND_CONTINUE=Ufänken
+
+PARTY_SONG_WHEREAMI=Party-Modus: Auswiel vum Lidd
+PARTY_SONG_LEGEND_CONTINUE=Sangen
+PARTY_SONG_MENU=Menü
+
+PARTY_SCORE_DESC=Score vun deser Ronn
+PARTY_SCORE_WHEREAMI=Party-Modus: Score
+
+PARTY_WIN_DESC=Gewënner vum Partyspill
+PARTY_WIN_WHEREAMI=Party 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=Retrogradéiert
+PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS2=huet gewonn!
+
+PLUGIN_HDL_NAME=Balken halen
+PLUGIN_HDL_DESC=Hal d'Bewäertung bis beim ugewisenen Sector.
+
+PLUGIN_UNTIL5000_NAME=Bis 5000
+PLUGIN_UNTIL5000_DESC=Wien als éischt 5000 Punkten huet, gewënnt.
+
+PLUGIN_DUELL_NAME=Duell
+PLUGIN_DUELL_DESC=Wien den héischsten Score huet gewënnt.
+
+PLUGIN_TEAMDUELL_NAME=Teamsangen
+PLUGIN_TEAMDUELL_DESC=Gëff den Mikro weider!
+
+PLUGIN_BLIND_NAME=Blann Modus
+PLUGIN_BLIND_DESC=Erreech blann déi héischst Punktenzuel.
+
+STAT_MAIN=Statistiken
+STAT_MAIN_DESC=Allgemeng
+STAT_MAIN_WHEREAMI=Statistiken
+
+STAT_OVERVIEW_INTRO=Statistiken vun %0:s \n Lescht Reinitialisatioun den %1:.2d.%2:.2d.%3:d
+STAT_OVERVIEW_SONG=%0:d Lidder (%3:d mat Video)\n%1:d goufen schonn op mannst emol gesongen, %2:d nach net. \n\n Dat meescht gesongend Lidd ass %5:s vun %4:s.
+STAT_OVERVIEW_PLAYER=%0:d verschidden Spiller hun gesongen seit der leschter Reinitialisatioun. \n\n Den beschten Spiller ass %1:s mat %2:d Punkten. \n Beschten Score, %4:d, gouf vun %3:s erreecht.
+
+STAT_FORMAT_DATE=%1:.2d.%0:.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 vun %3:d %3:d Eintrachen)
+
+STAT_DESC_SCORES=Highscore
+STAT_DESC_SCORES_REVERSED=Lowscores
+STAT_FORMAT_SCORES=%0:s - %1:d [%2:s] %5:s \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Beschten Sänger
+STAT_DESC_SINGERS_REVERSED=Schlechtesten Sänger
+STAT_FORMAT_SINGERS=%0:s \n Duerchschnëttlech Punktenzuel: %1:d
+
+STAT_DESC_SONGS=Beléifsten Lidder
+STAT_DESC_SONGS_REVERSED=Onbeléifsten Lidder
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx gesongen
+
+STAT_DESC_BANDS=Beléifsten Bands
+STAT_DESC_BANDS_REVERSED=Onbeléifsten Bands
+STAT_FORMAT_BANDS=%0:s \n Lidder gesongen: %1:d
+
+MSG_ERROR_TITLE=Feeler
+MSG_QUESTION_TITLE=Bestätegung
+MSG_QUIT_USDX=UltraStar verloossen?
+MSG_END_PARTY=Party-Modus verloossen?
+ERROR_NO_SONGS=Keng Lidder.
+ERROR_NO_PLUGINS=Keen Plugin.
+ERROR_CORRUPT_SONG=Lidd kann een net lueden.
+ERROR_CORRUPT_SONG_FILE_NOT_FOUND=Lidd kann een net lueden: Datei gouf net fond
+ERROR_CORRUPT_SONG_NO_NOTES=Lidd kann een net lueden: Et goufen keng Nouten fond
+ERROR_CORRUPT_SONG_NO_BREAKS=Lidd kann een net lueden: Et goufen keen Saazwiessel fond
+ERROR_CORRUPT_SONG_UNKNOWN_IN_LINE=Lidd kann een net lueden: Feeler beim Parzen vun der Zeil %0:d \ No newline at end of file
diff --git a/cmake/game/languages/Portuguese.ini b/cmake/game/languages/Portuguese.ini
index ad2d1152..686190bd 100644
--- a/cmake/game/languages/Portuguese.ini
+++ b/cmake/game/languages/Portuguese.ini
@@ -1,382 +1,401 @@
-[Text]
-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_BALCK=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=A Ler...
-
-SING_CHOOSE_MODE=Escolha o Modo
-SING_SING=Cantar
-SING_SING_DESC=Jogo Rápido: cantar a Solo ou em Dueto
-
-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ção de Gráficos
-SING_OPTIONS_GRAPHICS_DESC=Configuração 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=Côr
-
-SING_OPTIONS_RECORD_WHEREAMI=Opções de Gravação
-SING_OPTIONS_RECORD_DESC=Configuração 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_COUNT_HOW_OFTEN_SUNG=
-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=Selecção da Canção
-SING_SONG_SELECTION_GOTO=Ir para ..
-SING_SONG_SELECTION=Selecçã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 a 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
-
-POPUP_PERFECT=Perfeito!
-POPUP_AWESOME=Fantástico!
-POPUP_GREAT=Óptimo!
-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_DEL=Apagar mesmo?
-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 actual
-
-SONG_MENU_NAME_PLAYLIST_DEL=Apagar Playlist?
-
-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=Directório
-PARTY_PLAYLIST_PLAYLIST=Playlist
-PARTY_ROUNDS=Rondas
-PARTY_TEAMS=Equipas
-PARTY_TEAMS_PLAYER1=Jogador Equipa1
-PARTY_TEAMS_PLAYER2=Jogador Equipa2
-PARTY_TEAMS_PLAYER3=Jogador Equipa3
-
-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_PLAYER_LEGEND_CONTINUE=Iniciar Festa
-
-PARTY_ROUND_DESC=Jogadores seguintes para os microfones
-PARTY_ROUND_WHEREAMI=Ronda seguinte
-PARTY_ROUND_LEGEND_CONTINUE=Inicio da Ronda
-
-PARTY_SONG_WHEREAMI=Escolha da Canção
-PARTY_SONG_LEGEND_CONTINUE=Cantar
-PARTY_SONG_MENU=Menu Festa
-
-PARTY_SCORE_DESC=Pontuação da última ronda
-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=Ronda
-PARTY_ROUND_WINNER=Vencedor
-PARTY_NOTPLAYEDYET=Não tocada
-PARTY_NOBODY=Ninguém
-NEXT_ROUND=Ronda seguinte:
-
-PARTY_DISMISSED=Dispensado!
-PARTY_SCORE_WINS=%s
-PARTY_SCORE_WINS2=Ganhou!
-
-PLUGIN_HDL_NAME=Manter a linha
-PLUGIN_HDL_DESC=Não piorar o ponteiro que é mostrado na barra de pontuação
-
-PLUGIN_UNTIL5000_NAME=Até 5000
-PLUGIN_UNTIL5000_DESC=Quem obter primeiro 5000 pontos ganha a partida
-
-PLUGIN_DUELL_NAME=Duelo
-PLUGIN_DUELL_DESC=Fazer um Duelo até aos 10000 pontos.
-
-PLUGIN_TEAMDUELL_NAME=Duelo de equipa
-PLUGIN_TEAMDUELL_DESC=Passa o Microfone!
-
-PLUGIN_BLIND_NAME=Modo Cego
-PLUGIN_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_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] \n (%3:s - %4:s)
-
-STAT_DESC_SINGERS=Top Cantores
-STAT_DESC_SINGERS_REVERSED=Piores Cantores
-STAT_FORMAT_SINGERS=%0:s \n Pontuação Média: %1:d
-
-STAT_DESC_SONGS=Top Canções
-STAT_DESC_SONGS_REVERSED=Canções Menos Populares
-STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx Cantaram
-
-STAT_DESC_BANDS=Top Bandas
-STAT_DESC_BANDS_REVERSED=Bandas Menos Populares
-STAT_FORMAT_BANDS=%0:s \n %1:dx Cantaram
-
-MSG_ERROR_TITLE=Erro
-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_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!
+[Text]
+OPTION_VALUE_CATALAN=Catalan
+OPTION_VALUE_CROATIAN=Croatian
+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_ITALIAN=Italian
+OPTION_VALUE_JAPANESE=Japanese
+OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+OPTION_VALUE_PORTUGUESE=Portuguese
+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=A Ler...
+
+SING_CHOOSE_MODE=Escolha o Modo
+SING_SING=Cantar
+SING_SING_DESC=Jogo Rápido: cantar a Solo ou em Dueto
+
+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ção de Gráficos
+SING_OPTIONS_GRAPHICS_DESC=Configuração 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=Côr
+
+SING_OPTIONS_RECORD_WHEREAMI=Opções de Gravação
+SING_OPTIONS_RECORD_DESC=Configuração 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_COUNT_HOW_OFTEN_SUNG=
+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=Selecção da Canção
+SING_SONG_SELECTION_GOTO=Ir para ..
+SING_SONG_SELECTION=Selecçã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 a 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=switch difficulty
+
+POPUP_PERFECT=Perfeito!
+POPUP_AWESOME=Fantástico!
+POPUP_GREAT=Óptimo!
+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_DEL=Apagar mesmo?
+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 actual
+
+SONG_MENU_NAME_PLAYLIST_DEL=Apagar Playlist?
+
+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=Directório
+PARTY_PLAYLIST_PLAYLIST=Playlist
+PARTY_ROUNDS=Rondas
+PARTY_TEAMS=Equipas
+PARTY_TEAMS_PLAYER1=Jogador Equipa1
+PARTY_TEAMS_PLAYER2=Jogador Equipa2
+PARTY_TEAMS_PLAYER3=Jogador Equipa3
+
+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_PLAYER_LEGEND_CONTINUE=Iniciar Festa
+
+PARTY_ROUND_DESC=Jogadores seguintes para os microfones
+PARTY_ROUND_WHEREAMI=Ronda seguinte
+PARTY_ROUND_LEGEND_CONTINUE=Inicio da Ronda
+
+PARTY_SONG_WHEREAMI=Escolha da Canção
+PARTY_SONG_LEGEND_CONTINUE=Cantar
+PARTY_SONG_MENU=Menu Festa
+
+PARTY_SCORE_DESC=Pontuação da última ronda
+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=Ronda
+PARTY_ROUND_WINNER=Vencedor
+PARTY_NOTPLAYEDYET=Não tocada
+PARTY_NOBODY=Ninguém
+NEXT_ROUND=Ronda seguinte:
+
+PARTY_DISMISSED=Dispensado!
+PARTY_SCORE_WINS=%s
+PARTY_SCORE_WINS2=Ganhou!
+
+PLUGIN_HDL_NAME=Manter a linha
+PLUGIN_HDL_DESC=Não piorar o ponteiro que é mostrado na barra de pontuação
+
+PLUGIN_UNTIL5000_NAME=Até 5000
+PLUGIN_UNTIL5000_DESC=Quem obter primeiro 5000 pontos ganha a partida
+
+PLUGIN_DUELL_NAME=Duelo
+PLUGIN_DUELL_DESC=Fazer um Duelo até aos 10000 pontos.
+
+PLUGIN_TEAMDUELL_NAME=Duelo de equipa
+PLUGIN_TEAMDUELL_DESC=Passa o Microfone!
+
+PLUGIN_BLIND_NAME=Modo Cego
+PLUGIN_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=Top Cantores
+STAT_DESC_SINGERS_REVERSED=Piores Cantores
+STAT_FORMAT_SINGERS=%0:s \n Pontuação Média: %1:d
+
+STAT_DESC_SONGS=Top Canções
+STAT_DESC_SONGS_REVERSED=Canções Menos Populares
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx Cantaram
+
+STAT_DESC_BANDS=Top Bandas
+STAT_DESC_BANDS_REVERSED=Bandas Menos Populares
+STAT_FORMAT_BANDS=%0:s \n %1:dx Cantaram
+
+MSG_ERROR_TITLE=Erro
+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_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 \ No newline at end of file
diff --git a/cmake/game/languages/Spanish.ini b/cmake/game/languages/Spanish.ini
index f3b36494..c746e2e8 100644
--- a/cmake/game/languages/Spanish.ini
+++ b/cmake/game/languages/Spanish.ini
@@ -1,382 +1,401 @@
-[Text]
-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_BALCK=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=Cargando...
-
-SING_CHOOSE_MODE=elige modo
-SING_SING=Cantar
-SING_SING_DESC=Juego rápido: cantar solo o dueto
-
-SING_MULTI=Grupo
-SING_MULTI_DESC=cantar en modo grupo
-
-SING_TOOLS=Utilidades
-
-SING_STATS=Estadísticas
-SING_STATS_DESC=Ver las 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=Temas
-SING_OPTIONS_RECORD=Grabar
-SING_OPTIONS_ADVANCED=Avanzado
-SING_OPTIONS_EXIT=Atrás
-
-SING_OPTIONS_GAME_WHEREAMI=Opciones del juego
-SING_OPTIONS_GAME_DESC=Ajustes 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=Opciones gráficas
-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 vídeo
-
-SING_OPTIONS_SOUND_WHEREAMI=Opciones de sonido
-SING_OPTIONS_SOUND_DESC=Opciones de sonido
-SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Playback del micrófono
-SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Música de fondo
-SING_OPTIONS_SOUND_MIC_BOOST=Potenciar micrófono
-SING_OPTIONS_SOUND_CLICK_ASSIST=Asistente de notas
-SING_OPTIONS_SOUND_BEAT_CLICK=Asistente de golpes
-SING_OPTIONS_SOUND_THRESHOLD=Umbral
-SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Modo dos jugadores
-SING_OPTIONS_SOUND_PREVIEWVOLUME=Volumen de avance
-SING_OPTIONS_SOUND_PREVIEWFADING=Desvanecimiento
-
-SING_OPTIONS_LYRICS_WHEREAMI=Opciones de letras
-SING_OPTIONS_LYRICS_DESC=Opciones de letras
-SING_OPTIONS_LYRICS_FONT=Tipo de letra
-SING_OPTIONS_LYRICS_EFFECT=Efecto
-SING_OPTIONS_LYRICS_SOLMIZATION=Solfeo
-SING_OPTIONS_LYRICS_NOTELINES=Pentagramas
-
-SING_OPTIONS_THEMES_WHEREAMI=Opciones de temas
-SING_OPTIONS_THEMES_DESC=Opciones de temas
-SING_OPTIONS_THEMES_THEME=Tema
-SING_OPTIONS_THEMES_SKIN=Piel
-SING_OPTIONS_THEMES_COLOR=Color
-
-SING_OPTIONS_RECORD_WHEREAMI=Opciones de grabación
-SING_OPTIONS_RECORD_DESC=Opciones de micrófono
-SING_OPTIONS_RECORD_CARD=Tarjeta 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=Preguntas de seguridad
-SING_OPTIONS_ADVANCED_LINEBONUS=Bonus de línea
-SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG=
-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=Nombre(s) de jugador(es)
-SING_PLAYER_WHEREAMI=Nombre(s) de jugador(es)
-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=Selección de 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 de canciones
-SING_SONGS_IN_CAT=Canciones
-PLAYLIST_CATTEXT=Lista de canciones: %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=Puntuación
-SONG_SCORE_WHEREAMI=Puntuación
-
-SING_SCORE_TONE_DEAF=Sin oído
-SING_SCORE_AMATEUR=Aficionado
-SING_SCORE_WANNABE=Aspirante
-SING_SCORE_HOPEFUL=Promesa
-SING_SCORE_RISING_STAR=Prometes
-SING_SCORE_LEAD_SINGER=Artista
-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
-
-POPUP_PERFECT=¡Perfecto!
-POPUP_AWESOME=¡Asombroso!
-POPUP_GREAT=¡Genial!
-POPUP_GOOD=¡Bien!
-POPUP_NOTBAD=¡No está 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=Escoger 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=Añadir canción
-SONG_MENU_PLAYLIST_DEL=Borrar canción
-
-SONG_MENU_NAME_PLAYLIST_ADD=Añadir canción
-SONG_MENU_PLAYLIST_ADD_NEW=A nueva lista de canciones
-SONG_MENU_PLAYLIST_ADD_EXISTING=A lista existente
-SONG_MENU_PLAYLIST_NOEXISTING=No hay listas de canciones
-
-SONG_MENU_NAME_PLAYLIST_NEW=Nueva lista 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 lista
-SONG_MENU_PLAYLIST_LOAD=Abrir
-SONG_MENU_PLAYLIST_DELCURRENT=Borrar la lista actual
-
-SONG_MENU_NAME_PLAYLIST_DEL=¿Borrar la lista?
-
-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 canción(es) encontrada(s)
-SONG_JUMPTO_NOSONGSFOUND=No se han encontrado canciones
-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=Todas las canciones
-PARTY_PLAYLIST_CATEGORY=Carpeta
-PARTY_PLAYLIST_PLAYLIST=Lista de canciones
-PARTY_ROUNDS=Rondas
-PARTY_TEAMS=Equipos
-PARTY_TEAMS_PLAYER1=Miembros del equipo 1
-PARTY_TEAMS_PLAYER2=Miembros del equipo 2
-PARTY_TEAMS_PLAYER3=Miembros del equipo 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_PLAYER_LEGEND_CONTINUE=Empezar
-
-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=Puntuación de la última ronda
-PARTY_SCORE_WHEREAMI=Puntuación
-
-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ó!
-
-PLUGIN_HDL_NAME=Mantén la línea
-PLUGIN_HDL_DESC=No bajes tu puntuación de lo indicado en pantalla
-
-PLUGIN_UNTIL5000_NAME=Hasta 5000
-PLUGIN_UNTIL5000_DESC=Gana quien obtenga 5000 puntos.
-
-PLUGIN_DUELL_NAME=Duelo
-PLUGIN_DUELL_DESC=Canta un duelo hasta 10000 puntos.
-
-PLUGIN_TEAMDUELL_NAME=Duelo de equipos
-PLUGIN_TEAMDUELL_DESC=¡Pasa el micro!
-
-PLUGIN_BLIND_NAME=Modo a ciegas
-PLUGIN_BLIND_DESC=Duelo sin ver las notas.
-
-STAT_MAIN=Estadísticas
-STAT_MAIN_DESC=General
-STAT_MAIN_WHEREAMI=Estadísticas
-
-STAT_OVERVIEW_INTRO=%0:s Estadísticas. \n Último reinicio el %2:.2d.%1:.2d.%3:d
-STAT_OVERVIEW_SONG=%0:d Canciones(%3:d con vídeo), de las cuales %1:d han sido cantadas y %2:d aún no.\n La canción más popular es %5:s de %4:s.
-STAT_OVERVIEW_PLAYER=Hay registrados %0:d jugador(es) diferente(s).\n El mejor es %1:s con una puntuación promedio de %2:d puntos.\n %3:s ha hecho la mejor puntuación con %4:d puntos.
-
-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 de %3:d entradas)
-
-STAT_DESC_SCORES=Mejores puntuaciones
-STAT_DESC_SCORES_REVERSED=Peores puntuaciones
-STAT_FORMAT_SCORES=%0:s - %1:d [%2:s] \n (%3:s - %4:s)
-
-STAT_DESC_SINGERS=Mejores cantantes
-STAT_DESC_SINGERS_REVERSED=Peores cantantes
-STAT_FORMAT_SINGERS=%0:s \n Puntuación media: %1:d
-
-STAT_DESC_SONGS=Canciones más populares
-STAT_DESC_SONGS_REVERSED=Canciones menos populares
-STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx veces cantada
-
-STAT_DESC_BANDS=Grupos más populares
-STAT_DESC_BANDS_REVERSED=Grupos menos populares
-STAT_FORMAT_BANDS=%0:s \n %1:dx veces cantado
-
-MSG_ERROR_TITLE=Error
-MSG_QUESTION_TITLE=Pregunta
-MSG_QUIT_USDX=¿Seguro que quieres salir?
-MSG_END_PARTY=¿Seguro que quieres salir del modo grupo?
-ERROR_NO_SONGS=Sin canciones
-ERROR_NO_PLUGINS=Sin plugins
-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 \ No newline at end of file
+[Text]
+OPTION_VALUE_CATALAN=Catalan
+OPTION_VALUE_CROATIAN=Croatian
+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_ITALIAN=Italian
+OPTION_VALUE_JAPANESE=Japanese
+OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+OPTION_VALUE_PORTUGUESE=Portuguese
+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=Cargando...
+
+SING_CHOOSE_MODE=elige modo
+SING_SING=Cantar
+SING_SING_DESC=Juego rápido: cantar solo o dueto
+
+SING_MULTI=Grupo
+SING_MULTI_DESC=cantar en modo grupo
+
+SING_TOOLS=Utilidades
+
+SING_STATS=Estadísticas
+SING_STATS_DESC=Ver las 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=Temas
+SING_OPTIONS_RECORD=Grabar
+SING_OPTIONS_ADVANCED=Avanzado
+SING_OPTIONS_EXIT=Atrás
+
+SING_OPTIONS_GAME_WHEREAMI=Opciones del juego
+SING_OPTIONS_GAME_DESC=Ajustes 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=Opciones gráficas
+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 vídeo
+
+SING_OPTIONS_SOUND_WHEREAMI=Opciones de sonido
+SING_OPTIONS_SOUND_DESC=Opciones de sonido
+SING_OPTIONS_SOUND_VOICEPASSTHROUGH=Playback del micrófono
+SING_OPTIONS_SOUND_BACKGROUNDMUSIC=Música de fondo
+SING_OPTIONS_SOUND_MIC_BOOST=Potenciar micrófono
+SING_OPTIONS_SOUND_CLICK_ASSIST=Asistente de notas
+SING_OPTIONS_SOUND_BEAT_CLICK=Asistente de golpes
+SING_OPTIONS_SOUND_THRESHOLD=Umbral
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Modo dos jugadores
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Volumen de avance
+SING_OPTIONS_SOUND_PREVIEWFADING=Desvanecimiento
+
+SING_OPTIONS_LYRICS_WHEREAMI=Opciones de letras
+SING_OPTIONS_LYRICS_DESC=Opciones de letras
+SING_OPTIONS_LYRICS_FONT=Tipo de letra
+SING_OPTIONS_LYRICS_EFFECT=Efecto
+SING_OPTIONS_LYRICS_SOLMIZATION=Solfeo
+SING_OPTIONS_LYRICS_NOTELINES=Pentagramas
+
+SING_OPTIONS_THEMES_WHEREAMI=Opciones de temas
+SING_OPTIONS_THEMES_DESC=Opciones de temas
+SING_OPTIONS_THEMES_THEME=Tema
+SING_OPTIONS_THEMES_SKIN=Piel
+SING_OPTIONS_THEMES_COLOR=Color
+
+SING_OPTIONS_RECORD_WHEREAMI=Opciones de grabación
+SING_OPTIONS_RECORD_DESC=Opciones de micrófono
+SING_OPTIONS_RECORD_CARD=Tarjeta 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=Preguntas de seguridad
+SING_OPTIONS_ADVANCED_LINEBONUS=Bonus de línea
+SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG=
+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=Nombre(s) de jugador(es)
+SING_PLAYER_WHEREAMI=Nombre(s) de jugador(es)
+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=Selección de 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 de canciones
+SING_SONGS_IN_CAT=Canciones
+PLAYLIST_CATTEXT=Lista de canciones: %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=Puntuación
+SONG_SCORE_WHEREAMI=Puntuación
+
+SING_SCORE_TONE_DEAF=Sin oído
+SING_SCORE_AMATEUR=Aficionado
+SING_SCORE_WANNABE=Aspirante
+SING_SCORE_HOPEFUL=Promesa
+SING_SCORE_RISING_STAR=Prometes
+SING_SCORE_LEAD_SINGER=Artista
+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=switch difficulty
+
+POPUP_PERFECT=¡Perfecto!
+POPUP_AWESOME=¡Asombroso!
+POPUP_GREAT=¡Genial!
+POPUP_GOOD=¡Bien!
+POPUP_NOTBAD=¡No está 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=Escoger 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=Añadir canción
+SONG_MENU_PLAYLIST_DEL=Borrar canción
+
+SONG_MENU_NAME_PLAYLIST_ADD=Añadir canción
+SONG_MENU_PLAYLIST_ADD_NEW=A nueva lista de canciones
+SONG_MENU_PLAYLIST_ADD_EXISTING=A lista existente
+SONG_MENU_PLAYLIST_NOEXISTING=No hay listas de canciones
+
+SONG_MENU_NAME_PLAYLIST_NEW=Nueva lista 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 lista
+SONG_MENU_PLAYLIST_LOAD=Abrir
+SONG_MENU_PLAYLIST_DELCURRENT=Borrar la lista actual
+
+SONG_MENU_NAME_PLAYLIST_DEL=¿Borrar la lista?
+
+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 canción(es) encontrada(s)
+SONG_JUMPTO_NOSONGSFOUND=No se han encontrado canciones
+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=Todas las canciones
+PARTY_PLAYLIST_CATEGORY=Carpeta
+PARTY_PLAYLIST_PLAYLIST=Lista de canciones
+PARTY_ROUNDS=Rondas
+PARTY_TEAMS=Equipos
+PARTY_TEAMS_PLAYER1=Miembros del equipo 1
+PARTY_TEAMS_PLAYER2=Miembros del equipo 2
+PARTY_TEAMS_PLAYER3=Miembros del equipo 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_PLAYER_LEGEND_CONTINUE=Empezar
+
+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=Puntuación de la última ronda
+PARTY_SCORE_WHEREAMI=Puntuación
+
+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ó!
+
+PLUGIN_HDL_NAME=Mantén la línea
+PLUGIN_HDL_DESC=No bajes tu puntuación de lo indicado en pantalla
+
+PLUGIN_UNTIL5000_NAME=Hasta 5000
+PLUGIN_UNTIL5000_DESC=Gana quien obtenga 5000 puntos.
+
+PLUGIN_DUELL_NAME=Duelo
+PLUGIN_DUELL_DESC=Canta un duelo hasta 10000 puntos.
+
+PLUGIN_TEAMDUELL_NAME=Duelo de equipos
+PLUGIN_TEAMDUELL_DESC=¡Pasa el micro!
+
+PLUGIN_BLIND_NAME=Modo a ciegas
+PLUGIN_BLIND_DESC=Duelo sin ver las notas.
+
+STAT_MAIN=Estadísticas
+STAT_MAIN_DESC=General
+STAT_MAIN_WHEREAMI=Estadísticas
+
+STAT_OVERVIEW_INTRO=%0:s Estadísticas. \n Último reinicio el %2:.2d.%1:.2d.%3:d
+STAT_OVERVIEW_SONG=%0:d Canciones(%3:d con vídeo), de las cuales %1:d han sido cantadas y %2:d aún no.\n La canción más popular es %5:s de %4:s.
+STAT_OVERVIEW_PLAYER=Hay registrados %0:d jugador(es) diferente(s).\n El mejor es %1:s con una puntuación promedio de %2:d puntos.\n %3:s ha hecho la mejor puntuación con %4:d puntos.
+
+STAT_FORMAT_DATE=%1:.2d.%0:.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 de %3:d entradas)
+
+STAT_DESC_SCORES=Mejores puntuaciones
+STAT_DESC_SCORES_REVERSED=Peores puntuaciones
+STAT_FORMAT_SCORES=%0:s - %1:d [%2:s] %5:s \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Mejores cantantes
+STAT_DESC_SINGERS_REVERSED=Peores cantantes
+STAT_FORMAT_SINGERS=%0:s \n Puntuación media: %1:d
+
+STAT_DESC_SONGS=Canciones más populares
+STAT_DESC_SONGS_REVERSED=Canciones menos populares
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx veces cantada
+
+STAT_DESC_BANDS=Grupos más populares
+STAT_DESC_BANDS_REVERSED=Grupos menos populares
+STAT_FORMAT_BANDS=%0:s \n %1:dx veces cantado
+
+MSG_ERROR_TITLE=Error
+MSG_QUESTION_TITLE=Pregunta
+MSG_QUIT_USDX=¿Seguro que quieres salir?
+MSG_END_PARTY=¿Seguro que quieres salir del modo grupo?
+ERROR_NO_SONGS=Sin canciones
+ERROR_NO_PLUGINS=Sin plugins
+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 \ No newline at end of file
diff --git a/cmake/game/languages/Swedish.ini b/cmake/game/languages/Swedish.ini
index 5fa5b990..429080ef 100644
--- a/cmake/game/languages/Swedish.ini
+++ b/cmake/game/languages/Swedish.ini
@@ -1,381 +1,400 @@
-[Text]
-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_BALCK=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=Laddar...
-
-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=Fullskärm
-SING_OPTIONS_GRAPHICS_DEPTH=Färgdjup
-SING_OPTIONS_GRAPHICS_VISUALIZER=Visualisering
-SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Oscilloskåp
-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=Skin
-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=Laddningsanimering
-SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Säkerhetsfråga
-SING_OPTIONS_ADVANCED_LINEBONUS=Radbonus
-SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG=
-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 midifil
-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årighetsnivå
-SING_DIFFICULTY_WHEREAMI=Svårighetsnivå
-SING_DIFFICULTY_CONTINUE=till låtval
-SING_EASY=Lätt
-SING_MEDIUM=Normal
-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=toner
-SING_GOLDEN_NOTES=gyllene toner
-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
-
-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=avskyvärt!
-
-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 en mod
-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_ROUNDS=Omgångar
-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
-PARTY_PLAYER_LEGEND_CONTINUE=starta partyspel
-
-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!
-
-PLUGIN_HDL_NAME=Håll god ton
-PLUGIN_HDL_DESC=Bli inte sämre än vad markeringen på omdömesmätaren visar.
-PLUGIN_UNTIL5000_NAME=Till 5000
-PLUGIN_UNTIL5000_DESC=Den som först får 5000 poäng vinner matchen.
-
-PLUGIN_DUELL_NAME=Duell
-PLUGIN_DUELL_DESC=Sjung en duett till 10000 poäng.
-
-PLUGIN_TEAMDUELL_NAME=Lagduell
-PLUGIN_TEAMDUELL_DESC=Skicka micken!
-
-PLUGIN_BLIND_NAME=Blindläge
-PLUGIN_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_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] \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
-
-MSG_ERROR_TITLE=Fel
-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
-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 \ No newline at end of file
+[Text]
+OPTION_VALUE_CATALAN=Catalan
+OPTION_VALUE_CROATIAN=Croatian
+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_ITALIAN=Italian
+OPTION_VALUE_JAPANESE=Japanese
+OPTION_VALUE_LUXEMBOURGISH=Luxembourgish
+OPTION_VALUE_PORTUGUESE=Portuguese
+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=Laddar...
+
+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=Fullskärm
+SING_OPTIONS_GRAPHICS_DEPTH=Färgdjup
+SING_OPTIONS_GRAPHICS_VISUALIZER=Visualisering
+SING_OPTIONS_GRAPHICS_OSCILLOSCOPE=Oscilloskåp
+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=Skin
+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=Laddningsanimering
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Säkerhetsfråga
+SING_OPTIONS_ADVANCED_LINEBONUS=Radbonus
+SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG=
+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 midifil
+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årighetsnivå
+SING_DIFFICULTY_WHEREAMI=Svårighetsnivå
+SING_DIFFICULTY_CONTINUE=till låtval
+SING_EASY=Lätt
+SING_MEDIUM=Normal
+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=toner
+SING_GOLDEN_NOTES=gyllene toner
+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=switch difficulty
+
+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=avskyvärt!
+
+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 en mod
+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_ROUNDS=Omgångar
+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
+PARTY_PLAYER_LEGEND_CONTINUE=starta partyspel
+
+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!
+
+PLUGIN_HDL_NAME=HÃ¥ll god ton
+PLUGIN_HDL_DESC=Bli inte sämre än vad markeringen på omdömesmätaren visar.
+PLUGIN_UNTIL5000_NAME=Till 5000
+PLUGIN_UNTIL5000_DESC=Den som först får 5000 poäng vinner matchen.
+
+PLUGIN_DUELL_NAME=Duell
+PLUGIN_DUELL_DESC=Sjung en duett till 10000 poäng.
+
+PLUGIN_TEAMDUELL_NAME=Lagduell
+PLUGIN_TEAMDUELL_DESC=Skicka micken!
+
+PLUGIN_BLIND_NAME=Blindläge
+PLUGIN_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
+
+MSG_ERROR_TITLE=Fel
+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
+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 \ No newline at end of file
diff --git a/cmake/game/languages/convert.sh b/cmake/game/languages/convert.sh
new file mode 100755
index 00000000..328efcda
--- /dev/null
+++ b/cmake/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/cmake/game/languages/old/Catalan.ini b/cmake/game/languages/old/Catalan.ini
deleted file mode 100644
index 71454112..00000000
--- a/cmake/game/languages/old/Catalan.ini
+++ /dev/null
@@ -1,298 +0,0 @@
-[Text]
-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=Resoluciò
-SING_OPTIONS_GRAPHICS_FULLSCREEN=Pantalla complerta
-SING_OPTIONS_GRAPHICS_DEPTH=Profunditat
-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_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_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_COUNT_HOW_OFTEN_SUNG=Quantes vegades cantada
-SING_OPTIONS_ADVANCED_ONSONGCLICK=després de triar cançó
-SING_OPTIONS_ADVANCED_PARTYPOPUP=Menú Automàtic de festa
-
-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=Aficionat
-SING_SCORE_RISING_STAR=Futura estrella
-SING_SCORE_LEAD_SINGER=Bon cantant
-SING_SCORE_HIT_ARTIST=Líder de grup
-SING_SCORE_SUPERSTAR=Super estrella
-SING_SCORE_ULTRASTAR=Ultra estrella
-
-SING_TOP_5_CHARTS=millors 5 jugadors
-SING_TOP_5_CHARTS_WHEREAMI=millors 5
-SING_TOP_5_CHARTS_CONTINUE=a selecció de cançó
-
-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_ROUNDS=Rondes
-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
-PARTY_PLAYER_LEGEND_CONTINUE=iniciar festa
-
-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!
-
-PLUGIN_HDL_NAME=Aguantar la línia
-PLUGIN_HDL_DESC=No baixis de la fletxa a la barra de qualitat
-
-PLUGIN_UNTIL5000_NAME=Fins a 5000
-PLUGIN_UNTIL5000_DESC=El primer a arribar a 5000 punts guanya
-
-PLUGIN_DUELL_NAME=Duel
-PLUGIN_DUELL_DESC=Cantar un duela fins a 10000 punts
-
-PLUGIN_BLIND_NAME=Mode cec
-PLUGIN_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_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] \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
-
-MSG_ERROR_TITLE=Error
-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
-ERROR_CORRUPT_SONG=No es poden carregar les cançons \ No newline at end of file
diff --git a/cmake/game/languages/old/Danish.ini b/cmake/game/languages/old/Danish.ini
index a9871a65..39d0379d 100644
--- a/cmake/game/languages/old/Danish.ini
+++ b/cmake/game/languages/old/Danish.ini
@@ -1,297 +1,297 @@
-[Text]
-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
-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
-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
-
-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_COUNT_HOW_OFTEN_SUNG=
-SING_OPTIONS_ADVANCED_ONSONGCLICK=Efter sang valg
-SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto Festmodus
-
-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!
-SING_SCORE_RISING_STAR=Aspirende Stjerne
-SING_SCORE_LEAD_SINGER=Forsanger
-SING_SCORE_HIT_ARTIST=Etableret Stjerne
-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
-
-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_ROUNDS=Runder
-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
-PARTY_PLAYER_LEGEND_CONTINUE=Start Fest Spil
-
-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!
-
-PLUGIN_HDL_NAME=Hold Linien
-PLUGIN_HDL_DESC=Få ikke værrer end pilen på skalaen peger på
-
-PLUGIN_UNTIL5000_NAME=Until 5000
-PLUGIN_UNTIL5000_DESC=Hvem får 5000 point først vinder the kampen.
-
-PLUGIN_DUELL_NAME=Duell
-PLUGIN_DUELL_DESC=Syng en duel intil 10000 point.
-
-PLUGIN_BLIND_NAME=Blind Modus
-PLUGIN_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.
-
-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
-
-MSG_ERROR_TITLE=Fejl
-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
+[Text]
+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
+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
+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
+
+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_COUNT_HOW_OFTEN_SUNG=
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Efter sang valg
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto Festmodus
+
+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!
+SING_SCORE_RISING_STAR=Aspirende Stjerne
+SING_SCORE_LEAD_SINGER=Forsanger
+SING_SCORE_HIT_ARTIST=Etableret Stjerne
+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
+
+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_ROUNDS=Runder
+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
+PARTY_PLAYER_LEGEND_CONTINUE=Start Fest Spil
+
+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!
+
+PLUGIN_HDL_NAME=Hold Linien
+PLUGIN_HDL_DESC=Få ikke værrer end pilen på skalaen peger på
+
+PLUGIN_UNTIL5000_NAME=Until 5000
+PLUGIN_UNTIL5000_DESC=Hvem får 5000 point først vinder the kampen.
+
+PLUGIN_DUELL_NAME=Duell
+PLUGIN_DUELL_DESC=Syng en duel intil 10000 point.
+
+PLUGIN_BLIND_NAME=Blind Modus
+PLUGIN_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.
+
+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
+
+MSG_ERROR_TITLE=Fejl
+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
ERROR_CORRUPT_SONG=Sangen kunne ikke hentes. \ No newline at end of file
diff --git a/cmake/game/languages/old/French.ini b/cmake/game/languages/old/French.ini
index 41403934..8a841fab 100644
--- a/cmake/game/languages/old/French.ini
+++ b/cmake/game/languages/old/French.ini
@@ -1,310 +1,310 @@
-[Text]
-SING_LOADING=Chargement...
-
-SING_CHOOSE_MODE=Choisir un mode
-SING_SING=Solo
-SING_SING_DESC=Chanter
-
-SING_MULTI=Multi
-SING_MULTI_DESC=Chanter à plusieurs
-
-SING_TOOLS=Outils
-
-SING_STATS=Statistiques
-SING_STATS_DESC=Consulter les statistiques
-
-SING_EDITOR=Éditeur
-SING_EDITOR_DESC=Créer vos propre chansons
-
-SING_GAME_OPTIONS=Options
-SING_GAME_OPTIONS_DESC=Modifier les paramètres du jeu
-
-SING_EXIT=Quitter
-SING_EXIT_DESC=Quitter le jeu
-
-SING_OPTIONS=Options
-SING_OPTIONS_DESC=Changer 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 de jeu
-SING_OPTIONS_GAME_DESC=Options générales de jeu
-SING_OPTIONS_GAME_PLAYERS=Joueurs
-SING_OPTIONS_GAME_DIFFICULTY=Difficulté
-SING_OPTIONS_GAME_LANGUAGE=Langue
-SING_OPTIONS_GAME_TABS=Dossier
-SING_OPTIONS_GAME_SORTING=Tri
-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=Couleurs
-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 de son
-SING_OPTIONS_SOUND_DESC=Paramètres de son
-SING_OPTIONS_SOUND_MIC_BOOST=Amplif. mic.
-SING_OPTIONS_SOUND_CLICK_ASSIST=Clics d'aide
-SING_OPTIONS_SOUND_BEAT_CLICK=Métronome
-SING_OPTIONS_SOUND_THRESHOLD=Suppression bruit
-SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Mode 2 joueurs
-SING_OPTIONS_SOUND_PREVIEWVOLUME=Prévis. volume
-SING_OPTIONS_SOUND_PREVIEWFADING=Prévis. baisse
-
-SING_OPTIONS_LYRICS_WHEREAMI=Options de paroles
-SING_OPTIONS_LYRICS_DESC=Paramètres de paroles
-SING_OPTIONS_LYRICS_FONT=Caractères
-SING_OPTIONS_LYRICS_EFFECT=Effet
-SING_OPTIONS_LYRICS_SOLMIZATION=Afficher gamme
-
-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 sup.
-SING_OPTIONS_ADVANCED_LINEBONUS=Bonus de phrases
-SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG=Compteur de titres chantés
-SING_OPTIONS_ADVANCED_ONSONGCLICK=Choix ap. chanson
-SING_OPTIONS_ADVANCED_PARTYPOPUP=Menu multi auto
-
-SING_EDIT=Éditeur
-SING_EDIT_MENU_DESCRIPTION=Créer vos propre chansons
-
-SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Importer texte à une dossier de midi file
-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=Valider
-SING_LEGEND_ESC=Retour
-
-SING_PLAYER_DESC=Entrer le nom du joueur
-SING_PLAYER_WHEREAMI=Nom du joueur
-SING_PLAYER_ENTER_NAME=Modifier
-
-SING_DIFFICULTY_DESC=Choisir 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=Choisir une chanson
-SING_SONG_SELECTION_WHEREAMI=Sélection du titre
-SING_SONG_SELECTION_GOTO=Atteindre
-SING_SONG_SELECTION=Choix de chanson
-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
-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_RISING_STAR=Star en herbe
-SING_SCORE_LEAD_SINGER=Artiste
-SING_SCORE_HIT_ARTIST=Révélation
-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
-
-POPUP_PERFECT=Parfait !
-POPUP_AWESOME=Cool !
-POPUP_GREAT=Grandiose !
-POPUP_GOOD=Bien !
-POPUP_NOTBAD=O.K. !
-POPUP_BAD=Pas terrible !
-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 joueur
-SONG_MENU_EDIT=Éditeur
-SONG_MENU_MODI=Chanter un mode
-SONG_MENU_CANCEL=Annuler
-
-SONG_MENU_NAME_PLAYLIST=Menu
-SONG_MENU_PLAYLIST_ADD=Ajouter une chanson
-SONG_MENU_PLAYLIST_DEL=Supprimer la chanson
-
-SONG_MENU_NAME_PLAYLIST_ADD=Ajouter chanson
-SONG_MENU_PLAYLIST_ADD_NEW=À la nouvelle playlist
-SONG_MENU_PLAYLIST_ADD_EXISTING=Ajouter à la playlist
-SONG_MENU_PLAYLIST_NOEXISTING=Pas de playlist
-
-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_DEL=Supprimer la playlist ?
-
-SONG_MENU_NAME_PLAYLIST_LOAD=Ouvrir une playlist
-SONG_MENU_PLAYLIST_LOAD=Ouvrir
-SONG_MENU_PLAYLIST_DELCURRENT=Supprimer la playlist actuel
-
-SONG_MENU_NAME_PARTY_MAIN=Menu
-SONG_MENU_JOKER=Joker
-
-SONG_MENU_NAME_PARTY_JOKER=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=Entrer le texte à rechercher
-SONG_JUMPTO_CATTEXT=Recherche: %s
-
-PARTY_MODE=Mode multi
-PARTY_DIFFICULTY=Difficulté
-PARTY_PLAYLIST=Playlist
-PARTY_PLAYLIST_ALL=Toutes les chansons
-PARTY_PLAYLIST_CATEGORY=Dossier
-PARTY_PLAYLIST_PLAYLIST=Playlist
-PARTY_ROUNDS=Nbre manches
-PARTY_TEAMS=Nbre équipes
-PARTY_TEAMS_PLAYER1=Joueur(s) équipe 1
-PARTY_TEAMS_PLAYER2=Joueur(s) équipe 2
-PARTY_TEAMS_PLAYER3=Joueur(s) équipe 3
-
-PARTY_LEGEND_CONTINUE=Suivant
-
-PARTY_OPTIONS_DESC=Paramètres du mode multi
-PARTY_OPTIONS_WHEREAMI=Options du mode multi
-
-PARTY_PLAYER_DESC=Entrer le nom des équipes et des joueurs
-PARTY_PLAYER_WHEREAMI=Mode multi: Equipes
-PARTY_PLAYER_ENTER_NAME=Modifier
-PARTY_PLAYER_LEGEND_CONTINUE=Valider
-
-PARTY_ROUND_DESC=Joueurs suivants à vos micros !
-PARTY_ROUND_WHEREAMI=Mode multi: Manche suivante
-PARTY_ROUND_LEGEND_CONTINUE=Commencer
-
-PARTY_SONG_WHEREAMI=Mode multi: Choix de la chanson
-PARTY_SONG_LEGEND_CONTINUE=Chanter
-PARTY_SONG_MENU=Menu
-
-PARTY_SCORE_DESC=Score de la manche
-PARTY_SCORE_WHEREAMI=Mode multi: Score
-
-PARTY_WIN_DESC=Gagnant de la partie
-PARTY_WIN_WHEREAMI=Mode multi: 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 !
-
-PLUGIN_HDL_NAME=Tiens la barre
-PLUGIN_HDL_DESC=Maintiens la jauge dans le secteur indiqué
-
-PLUGIN_UNTIL5000_NAME=A 5000
-PLUGIN_UNTIL5000_DESC=Le 1er qui atteint 5000 points remporte la manche
-
-PLUGIN_DUELL_NAME=Duel
-PLUGIN_DUELL_DESC=Le meilleur score remporte la manche
-
-PLUGIN_BLIND_NAME=A l'aveugle
-PLUGIN_BLIND_DESC=Obtiens le meilleur score sans regarder l'écran.
-
-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=%0:d chansons (%3:d avec vidéo)\n%1:d ont déjà été chantées une fois, %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 Meilleur score, %4:d, atteint par %3:s.
-
-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=Score
-STAT_DESC_SCORES_REVERSED=Pires scores
-STAT_FORMAT_SCORES=%0:s - %1:d [%2:s] \n (%3:s - %4:s)
-
-STAT_DESC_SINGERS=Chanteurs
-STAT_DESC_SINGERS_REVERSED=Pires chanteurs
-STAT_FORMAT_SINGERS=%0:s \n Score moyen: %1:d
-
-STAT_DESC_SONGS=Chansons
-STAT_DESC_SONGS_REVERSED=Chansons impopulaires
-STAT_FORMAT_SONGS=%0:s - %1:s \n Chanté %2:dx
-
-STAT_DESC_BANDS=Artistes
-STAT_DESC_BANDS_REVERSED=Artistes impopulaires
-STAT_FORMAT_BANDS=%0:s \n Chansons chantées: %1:d
-
-MSG_ERROR_TITLE=Erreur
-MSG_QUESTION_TITLE=Confirmation
-MSG_QUIT_USDX=Quitter le jeu ?
-MSG_END_PARTY=Quitter la partie ?
-ERROR_NO_SONGS=Aucune chanson.
-ERROR_NO_PLUGINS=Aucun plugin.
+[Text]
+SING_LOADING=Chargement...
+
+SING_CHOOSE_MODE=Choisir un mode
+SING_SING=Solo
+SING_SING_DESC=Chanter
+
+SING_MULTI=Multi
+SING_MULTI_DESC=Chanter à plusieurs
+
+SING_TOOLS=Outils
+
+SING_STATS=Statistiques
+SING_STATS_DESC=Consulter les statistiques
+
+SING_EDITOR=Éditeur
+SING_EDITOR_DESC=Créer vos propre chansons
+
+SING_GAME_OPTIONS=Options
+SING_GAME_OPTIONS_DESC=Modifier les paramètres du jeu
+
+SING_EXIT=Quitter
+SING_EXIT_DESC=Quitter le jeu
+
+SING_OPTIONS=Options
+SING_OPTIONS_DESC=Changer 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 de jeu
+SING_OPTIONS_GAME_DESC=Options générales de jeu
+SING_OPTIONS_GAME_PLAYERS=Joueurs
+SING_OPTIONS_GAME_DIFFICULTY=Difficulté
+SING_OPTIONS_GAME_LANGUAGE=Langue
+SING_OPTIONS_GAME_TABS=Dossier
+SING_OPTIONS_GAME_SORTING=Tri
+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=Couleurs
+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 de son
+SING_OPTIONS_SOUND_DESC=Paramètres de son
+SING_OPTIONS_SOUND_MIC_BOOST=Amplif. mic.
+SING_OPTIONS_SOUND_CLICK_ASSIST=Clics d'aide
+SING_OPTIONS_SOUND_BEAT_CLICK=Métronome
+SING_OPTIONS_SOUND_THRESHOLD=Suppression bruit
+SING_OPTIONS_SOUND_TWO_PLAYERS_MODE=Mode 2 joueurs
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Prévis. volume
+SING_OPTIONS_SOUND_PREVIEWFADING=Prévis. baisse
+
+SING_OPTIONS_LYRICS_WHEREAMI=Options de paroles
+SING_OPTIONS_LYRICS_DESC=Paramètres de paroles
+SING_OPTIONS_LYRICS_FONT=Caractères
+SING_OPTIONS_LYRICS_EFFECT=Effet
+SING_OPTIONS_LYRICS_SOLMIZATION=Afficher gamme
+
+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 sup.
+SING_OPTIONS_ADVANCED_LINEBONUS=Bonus de phrases
+SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG=Compteur de titres chantés
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Choix ap. chanson
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Menu multi auto
+
+SING_EDIT=Éditeur
+SING_EDIT_MENU_DESCRIPTION=Créer vos propre chansons
+
+SING_EDIT_BUTTON_DESCRIPTION_CONVERT=Importer texte à une dossier de midi file
+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=Valider
+SING_LEGEND_ESC=Retour
+
+SING_PLAYER_DESC=Entrer le nom du joueur
+SING_PLAYER_WHEREAMI=Nom du joueur
+SING_PLAYER_ENTER_NAME=Modifier
+
+SING_DIFFICULTY_DESC=Choisir 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=Choisir une chanson
+SING_SONG_SELECTION_WHEREAMI=Sélection du titre
+SING_SONG_SELECTION_GOTO=Atteindre
+SING_SONG_SELECTION=Choix de chanson
+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
+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_RISING_STAR=Star en herbe
+SING_SCORE_LEAD_SINGER=Artiste
+SING_SCORE_HIT_ARTIST=Révélation
+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
+
+POPUP_PERFECT=Parfait !
+POPUP_AWESOME=Cool !
+POPUP_GREAT=Grandiose !
+POPUP_GOOD=Bien !
+POPUP_NOTBAD=O.K. !
+POPUP_BAD=Pas terrible !
+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 joueur
+SONG_MENU_EDIT=Éditeur
+SONG_MENU_MODI=Chanter un mode
+SONG_MENU_CANCEL=Annuler
+
+SONG_MENU_NAME_PLAYLIST=Menu
+SONG_MENU_PLAYLIST_ADD=Ajouter une chanson
+SONG_MENU_PLAYLIST_DEL=Supprimer la chanson
+
+SONG_MENU_NAME_PLAYLIST_ADD=Ajouter chanson
+SONG_MENU_PLAYLIST_ADD_NEW=À la nouvelle playlist
+SONG_MENU_PLAYLIST_ADD_EXISTING=Ajouter à la playlist
+SONG_MENU_PLAYLIST_NOEXISTING=Pas de playlist
+
+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_DEL=Supprimer la playlist ?
+
+SONG_MENU_NAME_PLAYLIST_LOAD=Ouvrir une playlist
+SONG_MENU_PLAYLIST_LOAD=Ouvrir
+SONG_MENU_PLAYLIST_DELCURRENT=Supprimer la playlist actuel
+
+SONG_MENU_NAME_PARTY_MAIN=Menu
+SONG_MENU_JOKER=Joker
+
+SONG_MENU_NAME_PARTY_JOKER=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=Entrer le texte à rechercher
+SONG_JUMPTO_CATTEXT=Recherche: %s
+
+PARTY_MODE=Mode multi
+PARTY_DIFFICULTY=Difficulté
+PARTY_PLAYLIST=Playlist
+PARTY_PLAYLIST_ALL=Toutes les chansons
+PARTY_PLAYLIST_CATEGORY=Dossier
+PARTY_PLAYLIST_PLAYLIST=Playlist
+PARTY_ROUNDS=Nbre manches
+PARTY_TEAMS=Nbre équipes
+PARTY_TEAMS_PLAYER1=Joueur(s) équipe 1
+PARTY_TEAMS_PLAYER2=Joueur(s) équipe 2
+PARTY_TEAMS_PLAYER3=Joueur(s) équipe 3
+
+PARTY_LEGEND_CONTINUE=Suivant
+
+PARTY_OPTIONS_DESC=Paramètres du mode multi
+PARTY_OPTIONS_WHEREAMI=Options du mode multi
+
+PARTY_PLAYER_DESC=Entrer le nom des équipes et des joueurs
+PARTY_PLAYER_WHEREAMI=Mode multi: Equipes
+PARTY_PLAYER_ENTER_NAME=Modifier
+PARTY_PLAYER_LEGEND_CONTINUE=Valider
+
+PARTY_ROUND_DESC=Joueurs suivants à vos micros !
+PARTY_ROUND_WHEREAMI=Mode multi: Manche suivante
+PARTY_ROUND_LEGEND_CONTINUE=Commencer
+
+PARTY_SONG_WHEREAMI=Mode multi: Choix de la chanson
+PARTY_SONG_LEGEND_CONTINUE=Chanter
+PARTY_SONG_MENU=Menu
+
+PARTY_SCORE_DESC=Score de la manche
+PARTY_SCORE_WHEREAMI=Mode multi: Score
+
+PARTY_WIN_DESC=Gagnant de la partie
+PARTY_WIN_WHEREAMI=Mode multi: 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 !
+
+PLUGIN_HDL_NAME=Tiens la barre
+PLUGIN_HDL_DESC=Maintiens la jauge dans le secteur indiqué
+
+PLUGIN_UNTIL5000_NAME=A 5000
+PLUGIN_UNTIL5000_DESC=Le 1er qui atteint 5000 points remporte la manche
+
+PLUGIN_DUELL_NAME=Duel
+PLUGIN_DUELL_DESC=Le meilleur score remporte la manche
+
+PLUGIN_BLIND_NAME=A l'aveugle
+PLUGIN_BLIND_DESC=Obtiens le meilleur score sans regarder l'écran.
+
+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=%0:d chansons (%3:d avec vidéo)\n%1:d ont déjà été chantées une fois, %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 Meilleur score, %4:d, atteint par %3:s.
+
+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=Score
+STAT_DESC_SCORES_REVERSED=Pires scores
+STAT_FORMAT_SCORES=%0:s - %1:d [%2:s] \n (%3:s - %4:s)
+
+STAT_DESC_SINGERS=Chanteurs
+STAT_DESC_SINGERS_REVERSED=Pires chanteurs
+STAT_FORMAT_SINGERS=%0:s \n Score moyen: %1:d
+
+STAT_DESC_SONGS=Chansons
+STAT_DESC_SONGS_REVERSED=Chansons impopulaires
+STAT_FORMAT_SONGS=%0:s - %1:s \n Chanté %2:dx
+
+STAT_DESC_BANDS=Artistes
+STAT_DESC_BANDS_REVERSED=Artistes impopulaires
+STAT_FORMAT_BANDS=%0:s \n Chansons chantées: %1:d
+
+MSG_ERROR_TITLE=Erreur
+MSG_QUESTION_TITLE=Confirmation
+MSG_QUIT_USDX=Quitter le jeu ?
+MSG_END_PARTY=Quitter la partie ?
+ERROR_NO_SONGS=Aucune chanson.
+ERROR_NO_PLUGINS=Aucun plugin.
ERROR_CORRUPT_SONG=Impossible de charger la chanson. \ No newline at end of file
diff --git a/cmake/game/languages/old/Norwegian.ini b/cmake/game/languages/old/Norwegian.ini
index c585691f..ddd97322 100644
--- a/cmake/game/languages/old/Norwegian.ini
+++ b/cmake/game/languages/old/Norwegian.ini
@@ -1,297 +1,297 @@
-[Text]
-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
-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
-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
-
-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_COUNT_HOW_OFTEN_SUNG=
-SING_OPTIONS_ADVANCED_ONSONGCLICK=Etter sang:
-SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto partymeny
-
-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
-SING_SCORE_RISING_STAR=Stigende stjerne
-SING_SCORE_LEAD_SINGER=Toppvokalist
-SING_SCORE_HIT_ARTIST=Hitartist
-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
-
-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_ROUNDS=Runder
-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
-PARTY_PLAYER_LEGEND_CONTINUE=start party-game
-
-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!
-
-PLUGIN_HDL_NAME=Hold linja
-PLUGIN_HDL_DESC=Ikke syng dårligere enn hva markøren på statuslinja viser.
-
-PLUGIN_UNTIL5000_NAME=Først til 5000
-PLUGIN_UNTIL5000_DESC=Førstemann til 5000 poeng vinner.
-
-PLUGIN_DUELL_NAME=Duell
-PLUGIN_DUELL_DESC=Syng en duell - først til 10000.
-
-PLUGIN_BLIND_NAME=Blindemodus
-PLUGIN_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.
-
-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
-
-MSG_ERROR_TITLE=Feil
-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
+[Text]
+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
+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
+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
+
+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_COUNT_HOW_OFTEN_SUNG=
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Etter sang:
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto partymeny
+
+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
+SING_SCORE_RISING_STAR=Stigende stjerne
+SING_SCORE_LEAD_SINGER=Toppvokalist
+SING_SCORE_HIT_ARTIST=Hitartist
+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
+
+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_ROUNDS=Runder
+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
+PARTY_PLAYER_LEGEND_CONTINUE=start party-game
+
+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!
+
+PLUGIN_HDL_NAME=Hold linja
+PLUGIN_HDL_DESC=Ikke syng dårligere enn hva markøren på statuslinja viser.
+
+PLUGIN_UNTIL5000_NAME=Først til 5000
+PLUGIN_UNTIL5000_DESC=Førstemann til 5000 poeng vinner.
+
+PLUGIN_DUELL_NAME=Duell
+PLUGIN_DUELL_DESC=Syng en duell - først til 10000.
+
+PLUGIN_BLIND_NAME=Blindemodus
+PLUGIN_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.
+
+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
+
+MSG_ERROR_TITLE=Feil
+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
ERROR_CORRUPT_SONG=Sangen kunne ikke lastes \ No newline at end of file
diff --git a/cmake/game/languages/old/Polish.ini b/cmake/game/languages/old/Polish.ini
index 51faa616..74ced1d0 100644
--- a/cmake/game/languages/old/Polish.ini
+++ b/cmake/game/languages/old/Polish.ini
@@ -1,304 +1,304 @@
-[Text]
-SING_LOADING=Wczytywanie...
-
-SING_CHOOSE_MODE=wybierz tryb
-SING_SING=œpiewaj
-SING_SING_DESC=œpiewaj solo lub w kilka osób
-
-SING_MULTI=impreza
-SING_MULTI_DESC=rozkrêæ imprezê!
-
-SING_TOOLS=narzêdzia
-
-SING_STATS=statystyki
-SING_STATS_DESC=zobacz statystyki
-
-SING_EDITOR=edytor
-SING_EDITOR_DESC=stwórz w³asne piosenki
-
-SING_GAME_OPTIONS=opcje
-SING_GAME_OPTIONS_DESC=zmieñ ustawienia
-
-SING_EXIT=wyjœcie
-SING_EXIT_DESC=wyjdŸ 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=s³owa
-SING_OPTIONS_THEMES=tematy
-SING_OPTIONS_RECORD=nagrywanie
-SING_OPTIONS_ADVANCED=zaawansowane
-SING_OPTIONS_EXIT=wstecz
-
-SING_OPTIONS_GAME_WHEREAMI=Opcje Gra
-SING_OPTIONS_GAME_DESC=opcje gry
-SING_OPTIONS_GAME_PLAYERS=IloϾ graczy
-SING_OPTIONS_GAME_DIFFICULTY=Poziom trudnoœci
-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 Grafika
-SING_OPTIONS_GAME_DESC=opcje gry
-SING_OPTIONS_GAME_PLAYERS=IloϾ graczy
-SING_OPTIONS_GAME_DIFFICULTY=Poziom trudnoœci
-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_LINEBONUS=Bonus Linii
-
-SING_OPTIONS_SOUND_WHEREAMI=Opcje DŸwiêk
-SING_OPTIONS_SOUND_DESC=opcje dŸwiêku
-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 S³owa
-SING_OPTIONS_LYRICS_DESC=opcje s³ów
-SING_OPTIONS_LYRICS_FONT=Czcionka
-SING_OPTIONS_LYRICS_EFFECT=Efekt
-SING_OPTIONS_LYRICS_SOLMIZATION=Solmizacja
-
-SING_OPTIONS_THEMES_WHEREAMI=Options Tematy
-SING_OPTIONS_THEMES_DESC=opcje tematów
-SING_OPTIONS_THEMES_THEME=Temat
-SING_OPTIONS_THEMES_SKIN=Skóra
-SING_OPTIONS_THEMES_COLOR=Kolor
-
-SING_OPTIONS_RECORD_WHEREAMI=Opcje Nagrywanie
-SING_OPTIONS_RECORD_DESC=opcje nagrywania
-SING_OPTIONS_RECORD_CARD=Karta dŸwiêkowa
-SING_OPTIONS_RECORD_INPUT=Wejœcie
-SING_OPTIONS_RECORD_CHANNEL=Kana³
-
-SING_OPTIONS_ADVANCED_WHEREAMI=Opcje Zaawansowane
-SING_OPTIONS_ADVANCED_DESC=ustawienia zaawansowane
-SING_OPTIONS_ADVANCED_EFFECTSING=Efekty specjalne
-SING_OPTIONS_ADVANCED_SCREENFADE=Przenikanie
-SING_OPTIONS_ADVANCED_LOADANIMATION=Animacja ³adowania
-SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Pytania przy wyjœciu
-SING_OPTIONS_ADVANCED_LINEBONUS=Bonus Linii
-SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG=Licznik
-SING_OPTIONS_ADVANCED_ONSONGCLICK=Po wyborze piosenki
-SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto Menu Imprezy
-
-SING_LEGEND_SELECT=wybierz
-SING_LEGEND_NAVIGATE=nawigacja
-SING_LEGEND_CONTINUE=dalej
-SING_LEGEND_ESC=wstecz
-
-SING_PLAYER_DESC=wprowadŸ imiê gracza
-SING_PLAYER_WHEREAMI=Imiê
-SING_PLAYER_ENTER_NAME=wpisz imiê
-
-SING_DIFFICULTY_DESC=wybierz poziom trudnoœci
-SING_DIFFICULTY_WHEREAMI=Poziom
-SING_DIFFICULTY_CONTINUE=do wyboru 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=Playlista: %s
-
-SING_TIME=CZAS
-SING_TOTAL=³¹cznie
-SING_MODE=œpiew solo
-SING_NOTES=nuty
-SING_GOLDEN_NOTES=z³ote nuty
-SING_PHRASE_BONUS=Bonus Linii
-
-SING_MENU=Menu G³ówne
-
-SONG_SCORE=wynik
-SONG_SCORE_WHEREAMI=Wynik
-
-SING_SCORE_TONE_DEAF=G³uche nuty
-SING_SCORE_AMATEUR=Amator
-SING_SCORE_RISING_STAR=Wschodz¹ca gwiazda
-SING_SCORE_LEAD_SINGER=Niez³y grajek
-SING_SCORE_HIT_ARTIST=Wielki Artysta
-SING_SCORE_SUPERSTAR=Supergwiazda
-SING_SCORE_ULTRASTAR=Ultrastar
-
-SING_TOP_5_CHARTS=lista 5 najlepszych
-SING_TOP_5_CHARTS_WHEREAMI=top 5
-SING_TOP_5_CHARTS_CONTINUE=do wyboru piosenki
-
-POPUP_PERFECT=idealnie!
-POPUP_AWESOME=niesamowicie!
-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=Jokera
-
-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=Wszystko
-PARTY_PLAYLIST_CATEGORY=Folder
-PARTY_PLAYLIST_PLAYLIST=Playlista
-PARTY_ROUNDS=Rundy
-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_PLAYER_LEGEND_CONTINUE=start!
-
-PARTY_ROUND_DESC=nastêpni 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
-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!
-
-PLUGIN_HDL_NAME=Trzymaj liniê
-PLUGIN_HDL_DESC=Œpiewaj lepiej ni¿ linia na wykresie.
-
-PLUGIN_UNTIL5000_NAME=Do 5000
-PLUGIN_UNTIL5000_DESC=Wygrywa ten, kto pierwszy uzyska 5000 punktów.
-
-PLUGIN_DUELL_NAME=Pojedynek
-PLUGIN_DUELL_DESC=Œpiewacie w pojedynku do 10000 punktów.
-
-PLUGIN_TEAMDUELL_NAME=Team Duell
-PLUGIN_TEAMDUELL_DESC=Pass The Mic!
-
-PLUGIN_BLIND_NAME=Œlepiec
-PLUGIN_BLIND_DESC=Pojedynek, w którym nie widzicie nut.
-
-STAT_MAIN=Statystyki
-STAT_MAIN_DESC=Ogólne
-STAT_MAIN_WHEREAMI=Statystyki
-
-STAT_OVERVIEW_INTRO=Statystyki dla: %0:d. \n Ostatnio resetowane: %2:.2d.%1:.2d.%3:d
-STAT_OVERVIEW_SONG=%0:d Piosenek (%3:d z filmem), z czego %1:d by³o granych a %2:d jeszcze nie.\n Najpopularniejsz¹ piosenk¹ jest %5:s z %4:s.
-STAT_OVERVIEW_PLAYER=Od ostatniego resetu:%0:d ró¿nych graczy.\n Najlepszym graczem jest %1:s ze œrednim wynikiem %2:d punktów.\n %3:s ustanowi³ rekord wynikiem %4:d punktów.
-
-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 \n (%2:d of %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] \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 piosenki
-STAT_DESC_SONGS_REVERSED=Najmniej popularne piosenki
-STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx œpiewane
-
-STAT_DESC_BANDS=Najpopularniejsi wykonawcy
-STAT_DESC_BANDS_REVERSED=Najmniej popularni wykonawcy
-STAT_FORMAT_BANDS=%0:s \n %1:dx œpiewani
-
-MSG_ERROR_TITLE=B³¹d
-MSG_QUESTION_TITLE=Pytanie
-MSG_QUIT_USDX=Na pewno chcesz wyjϾ?
-MSG_END_PARTY=Na pewno chcesz zakoñczyæ tryb imprezy?
-ERROR_NO_SONGS=Brak piosenek
-ERROR_NO_PLUGINS=Brak wtyczek
+[Text]
+SING_LOADING=Wczytywanie...
+
+SING_CHOOSE_MODE=wybierz tryb
+SING_SING=œpiewaj
+SING_SING_DESC=œpiewaj solo lub w kilka osób
+
+SING_MULTI=impreza
+SING_MULTI_DESC=rozkrêæ imprezê!
+
+SING_TOOLS=narzêdzia
+
+SING_STATS=statystyki
+SING_STATS_DESC=zobacz statystyki
+
+SING_EDITOR=edytor
+SING_EDITOR_DESC=stwórz w³asne piosenki
+
+SING_GAME_OPTIONS=opcje
+SING_GAME_OPTIONS_DESC=zmieñ ustawienia
+
+SING_EXIT=wyjœcie
+SING_EXIT_DESC=wyjdŸ 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=s³owa
+SING_OPTIONS_THEMES=tematy
+SING_OPTIONS_RECORD=nagrywanie
+SING_OPTIONS_ADVANCED=zaawansowane
+SING_OPTIONS_EXIT=wstecz
+
+SING_OPTIONS_GAME_WHEREAMI=Opcje Gra
+SING_OPTIONS_GAME_DESC=opcje gry
+SING_OPTIONS_GAME_PLAYERS=IloϾ graczy
+SING_OPTIONS_GAME_DIFFICULTY=Poziom trudnoœci
+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 Grafika
+SING_OPTIONS_GAME_DESC=opcje gry
+SING_OPTIONS_GAME_PLAYERS=IloϾ graczy
+SING_OPTIONS_GAME_DIFFICULTY=Poziom trudnoœci
+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_LINEBONUS=Bonus Linii
+
+SING_OPTIONS_SOUND_WHEREAMI=Opcje DŸwiêk
+SING_OPTIONS_SOUND_DESC=opcje dŸwiêku
+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 S³owa
+SING_OPTIONS_LYRICS_DESC=opcje s³ów
+SING_OPTIONS_LYRICS_FONT=Czcionka
+SING_OPTIONS_LYRICS_EFFECT=Efekt
+SING_OPTIONS_LYRICS_SOLMIZATION=Solmizacja
+
+SING_OPTIONS_THEMES_WHEREAMI=Options Tematy
+SING_OPTIONS_THEMES_DESC=opcje tematów
+SING_OPTIONS_THEMES_THEME=Temat
+SING_OPTIONS_THEMES_SKIN=Skóra
+SING_OPTIONS_THEMES_COLOR=Kolor
+
+SING_OPTIONS_RECORD_WHEREAMI=Opcje Nagrywanie
+SING_OPTIONS_RECORD_DESC=opcje nagrywania
+SING_OPTIONS_RECORD_CARD=Karta dŸwiêkowa
+SING_OPTIONS_RECORD_INPUT=Wejœcie
+SING_OPTIONS_RECORD_CHANNEL=Kana³
+
+SING_OPTIONS_ADVANCED_WHEREAMI=Opcje Zaawansowane
+SING_OPTIONS_ADVANCED_DESC=ustawienia zaawansowane
+SING_OPTIONS_ADVANCED_EFFECTSING=Efekty specjalne
+SING_OPTIONS_ADVANCED_SCREENFADE=Przenikanie
+SING_OPTIONS_ADVANCED_LOADANIMATION=Animacja ³adowania
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Pytania przy wyjœciu
+SING_OPTIONS_ADVANCED_LINEBONUS=Bonus Linii
+SING_OPTIONS_ADVANCED_COUNT_HOW_OFTEN_SUNG=Licznik
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Po wyborze piosenki
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto Menu Imprezy
+
+SING_LEGEND_SELECT=wybierz
+SING_LEGEND_NAVIGATE=nawigacja
+SING_LEGEND_CONTINUE=dalej
+SING_LEGEND_ESC=wstecz
+
+SING_PLAYER_DESC=wprowadŸ imiê gracza
+SING_PLAYER_WHEREAMI=Imiê
+SING_PLAYER_ENTER_NAME=wpisz imiê
+
+SING_DIFFICULTY_DESC=wybierz poziom trudnoœci
+SING_DIFFICULTY_WHEREAMI=Poziom
+SING_DIFFICULTY_CONTINUE=do wyboru 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=Playlista: %s
+
+SING_TIME=CZAS
+SING_TOTAL=³¹cznie
+SING_MODE=œpiew solo
+SING_NOTES=nuty
+SING_GOLDEN_NOTES=z³ote nuty
+SING_PHRASE_BONUS=Bonus Linii
+
+SING_MENU=Menu G³ówne
+
+SONG_SCORE=wynik
+SONG_SCORE_WHEREAMI=Wynik
+
+SING_SCORE_TONE_DEAF=G³uche nuty
+SING_SCORE_AMATEUR=Amator
+SING_SCORE_RISING_STAR=Wschodz¹ca gwiazda
+SING_SCORE_LEAD_SINGER=Niez³y grajek
+SING_SCORE_HIT_ARTIST=Wielki Artysta
+SING_SCORE_SUPERSTAR=Supergwiazda
+SING_SCORE_ULTRASTAR=Ultrastar
+
+SING_TOP_5_CHARTS=lista 5 najlepszych
+SING_TOP_5_CHARTS_WHEREAMI=top 5
+SING_TOP_5_CHARTS_CONTINUE=do wyboru piosenki
+
+POPUP_PERFECT=idealnie!
+POPUP_AWESOME=niesamowicie!
+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=Jokera
+
+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=Wszystko
+PARTY_PLAYLIST_CATEGORY=Folder
+PARTY_PLAYLIST_PLAYLIST=Playlista
+PARTY_ROUNDS=Rundy
+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_PLAYER_LEGEND_CONTINUE=start!
+
+PARTY_ROUND_DESC=nastêpni 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
+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!
+
+PLUGIN_HDL_NAME=Trzymaj liniê
+PLUGIN_HDL_DESC=Œpiewaj lepiej ni¿ linia na wykresie.
+
+PLUGIN_UNTIL5000_NAME=Do 5000
+PLUGIN_UNTIL5000_DESC=Wygrywa ten, kto pierwszy uzyska 5000 punktów.
+
+PLUGIN_DUELL_NAME=Pojedynek
+PLUGIN_DUELL_DESC=Œpiewacie w pojedynku do 10000 punktów.
+
+PLUGIN_TEAMDUELL_NAME=Team Duell
+PLUGIN_TEAMDUELL_DESC=Pass The Mic!
+
+PLUGIN_BLIND_NAME=Œlepiec
+PLUGIN_BLIND_DESC=Pojedynek, w którym nie widzicie nut.
+
+STAT_MAIN=Statystyki
+STAT_MAIN_DESC=Ogólne
+STAT_MAIN_WHEREAMI=Statystyki
+
+STAT_OVERVIEW_INTRO=Statystyki dla: %0:d. \n Ostatnio resetowane: %2:.2d.%1:.2d.%3:d
+STAT_OVERVIEW_SONG=%0:d Piosenek (%3:d z filmem), z czego %1:d by³o granych a %2:d jeszcze nie.\n Najpopularniejsz¹ piosenk¹ jest %5:s z %4:s.
+STAT_OVERVIEW_PLAYER=Od ostatniego resetu:%0:d ró¿nych graczy.\n Najlepszym graczem jest %1:s ze œrednim wynikiem %2:d punktów.\n %3:s ustanowi³ rekord wynikiem %4:d punktów.
+
+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 \n (%2:d of %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] \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 piosenki
+STAT_DESC_SONGS_REVERSED=Najmniej popularne piosenki
+STAT_FORMAT_SONGS=%0:s - %1:s \n %2:dx œpiewane
+
+STAT_DESC_BANDS=Najpopularniejsi wykonawcy
+STAT_DESC_BANDS_REVERSED=Najmniej popularni wykonawcy
+STAT_FORMAT_BANDS=%0:s \n %1:dx œpiewani
+
+MSG_ERROR_TITLE=B³¹d
+MSG_QUESTION_TITLE=Pytanie
+MSG_QUIT_USDX=Na pewno chcesz wyjϾ?
+MSG_END_PARTY=Na pewno chcesz zakoñczyæ tryb imprezy?
+ERROR_NO_SONGS=Brak piosenek
+ERROR_NO_PLUGINS=Brak wtyczek
ERROR_CORRUPT_SONG=Piosenka nie mog³a zostaæ za³adowana. \ No newline at end of file
diff --git a/cmake/game/languages/old/Serbian.ini b/cmake/game/languages/old/Serbian.ini
index b680eb44..1896c6de 100644
--- a/cmake/game/languages/old/Serbian.ini
+++ b/cmake/game/languages/old/Serbian.ini
@@ -1,298 +1,298 @@
-[Text]
-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
-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
-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
-
-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_COUNT_HOW_OFTEN_SUNG=
-SING_OPTIONS_ADVANCED_ONSONGCLICK=Posle Odabira Pesme
-SING_OPTIONS_ADVANCED_PARTYPOPUP=Automatski Timski Meni
-
-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
-SING_SCORE_RISING_STAR=Zvezda U Usponu
-SING_SCORE_LEAD_SINGER=Solista
-SING_SCORE_HIT_ARTIST=Hit Pevac
-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
-
-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_ROUNDS=Runde
-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
-PARTY_PLAYER_LEGEND_CONTINUE=zapocni timsku igru
-
-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!
-
-PLUGIN_HDL_NAME=Drzi liniju
-PLUGIN_HDL_DESC=Ne budi losiji nego sto ti strelica pokazuje.
-
-PLUGIN_UNTIL5000_NAME=Do 5000
-PLUGIN_UNTIL5000_DESC=Ko stigne prvi do 5000 poena pobedjuje.
-
-PLUGIN_DUELL_NAME=Duel
-PLUGIN_DUELL_DESC=Pevaj duel do 10000 poena.
-
-PLUGIN_BLIND_NAME=Slepi Mod
-PLUGIN_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.
-
-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
-
-MSG_ERROR_TITLE=Greska
-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
+[Text]
+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
+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
+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
+
+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_COUNT_HOW_OFTEN_SUNG=
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Posle Odabira Pesme
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Automatski Timski Meni
+
+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
+SING_SCORE_RISING_STAR=Zvezda U Usponu
+SING_SCORE_LEAD_SINGER=Solista
+SING_SCORE_HIT_ARTIST=Hit Pevac
+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
+
+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_ROUNDS=Runde
+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
+PARTY_PLAYER_LEGEND_CONTINUE=zapocni timsku igru
+
+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!
+
+PLUGIN_HDL_NAME=Drzi liniju
+PLUGIN_HDL_DESC=Ne budi losiji nego sto ti strelica pokazuje.
+
+PLUGIN_UNTIL5000_NAME=Do 5000
+PLUGIN_UNTIL5000_DESC=Ko stigne prvi do 5000 poena pobedjuje.
+
+PLUGIN_DUELL_NAME=Duel
+PLUGIN_DUELL_DESC=Pevaj duel do 10000 poena.
+
+PLUGIN_BLIND_NAME=Slepi Mod
+PLUGIN_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.
+
+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
+
+MSG_ERROR_TITLE=Greska
+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
ERROR_CORRUPT_SONG=Pesma se ne moze ucitati. \ No newline at end of file
diff --git a/cmake/game/languages/old/Slovak.ini b/cmake/game/languages/old/Slovak.ini
index 2e7ae87b..c7a7fb2e 100644
--- a/cmake/game/languages/old/Slovak.ini
+++ b/cmake/game/languages/old/Slovak.ini
@@ -1,301 +1,301 @@
-[Text]
-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
-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
-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
-
-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_COUNT_HOW_OFTEN_SUNG=
-SING_OPTIONS_ADVANCED_ONSONGCLICK=Po zvolení skladby
-SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto PartyMenu
-
-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
-SING_SCORE_RISING_STAR=Vychádzajúca hviezda
-SING_SCORE_LEAD_SINGER=Spevák
-SING_SCORE_HIT_ARTIST=Star
-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
-
-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_ROUNDS=Poèet kôl
-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á
-PARTY_PLAYER_LEGEND_CONTINUE=Pokraèova
-
-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
-
-PLUGIN_HDL_NAME=Superstar
-PLUGIN_HDL_DESC=nesmieš klesnú pod hranicu ukazovate¾a úspešnosti
-
-PLUGIN_UNTIL5000_NAME=Po 5000
-PLUGIN_UNTIL5000_DESC=kto prvý získa 5000 bodov sa stane víazom
-
-PLUGIN_DUELL_NAME=Duel
-PLUGIN_DUELL_DESC=spievaj, kým nedosiahneš 10000 bodov
-
-PLUGIN_TEAMDUELL_NAME=Duel Tímov
-PLUGIN_TEAMDUELL_DESC=každý hráè sa vystrieda za mikrofónom
-
-PLUGIN_BLIND_NAME=Slepý
-PLUGIN_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)
-
-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á
-
-MSG_ERROR_TITLE=Chyba
-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
-ERROR_CORRUPT_SONG=Skladbu sa nepodarilo nahra.
+[Text]
+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
+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
+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
+
+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_COUNT_HOW_OFTEN_SUNG=
+SING_OPTIONS_ADVANCED_ONSONGCLICK=Po zvolení skladby
+SING_OPTIONS_ADVANCED_PARTYPOPUP=Auto PartyMenu
+
+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
+SING_SCORE_RISING_STAR=Vychádzajúca hviezda
+SING_SCORE_LEAD_SINGER=Spevák
+SING_SCORE_HIT_ARTIST=Star
+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
+
+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_ROUNDS=Poèet kôl
+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á
+PARTY_PLAYER_LEGEND_CONTINUE=Pokraèova
+
+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
+
+PLUGIN_HDL_NAME=Superstar
+PLUGIN_HDL_DESC=nesmieš klesnú pod hranicu ukazovate¾a úspešnosti
+
+PLUGIN_UNTIL5000_NAME=Po 5000
+PLUGIN_UNTIL5000_DESC=kto prvý získa 5000 bodov sa stane víazom
+
+PLUGIN_DUELL_NAME=Duel
+PLUGIN_DUELL_DESC=spievaj, kým nedosiahneš 10000 bodov
+
+PLUGIN_TEAMDUELL_NAME=Duel Tímov
+PLUGIN_TEAMDUELL_DESC=každý hráè sa vystrieda za mikrofónom
+
+PLUGIN_BLIND_NAME=Slepý
+PLUGIN_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)
+
+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á
+
+MSG_ERROR_TITLE=Chyba
+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
+ERROR_CORRUPT_SONG=Skladbu sa nepodarilo nahra.
diff --git a/cmake/game/languages/old/Slovenian.ini b/cmake/game/languages/old/Slovenian.ini
index b1a76d4f..2fd50c9d 100644
--- a/cmake/game/languages/old/Slovenian.ini
+++ b/cmake/game/languages/old/Slovenian.ini
@@ -1,322 +1,322 @@
-[Text]
-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_COUNT_HOW_OFTEN_SUNG=
-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
-
-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_ROUNDS=Število rund
-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
-PARTY_PLAYER_LEGEND_CONTINUE=zacni zabavo
-
-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!
-
-PLUGIN_HDL_NAME=Zdrži nivo
-PLUGIN_HDL_DESC=Ne poj slabše, kot kaže kazalnik na števcu za ocenjevanje.
-
-PLUGIN_UNTIL5000_NAME=Do 5000
-PLUGIN_UNTIL5000_DESC=Kdor prvi doseže 5000 tock, zmaga.
-
-PLUGIN_DUELL_NAME=Dvoboj
-PLUGIN_DUELL_DESC=Tekmovanje do 10000 tock.
-
-PLUGIN_TEAMDUELL_NAME=Ekipni dvoboj
-PLUGIN_TEAMDUELL_DESC=Podaj mikrofon!
-
-PLUGIN_BLIND_NAME=Slepi dvoboj
-PLUGIN_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.
-
-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
-
-MSG_ERROR_TITLE=Napaka
-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
-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.
+[Text]
+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_COUNT_HOW_OFTEN_SUNG=
+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
+
+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_ROUNDS=Število rund
+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
+PARTY_PLAYER_LEGEND_CONTINUE=zacni zabavo
+
+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!
+
+PLUGIN_HDL_NAME=Zdrži nivo
+PLUGIN_HDL_DESC=Ne poj slabše, kot kaže kazalnik na števcu za ocenjevanje.
+
+PLUGIN_UNTIL5000_NAME=Do 5000
+PLUGIN_UNTIL5000_DESC=Kdor prvi doseže 5000 tock, zmaga.
+
+PLUGIN_DUELL_NAME=Dvoboj
+PLUGIN_DUELL_DESC=Tekmovanje do 10000 tock.
+
+PLUGIN_TEAMDUELL_NAME=Ekipni dvoboj
+PLUGIN_TEAMDUELL_DESC=Podaj mikrofon!
+
+PLUGIN_BLIND_NAME=Slepi dvoboj
+PLUGIN_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.
+
+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
+
+MSG_ERROR_TITLE=Napaka
+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
+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 \ No newline at end of file
diff --git a/cmake/game/languages/old/readme.txt b/cmake/game/languages/old/readme.txt
index eb2bd1c0..83ba6cd6 100644
--- a/cmake/game/languages/old/readme.txt
+++ b/cmake/game/languages/old/readme.txt
@@ -1,286 +1,286 @@
-.o0 Ultrastar Deluxe in your language 0o.
-
------------------------
- Table of Contents
------------------------
-1. Introduction
-2. Statistic wildcards
-3. Texts to add
-
------------------------
-1. Introduction:
------------------------
-To translate USD to a new language, take the English language file, or another one that is up to date and edit the texts behind the equal mark(=).
-
------------------------
-2. Statistic Wild-Cards:
------------------------
-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.
-
------------------------
-3. Texts to Add:
------------------------
-To port a language file from Ultrastar 0.5.2 or higher add the following texts to the end of the file:
-
-#Main Screen
-SING_MENU=Main Menu
-
-SING_MULTI=party
-SING_MULTI_DESC=Sing in PartyMode
-
-SING_TOOLS=Tools
-
-SING_STATS=stats
-SING_STATS_DESC=View the Statistics
-
-#Sound Options Screen
-SING_OPTIONS_SOUND_PREVIEWVOLUME=Preview Volume
-SING_OPTIONS_SOUND_PREVIEWFADING=Preview Fading
-
-#Advanced Options Screen
-SING_OPTIONS_ADVANCED=advanced
-SING_OPTIONS_ADVANCED_DESC=advanced options
-SING_OPTIONS_ADVANCED_EFFECTSING=Singscreen effects
-SING_OPTIONS_ADVANCED_SCREENFADE=Screen Fading
-SING_OPTIONS_ADVANCED_LOADANIMATION=Load Animation
-SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Savety Questions
-SING_OPTIONS_ADVANCED_LINEBONUS=Line Bonus
-SING_OPTIONS_ADVANCED_ONSONGCLICK=after SongSelection
-
-#Ratings at the Score Screen
-SING_SCORE_TONE_DEAF=Tone Deaf
-SING_SCORE_AMATEUR=Amateur
-SING_SCORE_RISING_STAR=Rising Star
-SING_SCORE_LEAD_SINGER=Lead Singer
-SING_SCORE_HIT_ARTIST=Hit Artist
-SING_SCORE_SUPERSTAR=Superstar
-SING_SCORE_ULTRASTAR=Ultrastar
-
-#Line Bonus PopUps
-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!
-
-#To connect strings with, e.g.: He, you and I
-IMPLODE_GLUE1=,
-IMPLODE_GLUE2= and
-
-#Song Screen Legend
-PLAYLIST_CATTEXT=Playlist: %s
-
-#Text for the legend bar at the bottom
-SING_LEGEND_CONTINUE=Continue
-
-#Texts of the menu that appears when M is pressed at the song selection
-SONG_MENU_NAME_MAIN=Song Menu
-SONG_MENU_PLAY=Sing
-SONG_MENU_EDIT=Edit
-SONG_MENU_MODI=Sing a Modi
-SONG_MENU_CHANGEPLAYERS=Change Players
-SONG_MENU_CANCEL=Cancel
-
-#Playlist Menu
-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 exiting 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_DEL=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?
-
-#Menu Party Modus
-SONG_MENU_NAME_PARTY_MAIN=Menu
-SONG_MENU_JOKER=Joker
-
-SONG_MENU_NAME_PARTY_JOKER=take Joker
-
-#Texts of the jump to window
-SONG_JUMPTO_DESC=Jump to 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
-
-#Texts for Party Mode
-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_ROUNDS=Rounds
-PARTY_TEAMS=Teams
-PARTY_TEAMS_PLAYER1=Player Team1
-PARTY_TEAMS_PLAYER2=Player Team2
-PARTY_TEAMS_PLAYER3=Player Team3
-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_PLAYER_LEGEND_CONTINUE=start party-game
-PARTY_SONG_WHEREAMI=Party Song-Selection
-PARTY_SONG_LEGEND_CONTINUE=sing
-PARTY_SONG_MENU=party menu
-PARTY_ROUND_DESC=next players to the mics
-PARTY_ROUND_WHEREAMI=Party Next Round
-PARTY_ROUND_LEGEND_CONTINUE=start round
-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!
-PARTY_SONG_WHEREAMI=Party Song-Selection
-PARTY_SONG_LEGEND_CONTINUE=Party-Menu
-
-#Texts describing Plugins or Modi
-PLUGIN_HDL_NAME=Hold the Line
-PLUGIN_HDL_DESC=Don't get worse than the pointer at the rating bar shows you.
-PLUGIN_UNTIL5000_NAME=Until 5000
-PLUGIN_UNTIL5000_DESC=Who gets 5000 points first wins the match.
-PLUGIN_DUELL_NAME=Duell
-PLUGIN_DUELL_DESC=Sing a duell until 10000 points.
-PLUGIN_BLIND_NAME=Blind Mode
-PLUGIN_BLIND_DESC=Duell without seeing the notes.
-PLUGIN_TEAMDUELL_NAME=Team Duell
-PLUGIN_TEAMDUELL_DESC=Pass The Mic!
-
-#Statistics Screen
-#For more info about the format strings look at the source code (UScreenStatMain)
-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 Detail Screen
-STAT_DETAIL=Statistics
-STAT_DETAIL_WHEREAMI=Detail Statistics
-
-STAT_NEXT=Next Page
-STAT_PREV=Previous Page
-STAT_REVERSE=Reverse Order
-STAT_PAGE=Seite %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] \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
-
-#Messages for Popup Message Boxes
-MSG_QUESTION_TITLE=Chicken Out
-MSG_QUIT_USDX=Really leave\n\nUltraStar?
-MSG_END_PARTY=Really end\n\nParty Mode?
-ERROR_NO_SONGS=Error: \n No Songs \n loaded
+.o0 Ultrastar Deluxe in your language 0o.
+
+-----------------------
+ Table of Contents
+-----------------------
+1. Introduction
+2. Statistic wildcards
+3. Texts to add
+
+-----------------------
+1. Introduction:
+-----------------------
+To translate USD to a new language, take the English language file, or another one that is up to date and edit the texts behind the equal mark(=).
+
+-----------------------
+2. Statistic Wild-Cards:
+-----------------------
+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.
+
+-----------------------
+3. Texts to Add:
+-----------------------
+To port a language file from Ultrastar 0.5.2 or higher add the following texts to the end of the file:
+
+#Main Screen
+SING_MENU=Main Menu
+
+SING_MULTI=party
+SING_MULTI_DESC=Sing in PartyMode
+
+SING_TOOLS=Tools
+
+SING_STATS=stats
+SING_STATS_DESC=View the Statistics
+
+#Sound Options Screen
+SING_OPTIONS_SOUND_PREVIEWVOLUME=Preview Volume
+SING_OPTIONS_SOUND_PREVIEWFADING=Preview Fading
+
+#Advanced Options Screen
+SING_OPTIONS_ADVANCED=advanced
+SING_OPTIONS_ADVANCED_DESC=advanced options
+SING_OPTIONS_ADVANCED_EFFECTSING=Singscreen effects
+SING_OPTIONS_ADVANCED_SCREENFADE=Screen Fading
+SING_OPTIONS_ADVANCED_LOADANIMATION=Load Animation
+SING_OPTIONS_ADVANCED_ASKBEFOREDEL=Savety Questions
+SING_OPTIONS_ADVANCED_LINEBONUS=Line Bonus
+SING_OPTIONS_ADVANCED_ONSONGCLICK=after SongSelection
+
+#Ratings at the Score Screen
+SING_SCORE_TONE_DEAF=Tone Deaf
+SING_SCORE_AMATEUR=Amateur
+SING_SCORE_RISING_STAR=Rising Star
+SING_SCORE_LEAD_SINGER=Lead Singer
+SING_SCORE_HIT_ARTIST=Hit Artist
+SING_SCORE_SUPERSTAR=Superstar
+SING_SCORE_ULTRASTAR=Ultrastar
+
+#Line Bonus PopUps
+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!
+
+#To connect strings with, e.g.: He, you and I
+IMPLODE_GLUE1=,
+IMPLODE_GLUE2= and
+
+#Song Screen Legend
+PLAYLIST_CATTEXT=Playlist: %s
+
+#Text for the legend bar at the bottom
+SING_LEGEND_CONTINUE=Continue
+
+#Texts of the menu that appears when M is pressed at the song selection
+SONG_MENU_NAME_MAIN=Song Menu
+SONG_MENU_PLAY=Sing
+SONG_MENU_EDIT=Edit
+SONG_MENU_MODI=Sing a Modi
+SONG_MENU_CHANGEPLAYERS=Change Players
+SONG_MENU_CANCEL=Cancel
+
+#Playlist Menu
+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 exiting 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_DEL=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?
+
+#Menu Party Modus
+SONG_MENU_NAME_PARTY_MAIN=Menu
+SONG_MENU_JOKER=Joker
+
+SONG_MENU_NAME_PARTY_JOKER=take Joker
+
+#Texts of the jump to window
+SONG_JUMPTO_DESC=Jump to 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
+
+#Texts for Party Mode
+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_ROUNDS=Rounds
+PARTY_TEAMS=Teams
+PARTY_TEAMS_PLAYER1=Player Team1
+PARTY_TEAMS_PLAYER2=Player Team2
+PARTY_TEAMS_PLAYER3=Player Team3
+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_PLAYER_LEGEND_CONTINUE=start party-game
+PARTY_SONG_WHEREAMI=Party Song-Selection
+PARTY_SONG_LEGEND_CONTINUE=sing
+PARTY_SONG_MENU=party menu
+PARTY_ROUND_DESC=next players to the mics
+PARTY_ROUND_WHEREAMI=Party Next Round
+PARTY_ROUND_LEGEND_CONTINUE=start round
+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!
+PARTY_SONG_WHEREAMI=Party Song-Selection
+PARTY_SONG_LEGEND_CONTINUE=Party-Menu
+
+#Texts describing Plugins or Modi
+PLUGIN_HDL_NAME=Hold the Line
+PLUGIN_HDL_DESC=Don't get worse than the pointer at the rating bar shows you.
+PLUGIN_UNTIL5000_NAME=Until 5000
+PLUGIN_UNTIL5000_DESC=Who gets 5000 points first wins the match.
+PLUGIN_DUELL_NAME=Duell
+PLUGIN_DUELL_DESC=Sing a duell until 10000 points.
+PLUGIN_BLIND_NAME=Blind Mode
+PLUGIN_BLIND_DESC=Duell without seeing the notes.
+PLUGIN_TEAMDUELL_NAME=Team Duell
+PLUGIN_TEAMDUELL_DESC=Pass The Mic!
+
+#Statistics Screen
+#For more info about the format strings look at the source code (UScreenStatMain)
+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 Detail Screen
+STAT_DETAIL=Statistics
+STAT_DETAIL_WHEREAMI=Detail Statistics
+
+STAT_NEXT=Next Page
+STAT_PREV=Previous Page
+STAT_REVERSE=Reverse Order
+STAT_PAGE=Seite %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] \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
+
+#Messages for Popup Message Boxes
+MSG_QUESTION_TITLE=Chicken Out
+MSG_QUIT_USDX=Really leave\n\nUltraStar?
+MSG_END_PARTY=Really end\n\nParty Mode?
+ERROR_NO_SONGS=Error: \n No Songs \n loaded
ERROR_NO_PLUGINS=Error: \n No Plugins \n loaded \ No newline at end of file
diff --git a/cmake/game/plugins/5000points.usdx b/cmake/game/plugins/5000points.usdx
new file mode 100644
index 00000000..75dc4e03
--- /dev/null
+++ b/cmake/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/cmake/game/plugins/PluginDescription.odt b/cmake/game/plugins/PluginDescription.odt
new file mode 100644
index 00000000..476e5113
--- /dev/null
+++ b/cmake/game/plugins/PluginDescription.odt
Binary files differ
diff --git a/cmake/game/plugins/blind.usdx b/cmake/game/plugins/blind.usdx
new file mode 100644
index 00000000..73bbd98d
--- /dev/null
+++ b/cmake/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/cmake/game/plugins/duel.usdx b/cmake/game/plugins/duel.usdx
new file mode 100644
index 00000000..596aa270
--- /dev/null
+++ b/cmake/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/cmake/game/plugins/hooks.txt b/cmake/game/plugins/hooks.txt
new file mode 100644
index 00000000..7a91643d
--- /dev/null
+++ b/cmake/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/cmake/game/plugins/teamduel.usdx b/cmake/game/plugins/teamduel.usdx
new file mode 100644
index 00000000..c5a35aa0
--- /dev/null
+++ b/cmake/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.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;
+
+-- 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/cmake/game/sounds/Bebeto_-_Loop010-license.txt b/cmake/game/sounds/Bebeto_-_Loop010-license.txt
new file mode 100644
index 00000000..462ce812
--- /dev/null
+++ b/cmake/game/sounds/Bebeto_-_Loop010-license.txt
@@ -0,0 +1,10 @@
+This work is licensed under a Creative Commons Sampling Plus 1.0 License.
+http://creativecommons.org/licenses/sampling+/1.0/
+
+Author:
+http://www.lucadebernardi.com
+
+Distributed by:
+Site: The Freesound Project (http://www.freesound.org)
+File: Loop010-ambient.wav
+URL: http://www.freesound.org/samplesViewSingle.php?id=18982
diff --git a/cmake/game/themes/Classic.ini b/cmake/game/themes/Classic.ini
index 1ea83f5e..8ea3fe83 100644
--- a/cmake/game/themes/Classic.ini
+++ b/cmake/game/themes/Classic.ini
@@ -1,90 +1,89 @@
-;0.5.1 Mod
+;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
-US_Version=USD 101
+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]
-Texts =2
-Fade = 1
-
[LoadingBackground]
-Tex=LoadingBG
+Tex = LoadingBG
+Color = DarkRed
+Type = Colorized
[LoadingText1]
-X =400
-Y =290
-Color =GrayDark
-Font =1
-Align =1
-Size = 42
-Text =SING_LOADING
+X = 350
+Y = 250
+Color = GrayDark
+Font = 1
+Align = 0
+Size = 48
+Text = SING_LOADING
+Reflection = 0
+
[LoadingText2]
-X =790
-Y =583
-Color=Grey
-Font =0
-Size = 18
-Align=2
-Text=US_VERSION
+X = 780
+Y = 570
+Color = GrayDark
+Font = 1
+Size = 24
+Align = 2
+Text = US_VERSION
+Reflection = 0
-[Main]
-Texts =3
-Statics=2
+[Main]
[MainBackground]
-Tex=MainBG
+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
+Color = GrayLight
+Font = 1
Size = 66
-Text=SING_CHOOSE_MODE
-Align=0
-
-[MainText2]
-X =226
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_NAVIGATE
-Align=0
-
-[MainText3]
-X =380
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_SELECT
-Align=0
-
-[MainText4]
-X =540
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_EDITOR
-Align=0
+Align = 0
+Text = SING_MENU
[MainTextDescription]
X =63
@@ -98,161 +97,216 @@ Text=
[MainTextDescriptionLong]
X =63
Y =265
-Color=Black
-Font =0
+Color = Black
+Font = 0
Size = 30
-Align=0
-Text=
+Align = 0
+Text =
-[MainStatic1]
-Tex =Logo
+[MainStatic2]
X =30
Y =270
W =740
H =283
-Color =ColorDark
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Tex = usdx_logo
+Color = ColorDark
+Type = Transparent
-[MainStatic2]
-Tex =MainIcon
-X =30
-Y =235
-W =32
-H =32
-Color =ColorDark
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
[MainStatic3]
-Tex =ButtonNavi
-X =196
-Y =553
-W =22
-H =22
-Color =Black
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+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]
-Tex =ButtonEnter
-X =350
-Y =553
-W =22
-H =22
-Color =Black
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+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]
-Tex =ButtonE
-X =510
-Y =553
-W =22
-H =22
-Color =Black
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+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 =472
-Y =220
-W =58
-H =56
-Tex =ButtonSolo
-Color =ColorDark
-Int = 1
-DColor = GrayLightest
-DInt = 0.5
-Type=Font Black
-Texts=0
+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 =532
-Y =220
-W =58
-H =56
-Tex =ButtonMulti
-Color =ColorDark
-Int = 1
-DColor = GrayLightest
-DInt = 0.5
-Type=Font Black
-Texts=0
+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 =592
-Y =220
-W =58
-H =56
-Tex =ButtonStats
-Color =ColorDark
-Int = 1
-DColor = GrayLightest
-DInt = 0.5
-Type=Font Black
-Texts=0
-
-[MainButtonEditor]
-X =592
-Y =220
-W =58
-H =56
-Tex =ButtonEditor
-Color =ColorDark
-Int = 1
-DColor = GrayLightest
-DInt = 0.5
-Type=Font Black
-Texts=0
-Visible=0
+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 =652
-Y =220
-W =58
-H =56
-Tex =ButtonOptions
-Color =ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
-Type=Font Black
-Texts=0
+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 =712
-Y =220
-W =58
-H =56
-Tex =ButtonExit
-Color =ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
-Type=Font Black
-Texts=0
+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]
-Texts =3
[SongBackground]
-Tex=SongBG
+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
@@ -263,13 +317,12 @@ Style=4
Reflections=0
[SongEqualizer]
-Visible=1
-Direction=1
+Visible = 1
+Direction = 1
Color =Black
-Alpha=1
+Alpha = 1
X=378
Y=488
-Z=1
PieceW=8
PieceH=3
Space=1
@@ -277,54 +330,25 @@ Bands=5
Length=7
[SongVideoIcon]
-X =384
-Y =104
+X=450
+Y=462
W =32
H =32
Z=1
Color=White
-Tex =VideoIcon
-Type=Font Black
-
-[SongStatic1]
-X =0
-Y =100
-W =800
-H =350
-Color=Black
-Tex =SongFade
-Type=Font Black
-TexX1=0.1
-TexY1=0.1
-TexX2=0.9
-TexY2=0.9
+Tex = icon_song_video
+Type = Transparent
-[SongStatic2]
-X =20
-Y =500
-W =32
-H =32
-Color =ColorDark
-Tex =MainIcon
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
[SongStatic3]
X =270
Y =120
W =260
H =240
-Z =0.45
-Color =Gray
-Tex =SongSelection
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Z =0.95
+Color = Gray
+Tex = SongSelection
+Type = Transparent
[SongStatic4]
X =378
@@ -334,11 +358,8 @@ W =44
H =28
Color =Black
Tex =SongEqualizerBG
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Type = Colorized
+
[SongTextArtist]
X =400
@@ -367,28 +388,6 @@ Size = 21
Align =1
Text=
-[SongTextCat]
-X =67
-Y =524
-Color=Gray
-Font =1
-Size = 21
-Align =0
-Text=
-
-#[SongStaticCat]
-#Tex =
-#X =12
-#Y =7
-#W =85
-#H =85
-#Color=White
-#Type=Plain
-#TexX1=0
-#TexY1=0
-#TexX2=1
-#TexY2=1
-
#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.
@@ -402,391 +401,414 @@ Text=
# SongTextNonParty[No]
#Here are the ones for singmode
-[SongStaticNonParty1]
-X =120
-Y =553
-W =22
-H =22
-Tex=ButtonAlt
-Color =White
-Type=Plain
+[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 =156
+X =110
Y =553
-W =22
-H =22
-Tex=ButtonAZ
-Color =White
-Type=Plain
+W = 32
+H = 30
+Z = 0.952
+Tex = ButtonAlt
+Color = White
+Type = Transparent
-[SongStaticNonParty3]
-X =298
-Y =553
-W =22
-H =22
-Tex=ButtonM
-Color =White
-Type=Plain
-[SongStaticNonParty4]
-X =414
+[SongTextNonParty2]
+X = 142
Y =553
-W =22
-H =22
-Tex=ButtonJ
-Color =White
-Type=Plain
+Z = 0.952
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = +
-[SongStaticNonParty5]
-X =585
+
+[SongStaticNonParty3]
+X =155
Y =553
-W =22
-H =22
-Tex=ButtonP
-Color =White
-Type=Plain
+W = 32
+H = 30
+Z = 0.952
+Tex = ButtonAZ
+Color = White
+Type = Transparent
-#Texts Non Party
-[SongTextNonParty1]
-X =30
-Y =455
-Color=GrayLight
-Font =1
-Size = 45
-Text=SING_SONG_SELECTION
-Align=0
-[SongTextNonParty2]
-X =50
-Y =500
-Color=GrayDark
-Font =1
+[SongTextNonParty3]
+X = 195
+Y = 555
+Z = 0.952
+Color = Black
+Font = 0
Size = 24
-Text=SING_SONG_SELECTION_DESC
-Align=0
+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
-[SongTextNonParty3]
-X =144
-Y =556
-Color=Black
-Font =1
-Size = 15
-Text=+
[SongTextNonParty4]
-X =186
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=SING_SONG_SELECTION_GOTO
+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 =328
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=SING_SONG_SELECTION_MENU
+X = 460
+Y = 555
+Z = 0.952
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SONG_JUMPTO_DESC
-[SongTextNonParty6]
-X =444
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=SONG_JUMPTO_DESC
-[SongTextNonParty7]
-X =615
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=SING_SONG_SELECTION_PLAYLIST
+# [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 theese are the ones for partymode
+#and these are the ones for partymode
[SongStaticParty1]
-X =187
-Y =553
-W =22
-H =22
-Tex=Button13
-Color =White
-Type=Plain
+X =20
+Y =500
+W =32
+H =32
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
+# NAVBAR for party
+# enter a number
[SongStaticParty2]
-X =363
-Y =553
-W =22
-H =22
-Tex=ButtonM
-Color =White
-Type=Plain
+X = 126
+Y = 545
+W =32
+H =30
+Tex = Button13
+Color = White
+Type = Transparent
-[SongStaticParty3]
-X =525
-Y =553
-W =22
-H =22
-Tex=ButtonEnter
-Color =White
-Type=Plain
+[SongTextParty2]
+X =166
+Y = 548
+Color = Black
+Size = 24
+Align = 0
+Text = SONG_MENU_NAME_PARTY_JOKER
-#Texts for Party Mode
-[SongTextParty1]
-X =30
-Y =455
-Color=GrayLight
-Font =1
-Size = 45
-Align=0
-Text=PARTY_MODE
+# menu
+[SongStaticParty3]
+X =330
+Y = 545
+W = 32
+H = 30
+Tex = ButtonM
+Color = White
+Type = Transparent
-[SongTextParty2]
-X =50
-Y =500
-Color=GrayDark
-Font =1
+[SongTextParty3]
+X =370
+Y = 548
+Color = Black
+Font = 0
Size = 24
-Align=0
-Text=PARTY_SONG_WHEREAMI
+Align = 0
+Text = PARTY_SONG_MENU
-[SongTextParty3]
-X =217
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=SONG_MENU_NAME_PARTY_JOKER
+
+[SongStaticParty4]
+X =530
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
[SongTextParty4]
-X =393
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=PARTY_SONG_MENU
+X =570
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_SONG_LEGEND_CONTINUE
-[SongTextParty5]
-X =555
-Y =552
-Color=Gray
+
+#Texts for Party Mode
+[SongTextParty1]
+X =30
+Y =455
+Color=GrayLight
Font =1
-Size = 21
-Align=0
-Text=PARTY_SONG_LEGEND_CONTINUE
+Size = 45
+Text = PARTY_MODE
#variable statics end
# Jokers, 5 for each team, only shown in party Mode
[SongStaticTeam1Joker1]
-Tex =Joker
+Tex = Joker
X =20
Y =30
W =50
H =50
-Color=P1Dark
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Color = P1Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
[SongStaticTeam1Joker2]
-Tex =Joker
+Tex = Joker
X =70
Y =30
W =50
H =50
-Color=P1Dark
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Color = P1Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
[SongStaticTeam1Joker3]
-Tex =Joker
+Tex = Joker
X =120
Y =30
W =50
H =50
-Color=P1Dark
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Color = P1Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
[SongStaticTeam1Joker4]
-Tex =Joker
+Tex = Joker
X =170
Y =30
W =50
H =50
-Color=P1Dark
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Color = P1Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
[SongStaticTeam1Joker5]
-Tex =Joker
+Tex = Joker
X =220
Y =30
W =50
H =50
-Color=P1Dark
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Color = P1Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
[SongStaticTeam2Joker1]
-Tex =Joker
+Tex = Joker
X =280
Y =30
W =50
H =50
-Color=P2Dark
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Color = P2Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
[SongStaticTeam2Joker2]
-Tex =Joker
+Tex = Joker
X =330
Y =30
W =50
H =50
-Color=P2Dark
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Color = P2Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
[SongStaticTeam2Joker3]
-Tex =Joker
+Tex = Joker
X =380
Y =30
W =50
H =50
-Color=P2Dark
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Color = P2Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
[SongStaticTeam2Joker4]
-Tex =Joker
+Tex = Joker
X =430
Y =30
W =50
H =50
-Color=P2Dark
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Color = P2Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
[SongStaticTeam2Joker5]
-Tex =Joker
+Tex = Joker
X =480
Y =30
W =50
H =50
-Color=P2Dark
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Color = P2Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
[SongStaticTeam3Joker1]
-Tex =Joker
+Tex = Joker
X =540
Y =30
W =50
H =50
-Color=P3Dark
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Color = P3Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
[SongStaticTeam3Joker2]
-Tex =Joker
+Tex = Joker
X =590
Y =30
W =50
H =50
-Color=P3Dark
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Color = P3Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
[SongStaticTeam3Joker3]
-Tex =Joker
+Tex = Joker
X =640
Y =30
W =50
H =50
-Color=P3Dark
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Color = P3Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
[SongStaticTeam3Joker4]
-Tex =Joker
+Tex = Joker
X =690
Y =30
W =50
H =50
-Color=P3Dark
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Color = P3Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
[SongStaticTeam3Joker5]
-Tex =Joker
+Tex = Joker
X =740
Y =30
W =50
H =50
-Color=P3Dark
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Color = P3Dark
+Type = Transparent
+TexX1 = 0
+TexY1 = 0
+TexX2 = 1
+TexY2 = 1
[Sing]
-Texts =1
+Texts = 1
+
+[SingBackground]
+Type=color
+ColR=1
+ColB=1
+ColG=1
[SingText1]
Text =SING_TIME
@@ -805,17 +827,17 @@ Y =490
W =780
H =105
Color =GrayLightest
-Type=Font Black
+Type = Transparent
[SingStatic2]
-;Time BG
+;TimeBar
Tex =LyricBar
X =12
Y =5
W =328
H =42
Color =GrayLightest
-Type=Font Black
+Type = Transparent
[SingStatic3]
Tex =Rectangle
@@ -841,1615 +863,1584 @@ Size = 24
Color =White
Align=1
-[SingStatic4]
-Tex =Bar
-X =20
-Y =10
-W =46
-H =30
-Color =Black
-Type=Font Black
-
+# O N E P L A Y E R M O D E # # # # # # # # # # # # # # # # # # # #
+#PlayerOne
[SingP1Static]
-Tex =P
-X =16
-Y =55
-W =45
-H =50
-Color =P1Dark
-Type=Font Black
-
-[SingP1Static2]
-Tex =ScoreBG
-X =75
-Y =55
-W =100
-H =40
-Color =P1Dark
-Type=Transparent
-TexX1=0.02
-TexY1=0.05
-TexX2=0.98
-TexY2=0.98
+Tex = P
+X = 20
+Y = 297
+W = 30
+H = 28
+Color = P1Dark
+Type = Colorized
[SingP1Text]
-Text =P1
-X =27
-Y =65
-Font =1
-Size = 24
-Color =White
-Align=0
+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 =90
-Y =60
-Font =0
+Text = 00000
+X = 698
+Y = 284
+Font = 0
Size = 30
-Color =White
-Align=0
+Color = White
+Align = 0
[SingP1SingBar]
-X =75
-Y =95
-W =100
-H =8
+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
-[SingP1TwoPSingBar]
-X =75
-Y =95
-W =100
-H =8
+[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
-[SingP1ThreePSingBar]
-X =75
-Y =95
-W =100
-H =8
+[SingP1TwoPSingBar]
+X = 680
+Y = 136
+W = 100
+H = 8
+#Player Two
[SingP2RStatic]
-Tex =P
-X =739
-Y =55
-W =45
-H =50
-Color =P2Dark
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[SingP2RStatic2]
-Tex =ScoreBG
-X =620
-Y =55
-W =100
-H =40
-Color =P2Dark
-Type=Transparent
-TexX1=0.02
-TexY1=0.05
-TexX2=0.98
-TexY2=0.98
+Tex = P
+X = 20
+Y = 297
+W = 30
+H = 28
+Color = P2Dark
+Type = Colorized
[SingP2RText]
-Text =P2
-X =750
-Y =65
-Font =1
-Size = 24
-Color =White
-Align=0
+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 =635
-Y =60
-Font =0
+Text = 00000
+X = 698
+Y = 284
+Font = 0
Size = 30
-Color =White
-Align=0
+Color = White
+Align = 0
[SingP2RSingBar]
-X =620
-Y =95
-W =100
-H =8
+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
-[SingP2MStatic]
-Tex =P
-X =311
-Y =55
-W =45
-H =50
-Color =P2Dark
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[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
-[SingP2MStatic2]
-Tex =ScoreBG
-X =370
-Y =55
-W =100
-H =40
-Color =P2Dark
-Type=Transparent
-TexX1=0.02
-TexY1=0.05
-TexX2=0.98
-TexY2=0.98
+[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 =65
-Font =1
+Text = P2
+X = 321
+Y = 66
+Font = 1
Size = 24
-Color =White
-Align=0
+Color = White
+Align = 0
+
+[SingP2MStatic2]
+Tex = ScoreBG
+X = 370
+Y = 61
+W = 100
+H = 36
+Color = P2Dark
+Type = Colorized
[SingP2MTextScore]
-Text =00000
-X =385
-Y =60
-Font =0
+Text = 00000
+X = 388
+Y = 63
+Font = 0
Size = 30
-Color =White
-Align=0
+Color = White
+Align = 0
[SingP2MSingBar]
-X =370
-Y =95
-W =100
-H =8
+X = 370
+Y = 95
+W = 100
+H = 8
+#Player Three
[SingP3RStatic]
-Tex =P
-X =611
-Y =55
-W =45
-H =50
-Color =P3Dark
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[SingP3RStatic2]
-Tex =ScoreBG
-X =670
-Y =55
-W =100
-H =40
-Color =P3Dark
-Type=Transparent
-TexX1=0.02
-TexY1=0.05
-TexX2=0.98
-TexY2=0.98
+Tex = P
+X = 611
+Y = 59
+W = 50
+H = 44
+Color = P3Dark
+Type = Colorized
[SingP3RText]
-Text =P3
-X =621
-Y =65
-Font =1
+Text = P3
+X = 621
+Y = 66
+Font = 1
Size = 24
-Color =White
-Align=0
+Color = White
+Align = 0
+
+[SingP3RStatic2]
+Tex = ScoreBG
+X = 670
+Y = 61
+W = 100
+H = 36
+Color = P3Dark
+Type = Colorized
[SingP3RTextScore]
-Text =00000
-X =685
-Y =60
-Font =0
+Text = 00000
+X = 688
+Y = 63
+Font = 0
Size = 30
-Color =White
-Align=0
+Color = White
+Align = 0
[SingP3SingBar]
-X =670
-Y =95
-W =100
-H =8
+X = 670
+Y = 95
+W = 100
+H = 8
[Score]
-Texts =1
+Texts = 1
[ScoreBackground]
-Tex=ScoresBG
+Tex = ScoreScreenBG
[ScoreText1]
-X =90
-Y =500
-Color =GrayDark
+X = 70
+Y = 6
+Color = GrayLight
Font =1
-Size = 51
-Text =SONG_SCORE_WHEREAMI
-Align=0
+Size = 60
+Text = SONG_SCORE
+Align = 0
+
+[ScoreTextArtistTitle]
+X = 105
+Y = 65
+Color = GrayDark
+Font = 0
+Size = 26
+Align = 0
+Text = ArtistTitle
[ScoreStatic1]
-Tex =ButtonEnter
+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 =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
[ScoreText2]
-X =380
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_CONTINUE
-Align=0
+X =390
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_LEGEND_CONTINUE
-[ScoreTextArtist]
-X =450
-Y =500
-Color=GrayDark
-Font =0
-Size = 27
-Text =Artist
-Align=0
-
-[ScoreTextTitle]
-X =450
-Y =525
-Font =0
-Size = 27
-Text =Title
-Align=0
-Color=Gray
+#end of main stuff
+# # # # # # # # # # # # # # # # # # One Player Score # # # # # # # # # # # #
[ScoreTextName1]
-X =200
-Y =160
-Font =1
-Size = 36
-Text =P1
-Color =P1Dark
-Align=0
-
-[ScoreTextName2]
-X =50
-Y =160
-Font =1
-Size = 36
-Text =P1
-Color =P1Dark
-Align=0
+X = 197
+Y = 290
+Font = 0
+Size = 30
+Text = P1
+Color = Black
+Align = 0
-[ScoreTextName3]
-X =510
-Y =160
-Font =1
-Size = 36
-Text =P2
-Color =P2Dark
-Align=0
+# Rating
+[ScoreStaticRatingPicture1]
+X = 385
+Y = 165
+H = 75
+W = 75
[ScoreTextScore1]
-X =250
-Y =110
-Color=GrayDark
-Font =1
-Size = 27
-Text =Tone Deaf
-Align=0
-
-[ScoreTextScore2]
-X =100
-Y =110
-Color=GrayDark
-Font =1
+X = 422
+Y = 235
+width = 100
+Color = Black
+Font = 0
Size = 27
-Text =Tone Deaf
-Align=0
+Text = Tone Deaf
+Align = 1
-[ScoreTextScore3]
-X =560
-Y =110
-Color=GrayDark
-Font =1
-Size = 27
-Text =Tone Deaf
-Align=0
+# Note Score
+[ScoreStaticBoxDark1]
+Tex = ScoreBar_box_dark
+X = 200
+Y = 327
+W = 22
+H = 20
+Color = P1Dark
+Type = Colorized
[ScoreTextNotes1]
-X =235
-Y =220
-Color=GrayDark
-Font =0
-Size = 27
-Text=SING_NOTES
-Align=0
-
-[ScoreTextNotes2]
-X =85
-Y =220
-Color=GrayDark
-Font =0
-Size = 27
-Text=SING_NOTES
-Align=0
-
-[ScoreTextNotes3]
-X =545
-Y =220
-Color=GrayDark
-Font =0
-Size = 27
-Text =SING_NOTES
-Align=0
+X = 227
+Y = 322
+Color = Black
+Font = 0
+Size = 30
+Text = SING_NOTES
+Align = 0
[ScoreTextNotesScore1]
-X =440
-Y =220
-Color=GrayDark
-Font =1
+X = 487
+Y = 322
+Color = Black
+Font = 0
Size = 30
-Align =2
-Text =0000
+Align = 2
+Text = 0
-[ScoreTextNotesScore2]
-X =290
-Y =220
-Color=GrayDark
-Font =1
-Size = 30
-Align =2
-Text =0000
+# A simple line
+[ScorePlayer1Static1]
+Tex = ScoreLine
+X = 200
+Y = 351
+W = 287
+H = 1
+Color = Gray
+Type = Transparent
-[ScoreTextNotesScore3]
-X =750
-Y =220
-Color=GrayDark
-Font =1
-Size = 30
-Align =2
-Text =0000
+# Line Bonus
+[ScoreStaticBoxLight1]
+Tex = ScoreBar_box_light
+X = 200
+Y = 358
+W = 22
+H = 20
+Color = P1Light
+Type = Colorized
[ScoreTextLineBonus1]
-X =235
-Y =260
-Color=GrayDark
-Font =0
-Size = 27
-Text =SING_PHRASE_BONUS
-Align=0
+X = 227
+Y = 352
+Color = Black
+Font = 0
+Size = 30
+Text = SING_PHRASE_BONUS
+Align = 0
-[ScoreTextLineBonus2]
-X =85
-Y =260
-Color=GrayDark
-Font =0
-Size = 27
-Text =SING_PHRASE_BONUS
-Align=0
+[ScoreTextLineBonusScore1]
+X = 487
+Y = 352
+Color = Black
+Font = 0
+Size = 30
+Align = 2
+Text = 0
-[ScoreTextLineBonus3]
-X =545
-Y =260
-Color=GrayDark
-Font =0
-Size = 27
-Text =SING_PHRASE_BONUS
-Align=0
+# A simple line
+[ScorePlayer1Static2]
+Tex = ScoreLine
+X = 200
+Y = 382
+W = 287
+H = 1
+Color = Gray
+Type = Transparent
-[ScoreTextLineBonusScore1]
-X =440
-Y =260
-Color=GrayDark
-Font =1
+# 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
-Align =2
-Text =0000
+Text = SING_GOLDEN_NOTES
+Align = 0
-[ScoreTextLineBonusScore2]
-X =290
-Y =260
-Color=GrayDark
-Font =1
+[ScoreTextGoldenNotesScore1]
+X = 487
+Y = 383
+Color = Black
+Font = 0
Size = 30
-Align =2
-Text =0000
+Align = 2
+Text = 0
+
+#Total Score
+[ScoreStaticPlayerIdBox1]
+Tex = PlayerIDBox01
+X = 200
+Y = 455
+W = 26
+H = 23
+Type = Transparent
+Color = White
-[ScoreTextLineBonusScore3]
-X =750
-Y =260
-Color=GrayDark
-Font =1
+
+[ScoreTextTotal1]
+X = 237
+Y = 454
+Color = Black
+Font = 0
Size = 30
-Align =2
-Text =0000
+Text = SING_TOTAL
+Align = 0
-[ScoreTextGoldenNotes1]
-X =235
-Y =300
-Color=GrayDark
-Font =0
-Size = 27
-Text =SING_GOLDEN_NOTES
-Align=0
-[ScoreTextGoldenNotes2]
-X =85
-Y =300
-Color=GrayDark
-Font =0
-Size = 27
-Text =SING_GOLDEN_NOTES
-Align=0
+[ScoreTextTotalSCore1]
+X = 487
+Y = 444
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 0
-[ScoreTextGoldenNotes3]
-X =545
-Y =300
-Color=GrayDark
-Font =0
-Size = 27
-Text =SING_GOLDEN_NOTES
-Align=0
+#ScoreBar
+[ScoreStaticBackLevel1]
+Tex = ScoreLevel
+X = 503
+Y = 168
+W = 95
+H = 310
+Color = P1Lightest
+Type = Colorized
-[ScoreTextGoldenNotesScore1]
-X =440
-Y =300
-Color=GrayDark
-Font =1
-Size = 30
-Align =2
-Text =0000
+[ScoreStaticBackLevelRound1]
+Tex = ScoreLevelRound
+X = 503
+Y = 138
+W = 95
+H = 8
+Color = P1Lightest
+Type = Colorized
-[ScoreTextGoldenNotesScore2]
-X =290
-Y =300
-Color=GrayDark
-Font =1
-Size = 30
-Align =2
-Text =0000
+[ScoreStaticLevel1]
+Tex = ScoreLevel
+X = 503
+Y = 400
+W = 95
+H = 10
+Color = P1Dark
+Type = Colorized
-[ScoreTextGoldenNotesScore3]
-X =750
-Y =300
-Color=GrayDark
-Font =1
+[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
-Align =2
-Text =0000
+Text = P1
+Color = Black
+Align = 0
-[ScoreTextTotal1]
-X =200
-Y =370
-Color=GrayDark
-Font =0
-Size = 27
-Text=SING_TOTAL
-Align=0
+[ScoreStaticRatingPicture2]
+X = 180
+Y = 165
+H = 75
+W = 75
-[ScoreTextTotal2]
-X =50
-Y =370
-Color=GrayDark
-Font =0
+[ScoreTextScore2]
+X = 217
+Y = 235
+Width = 100
+Color = Black
+Font = 0
Size = 27
-Text =SING_TOTAL
-Align=0
+Text = Tone Deaf
+Align = 1
-[ScoreTextTotal3]
-X =510
-Y =370
-Color=GrayDark
-Font =0
-Size = 27
-Text =SING_TOTAL
-Align=0
+[ScoreStaticBoxDark2]
+Tex = ScoreBar_box_dark
+X = 45
+Y = 327
+W = 22
+H = 20
+Color = P1Dark
+Type = Colorized
-[ScoreTextTotalSCore1]
-X =440
-Y =360
-Color=GrayDark
-Font =1
-Size = 45
-Align =2
-Text =00000
+[ScoreTextNotes2]
+X = 72
+Y = 324
+Color = Black
+Font = 0
+Size = 24
+Text = SING_NOTES
+Align = 0
-[ScoreTextTotalSCore2]
-X =290
-Y =360
-Color=GrayDark
-Font =1
-Size = 45
-Align =2
-Text =00000
+[ScoreTextNotesScore2]
+X = 282
+Y = 324
+Color = Black
+Font = 0
+Size = 24
+Align = 2
+Text = 0000
-[ScoreTextTotalScore3]
-X =750
-Y =360
-Color=GrayDark
-Font =1
-Size = 45
-Align =2
-Text =00000
+[ScoreStaticBoxLight2]
+Tex = ScoreBar_box_light
+X = 45
+Y = 358
+W = 22
+H = 20
+Color = P1Lightest
+Type = Colorized
-[ScorePlayer1Static1]
-Tex =ScoreLine
-X =200
-Y =205
-W =240
-H =6
-Color =GrayDark
-Type =Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[ScoreTextLineBonus2]
+X = 72
+Y = 355
+Color = Black
+Font = 0
+Size = 24
+Text = SING_PHRASE_BONUS
+Align = 0
-[ScorePlayer1Static2]
-Tex =ScoreLine
-X =200
-Y =345
-W =240
-H =6
-Type =Font Black
-Color =GrayDark
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[ScoreTextLineBonusScore2]
+X = 282
+Y = 355
+Color = Black
+Font = 0
+Size = 24
+Align = 2
+Text = 0000
-[ScorePlayer1Static3]
-Tex =ScoreLine
-X =200
-Y =410
-W =240
-H =6
-Type =Font Black
-Color =GrayDark
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[ScoreStaticBoxLightest2]
+Tex = ScoreBar_box_lightest
+X = 45
+Y = 390
+W = 22
+H = 20
+Color = P1Lightest
+Type = Colorized
-[ScoreStaticBoxLightest1]
-Tex =ScoreBox
-X =200
-Y =220
-W =30
-H =30
-Color =P1Lightest
-Type=
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[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
-[ScoreStaticBoxDark1]
-Tex =ScoreBox
-X =200
-Y =300
-W =30
-H =30
-Color =P1Dark
-Type=
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[ScoreTextTotalSCore2]
+X = 283
+Y = 444
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+
+
+# Lines
[ScorePlayer2Static1]
-Tex =ScoreLine
-X =50
-Y =205
-W =240
-H =6
-Type =Font Black
-Color =GrayDark
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Tex = ScoreLine
+X = 45
+Y = 351
+W = 237
+H = 1
+Type = Transparent
+Color = Gray
[ScorePlayer2Static2]
-Tex =ScoreLine
-X =50
-Y =345
-W =240
-H =6
-Type =Font Black
-Color =GrayDark
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+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 =ScoreLine
-X =50
-Y =410
-W =240
-H =6
-Type =Font Black
-Color =GrayDark
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+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
-[ScoreStaticBoxLightest2]
-Tex =ScoreBox
-X =50
-Y =220
-W =30
-H =30
-Color =P1Lightest
-Type=
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+# P L A Y E R T W O
+[ScoreTextName3]
+X = 758
+Y = 290
+Font = 0
+Size = 30
+Text = P2
+Color = Black
+Align = 2
-[ScoreStaticBoxDark2]
-Tex =ScoreBox
-X =50
-Y =300
-W =30
-H =30
-Color =P1Dark
-Type=
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[ScoreStaticRatingPicture3]
+X = 545
+Y = 165
+H = 75
+W = 75
-[ScorePlayer3Static1]
-Tex =ScoreLine
-X =510
-Y =205
-W =240
-H =6
-Type =Font Black
-Color =GrayDark
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[ScoreTextScore3]
+X = 583
+Y = 235
+width = 100
+Color = Black
+Font = 0
+Size = 27
+Text = Tone Deaf
+Align = 1
-[ScorePlayer3Static2]
-Tex =ScoreLine
-X =510
-Y =345
-W =240
-H =6
-Type =Font Black
-Color =GrayDark
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[ScoreStaticBoxDark3]
+Tex = ScoreBar_box_dark
+X = 733
+Y = 327
+W = 22
+H = 20
+Color = P2Dark
+Type = Colorized
-[ScorePlayer3Static3]
-Tex =ScoreLine
-X =510
-Y =410
-W =240
-H =6
-Type =Font Black
-Color =GrayDark
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[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 =ScoreBox
-X =510
-Y =220
-W =30
-H =30
-Color =P2Lightest
-Type=
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Tex = ScoreBar_box_lightest
+X = 733
+Y = 390
+W = 22
+H = 20
+Color = P2Lightest
+Type = Colorized
-[ScoreStaticBoxDark3]
-Tex =ScoreBox
-X =510
-Y =300
-W =30
-H =30
-Color =P2Dark
-Type=
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[ScoreTextGoldenNotes3]
+X = 728
+Y = 387
+Color = Black
+Font = 0
+Size = 24
+Text = SING_GOLDEN_NOTES
+Align = 2
-[ScoreStaticBackLevel1]
-Tex =ScoreLevel
-X =460
-Y =140
-W =120
-H =300
-Color =P1Lightest
-Type =Font Black
-TexX1=0
-TexY1=0.1
-TexX2=1
-TexY2=0.9
+[ScoreTextGoldenNotesScore3]
+X = 518
+Y = 387
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = 0000
-[ScoreStaticBackLevelRound1]
-Tex =ScoreLevelRound
-X =460
-Y =110
-W =120
-H =30
-Color =P1Lightest
-Type =Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=0.5
+[ScoreTextTotal3]
+X = 718
+Y = 454
+Color = Black
+Font = 0
+Size = 30
+Text = SING_TOTAL
+Align = 2
-[ScoreStaticLevel1]
-Tex =ScoreLevel
-X =460
-Y =410
-W =120
-H =30
-Color =P1Light
-Type =Font Black
-TexX1=0
-TexY1=0.1
-TexX2=1
-TexY2=0.9
-[ScoreStaticLevelRound1]
-Tex =ScoreLevelRound
-X =460
-Y =380
-W =120
-H =30
-Color =P1Light
-Type =Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=0.5
+[ScoreTextTotalScore3]
+X = 517
+Y = 444
+Color = Black
+Font = 0
+Size = 42
+Align = 0
+Text = 00000
-[ScoreStaticBackLevel2]
-Tex =ScoreLevel
-X =290
-Y =140
-W =120
-H =300
-Color =P1Lightest
-Type =Font Black
-TexX1=0
-TexY1=0.1
-TexX2=1
-TexY2=0.9
-[ScoreStaticBackLevelRound2]
-Tex =ScoreLevelRound
-X =290
-Y =110
-W =120
-H =30
-Color =P1Lightest
-Type =Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=0.5
+#Lines
+[ScorePlayer3Static1]
+Tex = ScoreLine
+X = 518
+Y = 351
+W = 237
+H = 1
+Type = Transparent
+Color = Gray
-[ScoreStaticLevel2]
-Tex =ScoreLevel
-X =290
-Y =410
-W =120
-H =30
-Color =P1Light
-Type =Font Black
-TexX1=0
-TexY1=0.1
-TexX2=1
-TexY2=0.9
+[ScorePlayer3Static2]
+Tex = ScoreLine
+X = 518
+Y = 382
+W = 237
+H = 1
+Type = Transparent
+Color = Gray
-[ScoreStaticLevelRound2]
-Tex =ScoreLevelRound
-X =290
-Y =380
-W =120
-H =30
-Color =P1Light
-Type =Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=0.5
+[ScoreStaticPlayerIdBox3]
+Tex = PlayerIDBox02
+X = 729
+Y = 455
+W = 26
+H = 23
+Type = Transparent
+Color = White
+
+#ScoreBar
[ScoreStaticBackLevel3]
-Tex =ScoreLevel
-X =390
-Y =140
-W =120
-H =300
-Color =P2Lightest
-Type =Font Black
-TexX1=0
-TexY1=0.1
-TexX2=1
-TexY2=0.9
+Tex = ScoreLevel
+X = 409
+Y = 168
+W = 95
+H = 310
+Color = P2Lightest
+Type = Colorized
[ScoreStaticBackLevelRound3]
-Tex =ScoreLevelRound
-X =390
-Y =110
-W =120
-H =30
-Color =P2Lightest
-Type =Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=0.5
+Tex = ScoreLevelRound
+X = 409
+Y = 138
+W = 95
+H = 8
+Color = P2Lightest
+Type = Colorized
[ScoreStaticLevel3]
-Tex =ScoreLevel
-X =390
-Y =410
-W =120
-H =30
-Color =P2Light
-Type =Font Black
-TexX1=0
-TexY1=0.1
-TexX2=1
-TexY2=0.9
+Tex = ScoreLevel
+X = 409
+Y = 400
+W = 95
+H = 10
+Color = P2Dark
+Type = Colorized
[ScoreStaticLevelRound3]
-Tex =ScoreLevelRound
-X =390
-Y =380
-W =120
-H =30
-Color =P2Light
-Type =Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=0.5
+Tex = ScoreLevelRound
+X = 409
+Y = 392
+W = 95
+H = 8
+Color = P2Dark
+Type = Colorized
-[ScorePlayer4Static1]
-X=20
-Y=205
-W=240
-H=6
-Tex=ScoreLine
-Type=Font Black
-Color=GrayDark
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[ScorePlayer4Static2]
-X=20
-Y=345
-W=240
-H=6
-Tex=ScoreLine
-Type=Font Black
-Color=GrayDark
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[ScorePlayer4Static3]
-X=20
-Y=410
-W=240
-H=6
-Tex=ScoreLine
-Type=Font Black
-Color=GrayDark
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[ScoreStaticBoxLightest4]
-X=20
-Y=220
-W=30
-H=30
-Tex=ScoreBox
-Type=
-Color=P1Lightest
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[ScoreStaticBoxDark4]
-X=20
-Y=300
-W=30
-H=30
-Tex=ScoreBox
-Type=
-Color=P1Dark
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[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=1
-Size = 36
-Align=0
-Text=P1
-Color=P1Dark
+X = 20
+Y = 160
+Font = 0
+Size = 42
+Align = 0
+Text = P1
+Color = Black
-[ScoreTextScore4]
-X=70
-Y=110
-Font=1
-Size = 27
-Align=0
-Text=Tone Deaf
-Color=GrayDark
+# Rating
+[ScoreStaticRatingPicture4]
+X = 200
+Y = 150
+H = 60
+W = 60
[ScoreTextNotes4]
-X=55
-Y=220
-Font=0
+X = 20
+Y = 220
+Font = 0
Size = 27
-Align=0
-Text=SING_NOTES
-Color=GrayDark
+Align = 0
+Text = SING_NOTES
+Color = Black
[ScoreTextNotesScore4]
-X=260
-Y=220
-Font=1
+X = 260
+Y = 220
+Font = 0
Size = 30
-Align=2
-Text=0000
-Color=GrayDark
+Align = 2
+Text = 0000
+Color = Black
[ScoreTextLineBonus4]
-X=55
-Y=260
-Font=0
+X = 20
+Y = 250
+Font = 0
Size = 27
-Align=0
-Text=SING_PHRASE_BONUS
-Color=GrayDark
+Align = 0
+Text = SING_PHRASE_BONUS
+Color = Black
[ScoreTextLineBonusScore4]
-X=260
-Y=260
-Font=1
+X = 260
+Y = 250
+Font = 0
Size = 30
-Align=2
-Text=0000
-Color=GrayDark
+Align = 2
+Text = 0000
+Color = Black
[ScoreTextGoldenNotes4]
-X=55
-Y=300
-Font=0
+X = 20
+Y = 280
+Font = 0
Size = 27
-Align=0
-Text=SING_GOLDEN_NOTES
-Color=GrayDark
+Align = 0
+Text = SING_GOLDEN_NOTES
+Color = Black
[ScoreTextGoldenNotesScore4]
-X=260
-Y=300
-Font=1
+X = 260
+Y = 280
+Font = 0
Size = 30
-Align=2
-Text=0000
-Color=GrayDark
+Align = 2
+Text = 0000
+Color = Black
-[ScoreTextTotal4]
-X=20
-Y=370
-Font=0
+[ScoreTextScore4]
+X = 20
+Y = 310
+Font = 1
Size = 27
-Align=0
-Text=SING_TOTAL
-Color=GrayDark
+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=360
-Font=1
-Size = 45
-Align=2
-Text=00000
-Color=GrayDark
+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
-[ScoreStaticBackLevel4]
-X=0
-Y=0
-W=0
-H=0
-Tex=
-Type=
-Color=
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[ScoreStaticBackLevelRound4]
-X=0
-Y=0
-W=0
-H=0
-Tex=
-Type=
-Color=
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[ScoreStaticLevel4]
-X=0
-Y=0
-W=0
-H=0
-Tex=
-Type=
-Color=
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[ScoreStaticLevelRound4]
-X=0
-Y=0
-W=0
-H=0
-Tex=
-Type=
-Color=
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[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=1
-Size = 36
-Align=0
-Text=P2
-Color=P2Dark
+X = 280
+Y = 160
+Font = 0
+Size = 42
+Align = 0
+Text = P2
+Color = Black
-[ScoreTextScore5]
-X=330
-Y=110
-Font=1
-Size = 27
-Align=0
-Text=Tone Deaf
-Color=GrayDark
+# Rating
+[ScoreStaticRatingPicture5]
+X = 460
+Y = 150
+H = 60
+W = 60
[ScoreTextNotes5]
-X=315
-Y=220
-Font=0
+X = 280
+Y = 220
+Font = 0
Size = 27
-Align=0
-Text=SING_NOTES
-Color=GrayDark
+Align = 0
+Text = SING_NOTES
+Color = Black
[ScoreTextNotesScore5]
-X=520
-Y=220
-Font=1
+X = 520
+Y = 220
+Font = 0
Size = 30
-Align=2
-Text=0000
-Color=GrayDark
+Align = 2
+Text = 0000
+Color = Black
[ScoreTextLineBonus5]
-X=315
-Y=260
-Font=0
+X = 280
+Y = 250
+Font = 0
Size = 27
-Align=0
-Text=SING_PHRASE_BONUS
-Color=GrayDark
+Align = 0
+Text = SING_PHRASE_BONUS
+Color = Black
[ScoreTextLineBonusScore5]
-X=520
-Y=260
-Font=1
+X = 520
+Y = 250
+Font = 0
Size = 30
-Align=2
-Text=0000
-Color=GrayDark
+Align = 2
+Text = 0000
+Color = Black
[ScoreTextGoldenNotes5]
-X=315
-Y=300
-Font=0
+X = 280
+Y = 280
+Font = 0
Size = 27
-Align=0
-Text=SING_GOLDEN_NOTES
-Color=GrayDark
+Align = 0
+Text = SING_GOLDEN_NOTES
+Color = Black
[ScoreTextGoldenNotesScore5]
-X=520
-Y=300
-Font=1
+X = 520
+Y = 280
+Font = 0
Size = 30
-Align=2
-Text=0000
-Color=GrayDark
+Align = 2
+Text = 0000
+Color = Black
-[ScoreTextTotal5]
-X=280
-Y=370
-Font=0
+[ScoreTextScore5]
+X = 280
+Y = 310
+Font = 1
Size = 27
-Align=0
-Text=SING_TOTAL
-Color=GrayDark
+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=360
-Font=1
-Size = 45
-Align=2
-Text=00000
-Color=GrayDark
+X = 520
+Y = 361
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+Color = Black
-[ScoreStaticBackLevel5]
-X=0
-Y=0
-W=0
-H=0
-Tex=
-Type=
-Color=
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[ScoreStaticBackLevelRound5]
-X=0
-Y=0
-W=0
-H=0
-Tex=
-Type=
-Color=
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[ScoreStaticLevel5]
-X=0
-Y=0
-W=0
-H=0
-Tex=
-Type=
-Color=
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[ScoreStaticLevelRound5]
-X=0
-Y=0
-W=0
-H=0
-Tex=
-Type=
-Color=
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[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=1
-Size = 36
-Align=0
-Text=P2
-Color=P3Dark
+X = 540
+Y = 160
+Font = 0
+Size = 42
+Align = 0
+Text = P3
+Color = Black
-[ScoreTextScore6]
-X=590
-Y=110
-Font=1
-Size = 27
-Align=0
-Text=Tone Deaf
-Color=GrayDark
+# Rating
+[ScoreStaticRatingPicture6]
+X = 720
+Y = 150
+H = 60
+W = 60
[ScoreTextNotes6]
-X=575
-Y=220
-Font=0
+X = 540
+Y = 220
+Font = 0
Size = 27
-Align=0
-Text=SING_NOTES
-Color=GrayDark
+Align = 0
+Text = SING_NOTES
+Color = Black
[ScoreTextNotesScore6]
-X=780
-Y=220
-Font=1
+X = 780
+Y = 220
+Font = 0
Size = 30
-Align=2
-Text=0000
-Color=GrayDark
+Align = 2
+Text = 0000
+Color = Black
[ScoreTextLineBonus6]
-X=575
-Y=260
-Font=0
+X = 540
+Y = 250
+Font = 0
Size = 27
-Align=0
-Text=SING_PHRASE_BONUS
-Color=GrayDark
+Align = 0
+Text = SING_PHRASE_BONUS
+Color = Black
[ScoreTextLineBonusScore6]
-X=780
-Y=260
-Font=1
+X = 780
+Y = 250
+Font = 0
Size = 30
-Align=2
-Text=0000
-Color=GrayDark
+Align = 2
+Text = 0000
+Color = Black
[ScoreTextGoldenNotes6]
-X=575
-Y=300
-Font=0
+X = 540
+Y = 280
+Font = 0
Size = 27
-Align=0
-Text=SING_GOLDEN_NOTES
-Color=GrayDark
+Align = 0
+Text = SING_GOLDEN_NOTES
+Color = Black
[ScoreTextGoldenNotesScore6]
-X=780
-Y=300
-Font=1
+X = 780
+Y = 280
+Font = 0
Size = 30
-Align=2
-Text=0000
-Color=GrayDark
+Align = 2
+Text = 0000
+Color = Black
-[ScoreTextTotal6]
-X=540
-Y=370
-Font=0
+[ScoreTextScore6]
+X = 540
+Y = 310
+Font = 1
Size = 27
-Align=0
-Text=SING_TOTAL
-Color=GrayDark
-
-[ScoreTextTotalScore6]
-X=780
-Y=360
-Font=1
-Size = 45
-Align=2
-Text=00000
-Color=GrayDark
+Align = 0
+Text = Tone Deaf
+Color = Black
-[ScoreStaticBackLevel6]
-X=0
-Y=0
-W=0
-H=0
-Tex=
-Type=
-Color=
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[ScoreStaticBackLevelRound6]
-X=0
-Y=0
-W=0
-H=0
-Tex=
-Type=
-Color=
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[ScoreStaticLevel6]
-X=0
-Y=0
-W=0
-H=0
-Tex=
-Type=
-Color=
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[ScoreStaticLevelRound6]
-X=0
-Y=0
-W=0
-H=0
-Tex=
-Type=
-Color=
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[ScoreTextTotal6]
+X = 567
+Y = 371
+Font = 0
+Size = 30
+Align = 0
+Text = SING_TOTAL
+Color = Black
-[ScorePlayer5Static1]
-X=280
-Y=205
-W=240
-H=6
-Tex=ScoreLine
-Type=Font Black
-Color=GrayDark
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[ScoreTextTotalScore6]
+X = 780
+Y = 361
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
+Color = Black
-[ScorePlayer5Static2]
-X=280
-Y=345
-W=240
-H=6
-Tex=ScoreLine
-Type=Font Black
-Color=GrayDark
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[ScoreStaticBoxDark6]
+Tex = PlayerNumberBox
+X = 540
+Y = 370
+W = 25
+H = 25
+Type = Colorized
+Color = P3Dark
+Z = 0.9
-[ScorePlayer5Static3]
-X=280
-Y=410
-W=240
-H=6
-Tex=ScoreLine
-Type=Font Black
-Color=GrayDark
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[ScoreStaticBoxLightest5]
-X=280
-Y=220
-W=30
-H=30
-Tex=ScoreBox
-Type=
-Color=P2Lightest
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-[ScoreStaticBoxDark5]
-X=280
-Y=300
-W=30
-H=30
-Tex=ScoreBox
-Type=
-Color=P2Dark
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[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=205
-W=240
-H=6
-Tex=ScoreLine
-Type=Font Black
-Color=GrayDark
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+X = 540
+Y = 218
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Gray
[ScorePlayer6Static2]
-X=540
-Y=345
-W=240
-H=6
-Tex=ScoreLine
-Type=Font Black
-Color=GrayDark
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+X = 540
+Y = 248
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Gray
[ScorePlayer6Static3]
-X=540
-Y=410
-W=240
-H=6
-Tex=ScoreLine
-Type=Font Black
-Color=GrayDark
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[ScoreStaticBoxLightest6]
-X=540
-Y=220
-W=30
-H=30
-Tex=ScoreBox
-Type=
-Color=P3Lightest
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+X = 540
+Y = 278
+W = 240
+H = 2
+Tex = ScoreLine
+Type = Transparent
+Color = Gray
-[ScoreStaticBoxDark6]
-X=540
-Y=300
-W=30
-H=30
-Tex=ScoreBox
-Type=
-Color=P3Dark
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[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 = 3
+Texts = 6
+Fade = 2
[OptionsBackground]
-Tex=OptionsBG
+Tex = OptionsBG
+
+[OptionsStatic1]
+X=40
+Y=250
+W=32
+H=32
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
[OptionsText1]
X = 50
Y = 170
-Color=GrayLight
+Color = GrayLight
Font = 1
Size = 75
Text = SING_OPTIONS
+Align = 0
-[OptionsStatic1]
-Tex=MainIcon
-X=40
-Y=250
-W=32
-H=32
-Color=ColorDark
-Type=Font Black
+
+[OptionsTextDescription]
+X = 70
+Y = 248
+Color = GrayDark
+Font = 1
+Size = 30
+Align = 0
+Text =
[OptionsStatic2]
-Tex =ButtonNavi
+X = 156
+Y = 545
+W =32
+H =30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
+
+
+[OptionsText2]
X =196
-Y =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Y = 548
+Color = Black
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
-[OptionsStatic3]
-Tex =ButtonEnter
-X =350
-Y =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-[OptionsStatic4]
-Tex =ButtonEsc
-X =510
-Y =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[OptionsStatic3]
+X =340
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
-[OptionsText2]
-X =226
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_NAVIGATE
-Align=0
[OptionsText3]
X =380
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_SELECT
-Align=0
+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 =540
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_ESC
-Align=0
+X =570
+Y = 548
+Color = Black
+Size = 24
+Align = 0
+Text = SING_LEGEND_ESC
-[OptionsTextDescription]
-X = 70
-Y = 248
-Color=GrayDark
-Font = 1
-Size = 30
[OptionsButtonGame]
X = 40
@@ -2458,20 +2449,19 @@ W = 180
H = 70
Tex = Button
Color = ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
-Type = Font Black
-Texts=1
+DColor = Gray
+Type = Transparent
+Texts = 1
+
[OptionsButtonGameText1]
-X =16
-Y =15
-Font=0
-Size = 39
-Align=0
-Text=SING_OPTIONS_GAME
-Color=White
+X =20
+Y =20
+Font = 1
+Size = 32
+Align = 0
+Text = SING_OPTIONS_GAME
+Color = White
[OptionsButtonGraphics]
X = 220
@@ -2480,20 +2470,19 @@ W = 180
H = 70
Tex = Button
Color = ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
-Type = Font Black
-Texts=1
+DColor = Gray
+Type = Transparent
+Texts = 1
+
[OptionsButtonGraphicsText1]
-X =16
-Y =15
-Font=0
-Size = 39
-Align=0
-Text=SING_OPTIONS_GRAPHICS
-Color=White
+X =20
+Y =20
+Font = 1
+Size = 32
+Align = 0
+Text = SING_OPTIONS_GRAPHICS
+Color = White
[OptionsButtonSound]
X = 400
@@ -2502,20 +2491,18 @@ W = 180
H = 70
Tex = Button
Color = ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
-Type = Font Black
-Texts=1
+DColor = Gray
+Type = Transparent
+Texts = 1
[OptionsButtonSoundText1]
-X =16
-Y =15
-Font=0
-Size = 39
-Align=0
-Text=SING_OPTIONS_SOUND
-Color=White
+X =20
+Y =20
+Font = 1
+Size = 32
+Align = 0
+Text = SING_OPTIONS_SOUND
+Color = White
[OptionsButtonLyrics]
X = 580
@@ -2524,20 +2511,19 @@ W = 180
H = 70
Tex = Button
Color = ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
-Type = Font Black
-Texts=1
+DColor = Gray
+Type = Transparent
+Align = 0
+Texts = 1
[OptionsButtonLyricsText1]
-X =16
-Y =15
-Font=0
-Size = 39
-Align=0
-Text=SING_OPTIONS_LYRICS
-Color=White
+X =20
+Y =20
+Font = 1
+Size = 32
+Align = 0
+Text = SING_OPTIONS_LYRICS
+Color = White
[OptionsButtonThemes]
X = 40
@@ -2546,20 +2532,20 @@ W = 180
H = 70
Tex = Button
Color = ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
-Type = Font Black
-Texts=1
+DColor = Gray
+Type = Transparent
+Align = 0
+Texts = 1
+
[OptionsButtonThemesText1]
-X =16
-Y =15
-Font=0
-Size = 39
-Align=0
-Text=SING_OPTIONS_THEMES
-Color=White
+X =20
+Y =20
+Font = 1
+Size = 32
+Align = 0
+Text = SING_OPTIONS_THEMES
+Color = White
[OptionsButtonRecord]
X = 220
@@ -2568,21 +2554,20 @@ W = 180
H = 70
Tex = Button
Color = ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
-Type = Font Black
-Texts=1
+DColor = Gray
+Type = Transparent
+Align = 0
+Texts = 1
[OptionsButtonRecordText1]
-X =16
-Y =15
-Font=0
-Size = 39
-Align=0
-Text=SING_OPTIONS_RECORD
-Color=White
-Texts=1
+X =20
+Y =20
+Font = 1
+Size = 32
+Align = 0
+Text = SING_OPTIONS_RECORD
+Color = White
+Texts = 1
[OptionsButtonAdvanced]
X = 400
@@ -2591,21 +2576,20 @@ W = 180
H = 70
Tex = Button
Color = ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
-Type = Font Black
-Texts=1
+DColor = Gray
+Type = Transparent
+Align = 0
+Texts = 1
[OptionsButtonAdvancedText1]
-X =16
-Y =15
-Font=0
-Size = 39
-Align=0
-Text=SING_OPTIONS_ADVANCED
-Color=White
-Texts=1
+X =20
+Y =20
+Font = 1
+Size = 32
+Align = 0
+Text = SING_OPTIONS_ADVANCED
+Color = White
+Texts = 1
[OptionsButtonExit]
X = 580
@@ -2614,83 +2598,100 @@ W = 180
H = 70
Tex = Button
Color = ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
-Type = Font Black
-Texts=1
+DColor = Gray
+Type = Transparent
+Align = 0
+Texts = 1
+
[OptionsButtonExitText1]
-X =16
-Y =15
-Font=0
-Size = 39
-Align=0
-Text=SING_OPTIONS_EXIT
-Color=White
+X =20
+Y =20
+Font = 1
+Size = 32
+Align = 0
+Text = SING_OPTIONS_EXIT
+Color = White
[OptionsGame]
-Texts = 3
+Texts = 5
[OptionsGameBackground]
-Tex=OptionsBG
+Tex = OptionsBG
[OptionsGameStatic1]
-X =275
-Y =553
-W =22
-H =22
-Tex=ButtonNavi
-Color =White
-Type=Plain
-Style=5
+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
-[OptionsGameStatic2]
-X =435
-Y =553
-W =22
-H =22
-Tex=ButtonEsc
-Color =White
-Type=Plain
[OptionsGameText2]
-X =305
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=SING_LEGEND_NAVIGATE
+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 =465
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=SING_LEGEND_ESC
+X = 290
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
-[OptionsGameText1]
-X = 50
-Y = 10
-ColR = 0.7
-ColG = 0.7
-ColB = 0.7
-Font = 1
-Size = 75
-Text=SING_OPTIONS_GAME_WHEREAMI
+[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
-TexSBG = MainBar
-Text =SING_OPTIONS_GAME_PLAYERS
-X = 40
-Y = 85
-W = 230
-H = 70
-SkipX = 50
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
Color = ColorDark
DColor = Gray
@@ -2703,14 +2704,16 @@ STColor = White
STDColor = GrayDark
[OptionsGameSelectDifficulty]
+Text = SING_OPTIONS_GAME_DIFFICULTY
Tex = MainBar
-TexSBG = MainBar
-Text =SING_OPTIONS_GAME_DIFFICULTY
-X = 40
-Y = 140
-W = 230
-H = 70
-SkipX = 50
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
Color = ColorDark
DColor = Gray
@@ -2723,14 +2726,16 @@ STColor = White
STDColor = GrayDark
[OptionsGameSelectSlideLanguage]
+Text = SING_OPTIONS_GAME_LANGUAGE
Tex = MainBar
-TexSBG = MainBar
-Text =SING_OPTIONS_GAME_LANGUAGE
-X = 40
-Y = 195
-W = 230
-H = 70
-SkipX = 50
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
Color = ColorDark
DColor = Gray
@@ -2743,773 +2748,918 @@ STColor = White
STDColor = GrayDark
[OptionsGameSelectTabs]
-Tex =MainBar
-TexSBG =MainBar
-Text =SING_OPTIONS_GAME_TABS
-X = 40
-Y = 250
-W = 230
-H = 70
-SkipX = 50
+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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
[OptionsGameSelectSlideSorting]
-Tex =MainBar
-TexSBG =MainBar
-Text =SING_OPTIONS_GAME_SORTING
-X = 40
-Y = 305
-W = 230
-H = 70
-SkipX = 50
+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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
[OptionsGameSelectDebug]
-Tex =MainBar
-TexSBG =MainBar
-Text =SING_OPTIONS_GAME_DEBUG
-X = 40
-Y = 360
-W = 230
-H = 70
-SkipX = 50
+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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
[OptionsGameButtonExit]
-X = 40
-Y = 415
-W = 230
-H = 70
-Tex =MainBar
+X = 70
+Y = 440
+W = 250
+H = 40
+Tex = MainBar
Color = ColorDark
DColor = Gray
-Type = Font Black
+Type = Transparent
[OptionsGraphics]
-Texts = 3
+Texts = 5
[OptionsGraphicsBackground]
-Tex=OptionsBG
+Tex = OptionsBG
[OptionsGraphicsStatic1]
-X =275
-Y =553
-W =22
-H =22
-Tex=ButtonNavi
-Color =White
-Type=Plain
-Style=5
+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
-[OptionsGraphicsStatic2]
-X =435
-Y =553
-W =22
-H =22
-Tex=ButtonEsc
-Color =White
-Type=Plain
[OptionsGraphicsText2]
-X =305
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=SING_LEGEND_NAVIGATE
+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 =465
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=SING_LEGEND_ESC
+X = 290
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
-[OptionsGraphicsText1]
-X = 50
-Y = 10
-ColR = 0.7
-ColG = 0.7
-ColB = 0.7
-Font = 1
-Size = 75
-Text=SING_OPTIONS_GRAPHICS_WHEREAMI
+[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]
-Tex =MainBar
-TexSBG =MainBar
-Text=SING_OPTIONS_GRAPHICS_RESOLUTION
-X = 40
-Y = 85
-W = 230
-H = 70
-SkipX = 50
+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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
[OptionsGraphicsSelectFullscreen]
-Tex =MainBar
-TexSBG =MainBar
-Text =SING_OPTIONS_GRAPHICS_FULLSCREEN
-X = 40
-Y = 140
-W = 230
-H = 70
-SkipX = 50
+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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
[OptionsGraphicsSelectDepth]
-Tex =MainBar
-TexSBG =MainBar
-Text =SING_OPTIONS_GRAPHICS_DEPTH
-X = 40
-Y = 195
-W = 230
-H = 70
-SkipX = 50
+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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
[OptionsGraphicsSelectOscilloscope]
-Tex =MainBar
-TexSBG =MainBar
-Text =SING_OPTIONS_GRAPHICS_OSCILLOSCOPE
-X = 40
-Y = 250
-W = 230
-H = 70
-SkipX = 50
+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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
[OptionsGraphicsSelectMovieSize]
-Tex =MainBar
-TexSBG =MainBar
-Text =SING_OPTIONS_GRAPHICS_MOVIE_SIZE
-X = 40
-Y = 305
-W = 230
-H = 70
-SkipX = 50
+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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
[OptionsGraphicsButtonExit]
-X = 40
-Y = 360
-W = 230
-H = 70
-Tex =MainBar
+X = 70
+Y = 440
+W = 250
+H = 40
+Tex = MainBar
Color = ColorDark
DColor = Gray
-Type = Font Black
+Type = Transparent
[OptionsSound]
-Texts = 3
+Texts = 5
[OptionsSoundBackground]
-Tex=OptionsBG
+Tex = OptionsBG
[OptionsSoundStatic1]
-X =275
-Y =553
-W =22
-H =22
-Tex=ButtonNavi
-Color =White
-Type=Plain
-Style=5
+X = 70
+Y = 80
+W = 32
+H = 32
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
-[OptionsSoundStatic2]
-X =435
-Y =553
-W =22
-H =22
-Tex=ButtonEsc
-Color =White
-Type=Plain
+[OptionsSoundText1]
+X = 70
+Y = 15
+Font = 1
+Color = Gray
+Size = 65
+Text = SING_OPTIONS
[OptionsSoundText2]
-X =305
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=SING_LEGEND_NAVIGATE
+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 =465
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=SING_LEGEND_ESC
+X = 290
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
-[OptionsSoundText1]
-X = 50
-Y = 10
-ColR = 0.7
-ColG = 0.7
-ColB = 0.7
-Font = 1
-Size = 75
-Text =SING_OPTIONS_SOUND_WHEREAMI
+[OptionsSoundStatic3]
+X = 410
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
-[OptionsSoundSelectMicBoost]
-Tex =MainBar
-TexSBG =MainBar
-Text =SING_OPTIONS_SOUND_MIC_BOOST
-X = 40
-Y = 85
-W = 230
-H = 70
-SkipX = 50
+[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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
-[OptionsSoundSelectClickAssist]
-Tex =MainBar
-TexSBG =MainBar
-Text =SING_OPTIONS_SOUND_CLICK_ASSIST
-X = 40
-Y = 140
-W = 230
-H = 70
-SkipX = 50
+[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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
-[OptionsSoundSelectBeatClick]
-Tex =MainBar
-TexSBG =MainBar
-Text =SING_OPTIONS_SOUND_BEAT_CLICK
-X = 40
-Y = 195
-W = 230
-H = 70
-SkipX = 50
+[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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
-[OptionsSoundSelectThreshold]
-Tex =MainBar
-TexSBG =MainBar
-Text =SING_OPTIONS_SOUND_THRESHOLD
-X = 40
+[OptionsSoundSelectClickAssist]
+Tex = MainBar
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+Text = SING_OPTIONS_SOUND_CLICK_ASSIST
+X = 70
Y = 250
-W = 230
-H = 70
-SkipX = 50
+W = 250
+H = 35
+SkipX = 10
Color = ColorDark
DColor = Gray
TColor = White
TDColor = White
-SBGTex =MainBar
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
-[OptionsSoundSelectTwoPlayerMode]
-Tex =MainBar
-TexSBG =MainBar
-Text =SING_OPTIONS_SOUND_TWO_PLAYERS_MODE
-X = 40
-Y = 305
-W = 230
-H = 70
-SkipX = 50
+[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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
[OptionsSoundSelectSlidePreviewVolume]
-Tex =MainBar
-TexSBG =MainBar
-Text=SING_OPTIONS_SOUND_PREVIEWVOLUME
-X = 40
-Y = 305
-W = 230
-H = 70
-SkipX = 50
+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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
-[OptionsSoundSelectSlidePreviewFading]
-Tex =MainBar
-TexSBG =MainBar
-Text=SING_OPTIONS_SOUND_PREVIEWFADING
-X = 40
-Y = 360
-W = 230
-H = 70
-SkipX = 50
+[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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
[OptionsSoundButtonExit]
-X = 40
-Y = 415
-W = 230
-H = 70
-Tex =MainBar
+X = 70
+Y = 460
+W = 250
+H = 40
+Tex = MainBar
Color = ColorDark
DColor = Gray
-Type = Font Black
-
+Type = Transparent
[OptionsLyrics]
-Texts = 3
+Texts = 1
[OptionsLyricsBackground]
-Tex=OptionsBG
+Tex = OptionsBG
[OptionsLyricsStatic1]
-X =275
-Y =553
-W =22
-H =22
-Tex=ButtonNavi
-Color =White
-Type=Plain
-Style=5
+X = 70
+Y = 80
+W = 32
+H = 32
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
-[OptionsLyricsStatic2]
-X =435
-Y =553
-W =22
-H =22
-Tex=ButtonEsc
-Color =White
-Type=Plain
+
+[OptionsLyricsText1]
+X = 70
+Y = 15
+Font = 1
+Color = Gray
+Size = 65
+Text = SING_OPTIONS
[OptionsLyricsText2]
-X =305
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=SING_LEGEND_NAVIGATE
+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 =465
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=SING_LEGEND_ESC
+X = 290
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
-[OptionsLyricsText1]
-X = 50
-Y = 10
-ColR = 0.7
-ColG = 0.7
-ColB = 0.7
-Font = 1
-Size = 75
-Text =SING_OPTIONS_LYRICS_WHEREAMI
+[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
-TexSBG =MainBar
-Text =SING_OPTIONS_LYRICS_FONT
-X = 40
-Y = 85
-W = 230
-H = 70
-SkipX = 50
+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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
[OptionsLyricsSelectLyricsEffect]
-Tex =MainBar
-TexSBG =MainBar
-Text =SING_OPTIONS_LYRICS_EFFECT
-X = 40
-Y = 140
-W = 230
-H = 70
-SkipX = 50
-
-Color = ColorDark
-DColor = Gray
-TColor = White
-TDColor = White
-SBGTex =MainBar
-SBGColor = ColorDark
-SBGDColor = Gray
-STColor = White
-STDColor = GrayDark
-
-[OptionsLyricsSelectSolmization]
-Tex =MainBar
-TexSBG =MainBar
-Text =SING_OPTIONS_LYRICS_SOLMIZATION
-X = 40
-Y = 195
-W = 230
-H = 70
-SkipX = 50
+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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
[OptionsLyricsSelectNoteLines]
-Tex =MainBar
-TexSBG =SelectBG
-Text =SING_OPTIONS_LYRICS_NOTELINES
-X = 40
-Y = 250
-W = 230
-H = 70
-SkipX = 50
+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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
[OptionsLyricsButtonExit]
-X = 40
-Y = 305
-W = 230
-H = 70
-Tex =MainBar
+X = 70
+Y = 290
+W = 250
+H = 40
+Tex = MainBar
Color = ColorDark
DColor = Gray
-Type = Font Black
-
+Type = Transparent
[OptionsThemes]
Texts = 5
[OptionsThemesBackground]
-Tex=OptionsBG
+Tex = OptionsBG
[OptionsThemesStatic1]
-X =275
-Y =553
-W =22
-H =22
-Tex=ButtonNavi
-Color =White
-Type=Plain
-Style=5
+X = 70
+Y = 80
+W = 32
+H = 32
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
-[OptionsThemesStatic2]
-X =435
-Y =553
-W =22
-H =22
-Tex=ButtonEsc
-Color =White
-Type=Plain
+
+[OptionsThemesText1]
+X = 70
+Y = 15
+Font = 1
+Color = Gray
+Size = 65
+Text = SING_OPTIONS
[OptionsThemesText2]
-X =305
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=SING_LEGEND_NAVIGATE
+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 =465
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=SING_LEGEND_ESC
+X = 290
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
-[OptionsThemesText1]
-X = 50
-Y = 10
-ColR = 0.7
-ColG = 0.7
-ColB = 0.7
-Font = 1
-Size = 75
-Text =SING_OPTIONS_THEMES_WHEREAMI
+[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]
-Tex =MainBar
-TexSBG =MainBar
-Text =SING_OPTIONS_THEMES_THEME
-X = 40
-Y = 85
-W = 230
-H = 70
-SkipX = 50
+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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
[OptionsThemesSelectSkin]
-Tex =MainBar
-TexSBG =MainBar
-Text =SING_OPTIONS_THEMES_SKIN
-X = 40
-Y = 140
-W = 230
-H = 70
-SkipX = 50
+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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
[OptionsThemesSelectColor]
-Tex =MainBar
-TexSBG =MainBar
-Text =SING_OPTIONS_THEMES_COLOR
-X = 40
-Y = 195
-W = 230
-H = 70
-SkipX = 50
+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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
[OptionsThemesButtonExit]
-X = 40
-Y = 250
-W = 230
-H = 70
-Tex =MainBar
+X = 70
+Y = 290
+W = 250
+H = 40
+Tex = MainBar
Color = ColorDark
DColor = Gray
-Type = Font Black
-
+Type = Transparent
[OptionsRecord]
-Texts = 3
+Texts = 5
[OptionsRecordBackground]
-Tex=OptionsBG
+Tex = OptionsBG
[OptionsRecordStatic1]
-X =275
-Y =553
-W =22
-H =22
-Tex=ButtonNavi
-Color =White
-Type=Plain
-Style=5
+X = 70
+Y = 80
+W = 32
+H = 32
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
-[OptionsRecordStatic2]
-X =435
-Y =553
-W =22
-H =22
-Tex=ButtonEsc
-Color =White
-Type=Plain
+[OptionsRecordText1]
+X = 70
+Y = 15
+Font = 1
+Color = Gray
+Size = 65
+Text = SING_OPTIONS
[OptionsRecordText2]
-X =305
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=SING_LEGEND_NAVIGATE
+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 =465
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=SING_LEGEND_ESC
+X = 290
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
-[OptionsRecordText1]
-X = 50
-Y = 10
-ColR = 0.7
-ColG = 0.7
-ColB = 0.7
-Font = 1
-Size = 75
-Text=SING_OPTIONS_RECORD_WHEREAMI
+[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
-TexSBG = MainBar
-Text =SING_OPTIONS_RECORD_CARD
-X = 40
-Y = 85
-W = 230
-H = 70
-SkipX = 50
-Fields=1
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 130
+W = 250
+H = 40
+SkipX = 10
Color = ColorDark
DColor = Gray
@@ -3522,15 +3672,16 @@ STColor = White
STDColor = GrayDark
[OptionsRecordSelectSlideInput]
+Text = SING_OPTIONS_RECORD_INPUT
Tex = MainBar
-TexSBG = MainBar
-Text =SING_OPTIONS_RECORD_INPUT
-X = 40
-Y = 140
-W = 230
-H = 70
-SkipX = 50
-Fields=1
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 180
+W = 250
+H = 40
+SkipX = 10
Color = ColorDark
DColor = Gray
@@ -3543,15 +3694,16 @@ STColor = White
STDColor = GrayDark
[OptionsRecordSelectSlideChannel]
+Text = SING_OPTIONS_RECORD_CHANNEL
Tex = MainBar
-TexSBG = MainBar
-Text =SING_OPTIONS_RECORD_CHANNEL
-X = 40
-Y = 195
-W = 230
-H = 70
-SkipX = 50
-Fields=7
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+X = 70
+Y = 230
+W = 250
+H = 40
+SkipX = 10
Color = ColorDark
DColor = Gray
@@ -3564,696 +3716,863 @@ STColor = White
STDColor = GrayDark
[OptionsRecordButtonExit]
-X = 40
-Y = 305
-W = 230
-H = 70
+X = 70
+Y = 390
+W = 250
+H = 40
Tex = MainBar
Color = ColorDark
DColor = Gray
-Type = Font Black
-
+Type = Transparent
[OptionsAdvanced]
-Texts = 3
+Texts = 5
[OptionsAdvancedBackground]
-Tex=OptionsBG
+Tex = OptionsBG
[OptionsAdvancedStatic1]
-X =275
-Y =553
-W =22
-H =22
-Tex=ButtonNavi
-Color =White
-Type=Plain
-Style=5
+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
-[OptionsAdvancedStatic2]
-X =435
-Y =553
-W =22
-H =22
-Tex=ButtonEsc
-Color =White
-Type=Plain
[OptionsAdvancedText2]
-X =305
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=SING_LEGEND_NAVIGATE
+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 =465
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=SING_LEGEND_ESC
+X = 290
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
-[OptionsAdvancedText1]
-X = 50
-Y = 10
-ColR = 0.7
-ColG = 0.7
-ColB = 0.7
-Font = 1
-Size = 75
-Text=SING_OPTIONS_ADVANCED_WHEREAMI
-[OptionsAdvancedSelectLoadAnimation]
-Tex =MainBar
-TexSBG =MainBar
-Text=SING_OPTIONS_ADVANCED_LOADANIMATION
-X = 40
-Y = 85
-W = 230
-H = 70
-SkipX = 50
+[OptionsAdvancedStatic5]
+X = 410
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEsc
+Color = White
+Type = Transparent
-Color = ColorDark
-DColor = Gray
-TColor = White
-TDColor = White
-SBGTex =MainBar
-SBGColor = ColorDark
-SBGDColor = Gray
-STColor = White
-STDColor = GrayDark
+[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]
-Tex =MainBar
-TexSBG =MainBar
-Text =SING_OPTIONS_ADVANCED_SCREENFADE
-X = 40
-Y = 140
-W = 230
-H = 70
-SkipX = 50
+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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
[OptionsAdvancedSelectEffectSing]
-Tex =MainBar
-TexSBG =MainBar
-Text =SING_OPTIONS_ADVANCED_EFFECTSING
-X = 40
-Y = 195
-W = 230
-H = 70
-SkipX = 50
+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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
[OptionsAdvancedSelectLineBonus]
-Tex =MainBar
-TexSBG =MainBar
-Text =SING_OPTIONS_GRAPHICS_LINEBONUS
-X = 40
-Y = 250
-W = 230
-H = 70
-SkipX = 50
+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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
[OptionsAdvancedSelectSlideOnSongClick]
-Tex =MainBar
-TexSBG =MainBar
-Text=SING_OPTIONS_ADVANCED_ONSONGCLICK
-X = 40
-Y = 305
-W = 230
-H = 70
-SkipX = 50
+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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
[OptionsAdvancedSelectAskbeforeDel]
-Tex =MainBar
-TexSBG =MainBar
-Text =SING_OPTIONS_ADVANCED_ASKBEFOREDEL
-X = 40
-Y = 360
-W = 230
-H = 70
-SkipX = 50
+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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
[OptionsAdvancedSelectPartyPopup]
-Tex =MainBar
-TexSBG =MainBar
-Text =SING_OPTIONS_ADVANCED_PARTYPOPUP
-X = 40
-Y = 415
-W = 230
-H = 70
-SkipX = 50
+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
+SBGTex = MainBar
SBGColor = ColorDark
SBGDColor = Gray
STColor = White
STDColor = GrayDark
[OptionsAdvancedButtonExit]
-X = 40
-Y = 470
-W = 230
-H = 70
-Tex =MainBar
+X = 70
+Y = 440
+W = 250
+H = 40
+Tex = MainBar
Color = ColorDark
DColor = Gray
-Type = Font Black
+Type = Transparent
[Top5]
-Texts=1
+Texts = 1
[Top5Background]
-Tex=Top5BG
-
-[Top5Static2]
-Tex =ButtonEnter
-X =350
-Y =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[Top5Text2]
-X =380
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_CONTINUE
-Align=0
+Tex = Top5BG
[Top5Text1]
-X =100
-Y =50
-Color =Gray
+X = 70
+Y = 6
+Color = GrayLight
Font =1
Size = 60
-Align =0
-Text =SING_TOP_5_CHARTS
+Text = SING_TOP_5_CHARTS
-[Top5Static1]
-Tex=Bar
-X=560
-Y=55
-W=140
-H=50
-Color=ColorLight
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[Top5TextArtistTitle]
+X = 105
+Y = 65
+Color = GrayDark
+Font = 0
+Size = 26
+Align = 0
+Text = artist - title
-[Top5TextLevel]
-X =630
-Y =65
-Color =White
-Font =1
+[Top5Text4]
+X = 390
+Y = 30
+Color = Black
+Font = 0
Size = 30
-Align =1
-Text =easy
+Align = 0
+Text = SING_OPTIONS_GAME_DIFFICULTY
-[Top5TextArtistTitle]
-X =100
-Y =120
-Color =Black
-Font =0
+[Top5TextLevel]
+X = 600
+Y = 30
+Color = Black
+Font = 0
Size = 30
-Align =0
-Text =artist - title
+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 =170
-Y =200
-Color =GrayDark
-Font =1
+X = 150
+Y = 190
+Color = Black
+Font = 0
Size = 42
-Align =0
-Text =1. Player1
+Align = 0
+Text = 1. Player1
[Top5TextName2]
-X =150
-Y =290
-Color =GrayDark
-Font =0
-Size = 33
-Align =0
-Text =2. Player2
+X = 150
+Y = 240
+Color = Black
+Font = 0
+Size = 42
+Align = 0
+Text = 2. Player2
[Top5TextName3]
-X =150
-Y =340
-Color =GrayDark
-Font =0
-Size = 33
-Align =0
-Text =3. Player3
+X = 150
+Y = 290
+Color = Black
+Font = 0
+Size = 42
+Align = 0
+Text = 3. Player3
[Top5TextName4]
-X =150
-Y =390
-Color =GrayDark
-Font =0
-Size = 33
-Align =0
-Text =4. Player4
+X = 150
+Y = 340
+Color = Black
+Font = 0
+Size = 42
+Align = 0
+Text = 4. Player4
[Top5TextName5]
-X =150
-Y =440
-Color =GrayDark
-Font =0
-Size = 33
-Align =0
-Text =5. Player5
+X = 150
+Y = 390
+Color = Black
+Font = 0
+Size = 42
+Align = 0
+Text = 5. Player5
[Top5TextScore1]
-X =680
-Y =195
-Color =GrayDark
-Font =1
-Size = 51
-Align =2
-Text =00000
+X = 560
+Y = 190
+Color = Black
+Font = 0
+Size = 42
+Align = 2
+Text = 00000
[Top5TextScore2]
-X =680
-Y =290
-Color =GrayDark
-Font =1
+X = 560
+Y = 240
+Color = Black
+Font = 0
Size = 42
-Align =2
-Text =00000
+Align = 2
+Text = 00000
[Top5TextScore3]
-X =680
-Y =340
-Color =GrayDark
-Font =1
+X = 560
+Y = 290
+Color = Black
+Font = 0
Size = 42
-Align =2
-Text =00000
+Align = 2
+Text = 00000
[Top5TextScore4]
-X =680
-Y =390
-Color =GrayDark
-Font =1
+X = 560
+Y = 340
+Color = Black
+Font = 0
Size = 42
-Align =2
-Text =00000
+Align = 2
+Text = 00000
[Top5TextScore5]
-X =680
-Y =440
-Color =GrayDark
-Font =1
+X = 560
+Y = 390
+Color = Black
+Font = 0
Size = 42
-Align =2
-Text =00000
+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 =130
-Y =202
-Color =White
-Font =1
-Size = 33
-Align =1
-Text =1
+X = 120
+Y = 193
+Color = White
+Font = 1
+Size = 27
+Align = 1
+Text = 1
[Top5TextNumber2]
-X =120
-Y =293
-Color =White
-Font =1
+X = 120
+Y = 243
+Color = White
+Font = 1
Size = 27
-Align =1
-Text =2
+Align = 1
+Text = 2
[Top5TextNumber3]
-X =120
-Y =343
-Color =White
-Font =1
+X = 120
+Y = 293
+Color = White
+Font = 1
Size = 27
-Align =1
-Text =3
+Align = 1
+Text = 3
[Top5TextNumber4]
-X =120
-Y =393
-Color =White
-Font =1
+X = 120
+Y = 343
+Color = White
+Font = 1
Size = 27
-Align =1
-Text =4
+Align = 1
+Text = 4
[Top5TextNumber5]
-X =120
-Y =443
-Color =White
-Font =1
+X = 120
+Y = 393
+Color = White
+Font = 1
Size = 27
-Align =1
-Text =5
+Align = 1
+Text = 5
[Top5StaticNumber1]
-Tex=Bar
-X=100
-Y=190
-W=60
-H=60
-Color=ColorLight
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Tex = PlayerNumberBox
+X = 100
+Y = 186
+W = 40
+H = 40
+Color = P1Dark
+Type = Colorized
[Top5StaticNumber2]
-Tex=Bar
-X=100
-Y=286
-W=40
-H=40
-Color=ColorLight
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Tex = PlayerNumberBox
+X = 100
+Y = 236
+W = 40
+H = 40
+Color = P1Dark
+Type = Colorized
[Top5StaticNumber3]
-Tex=Bar
-X=100
-Y=336
-W=40
-H=40
-Color=ColorLight
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Tex = PlayerNumberBox
+X = 100
+Y = 286
+W = 40
+H = 40
+Color = P1Dark
+Type = Colorized
[Top5StaticNumber4]
-Tex=Bar
-X=100
-Y=386
-W=40
-H=40
-Color=ColorLight
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Tex = PlayerNumberBox
+X = 100
+Y = 336
+W = 40
+H = 40
+Color = P1Dark
+Type = Colorized
[Top5StaticNumber5]
-Tex=Bar
-X=100
-Y=436
-W=40
-H=40
-Color=ColorLight
-Type=Font Black
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Tex = PlayerNumberBox
+X = 100
+Y = 386
+W = 40
+H = 40
+Color = P1Dark
+Type = Colorized
[Edit]
-Texts = 1
+Texts = 5
[EditBackground]
Tex = EditBG
-# main title
-[EditText1]
-X = 50
-Y = 170
-Color = GrayLight
-Font = 1
-Size = 75
-Text = SING_EDIT
-
# main icon
[EditStatic1]
-X = 40
-Y = 250
-W = 32
-H = 32
+X = 65
+Y = 65
+W = 27
+H = 27
Color = ColorDark
Tex = MainIcon
-Type = Font Black
+Type = Transparent
-# Navigate button text
-[EditText2]
-X = 226
-Y = 553
+# Type = Colorized
+
+# main icon title
+[EditText1]
+X = 70
+Y = 5
Color = Gray
Font = 1
-Size = 21
+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
-[EditText3]
-X = 380
-Y = 553
-Color = Gray
-Font = 1
-Size = 21
+[EditText4]
+X =350
+Y = 548
+Color = Black
+Font = 0
+Size = 24
Align = 0
Text = SING_EDIT_SELECT
-# Escape button text
-[EditText4]
-X = 540
-Y = 553
-Color = Gray
-Font = 1
-Size = 21
+
+# Esc button text
+[EditText5]
+X =570
+Y = 548
+Color = Black
+Font = 0
+Size = 24
Align = 0
Text = SING_EDIT_EXIT
+
[EditTextDescription]
-X = 72
-Y = 248
-Color = GrayDark
-Font = 1
+X = 95
+Y = 195
+Color = Black
+Font = 0
Size = 30
-#Text = SING_EDIT_TEXTDESCRIPTION
+Align = 0
+Text = SING_EDIT_TEXTDESCRIPTION
[EditStatic2]
-X = 196
-Y = 553
-W = 22
-H = 22
+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 = Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Type = Transparent
-[EditStatic3]
-X = 350
-Y = 552
-W = 22
-H = 22
+
+[EditStatic5]
+X =310
+Y = 545
+W = 32
+H = 30
Tex = ButtonEnter
Color = White
-Type = Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Type = Transparent
-[EditStatic4]
-X = 510
-Y = 553
-W = 22
-H = 22
+[EditStatic6]
+X =530
+Y = 545
+W = 32
+H = 30
Tex = ButtonEsc
Color = White
-Type = Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Type = Transparent
[EditButtonConvert]
-X = 40
-Y = 310
-W = 250
-H = 70
+X = 250
+Y = 270
+W = 150
+H = 50
Tex = Button
Color = ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
-Type = Font Black
+DColor = Gray
+Type = Transparent
Texts = 1
[EditButtonConvertText1]
-X = 115
-Y = 20
-Font = 1
-Size = 27
+X = 75
+Y = 10
+Font = 0
+Size = 30
Align = 1
Text = SING_EDIT_BUTTON_CONVERT
Color = White
-[Level]
-Texts=2
+[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
+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]
-Tex =ButtonNavi
-X =196
-Y =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
[LevelStatic3]
-Tex =ButtonEnter
-X =350
-Y =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
[LevelStatic4]
-Tex =ButtonEsc
-X =510
-Y =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+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 =226
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_NAVIGATE
-Align=0
+X =256
+Y = 548
+Color = Black
+Size = 24
+Align = 0
+Text = SING_LEGEND_NAVIGATE
-[LevelText4]
-X =380
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_SELECT
-Align=0
-[LevelText5]
-X =540
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_ESC
-Align=0
+[LevelText4]
+X =440
+Y = 548
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = SING_DIFFICULTY_CONTINUE
-[LevelStatic1]
-X=20
-Y=250
-W=32
-H=32
-Tex=MainIcon
-Type=Font Black
-Color=ColorDark
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
[LevelButtonEasy]
Tex=Button
@@ -4261,12 +4580,10 @@ X=25
Y=310
W=250
H=70
-Type=Font Black
-Texts=1
-Color=ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
[LevelButtonMedium]
Tex=Button
@@ -4274,12 +4591,11 @@ X=275
Y=310
W=250
H=70
-Type=Font Black
-Texts=1
-Color=ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+
[LevelButtonHard]
Tex=Button
@@ -4287,30 +4603,12 @@ X=525
Y=310
W=250
H=70
-Type=Font Black
-Texts=1
-Color=ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
-
-[LevelText1]
-X=30
-Y=180
-Font=1
-Size = 66
-Align=0
-Text=SING_DIFFICULTY_WHEREAMI
-Color=GrayLight
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
-[LevelText2]
-X=50
-Y=248
-Font=1
-Size = 30
-Align=0
-Text=SING_DIFFICULTY_DESC
-Color=GrayDark
[LevelButtonEasyText1]
X=115
@@ -4339,91 +4637,20 @@ Align=1
Text=SING_HARD
Color=White
-
[Name]
-Texts=2
+Texts = 2
[NameBackground]
-Tex=MainBG
-
-[NameStatic2]
-Tex =ButtonNavi
-X =176
-Y =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[NameStatic3]
-Tex =ButtonAZ
-X =330
-Y =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[NameStatic4]
-Tex =ButtonEnter
-X =532
-Y =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[NameText3]
-X =206
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_NAVIGATE
-Align=0
-
-[NameText4]
-X =360
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_PLAYER_ENTER_NAME
-Align=0
-
-[NameText5]
-X =562
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_CONTINUE
-Align=0
+Tex = MainBG
[NameStatic1]
X=20
Y=250
W=32
H=32
-Tex=MainIcon
-Type=Font Black
-Color=ColorDark
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
[NameText1]
X=30
@@ -4431,7 +4658,7 @@ Y=180
Font=1
Size = 66
Align=0
-Text=SING_PLAYER_WHEREAMI
+Text = SING_MODE
Color=GrayLight
[NameText2]
@@ -4443,1507 +4670,1521 @@ 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]
-Tex=Button
X=25
Y=310
W=250
H=70
-Type=Font Black
-Texts=1
-Color=P1Dark
-DColor=P1Lightest
-DInt=0.5
+Tex = Button
+Color = P1Dark
+DColor = P1Light
+Type = Transparent
+Texts = 1
+
[NameButtonPlayer1Text1]
X=115
Y=20
-Font=1
-Size = 27
-Align=1
-Text=
-Color=White
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
[NameButtonPlayer2]
-Tex=Button
-X=25
-Y=380
+X = 275
+Y=310
W=250
H=70
-Type=Font Black
-Texts=1
-Color=P2Dark
-DColor=P2Lightest
-DInt=0.5
+Tex = Button
+Color = P2Dark
+DColor = P2Light
+Type = Transparent
+Texts = 1
+
[NameButtonPlayer2Text1]
X=115
Y=20
-Font=1
-Size = 27
-Align=1
-Text=
-Color=White
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
[NameButtonPlayer3]
-Tex=Button
-X=25
-Y=450
+X = 525
+Y=310
W=250
H=70
-Type=Font Black
-Texts=1
-Color=P3Dark
-DColor=P3Lightest
-DInt=0.5
+Tex = Button
+Color = P3Dark
+DColor = P3Light
+Type = Transparent
+Texts = 1
+
[NameButtonPlayer3Text1]
X=115
Y=20
-Font=1
-Size = 27
-Align=1
-Text=
-Color=White
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
[NameButtonPlayer4]
-Tex=Button
-X=425
-Y=310
+X=25
+Y=400
W=250
H=70
-Type=Font Black
-Texts=1
-Color=P4Dark
-DColor=P4Lightest
-DInt=0.5
+Tex = Button
+Color = P4Dark
+DColor = P4Light
+Type = Transparent
+Texts = 1
+
[NameButtonPlayer4Text1]
X=115
Y=20
-Font=1
-Size = 27
-Align=1
-Text=
-Color=White
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
[NameButtonPlayer5]
-Tex=Button
-X=425
-Y=380
+X = 275
+Y=400
W=250
H=70
-Type=Font Black
-Texts=1
-Color=P5Dark
-DColor=P5Lightest
-DInt=0.5
+Tex = Button
+Color = P5Dark
+DColor = P5Light
+Type = Transparent
+Texts = 1
+
[NameButtonPlayer5Text1]
X=115
Y=20
-Font=1
-Size = 27
-Align=1
-Text=
-Color=White
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
[NameButtonPlayer6]
-Tex=Button
-X=425
-Y=450
+X = 525
+Y=400
W=250
H=70
-Type=Font Black
-Texts=1
-Color=P6Dark
-DColor=P6Lightest
-DInt=0.5
+Tex = Button
+Color = P6Dark
+DColor = P6Light
+Type = Transparent
+Texts = 1
+
[NameButtonPlayer6Text1]
X=115
Y=20
-Font=1
-Size = 27
-Align=1
-Text=
-Color=White
+Font = 0
+Size = 30
+Align = 1
+Color = White
+Text =
[PartyNewRound]
-Texts =7
+Texts = 7
+
+[PartyNewRoundBackground]
+Tex = MainBG
[PartyNewRoundStatic1]
-X =0
-Y =549
-W =252
-H =28
-Tex=Leiste1
-Color =Gray
-Type=Plain
-Reflection=1
-ReflectionSpacing=1
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
[PartyNewRoundStatic2]
-X =254
-Y =549
-W =548
-H =28
-Tex=Leiste2
-Color =Gray
-Type=Plain
-Reflection=1
-ReflectionSpacing=1
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
[PartyNewRoundStatic3]
-X =37
-Y =72
-W =27
-H =27
-Color =ColorDark
-Tex =MainIcon
-Type=Font Black
+X = 65
+Y = 65
+W = 27
+H = 27
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
[PartyNewRoundText1]
-X =40
-Y =4
+X = 70
+Y = 5
+ColR = 0.7
+ColG = 0.7
+ColB = 0.7
Font = 1
-Size = 66
-Color =GrayLight
-Text=PARTY_MODE
+Size = 60
+Color = GrayLight
+Text = PARTY_MODE
[PartyNewRoundText2]
-X =62
-Y =67
-Color=Black
-Font =1
-Size = 27
-Align =0
-Text=PARTY_ROUND_DESC
+X = 100
+Y = 63
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_ROUND_DESC
[PartyNewRoundText3]
-X =398
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=2
-Text=PARTY_ROUND_WHEREAMI
+X = 388
+Y = 555
+Color = Black
+Font = 0
+Size = 24
+Align = 2
+Text = PARTY_ROUND_WHEREAMI
[PartyNewRoundText4]
-X =450
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=PARTY_ROUND_LEGEND_CONTINUE
+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
+X = 460
+Y = 100
+Color = White
+Font = 0
Size = 30
-Text =PARTY_ROUND
-Align=0
+Text = PARTY_ROUND
+Align = 0
[PartyNewRoundText6]
-X =600
-Y =100
-Color =White
-Font =0
+X = 600
+Y = 100
+Color = White
+Font = 0
Size = 30
-Text =PARTY_ROUND_WINNER
-Align=0
+Text = PARTY_ROUND_WINNER
+Align = 0
[PartyNewRoundText7]
-X =448
-Y =350
-Color =White
-Font =0
+X = 448
+Y = 350
+Color = White
+Font = 0
Size = 54
-Text =PARTY_ROUND
-Align=2
+Text = PARTY_ROUND
+Align = 2
[PartyNewRoundTextTeam1Players]
-X =30
-Y =137
-Color=White
-Font =0
+X = 30
+Y = 137
+Color = White
+Font = 0
Size = 21
-Align=0
-Text=Dummytext, Player2, Player3, Player4
+Align = 0
+Text = Dummytext, Player2, Player3, Player4
[PartyNewRoundTextTeam2Players]
-X =30
-Y =218
-Color=White
-Font =0
+X = 30
+Y = 218
+Color = White
+Font = 0
Size = 21
-Align=0
-Text=Dummytext, Player2, Player3, Player4
+Align = 0
+Text = Dummytext, Player2, Player3, Player4
[PartyNewRoundTextTeam3Players]
-X =30
-Y =299
-Color=White
-Font =0
+X = 30
+Y = 299
+Color = White
+Font = 0
Size = 21
-Align=0
-Text=Dummytext, Player2, Player3, Player4
+Align = 0
+Text = Dummytext, Player2, Player3, Player4
[PartyNewRoundStatic4]
-Tex =PartyRoundBG1
-X =450
-Y =103
+Tex = PartyRoundBG1
+X = 450
+Y = 103
W = 330
H = 24
-Int=1
-Color =Gray
-Type=Font Black
+Color = Gray
+Type = Transparent
[PartyNewRoundStatic5]
-X =420
-Y =553
-W =26
-H =22
-Tex=ButtonEnter
-Color =White
-Type=Plain
+X = 410
+Y = 553
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
[PartyNewRoundStatic6]
-Tex =PartyRoundBG3
-X =250
-Y =350
+Tex = PartyRoundBG3
+X = 250
+Y = 350
W = 300
H = 50
-Int=1
-Color =Gray
-Type=Font Black
+Color = Gray
+Type = Transparent
[PartyNewRoundStatic7]
-Tex =PartyRoundBG4
-X =50
-Y =495
+Tex = PartyRoundBG4
+X = 50
+Y = 495
W = 700
H = 30
-Int=1
-Color =GrayLight
-Type=Font Black
+Color = GrayLight
+Type = Transparent
[PartyNewRoundStaticTeam1]
-Tex =PartyTeamButton1
-X =20
-Y =110
-W =400
-H =50
-Int=1
-Color =P1Dark
-Type=Font Black
-Reflection=0
+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
-Int=1
-Color =P2Dark
-Type=Font Black
-Reflection=0
+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
-Int=1
-Color =P3Dark
-Type=Font Black
-Reflection=0
+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=Font Black
-Texts=1
-Color =P1Light
-Reflection=1
-ReflectionSpacing=2
+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=Font Black
-Texts=1
-Color =P2Light
-Reflection=1
-ReflectionSpacing=2
+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=Font Black
-Texts=1
-Color =P3Light
-Reflection=1
-ReflectionSpacing=2
+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
+X = 460
+Y = 133
+Color = White
+Font = 0
Size = 24
-Text =Round 1
-Align=0
+Text = Round 1
+Align = 0
[PartyNewRoundTextRound2]
-X =460
-Y =162
-Color =White
-Font =0
+X = 460
+Y = 162
+Color = White
+Font = 0
Size = 24
-Text =Round 2
-Align=0
+Text = Round 2
+Align = 0
[PartyNewRoundTextRound3]
-X =460
-Y =191
-Color =White
-Font =0
+X = 460
+Y = 191
+Color = White
+Font = 0
Size = 24
-Text =Round 3
-Align=0
+Text = Round 3
+Align = 0
[PartyNewRoundTextRound4]
-X =460
-Y =220
-Color =White
-Font =0
+X = 460
+Y = 220
+Color = White
+Font = 0
Size = 24
-Text =Round 4
-Align=0
+Text = Round 4
+Align = 0
[PartyNewRoundTextRound5]
-X =460
-Y =249
-Color =White
-Font =0
+X = 460
+Y = 249
+Color = White
+Font = 0
Size = 24
-Text =Round 5
-Align=0
+Text = Round 5
+Align = 0
[PartyNewRoundTextRound6]
-X =460
-Y =278
-Color =White
-Font =0
+X = 460
+Y = 278
+Color = White
+Font = 0
Size = 24
-Text =Round 6
-Align=0
+Text = Round 6
+Align = 0
[PartyNewRoundTextRound7]
-X =460
-Y =307
-Color =White
-Font =0
+X = 460
+Y = 307
+Color = White
+Font = 0
Size = 24
-Text =Round 7
-Align=0
+Text = Round 7
+Align = 0
[PartyNewRoundTextWinner1]
-X =600
-Y =133
-Color =White
-Font =0
+X = 600
+Y = 133
+Color = White
+Font = 0
Size = 24
-Text =Winner 1
-Align=0
+Text = Winner 1
+Align = 0
[PartyNewRoundTextWinner2]
-X =600
-Y =162
-Color =White
-Font =0
+X = 600
+Y = 162
+Color = White
+Font = 0
Size = 24
-Text =Winner 2
-Align=0
+Text = Winner 2
+Align = 0
[PartyNewRoundTextWinner3]
-X =600
-Y =191
-Color =White
-Font =0
+X = 600
+Y = 191
+Color = White
+Font = 0
Size = 24
-Text =Winner 3
-Align=0
+Text = Winner 3
+Align = 0
[PartyNewRoundTextWinner4]
-X =600
-Y =220
-Color =White
-Font =0
+X = 600
+Y = 220
+Color = White
+Font = 0
Size = 24
-Text =Winner 4
-Align=0
+Text = Winner 4
+Align = 0
[PartyNewRoundTextWinner5]
-X =600
-Y =249
-Color =White
-Font =0
+X = 600
+Y = 249
+Color = White
+Font = 0
Size = 24
-Text =Winner 5
-Align=0
+Text = Winner 5
+Align = 0
[PartyNewRoundTextWinner6]
-X =600
-Y =278
-Color =White
-Font =0
+X = 600
+Y = 278
+Color = White
+Font = 0
Size = 24
-Text =Winner 6
-Align=0
+Text = Winner 6
+Align = 0
[PartyNewRoundTextWinner7]
-X =600
-Y =307
-Color =White
-Font =0
+X = 600
+Y = 307
+Color = White
+Font = 0
Size = 24
-Text =Winner 7
-Align=0
+Text = Winner 7
+Align = 0
[PartyNewRoundStaticRound1]
-Tex =PartyRoundBG2
-X =450
-Y =135
+Tex = PartyRoundBG2
+X = 450
+Y = 135
W = 330
H = 20
-Color =GrayLight
-Type =Font Black
+Color = GrayLight
+Type = Transparent
[PartyNewRoundStaticRound2]
-Tex =PartyRoundBG2
-X =450
-Y =164
+Tex = PartyRoundBG2
+X = 450
+Y = 164
W = 330
H = 20
-Color =GrayLight
-Type =Font Black
+Color = GrayLight
+Type = Transparent
[PartyNewRoundStaticRound3]
-Tex =PartyRoundBG2
-X =450
-Y =193
+Tex = PartyRoundBG2
+X = 450
+Y = 193
W = 330
H = 20
-Color =GrayLight
-Type =Font Black
-
+Color = GrayLight
+Type = Transparent
[PartyNewRoundStaticRound4]
-Tex =PartyRoundBG2
-X =450
-Y =222
+Tex = PartyRoundBG2
+X = 450
+Y = 222
W = 330
H = 20
-Color =GrayLight
-Type =Font Black
-
+Color = GrayLight
+Type = Transparent
[PartyNewRoundStaticRound5]
-Tex =PartyRoundBG2
-X =450
-Y =251
+Tex = PartyRoundBG2
+X = 450
+Y = 251
W = 330
H = 20
-Color =GrayLight
-Type =Font Black
+Color = GrayLight
+Type = Transparent
[PartyNewRoundStaticRound6]
-Tex =PartyRoundBG2
-X =450
-Y =280
+Tex = PartyRoundBG2
+X = 450
+Y = 280
W = 330
H = 20
-Color =GrayLight
-Type =Font Black
+Color = GrayLight
+Type = Transparent
[PartyNewRoundStaticRound7]
-Tex =PartyRoundBG2
-X =450
-Y =309
+Tex = PartyRoundBG2
+X = 450
+Y = 309
W = 330
H = 20
-Color =GrayLight
-Type =Font Black
+Color = GrayLight
+Type = Transparent
[PartyNewRoundTextNextRound]
-X =400
-Y =495
-Color =White
-Font =0
+X = 400
+Y = 495
+Color = White
+Font = 0
Size = 30
-Text =Next Round
-Align=1
+Text = Next Round
+Align = 1
[PartyNewRoundTextNextRoundNo]
-X =457
-Y =350
-Color =White
-Font =0
+X = 457
+Y = 350
+Color = White
+Font = 0
Size = 54
-Text =99
-Align=0
+Text = 99
+Align = 0
[PartyNewRoundTextScoreTeam1]
-X =390
-Y =110
-Color =White
-Font =0
+X = 390
+Y = 110
+Color = White
+Font = 0
Size = 51
-Text =3000
-Align=1
+Text = 3000
+Align = 1
[PartyNewRoundTextScoreTeam2]
-X =390
-Y =191
-Color =White
-Font =0
+X = 390
+Y = 191
+Color = White
+Font = 0
Size = 51
-Text =2000
-Align=1
+Text = 2000
+Align = 1
[PartyNewRoundTextScoreTeam3]
-X =390
-Y =272
-Color =White
-Font =0
+X = 390
+Y = 272
+Color = White
+Font = 0
Size = 51
-Text =1000
-Align=1
+Text = 1000
+Align = 1
[PartyNewRoundTextNameTeam1]
-X =30
-Y =108
-Color =White
-Font =0
+X = 30
+Y = 108
+Color = White
+Font = 0
Size = 36
-Text =Team 1
-Align=0
+Text = Team 1
+Align = 0
[PartyNewRoundTextNameTeam2]
-X =30
-Y =189
-Color =White
-Font =0
+X = 30
+Y = 189
+Color = White
+Font = 0
Size = 36
-Text =Team 2
-Align=0
+Text = Team 2
+Align = 0
[PartyNewRoundTextNameTeam3]
-X =30
-Y =270
-Color =White
-Font =0
+X = 30
+Y = 270
+Color = White
+Font = 0
Size = 36
-Text =Team 3
-Align=0
+Text = Team 3
+Align = 0
[PartyNewRoundTextNextPlayer1]
-X =230
-Y =425
-Color =White
-Font =0
+X = 230
+Y = 425
+Color = White
+Font = 0
Size = 30
-Text =Player 1
-Align=1
+Text = Player 1
+Align = 1
[PartyNewRoundTextNextPlayer2]
-X =400
-Y =425
-Color =White
-Font =0
+X = 400
+Y = 425
+Color = White
+Font = 0
Size = 30
-Text =Player 2
-Align=1
+Text = Player 2
+Align = 1
[PartyNewRoundTextNextPlayer3]
-X =570
-Y =425
-Color =White
-Font =0
+X = 570
+Y = 425
+Color = White
+Font = 0
Size = 30
-Text =Player 3
-Align=1
+Text = Player 3
+Align = 1
+
[PartyScore]
-Texts=5
+Texts = 5
[PartyScoreBackground]
-Tex=PartyBG
+Tex = PartyBG
[PartyScoreDecoTextures]
-ChangeTextures =1
+ChangeTextures = 1
-FirstTexture =PartyScoreDeco
-FirstTyp =Font Black
-FirstColor =Gold
+FirstTexture = PartyScoreDeco
+FirstTyp = Colorized
+FirstColor = Gold
-SecondTexture =PartyScoreDeco
-SecondTyp =Font Black
-SecondColor =Silver
+SecondTexture = PartyScoreDeco
+SecondTyp = Colorized
+SecondColor = Silver
-ThirdTexture =PartyScoreDeco
-ThirdTyp =Font Black
-ThirdColor =Bronze
+ThirdTexture = PartyScoreDeco
+ThirdTyp = Colorized
+ThirdColor = Bronze
[PartyScoreStatic1]
-X =0
-Y =549
-W =252
-H =28
-Tex=Leiste1
-Color =White
-Type=Plain
-Reflection=1
-ReflectionSpacing=1
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
[PartyScoreStatic2]
-X =254
-Y =549
-W =548
-H =28
-Tex=Leiste2
-Color =White
-Type=Plain
-Reflection=1
-ReflectionSpacing=1
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
[PartyScoreStatic3]
-X =37
-Y =72
-W =27
-H =27
-Color =ColorDark
-Tex =MainIcon
-Type=Font Black
+X = 65
+Y = 65
+W = 27
+H = 27
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
[PartyScoreStatic4]
-X =410
-Y =553
-W =26
-H =22
-Tex=ButtonEnter
-Color =White
-Type=Plain
+X = 330
+Y = 553
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
[PartyScoreText1]
-X =40
-Y =4
+X = 70
+Y = 5
ColR = 0.7
ColG = 0.7
ColB = 0.7
Font = 1
-Size = 66
-Color =GrayLight
-Text=PARTY_MODE
+Size = 60
+Color = GrayLight
+Text = PARTY_MODE
[PartyScoreText2]
-X =62
-Y =67
-Color=Black
-Font =1
-Size = 27
-Align =0
-Text=PARTY_SCORE_DESC
+X = 100
+Y = 63
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_SCORE_DESC
-[PartyScoreText3]
-X =388
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=2
-Text=PARTY_SCORE_WHEREAMI
-[PartyScoreText4]
-X =440
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=PARTY_LEGEND_CONTINUE
+[PartyScoreText3]
+X = 370
+Y = 555
+Color = Black
+Font = 0
+Size = 24
+Align = 0
+Text = PARTY_LEGEND_CONTINUE
[PartyScoreStatic5]
-Tex =PartyScoreBG1
-X =50
-Y =100
+Tex = PartyScoreBG1
+X = 50
+Y = 100
W = 700
H = 80
-Int=1
-Color =Gray
-Type=Font Black
+Color = Gray
+Type = Transparent
[PartyScoreStatic6]
-Tex =PartyScoreBG2
-X =50
-Y =495
+Tex = PartyScoreBG2
+X = 50
+Y = 495
W = 700
H = 20
-Int=1
-Color =GrayLight
-Type=Font Black
+Color = Gray
+Type = Transparent
[PartyScoreText5]
-X =400
-Y =136
-Color =White
-Font =0
-Size = 54
-Text =PARTY_SCORE_WINS2
-Align=1
+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
+X = 400
+Y = 98
+Color = White
+Font = 0
Size = 54
-Text =The Winner is...
-Align=1
+Text = The Winner is...
+Align = 1
[PartyScoreTextScoreTeam1]
-X =568
-Y =198
-Color =White
-Font =0
+X = 568
+Y = 198
+Color = White
+Font = 0
Size = 36
-Text =3000
-Align=2
+Text = 3000
+Align = 2
[PartyScoreTextScoreTeam2]
-X =568
-Y =298
-Color =White
-Font =0
+X = 568
+Y = 298
+Color = White
+Font = 0
Size = 36
-Text =2000
-Align=2
+Text = 2000
+Align = 2
[PartyScoreTextScoreTeam3]
-X =568
-Y =398
-Color =White
-Font =0
+X = 568
+Y = 398
+Color = White
+Font = 0
Size = 36
-Text =1000
-Align=2
+Text = 1000
+Align = 2
[PartyScoreTextNameTeam1]
-X =188
-Y =198
-Font=0
+X = 188
+Y = 198
+Font = 0
Size = 36
-Align=0
-Text=Team 1
-Color=White
+Align = 0
+Text = Team 1
+Color = White
[PartyScoreTextNameTeam2]
-X =188
-Y =298
-Color =White
-Font =0
+X = 188
+Y = 298
+Color = White
+Font = 0
Size = 36
-Text =Team 2
-Align=0
+Text = Team 2
+Align = 0
[PartyScoreTextNameTeam3]
-X =188
-Y =398
-Color =White
-Font =0
+X = 188
+Y = 398
+Color = White
+Font = 0
Size = 36
-Text =Team 3
-Align=0
+Text = Team 3
+Align = 0
[PartyScoreStaticTeam1]
-X =188
-Y =230
-W =380
-H =16
-Z =1
-Tex=PartyTeamPoints
-Color =P1Dark
-Int = 1
-Type=Font Black
-Reflection=1
-ReflectionSpacing=12
+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=Font Black
-Color =P1Dark
-Reflection=1
-ReflectionSpacing=2
+Tex = PartyTeamButton2
+X = 178
+Y = 200
+W = 400
+H = 50
+Type = Transparent
+Color = P1Dark
+
[PartyScoreStaticTeam1Deco]
-Tex =PartyScoreDeco
+Tex = PartyScoreDeco
X = 563
Y = 191
W = 64
H = 64
-Type =Font Black
-Color =Gold
-Reflection=1
-ReflectionSpacing=-5
+Type = Transparent
+Color = Gold
+
[PartyScoreStaticTeam2]
-X =188
-Y =330
-W =380
-H =15
-Z =1
-Tex=PartyTeamPoints
-Color =P2Dark
-Int = 1
-Type=Font Black
-Reflection=1
-ReflectionSpacing=12
+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=Font Black
-Color =P2Dark
-Reflection=1
-ReflectionSpacing=2
+Tex = PartyTeamButton2
+X = 178
+Y = 300
+W = 400
+H = 50
+Type = Transparent
+Color = P2Dark
+
[PartyScoreStaticTeam2Deco]
-Tex =PartyScoreDeco
+Tex = PartyScoreDeco
X = 563
Y = 291
W = 64
H = 64
-Type =Font Black
-Color =Gold
-Reflection=1
-ReflectionSpacing=-5
+Type = Transparent
+Color = Gold
+
[PartyScoreStaticTeam3]
-X =188
-Y =430
-W =380
-H =15
-Z =1
-Tex=PartyTeamPoints
-Color =P3Dark
-Int = 1
-Type=Font Black
-Reflection=1
-ReflectionSpacing=12
+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=Font Black
-Color =P3Dark
-Reflection=1
-ReflectionSpacing=2
+Tex = PartyTeamButton2
+X = 178
+Y = 400
+W = 400
+H = 50
+Type = Transparent
+Color = P3Dark
+
[PartyScoreStaticTeam3Deco]
-Tex =PartyScoreDeco
+Tex = PartyScoreDeco
X = 563
Y = 391
W = 64
H = 64
-Type =Font Black
-Color =Gold
-Reflection=1
-ReflectionSpacing=-5
+Type = Transparent
+Color = Gold
+
[PartyWin]
-Texts=4
+Texts = 4
[PartyWinBackground]
-Tex=PartyBG
+Tex = PartyBG
[PartyWinStatic1]
-X =0
-Y =549
-W =252
-H =28
-Tex=Leiste1
-Color =White
-Type=Plain
-Reflection=1
-ReflectionSpacing=1
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
[PartyWinStatic2]
-X =254
-Y =549
-W =548
-H =28
-Tex=Leiste2
-Color =White
-Type=Plain
-Reflection=1
-ReflectionSpacing=1
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
[PartyWinStatic3]
-X =37
-Y =72
-W =27
-H =27
-Color =ColorDark
-Tex =MainIcon
-Type=Font Black
+X = 65
+Y = 65
+W = 27
+H = 27
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
[PartyWinStatic4]
-X =380
-Y =553
-W =26
-H =22
-Tex=ButtonEnter
-Color =White
-Type=Plain
+X = 260
+Y = 545
+W = 32
+H = 30
+Tex = Button
+Enter
+Color = White
+Type = Transparent
[PartyWinText1]
-X =40
-Y =4
+X = 70
+Y = 5
ColR = 0.7
ColG = 0.7
ColB = 0.7
Font = 1
-Size = 66
-Color =GrayLight
-Text=PARTY_MODE
+Size = 60
+Color = GrayLight
+Text = PARTY_MODE
[PartyWinText2]
-X =62
-Y =67
-Color=Black
-Font =1
-Size = 27
-Align =0
-Text=PARTY_WIN_DESC
+X = 100
+Y = 63
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 0
+Text = PARTY_WIN_DESC
[PartyWinText3]
-X =358
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=2
-Text=PARTY_WIN_WHEREAMI
-
-[PartyWinText4]
-X =410
-Y =552
-Color=Gray
-Font =1
-Size = 21
-Align=0
-Text=PARTY_WIN_LEGEND_CONTINUE
+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
+#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
+X = 699
+Y = 183
+Color = White
+Font = 0
Size = 57
-Text =3000
-Align=2
+Text = 3000
+Align = 2
[PartyWinTextScoreTeam2]
-X =669
-Y =298
-Color =White
-Font =0
+X = 669
+Y = 298
+Color = White
+Font = 0
Size = 36
-Text =2000
-Align=2
+Text = 2000
+Align = 2
[PartyWinTextScoreTeam3]
-X =649
-Y =398
-Color =White
-Font =0
+X = 649
+Y = 398
+Color = White
+Font = 0
Size = 27
-Text =1000
-Align=2
+Text = 1000
+Align = 2
[PartyWinTextNameTeam1]
-X =169
-Y =183
-Font=0
+X = 169
+Y = 183
+Font = 0
Size = 57
-Align=0
-Text=Team 1
-Color=White
+Align = 0
+Text = Team 1
+Color = White
[PartyWinTextNameTeam2]
-X =289
-Y =298
-Color =White
-Font =0
+X = 289
+Y = 298
+Color = White
+Font = 0
Size = 36
-Text =Team 2
-Align=0
+Text = Team 2
+Align = 0
[PartyWinTextNameTeam3]
-X =369
-Y =398
-Color =White
-Font =0
+X = 369
+Y = 398
+Color = White
+Font = 0
Size = 27
-Text =Team 3
-Align=0
+Text = Team 3
+Align = 0
[PartyWinStaticTeam1]
-X =169
-Y =230
-W =530
-H =16
-Z =1
-Tex=PartyTeamPoints
-Color =TeamColor
-Int = 1
-Type=Font Black
-Reflection=1
-ReflectionSpacing=12
+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=Font Black
-Color =TeamColor
-Reflection=1
-ReflectionSpacing=2
+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
-Int = 1
-Type=Font Black
-Reflection=1
-ReflectionSpacing=12
+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=Font Black
-Color =P1Dark
-Reflection=1
-ReflectionSpacing=2
+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
-Int = 1
-Type=Font Black
-Reflection=1
-ReflectionSpacing=12
+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=Font Black
-Color =P1Dark
-Reflection=1
-ReflectionSpacing=2
+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
-Int = 1
-Type=Font Black
-Reflection=1
-ReflectionSpacing=12
+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=Font Black
-Color =P1Dark
-Reflection=1
-ReflectionSpacing=2
+Tex = PartyTeamButton3
+X = 359
+Y = 400
+W = 300
+H = 40
+Type = Transparent
+Color = P1Dark
+
[PartyWinStaticTeam1Deco]
-Tex =PartyWinDeco1
+Tex = PartyWinDeco1
X = 91
Y = 176
W = 79
H = 79
-Type =Font Black
-Color =Gold
-Reflection=1
-ReflectionSpacing=3
+Type = Colorized
+Color = Gold
+
[PartyWinStaticTeam2]
-X =289
-Y =330
-W =380
-H =15
-Z =1
-Tex=PartyTeamPoints
-Color =TeamColor
-Int = 1
-Type=Font Black
-Reflection=1
-ReflectionSpacing=12
+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=Font Black
-Color =TeamColor
-Reflection=1
-ReflectionSpacing=2
+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
-Int = 1
-Type=Font Black
-Reflection=1
-ReflectionSpacing=12
+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=Font Black
-Color =P2Dark
-Reflection=1
-ReflectionSpacing=2
+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
-Int = 1
-Type=Font Black
-Reflection=1
-ReflectionSpacing=12
+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=Font Black
-Color =P2Dark
-Reflection=1
-ReflectionSpacing=2
+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
-Int = 1
-Type=Font Black
-Reflection=1
-ReflectionSpacing=12
+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=Font Black
-Color =TeamColor
-Reflection=1
-ReflectionSpacing=2
+Tex = PartyTeamButton4
+X = 359
+Y = 400
+W = 300
+H = 40
+Type = Colorized
+Color = TeamColor
+
[PartyWinStaticTeam2Deco]
-Tex =PartyWinDeco2
+Tex = PartyWinDeco2
X = 226
Y = 291
W = 64
H = 64
-Type =Font Black
-Color =Silver
-Reflection=1
-ReflectionSpacing=3
+Type = Colorized
+Color = Silver
+
[PartyWinStaticTeam3]
-X =369
-Y =420
-W =280
-H =15
-Z =1
-Tex=PartyTeamPoints
-Color =TeamColor
-Int = 1
-Type=Font Black
-Reflection=1
-ReflectionSpacing=12
+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=Font Black
-Color =TeamColor
-Reflection=1
-ReflectionSpacing=2
+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
-Int = 1
-Type=Font Black
-Reflection=1
-ReflectionSpacing=12
+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=Font Black
-Color =P3Dark
-Reflection=1
-ReflectionSpacing=2
+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
-Int = 1
-Type=Font Black
-Reflection=1
-ReflectionSpacing=12
+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=Font Black
-Color =P3Dark
-Reflection=1
-ReflectionSpacing=2
+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
-Int = 1
-Type=Font Black
-Reflection=1
-ReflectionSpacing=12
+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=Font Black
-Color =P3Dark
-Reflection=1
-ReflectionSpacing=2
+Tex = PartyTeamButton5
+X = 359
+Y = 400
+W = 300
+H = 40
+Type = Colorized
+Color = P3Dark
+
[PartyWinStaticTeam3Deco]
-Tex =PartyWinDeco3
+Tex = PartyWinDeco3
X = 316
Y = 391
W = 54
H = 54
-Type =Font Black
-Color =Bronze
-Reflection=1
-ReflectionSpacing=3
+Type = Colorized
+Color = Bronze
+
[PartyOptions]
-Texts = 3
+Texts = 5
[PartyOptionsBackground]
-Tex=PartyBG
+Tex = PartyBG
[PartyOptionsStatic1]
-Tex =ButtonNavi
-X =196
-Y =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
[PartyOptionsStatic2]
-Tex =ButtonEnter
-X =350
-Y =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
[PartyOptionsStatic3]
-Tex =ButtonEsc
-X =510
-Y =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[PartyOptionsText2]
-X =226
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_NAVIGATE
-Align=0
+X = 65
+Y = 65
+W = 27
+H = 27
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
-[PartyOptionsText3]
-X =380
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_CONTINUE
-Align=0
+[PartyOptionsStatic4]
+X = 250
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
-[PartyOptionsText4]
-X =540
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_ESC
-Align=0
+[PartyOptionsStatic5]
+X = 410
+Y = 545
+W = 32
+H = 30
+Tex = ButtonEnter
+Color = White
+Type = Transparent
[PartyOptionsText1]
-X = 50
-Y = 10
+X = 70
+Y = 5
ColR = 0.7
ColG = 0.7
ColB = 0.7
Font = 1
-Size = 75
-Text=PARTY_OPTIONS_WHEREAMI
+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
-TexSBG = MainBar
-Text =PARTY_DIFFICULTY
-X = 40
-Y = 85
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+Text = PARTY_DIFFICULTY
+X = 70
+Y = 110
W = 230
-H = 70
-SkipX = 50
-Fields=1
+H = 40
+SkipX = 10
+Fields = 1
Color = ColorDark
DColor = Gray
@@ -5955,16 +6196,23 @@ SBGDColor = Gray
STColor = White
STDColor = GrayDark
+#TexSBG = SelectBG
+#W = 230
+#H = 40
+#SkipX = 10
+
[PartyOptionsSelectPlayList]
Tex = MainBar
-TexSBG = MainBar
-Text =PARTY_PLAYLIST
-X = 40
-Y = 140
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+Text = PARTY_PLAYLIST
+X = 70
+Y = 165
W = 230
-H = 70
-SkipX = 50
-Fields=1
+H = 40
+SkipX = 10
+Fields = 1
Color = ColorDark
DColor = Gray
@@ -5978,14 +6226,16 @@ STDColor = GrayDark
[PartyOptionsSelectPlayList2]
Tex = MainBar
-TexSBG = MainBar
-Text =PARTY_PLAYLIST
-X = 40
-Y = 195
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+Text = PARTY_PLAYLIST
+X = 70
+Y = 220
W = 230
-H = 70
-SkipX = 50
-Fields=1
+H = 40
+SkipX = 10
+Fields = 1
Color = ColorDark
DColor = Gray
@@ -5999,14 +6249,16 @@ STDColor = GrayDark
[PartyOptionsSelectRounds]
Tex = MainBar
-TexSBG = MainBar
-Text =PARTY_ROUNDS
-X = 40
+Type = Transparent
+TexSBG = SelectBG
+TypeSBG = Transparent
+Text = PARTY_ROUNDS
+X = 70
Y = 250
W = 230
-H = 70
-SkipX = 50
-Fields=7
+H = 40
+SkipX = 10
+Fields = 7
Color = ColorDark
DColor = Gray
@@ -6018,1447 +6270,1732 @@ SBGDColor = Gray
STColor = White
STDColor = GrayDark
-[PartyOptionsSelectTeams]
-Tex = MainBar
-TexSBG = MainBar
-Text =PARTY_TEAMS
-X = 40
-Y = 305
-W = 230
-H = 70
-SkipX = 50
-Fields=7
+
+[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
-DColor = Gray
-TColor = White
-TDColor = White
-SBGTex = MainBar
-SBGColor = ColorDark
-SBGDColor = Gray
-STColor = White
-STDColor = GrayDark
+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
-[PartyOptionsSelectPlayers1]
+[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 = MainBar
-Text =PARTY_TEAMS_PLAYER1
-X = 40
-Y = 360
-W = 230
-H = 70
-SkipX = 50
-Fields=7
+TexSBG = PartyPlayerSelectBG
+Text = PARTY_TEAMS
+X = 75
+Y = 105
+W = 310
+SBGW = 150
+H = 40
+SkipX = 160
+Fields = 2
-Color = ColorDark
+Type = Transparent
+TypeSBG = Transparent
+
+
+Color = GrayLight
DColor = Gray
TColor = White
TDColor = White
SBGTex = MainBar
-SBGColor = ColorDark
+SBGColor = GrayLight
SBGDColor = Gray
STColor = White
STDColor = GrayDark
-[PartyOptionsSelectPlayers2]
-Tex = MainBar
-TexSBG = MainBar
-Text =PARTY_TEAMS_PLAYER2
-X = 40
-Y = 415
-W = 230
-H = 70
-SkipX = 50
-Fields=7
-
-Color = ColorDark
-DColor = Gray
+[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
-SBGTex = MainBar
-SBGColor = ColorDark
-SBGDColor = Gray
+
+SBGColor = P1Light
+SBGDColor = P1Dark
STColor = White
STDColor = GrayDark
-[PartyOptionsSelectPlayers3]
-Tex = MainBar
-TexSBG = MainBar
-Text =PARTY_TEAMS_PLAYER3
-X = 40
-Y = 470
-W = 230
-H = 70
-SkipX = 50
-Fields=7
-
-Color = ColorDark
-DColor = Gray
+[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
-SBGTex = MainBar
-SBGColor = ColorDark
-SBGDColor = Gray
+
+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
-[PartyPlayer]
-Texts=6
-
-[PartyPlayerBackground]
-Tex=PartyBG
-
-[PartyPlayerStatic1]
-X =40
-Y =22
-W =27
-H =27
-Color =White
-Tex =PartyIcon
-Type=Font Black
-
-[PartyPlayerText1]
-X = 50
-Y = 10
-ColR = 0.7
-ColG = 0.7
-ColB = 0.7
-Font = 1
-Size = 75
-Text=PARTY_PLAYER_WHEREAMI
-
-[PartyPlayerStatic2]
-Tex =ButtonNavi
-X =176
-Y =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[PartyPlayerStatic3]
-Tex =ButtonAZ
-X =330
-Y =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[PartyPlayerStatic4]
-Tex =ButtonEnter
-X =532
-Y =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[PartyPlayerText2]
-X =206
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_NAVIGATE
-Align=0
+SBGColor = P3Light
+SBGDColor = P3Dark
+STColor = White
+STDColor = GrayDark
-[PartyPlayerText3]
-X =360
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_PLAYER_ENTER_NAME
-Align=0
-[PartyPlayerText4]
-X =562
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_CONTINUE
-Align=0
[PartyPlayerTeam1Name]
-Tex=PartyTeamButton2
-X=85
-Y=100
-W=310
-H=50
-Type=Font Black
-Texts=1
-Color =P1Lightest
-DColor =P1Dark
+Tex = PartyTeamButton2
+X = 75
+Y = 160
+W = 310
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Dark
[PartyPlayerTeam1NameText1]
-X =155
-Y =8
-Font=1
-Size = 33
-Align=1
-Text=Team 1
-Color=White
+X = 115
+Y = 8
+Font = 0
+Size = 36
+Align = 1
+Text = Team 1
+Color = White
[PartyPlayerPlayer1Name]
-Tex=Button
-X=81
-Y=160
-W =158
-H =54
-Type=Font Black
-Texts=1
-Color =P1Lightest
-DColor =P1Light
+Tex = Button
+X = 70
+Y = 220
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Dark
[PartyPlayerPlayer1NameText1]
-X =79
-Y =12
-Font=1
-Size = 27
-Align=1
-Text=Player 1
-Color=White
+X = 65
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 1
+Color = White
[PartyPlayerPlayer2Name]
-Tex=Button
-X=241
-Y=160
-W =158
-H =54
-Type=Font Black
-Texts=1
-Color =P1Lightest
-DColor =P1Light
+Tex = Button
+X = 225
+Y = 220
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Dark
[PartyPlayerPlayer2NameText1]
-X =79
-Y =12
-Font=1
-Size = 27
-Align=1
-Text=Player 2
-Color=White
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 2
+Color = White
[PartyPlayerPlayer3Name]
-Tex=Button
-X=401
-Y=160
-W =158
-H =54
-Type=Font Black
-Texts=1
-Color =P1Lightest
-DColor =P1Light
+Tex = Button
+X = 380
+Y = 220
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Dark
[PartyPlayerPlayer3NameText1]
-X =79
-Y =12
-Font=1
-Size = 27
-Align=1
-Text=Player 3
-Color=White
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 3
+Color = White
[PartyPlayerPlayer4Name]
-Tex=Button
-X=561
-Y=160
-W =158
-H =54
-Type=Font Black
-Texts=1
-Color =P1Lightest
-DColor =P1Light
+Tex = Button
+X = 535
+Y = 220
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P1Lightest
+DColor = P1Dark
[PartyPlayerPlayer4NameText1]
-X =79
-Y =12
-Font=1
-Size = 27
-Align=1
-Text=Player 4
-Color=White
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 4
+Color = White
[PartyPlayerTeam2Name]
-Tex=PartyTeamButton2
-X=85
-Y=240
-W=310
-H=50
-Type=Font Black
-Texts=1
-Color =P2Lightest
-DColor =P2Dark
+Tex = PartyTeamButton2
+X = 75
+Y = 290
+W = 310
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Dark
[PartyPlayerTeam2NameText1]
-X =155
-Y =8
-Font=1
-Size = 33
-Align=1
-Text=Team 2
-Color=White
+X = 115
+Y = 8
+Font = 0
+Size = 36
+Align = 1
+Text = Team 2
+Color = White
[PartyPlayerPlayer5Name]
-Tex=Button
-X=81
-Y=300
-W =158
-H =54
-Type=Font Black
-Texts=1
-Color =P2Lightest
-DColor =P2Light
+Tex = Button
+X = 70
+Y = 350
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Dark
[PartyPlayerPlayer5NameText1]
-X =79
-Y =12
-Font=1
-Size = 27
-Align=1
-Text=Player 5
-Color=White
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 5
+Color = White
[PartyPlayerPlayer6Name]
-Tex=Button
-X=241
-Y=300
-W =158
-H =54
-Type=Font Black
-Texts=1
-Color =P2Lightest
-DColor =P2Light
+Tex = Button
+X = 225
+Y = 350
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Dark
[PartyPlayerPlayer6NameText1]
-X =79
-Y =12
-Font=1
-Size = 27
-Align=1
-Text=Player 6
-Color=White
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 6
+Color = White
[PartyPlayerPlayer7Name]
-Tex=Button
-X=401
-Y=300
-W =158
-H =54
-Type=Font Black
-Texts=1
-Color =P2Lightest
-DColor =P2Light
+Tex = Button
+X = 380
+Y = 350
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Dark
[PartyPlayerPlayer7NameText1]
-X =79
-Y =12
-Font=1
-Size = 27
-Align=1
-Text=Player 7
-Color=White
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 7
+Color = White
[PartyPlayerPlayer8Name]
-Tex=Button
-X=561
-Y=300
-W =158
-H =54
-Type=Font Black
-Texts=1
-Color =P2Lightest
-DColor =P2Light
+Tex = Button
+X = 535
+Y = 350
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P2Lightest
+DColor = P2Dark
[PartyPlayerPlayer8NameText1]
-X =79
-Y =12
-Font=1
-Size = 27
-Align=1
-Text=Player 8
-Color=White
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 8
+Color = White
[PartyPlayerTeam3Name]
-Tex=Button
-Tex=PartyTeamButton2
-X=85
-Y=380
-W=310
-H=50
-Type=Font Black
-Texts=1
-Color =P3Lightest
-DColor =P3Dark
+Tex = PartyTeamButton2
+X = 75
+Y = 420
+W = 310
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Dark
[PartyPlayerTeam3NameText1]
-X =155
-Y =8
-Font=1
-Size = 33
-Align=1
-Text=Team 3
-Color=White
+X = 115
+Y = 8
+Font = 0
+Size = 36
+Align = 1
+Text = Team 3
+Color = White
[PartyPlayerPlayer9Name]
-Tex=Button
-X=81
-Y=440
-W =158
-H =54
-Type=Font Black
-Texts=1
-Color =P3Lightest
-DColor =P3Light
+Tex = Button
+X = 70
+Y = 480
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Dark
[PartyPlayerPlayer9NameText1]
-X =79
-Y =12
-Font=1
-Size = 27
-Align=1
-Text=Player 9
-Color=White
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 9
+Color = White
[PartyPlayerPlayer10Name]
-Tex=Button
-X=241
-Y=440
-W =158
-H =54
-Type=Font Black
-Texts=1
-Color =P3Lightest
-DColor =P3Light
+Tex = Button
+X = 225
+Y = 480
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Dark
[PartyPlayerPlayer10NameText1]
-X =79
-Y =12
-Font=1
-Size = 27
-Align=1
-Text=Player 10
-Color=White
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 10
+Color = White
[PartyPlayerPlayer11Name]
-Tex=Button
-X=401
-Y=440
-W =158
-H =54
-Type=Font Black
-Texts=1
-Color =P3Lightest
-DColor =P3Light
+Tex = Button
+X = 380
+Y = 480
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Dark
[PartyPlayerPlayer11NameText1]
-X =79
-Y =12
-Font=1
-Size = 27
-Align=1
-Text=Player 11
-Color=White
+X = 75
+Y = 10
+Font = 0
+Size = 30
+Align = 1
+Text = Player 11
+Color = White
[PartyPlayerPlayer12Name]
-Tex=Button
-X=561
-Y=440
-W =158
-H =54
-Type=Font Black
-Texts=1
-Color =P3Lightest
-DColor =P3Light
+Tex = Button
+X = 535
+Y = 480
+Z = 0.6
+W = 150
+H = 50
+Type = Transparent
+Texts = 1
+Color = P3Lightest
+DColor = P3Dark
[PartyPlayerPlayer12NameText1]
-X =79
-Y =12
-Font=1
-Size = 27
-Align=1
-Text=Player 12
-Color=White
+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
+
+
-# # # # Song Extensions # # # #
[SongMenu]
-Texts=0
-Statics=1
+
+[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 = 505
+X = 548
Y = 195
-W = 220
+Z = 0.97
+W = 210
H = 25
-Tex = SongMenuButton
-Color =ColorDark
+Tex = Rectangle
+Color = ColorDark
DColor = Gray
-Type=Font Black
-Texts=1
-Z = 0.988
+Type = Transparent
+Texts = 1
[SongMenuButton1Text1]
-X =110
-Y =0
-Color=Black
-Font =0
+X = 6
+Y = 0
+Z = 0.97
+Color = White
Size = 24
-Text=SONG_MENU_PLAY
-Align=1
-Z=0.99
+Text = SONG_MENU_PLAY
[SongMenuButton2]
-X = 505
+X = 548
Y = 225
-W = 220
+Z = 0.97
+W = 210
H = 25
-Tex = SongMenuButton
-Color =ColorDark
+Tex = Rectangle
+Color = ColorDark
DColor = Gray
-Type=Font Black
-Texts=1
-Z = 0.988
+Type = Transparent
+Texts = 1
[SongMenuButton2Text1]
-X =110
-Y =0
-Color=Black
-Font =0
+X = 6
+Y = 0
+Color = White
Size = 24
-Text=SONG_MENU_EDIT
-Align=1
-Z=0.99
+Text = SONG_MENU_EDIT
+Z = 0.97
[SongMenuButton3]
-X = 505
+X = 548
Y = 255
-W = 220
+Z = 0.97
+W = 210
H = 25
-Tex = SongMenuButton
-Color =ColorDark
+Tex = Rectangle
+Color = ColorDark
DColor = Gray
-Type=Font Black
-Texts=1
-Z = 0.988
+Type = Transparent
+Texts = 1
[SongMenuButton3Text1]
-X =110
-Y =0
-Color=Black
-Font =0
-Size = 24
-Text=SONG_MENU_MODI
-Align=1
-Z=0.99
-
-[SongMenuButton4]
-X = 505
-Y = 285
-W = 220
-H = 25
-Tex = SongMenuButton
-Color =ColorDark
-DColor = Gray
-Type=Font Black
-Texts=1
-Z = 0.988
-
-[SongMenuButton4Text1]
-X =110
-Y =0
-Color=Black
-Font =0
+X = 6
+Y = 0
+Color = White
+Font = 0
Size = 24
-Text=SONG_MENU_CANCEL
-Align=1
-Z=0.99
+Text = SONG_MENU_MODI
+Align = 0
+Z = 0.97
+# shows up instead of BUtton 3
+# in some song menus
[SongMenuSelectSlide3]
-Tex = Rectangle
-TexSBG = SongMenuSelectBG
-Text =
-X = 505
-Y = 255
+TexSBG = Rectangle
+Text =
+TypeSBG = Transparent
+ShowArrows = 1
+OneItemOnly = 1
+X = 548
+Y = 235
W = 0
H = 25
-Z = 0.988
+Z = 0.97
SkipX = 0
-SBGW=220
-
+SBGW = 210
TextSize = 24
-
Color = ColorDark
DColor = Gray
TColor = White
TDColor = White
-SBGTex = MainBar
+
SBGColor = ColorDark
SBGDColor = Gray
-STColor = Black
-STDColor = Black
-
-[SongMenuTextMenu]
-X =615
-Y =140
-Color=Black
-Font =0
-Size = 39
-Text=MENU
-Align=1
-Z=0.99
-
-[SongMenuStatic1]
-X =400
-Y =100
-W =200
-H =262
-Z =0.45
-Color=White
-Tex =Rectangle
-Type=Font Black
-TexX1=0.1
-TexY1=0.1
-TexX2=0.9
-TexY2=0.9
-
-[SongMenuStatic2]
-X =400
-Y =100
-W =200
-H =262
-Z =0.45
-Color=Black
-Tex =SongFade
-Type=Font Black
-TexX1=0.5
-TexY1=0.1
-TexX2=0.7
-TexY2=0.7
-
-[SongMenuStatic3]
-Tex =SongMenuBG
-X =500
-Y =140
-W =230
-H =200
-Z =0.985
-Int=1
-Color =White
-Type=Font Black
+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
-[SongMenuStatic4]
-X =705
-Y =120
-W =42
-H =240
-Z=0.985
-Color =Gray
-Tex =SongMenuBorder
-Type=Font Black
-Z=0.98
+[SongMenuButton4Text1]
+X = 6
+Y = 0
+Color = White
+Font = 0
+Size = 24
+Text = SONG_MENU_CANCEL
+Align = 0
+Z = 0.97
-# # # # Song Jump to Menu # # # #
[SongJumpto]
-Texts=0
-Statics=1
+
+[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 =30
-Y =7
-Color=Black
-Font =1
-Size = 30
-Text=SONG_JUMPTO_TYPE_DESC
-Align=0
-Z=0.99
+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]
-Tex = button
-TexSBG = mainicon
#Text = SONG_JUMPTO_TYPE_DESC
-Font=1
-X = 160
-Y = 10
-Z = 0.99
-W = 0
+X = 516
+Y = 383
+Z = 0.97
H = 30
-SkipX = 0
-SBGW= 120
-Fields=2
-DColor = White
-TColor = Gray
-TDColor = Gray
-SBGTex = button
-SBGDColor = White
-STColor = Gray
-STDColor = White
+SBGW = 150
+SkipX = 4
-[SongJumptoButtonSearchText]
-X = 30
-Y = 40
-Z = 0.99
-W = 208
-H = 25
-Tex=JumpToBG
-Type=Font Black
-Color=Black
-Texts=1
+Size = 36
-[SongJumptoButtonSearchTextText1]
-X = 2
-Y = -1
-Size = 27
-Font=0
-Color=Black
-Align=0
+#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 =30
-Y =70
-Color=Black
-Font =0
+X = 539
+Y = 445
+Color = Black
+Font = 0
Size = 24
-Text=SONG_JUMPTO_HELP
-Align=0
-Z=0.99
+Text = SONG_JUMPTO_HELP
+Align = 0
+Z = 0.97
-# # # # Statistic Screens # # # #
[StatMain]
-Texts=4
-Statics=6
+Texts = 0
+Statics = 0
[StatMainBackground]
-Tex=MainBG
-
-[StatMainStatic5]
-Tex =ButtonNavi
-X =196
-Y =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[StatMainStatic6]
-Tex =ButtonEnter
-X =350
-Y =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[StatMainStatic7]
-Tex =ButtonEsc
-X =510
-Y =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-
-[StatMainText3]
-X =226
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_NAVIGATE
-Align=0
-
-[StatMainText4]
-X =380
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_SELECT
-Align=0
-
-[StatMainText5]
-X =540
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_ESC
-Align=0
+Tex = MainBG
[StatMainButtonScores]
-X =589
-Y =120
-W =190
-H =50
+X = 589
+Y = 100
+W = 190
+H = 50
Tex = Button
Color = ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
-Type = Font Black
-Texts=1
+DColor = Gray
+Type = Transparent
+Texts = 1
+Reflection = 0
[StatMainButtonScoresText1]
-X =95
-Y =10
-Font=0
+X = 95
+Y = 10
+Font = 0
Size = 30
-Align=1
-Text=STAT_DESC_SCORES
-Color=White
+Align = 1
+Text = STAT_DESC_SCORES
+Color = White
[StatMainButtonSingers]
-X =589
-Y =180
-W =190
-H =50
+X = 589
+Y = 160
+W = 190
+H = 50
Tex = Button
Color = ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
-Type = Font Black
-Texts=1
+DColor = Gray
+Type = Transparent
+Texts = 1
+Reflection = 0
[StatMainButtonSingersText1]
-X =95
-Y =10
-Font=0
+X = 95
+Y = 10
+Font = 0
Size = 30
-Align=1
-Text=STAT_DESC_SINGERS
-Color=White
+Align = 1
+Text = STAT_DESC_SINGERS
+Color = White
[StatMainButtonSongs]
-X =589
-Y =240
-W =190
-H =50
+X = 589
+Y = 220
+W = 190
+H = 50
Tex = Button
Color = ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
-Type = Font Black
-Texts=1
+DColor = Gray
+Type = Transparent
+Texts = 1
+Reflection = 0
[StatMainButtonSongsText1]
-X =95
-Y =13
-Font=0
+X = 95
+Y = 13
+Font = 0
Size = 24
-Align=1
-Text=STAT_DESC_SONGS
-Color=White
+Align = 1
+Text = STAT_DESC_SONGS
+Color = White
[StatMainButtonBands]
-X =589
-Y =300
-W =190
-H =50
+X = 589
+Y = 280
+W = 190
+H = 50
Tex = Button
Color = ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
-Type = Font Black
-Texts=1
+DColor = Gray
+Type = Transparent
+Texts = 1
+Reflection = 0
[StatMainButtonBandsText1]
-X =95
-Y =13
-Font=0
+X = 95
+Y = 13
+Font = 0
Size = 24
-Align=1
-Text=STAT_DESC_BANDS
-Color=White
+Align = 1
+Text = STAT_DESC_BANDS
+Color = White
[StatMainButtonExit]
-X =589
-Y =360
-W =190
-H =50
+X = 589
+Y = 340
+W = 190
+H = 50
Tex = Button
Color = ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
-Type = Font Black
-Texts=1
+DColor = Gray
+Type = Transparent
+Texts = 1
+Reflection = 0
[StatMainButtonExitText1]
-X =95
-Y =10
-Font=0
+X = 95
+Y = 10
+Font = 0
Size = 30
-Align=1
-Text=SING_OPTIONS_EXIT
-Color=White
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = White
[StatMainTextOverview]
-X =45
-Y =145
-W =510
-Color=Black
-Font =0
+X = 45
+Y = 125
+W = 510
+Color = White
+Font = 0
Size = 27
-Align=0
-Text=
+Align = 0
+Text =
[StatMainStatic1]
-X =40
-Y =71
-W =32
-H =32
-Color =ColorDark
-Tex =MainIcon
-Type=Font Black
+X = 35
+Y = 65
+W = 27
+H = 27
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
[StatMainStatic2]
-X =40
-Y =120
-W =520
-H =20
-Tex=StatMainBG1
-Color =ColorLight
-Type=Font Black
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
[StatMainStatic3]
-X =40
-Y =140
-W =520
-H =300
-Tex=StatMainBG2
-Color =ColorDark
-Type=Font Black
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
[StatMainStatic4]
-X =40
-Y =440
-W =520
-H =20
-Tex=StatMainBG3
-Color =ColorLight
-Type=Font Black
-
-[StatMainText1]
-X =40
-Y =6
-Color=GrayLight
-Font =1
-Size = 66
-Text=STAT_MAIN
-Align=0
+X = 250
+Y = 545
+W = 32
+H = 30
+Tex = ButtonNavi
+Color = White
+Type = Transparent
-[StatMainText2]
-X =73
-Y =69
-Color=GrayDark
-Font =1
-Size = 30
-Align =0
-Text=STAT_MAIN_DESC
+[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
-[StatDetail]
-Texts=0
-Statics=0
+[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
-[StatDetailBackground]
-Tex=MainBG
+[StatMainText1]
+X = 40
+Y = 5
+Font = 1
+Size = 60
+Color = GrayLight
+Text = STAT_MAIN
+Align = 0
-[StatDetailStatic5]
-Tex =ButtonNavi
-X =196
-Y =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
-[StatDetailStatic6]
-Tex =ButtonEnter
-X =350
-Y =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[StatMainText2]
+X = 70
+Y = 63
+Color = GrayDark
+Font = 0
+Size = 30
+Align = 0
+Text = STAT_MAIN_DESC
-[StatDetailStatic7]
-Tex =ButtonEsc
-X =510
-Y =553
-W =22
-H =22
-Color =White
-Type=Plain
-TexX1=0
-TexY1=0
-TexX2=1
-TexY2=1
+[StatMainText3]
+X = 290
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_NAVIGATE
-[StatDetailText2]
-X =226
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_NAVIGATE
-Align=0
+[StatMainText4]
+X = 450
+Y = 548
+Z = 0.5
+Color = Black
+Size = 24
+Text = SING_LEGEND_ESC
-[StatDetailText3]
-X =380
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_SELECT
-Align=0
+[StatDetail]
+Texts = 0
+Statics = 0
-[StatDetailText4]
-X =540
-Y =553
-Color=Gray
-Font =1
-Size = 21
-Text=SING_LEGEND_ESC
-Align=0
+[StatDetailBackground]
+Tex = MainBG
[StatDetailButtonNext]
-X =589
-Y =120
-W =190
-H =50
+X = 589
+Y = 100
+W = 190
+H = 50
Tex = Button
Color = ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
-Type = Font Black
-Texts=1
+DColor = Gray
+Type = Transparent
+Texts = 1
+Reflection = 0
[StatDetailButtonNextText1]
-X =95
-Y =10
-Font=0
+X = 95
+Y = 10
+Font = 0
Size = 30
-Align=1
-Text=STAT_NEXT
-Color=White
+Align = 1
+Text = STAT_NEXT
+Color = White
[StatDetailButtonPrev]
-X =589
-Y =180
-W =190
-H =50
+X = 589
+Y = 160
+W = 190
+H = 50
Tex = Button
Color = ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
-Type = Font Black
-Texts=1
+DColor = Gray
+Type = Transparent
+Texts = 1
+Reflection = 0
[StatDetailButtonPrevText1]
-X =95
-Y =10
-Font=0
+X = 95
+Y = 10
+Font = 0
Size = 30
-Align=1
-Text=STAT_PREV
-Color=White
+Align = 1
+Text = STAT_PREV
+Color = White
[StatDetailButtonReverse]
-X =589
-Y =240
-W =190
-H =50
+X = 589
+Y = 220
+W = 190
+H = 50
Tex = Button
Color = ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
-Type = Font Black
-Texts=1
+DColor = Gray
+Type = Transparent
+Texts = 1
+Reflection = 0
[StatDetailButtonReverseText1]
-X =95
-Y =10
-Font=0
+X = 95
+Y = 10
+Font = 0
Size = 30
-Align=1
-Text=STAT_REVERSE
-Color=White
+Align = 1
+Text = STAT_REVERSE
+Color = White
[StatDetailButtonExit]
-X =589
-Y =300
-W =190
-H =50
+X = 589
+Y = 280
+W = 190
+H = 50
Tex = Button
Color = ColorDark
-Int = 1
-DColor = White
-DInt = 0.5
-Type = Font Black
-Texts=1
+DColor = Gray
+Type = Transparent
+Texts = 1
+Reflection = 0
[StatDetailButtonExitText1]
-X =95
-Y =10
-Font=0
+X = 95
+Y = 10
+Font = 0
Size = 30
-Align=1
-Text=SING_OPTIONS_EXIT
-Color=White
+Align = 1
+Text = SING_OPTIONS_EXIT
+Color = White
[StatDetailTextDescription]
-X =73
-Y =69
-Color=GrayDark
-Font =1
+X = 70
+Y = 63
+Color = GrayDark
+Font = 0
Size = 30
-Align =0
-Text=
+Align = 0
+Text =
[StatDetailTextPage]
X = 546
-Y = 118
-Color= Black
+Y = 98
+Color = Black
Font = 0
Size = 15
-Align=2
-Text=
+Align = 2
+Text =
[StatDetailTextList1]
X = 45
-Y = 142
-Color=Black
+Y = 122
+Color = White
Font = 0
-Size = 24
-Text=Stat1
+Size = 21
+Text = Stat1
[StatDetailTextList2]
X = 45
-Y = 180
-Color=Black
+Y = 160
+Color = White
Font = 0
-Size = 24
-Text=Stat2
+Size = 21
+Text = Stat2
[StatDetailTextList3]
X = 45
-Y = 218
-Color=Black
+Y = 198
+Color = White
Font = 0
-Size = 24
-Text=
+Size = 21
+Text =
[StatDetailTextList4]
X = 45
-Y = 256
-Color=Black
+Y = 236
+Color = White
Font = 0
-Size = 24
-Text=
+Size = 21
+Text =
[StatDetailTextList5]
X = 45
-Y = 294
-Color=Black
+Y = 274
+Color = White
Font = 0
-Size = 24
-Text=
+Size = 21
+Text =
[StatDetailTextList6]
X = 45
-Y = 332
-Color=Black
+Y = 312
+Color = White
Font = 0
-Size = 24
-Text=
+Size = 21
+Text =
[StatDetailTextList7]
X = 45
-Y = 370
-Color=Black
+Y = 350
+Color = White
Font = 0
-Size = 24
-Text=
+Size = 21
+Text =
[StatDetailTextList8]
X = 45
-Y = 408
-Color=Black
+Y = 388
+Color = White
Font = 0
-Size = 24
-Text=
+Size = 21
+Text =
[StatDetailTextList9]
X = 45
-Y = 446
-Color=Black
+Y = 426
+Color = White
Font = 0
-Size = 24
-Text=
+Size = 21
+Text =
[StatDetailTextList10]
X = 45
-Y = 484
-Color=Black
+Y = 464
+Color = White
Font = 0
-Size = 24
-Text=
+Size = 21
+Text =
[StatDetailStatic1]
-X =40
-Y =71
-W =32
-H =32
-Color =ColorDark
-Tex =MainIcon
-Type=Font Black
+X = 35
+Y = 65
+W = 27
+H = 27
+Color = ColorDark
+Tex = MainIcon
+Type = Transparent
[StatDetailStatic2]
-X =40
-Y =120
-W =520
-H =24
-Tex=StatDetailBG1
-Color =ColorLight
-Type=Font Black
+X = 0
+Y = 545
+W = 250
+H = 30
+Tex = Leiste1
+Color = ColorLight
+Type = Colorized
+Reflection = 1
+ReflectionSpacing = 2
[StatDetailStatic3]
-X =40
-Y =144
-W =520
-H =379
-Tex=StatMainBG2
-Color =ColorDark
-Type=Font Black
+X = 250
+Y = 545
+W = 550
+H = 30
+Tex = Leiste2
+Color = White
+Type = Transparent
+Reflection = 1
+ReflectionSpacing = 2
[StatDetailStatic4]
-X =40
-Y =523
-W =520
-H =20
-Tex=StatMainBG3
-Color =ColorLight
-Type=Font Black
+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 =6
-Color=GrayLight
-Font =1
-Size = 66
-Text=STAT_DETAIL
-Align=0
+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
-# # # # OnScreen PopUp Error / Question Messages # # # #
[CheckPopup]
-Texts=0
-Statics=3
+
+[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 = 192
-Y = 327
-W = 128
-H = 50
-Tex =MainBar
+X = 285
+Y = 310
+W = 100
+H = 25
+Tex = Button
Color = ColorDark
-DColor = White
-Int=1
-DInt=0.5
-Type=Font Black
-Texts=1
+DColor = Gray
+Type = Transparent
+Texts = 1
Z = 1
[CheckPopupButton1Text1]
-X =64
-Y =13
-Color=White
-Font =0
+X = 50
+Y = 0
+Color = White
+Font = 0
Size = 24
-Text=Yes
-Align=1
-Z=1
+Text = YES
+Align = 1
+Z = 1
[CheckPopupButton2]
-X = 480
-Y = 327
-W = 128
-H = 50
-Tex =MainBar
+X = 415
+Y = 310
+W = 100
+H = 25
+Tex = Button
Color = ColorDark
-DColor = White
-Int=1
-DInt=0.5
-Type=Font Black
-Texts=1
+DColor = Gray
+Type = Transparent
+Texts = 1
Z = 1
[CheckPopupButton2Text1]
-X =64
-Y =13
-Color=White
-Font =0
+X = 50
+Y = 0
+Color = White
+Font = 0
Size = 24
-Text=No
-Align=1
-Z=1
-
-[CheckPopupText]
-X =400
-Y =226
-W =500
-Color=Black
-Font =0
-Size = 42
-Text=
-Align=1
-Z=1
-
-[CheckPopupStatic1]
-Tex =PopUpBG
-X =99
-Y =224
-W =602
-H =152
-Z =1
-Int=1
-Color =White
-Type=Font Black
-
-[CheckPopupStatic2]
-Tex =PopUpFG
-X =99
-Y =224
-W =602
-H =152
-Z =1
-Int=1
-Color =Black
-Type=Font Black
+Text = NO
+Align = 1
+Z = 1
-[CheckPopupStatic3]
-Tex =IconQuestion
-X =124
-Y =235
-W =44
-H =44
-Z =1
-Int=1
-Color =Black
-Type=Font Black
[ErrorPopup]
-Texts=1
-Statics=1
-[ErrorPopupButton1]
-X = 366
-Y = 342
-W =22
-H =22
-Tex =ButtonEnter
-Color = White
-DColor = White
-Type=Plain
-Texts=1
+[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
-[ErrorPopupButton1Text1]
-X =32
-Y =0
-Color=Black
-Font =0
-Size = 30
-Text=OK
-Align=0
-Z=0
+[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 =226
-W =500
-Color=Black
-Font =0
-Size = 42
-Text=
-Align=1
-Z=1
+X = 400
+Y = 210
+W = 280
+Color = GrayDark
+Font = 0
+Size = 35
+Text = error text
+Align = 1
+Z = 1
-[ErrorPopupStatic1]
-Tex =PopUpBG
-X =99
-Y =224
-W =602
-H =152
-Z =1
-Int=1
-Color =White
-Type=Font Black
-
-[ErrorPopupStatic2]
-Tex =PopUpFG
-X =99
-Y =224
-W =602
-H =152
-Z =1
-Int=1
-Color =Black
-Type=Font Black
+[ErrorPopupButton1]
+X = 350
+Y = 310
+W = 100
+H = 25
+Tex = Button
+Color = ColorDark
+DColor = Gray
+Type = Transparent
+Texts = 1
+Z = 1
-[ErrorPopupStatic3]
-Tex =IconError
-X =124
-Y =235
-W =44
-H =44
-Z =1
-Int=1
-Color =Black
-Type=Font Black
+[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
diff --git a/cmake/game/themes/Classic/Star.ini b/cmake/game/themes/Classic/Star.ini
index 263118b9..e72bdbec 100644
--- a/cmake/game/themes/Classic/Star.ini
+++ b/cmake/game/themes/Classic/Star.ini
@@ -6,155 +6,241 @@
[Skin]
Theme=Classic
Name=Star
-Creator=UltraStar Deluxe Team
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.jpg
-ButtonF = [main]ButtonEditor.jpg
-MainBar = [main]Bar.jpg
-Logo = [main]Logo.jpg
+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 = #Placeholder for new Classic Skins
-#MainBG =
-#SongBG =
-#ScoresBG =
-#Top5BG =
-#OptionsBG =
-#PartyBG =
+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
-MainIcon = [icon]Star.jpg
-MainSearch = [icon]Search.jpg
-IconOption = [icon]Options.jpg
-IconSongMenu = [icon]SongMenu.jpg
-ScoreIcon = [icon]Score.jpg
-PartyIcon = [icon]Party.jpg
-StatIcon = [icon]Stats.jpg
-SongCD = [icon]cd.jpg
-IconQuestion = [icon]question.jpg
-IconError = [icon]error.jpg
-VideoIcon = [icon]video.jpg
-
-# # # M A I N S C R E E N # # #
-ButtonSolo = [mainbutton]Solo.jpg
-ButtonMulti = [mainbutton]Multi.jpg
-ButtonEditor = [mainbutton]Solo.jpg
-ButtonStats = [mainbutton]Stats.jpg
-ButtonOptions = [mainbutton]Options.jpg
-ButtonExit = [mainbutton]Exit.jpg
+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.jpg
-SongFade = [song]BGFade.jpg
-SongEqualizerBG= [song]EqualizerBG.jpg
+SongSelection = [song]selection.png
SongCover = [main]songCover.jpg
# # # S I N G # # #
#the bar where the lyrics reside
-LyricBar = [sing]textBar.jpg
+LyricBar = [sing]textBar.png
#this one slides in, to tell you that singing starts immediately
-LyricHelpBar = [sing]lyricsHelpBar.bmp
-
-#the time progress bar (not skinned in this theme :P )
-TimeBar1 = [sing]timeBarBG.jpg
+LyricHelpBar = [sing]lyricsHelpBar.png
#the bar behind the timestuff
-TimeBar2 = [sing]timeBar.jpg
+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.jpg
+LineBonusBack = [sing]lineBonusPopUp.png
#Singbar (the thing beneath the scores)
-SingBarBack = [sing]singBarBack.jpg
-SingBarBar = [sing]singBarBar.jpg
-SingBarFront = [sing]singBarFront.jpg
+SingBarBack = [sing]singBarBack.png
+SingBarBar = [sing]singBarBar.png
+SingBarFront = [sing]singBarFront.png
#Background for scores
-ScoreBG = [sing]scoreBg.jpg
+ScoreBG = [sing]scoreBg.png
#Background for the P1, P2 and so on
-P = [sing]p.jpg
+P = [sing]p.png
#Pointer for lyrics
Ball = [sing]LyricsBall.png
# # # S C O R E / T O P 5 # # #
-ScoreBox = [score]Box.jpg
-ScoreLevel = [score]level.jpg
-ScoreLevelRound = [score]levelRound.jpg
-ScoreLine = [score]line.jpg
-PlayerNumberBox = [main]playerNumberBox.jpg
+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.jpg
-PartyPlayerButton =[party]playerButton.jpg
-PartyTeamButton1 =[party]roundTeamButton.jpg
-PartyTeamButton2 =[party]playerTeamButton.jpg
-PartyTeamButton3 =[party]winTeamButton1.jpg
-PartyTeamButton4 =[party]winTeamButton2.jpg
-PartyTeamButton5 =[party]winTeamButton3.jpg
-PartyRoundBG1 =[party]roundBG1.jpg
-PartyRoundBG2 =[party]roundBG2.jpg
-PartyRoundBG3 =[party]roundBG3.jpg
-PartyRoundBG4 =[party]roundBG4.jpg
-HDL_Pointer =[party]pointer.bmp
-PartyTeamPoints =[party]teamPoints.jpg
-PartyScoreDeco =[party]scoreDecoration.jpg
-PartyScoreBG1 =[party]scoreBG1.jpg
-PartyScoreBG2 =[party]scoreBG2.jpg
-PartyWinDeco1 =[party]winDecoration.jpg
-PartyWinDeco2 =[party]winDecoration.jpg
-PartyWinDeco3 =[party]winDecoration.jpg
+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.jpg
-StatMainBG2 = [stat]mainBG2.jpg
-StatMainBG3 = [stat]mainBG3.jpg
-StatDetailBG1 = [stat]detailBG1.jpg
+StatMainBG1 = [stat]mainBG1.png
+StatMainBG2 = [stat]mainBG2.png
+StatMainBG3 = [stat]mainBG3.png
+StatDetailBG1 = [stat]detailBG1.png
# # # N A V I # # #
-ButtonP = [button]p.jpg
-ButtonE = [button]e.jpg
-ButtonM = [button]m.jpg
-ButtonJ = [button]j.jpg
-ButtonAlt = [button]alt.jpg
-ButtonAZ = [button]az.jpg
-ButtonEnter = [button]enter.jpg
-ButtonNavi = [button]navi.jpg
-ButtonEsc = [button]esc.jpg
-Button13 = [button]13.jpg
-
-JumpToBG = [menu]JumptoBg.jpg
-SongMenuBG = [menu]songMenuBg.jpg
-SongMenuBorder = [menu]songMenuBorder.jpg
-SongMenuButton = [menu]songMenuButtonBG.jpg
-SongMenuSelectBG = [menu]songMenuSelectBg.jpg
-PopUpBG = [menu]popUpBG.jpg
-PopUpFG = [menu]popUpFG.jpg
+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 # # #
-GrayLeft = [sing]notesLeft.bmp
-GrayMid = [sing]notesMid.bmp
-GrayRight = [sing]notesRight.bmp
-NoteBGLeft = [sing]notesBgLeft.bmp
-NoteBGMid = [sing]notesBgMid.bmp
-NoteBGRight = [sing]notesBgRight.bmp
+# 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.jpg
-NotePerfectStar = [effect]perfectNoteStar.jpg
+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/cmake/game/themes/Classic/[bg-load]star.jpg b/cmake/game/themes/Classic/[bg-load]star.jpg
new file mode 100644
index 00000000..c94a7f9c
--- /dev/null
+++ b/cmake/game/themes/Classic/[bg-load]star.jpg
Binary files differ
diff --git a/cmake/game/themes/Classic/[bg-main]star.jpg b/cmake/game/themes/Classic/[bg-main]star.jpg
new file mode 100644
index 00000000..0cd0a9aa
--- /dev/null
+++ b/cmake/game/themes/Classic/[bg-main]star.jpg
Binary files differ
diff --git a/cmake/game/themes/Classic/[button]13.jpg b/cmake/game/themes/Classic/[button]13.jpg
deleted file mode 100644
index 5787bb24..00000000
--- a/cmake/game/themes/Classic/[button]13.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[button]13.png b/cmake/game/themes/Classic/[button]13.png
new file mode 100644
index 00000000..9b1a8761
--- /dev/null
+++ b/cmake/game/themes/Classic/[button]13.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[button]alt.jpg b/cmake/game/themes/Classic/[button]alt.jpg
deleted file mode 100644
index ec3e630f..00000000
--- a/cmake/game/themes/Classic/[button]alt.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[button]alt.png b/cmake/game/themes/Classic/[button]alt.png
new file mode 100644
index 00000000..6232f783
--- /dev/null
+++ b/cmake/game/themes/Classic/[button]alt.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[button]az.jpg b/cmake/game/themes/Classic/[button]az.jpg
deleted file mode 100644
index b486604e..00000000
--- a/cmake/game/themes/Classic/[button]az.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[button]az.png b/cmake/game/themes/Classic/[button]az.png
new file mode 100644
index 00000000..ffd356bd
--- /dev/null
+++ b/cmake/game/themes/Classic/[button]az.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[button]e.jpg b/cmake/game/themes/Classic/[button]e.jpg
deleted file mode 100644
index 7b247260..00000000
--- a/cmake/game/themes/Classic/[button]e.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[button]e.png b/cmake/game/themes/Classic/[button]e.png
new file mode 100644
index 00000000..948d4911
--- /dev/null
+++ b/cmake/game/themes/Classic/[button]e.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[button]enter.jpg b/cmake/game/themes/Classic/[button]enter.jpg
deleted file mode 100644
index 16ee885a..00000000
--- a/cmake/game/themes/Classic/[button]enter.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[button]enter.png b/cmake/game/themes/Classic/[button]enter.png
new file mode 100644
index 00000000..51e994e1
--- /dev/null
+++ b/cmake/game/themes/Classic/[button]enter.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[button]esc.jpg b/cmake/game/themes/Classic/[button]esc.jpg
deleted file mode 100644
index 7c40487a..00000000
--- a/cmake/game/themes/Classic/[button]esc.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[button]esc.png b/cmake/game/themes/Classic/[button]esc.png
new file mode 100644
index 00000000..075e4e97
--- /dev/null
+++ b/cmake/game/themes/Classic/[button]esc.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[button]j.jpg b/cmake/game/themes/Classic/[button]j.jpg
deleted file mode 100644
index b6eed56c..00000000
--- a/cmake/game/themes/Classic/[button]j.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[button]j.png b/cmake/game/themes/Classic/[button]j.png
new file mode 100644
index 00000000..31010a41
--- /dev/null
+++ b/cmake/game/themes/Classic/[button]j.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[button]m.jpg b/cmake/game/themes/Classic/[button]m.jpg
deleted file mode 100644
index ebb7156e..00000000
--- a/cmake/game/themes/Classic/[button]m.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[button]m.png b/cmake/game/themes/Classic/[button]m.png
new file mode 100644
index 00000000..2cf5f02f
--- /dev/null
+++ b/cmake/game/themes/Classic/[button]m.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[button]navi.jpg b/cmake/game/themes/Classic/[button]navi.jpg
deleted file mode 100644
index 41b44525..00000000
--- a/cmake/game/themes/Classic/[button]navi.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[button]navi.png b/cmake/game/themes/Classic/[button]navi.png
new file mode 100644
index 00000000..1b479aaf
--- /dev/null
+++ b/cmake/game/themes/Classic/[button]navi.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[button]p.jpg b/cmake/game/themes/Classic/[button]p.jpg
deleted file mode 100644
index d2d60c02..00000000
--- a/cmake/game/themes/Classic/[button]p.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[button]p.png b/cmake/game/themes/Classic/[button]p.png
new file mode 100644
index 00000000..d12d04c5
--- /dev/null
+++ b/cmake/game/themes/Classic/[button]p.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[effect]goldenNoteStar.jpg b/cmake/game/themes/Classic/[effect]goldenNoteStar.jpg
deleted file mode 100644
index 1b31d267..00000000
--- a/cmake/game/themes/Classic/[effect]goldenNoteStar.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[effect]goldenNoteStar.png b/cmake/game/themes/Classic/[effect]goldenNoteStar.png
new file mode 100644
index 00000000..7bd6225f
--- /dev/null
+++ b/cmake/game/themes/Classic/[effect]goldenNoteStar.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[effect]perfectNoteStar.jpg b/cmake/game/themes/Classic/[effect]perfectNoteStar.jpg
deleted file mode 100644
index 189a22a3..00000000
--- a/cmake/game/themes/Classic/[effect]perfectNoteStar.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[effect]perfectNoteStar.png b/cmake/game/themes/Classic/[effect]perfectNoteStar.png
new file mode 100644
index 00000000..99132c39
--- /dev/null
+++ b/cmake/game/themes/Classic/[effect]perfectNoteStar.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[helper]buttonFade.png b/cmake/game/themes/Classic/[helper]buttonFade.png
new file mode 100644
index 00000000..27a94c44
--- /dev/null
+++ b/cmake/game/themes/Classic/[helper]buttonFade.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[helper]rectangle.jpg b/cmake/game/themes/Classic/[helper]rectangle.jpg
index e03f98fc..9b4ba0f9 100644
--- a/cmake/game/themes/Classic/[helper]rectangle.jpg
+++ b/cmake/game/themes/Classic/[helper]rectangle.jpg
Binary files differ
diff --git a/cmake/game/themes/Classic/[icon]Star.jpg b/cmake/game/themes/Classic/[icon]Star.jpg
deleted file mode 100644
index ee98f9d7..00000000
--- a/cmake/game/themes/Classic/[icon]Star.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[icon]Star.png b/cmake/game/themes/Classic/[icon]Star.png
new file mode 100644
index 00000000..409e9599
--- /dev/null
+++ b/cmake/game/themes/Classic/[icon]Star.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[icon]cd.png b/cmake/game/themes/Classic/[icon]cd.png
new file mode 100644
index 00000000..2633d235
--- /dev/null
+++ b/cmake/game/themes/Classic/[icon]cd.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[icon]error.jpg b/cmake/game/themes/Classic/[icon]error.jpg
deleted file mode 100644
index 5802e312..00000000
--- a/cmake/game/themes/Classic/[icon]error.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[icon]error.png b/cmake/game/themes/Classic/[icon]error.png
new file mode 100644
index 00000000..f952f3fa
--- /dev/null
+++ b/cmake/game/themes/Classic/[icon]error.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[icon]main.png b/cmake/game/themes/Classic/[icon]main.png
new file mode 100644
index 00000000..f7d50067
--- /dev/null
+++ b/cmake/game/themes/Classic/[icon]main.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[icon]options.png b/cmake/game/themes/Classic/[icon]options.png
new file mode 100644
index 00000000..9fac0bfd
--- /dev/null
+++ b/cmake/game/themes/Classic/[icon]options.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[icon]party.png b/cmake/game/themes/Classic/[icon]party.png
new file mode 100644
index 00000000..e23230e3
--- /dev/null
+++ b/cmake/game/themes/Classic/[icon]party.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[icon]question.jpg b/cmake/game/themes/Classic/[icon]question.jpg
deleted file mode 100644
index e78fe6a8..00000000
--- a/cmake/game/themes/Classic/[icon]question.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[icon]question.png b/cmake/game/themes/Classic/[icon]question.png
new file mode 100644
index 00000000..a72a5c43
--- /dev/null
+++ b/cmake/game/themes/Classic/[icon]question.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[icon]score.png b/cmake/game/themes/Classic/[icon]score.png
new file mode 100644
index 00000000..ccc3d8ff
--- /dev/null
+++ b/cmake/game/themes/Classic/[icon]score.png
Binary files differ
diff --git a/cmake/game/themes/Deluxe/icon/song_menu.png b/cmake/game/themes/Classic/[icon]song_menu.png
index acf69bfb..acf69bfb 100644
--- a/cmake/game/themes/Deluxe/icon/song_menu.png
+++ b/cmake/game/themes/Classic/[icon]song_menu.png
Binary files differ
diff --git a/cmake/game/themes/Deluxe/icon/song_search.png b/cmake/game/themes/Classic/[icon]song_search.png
index f5190315..f5190315 100644
--- a/cmake/game/themes/Deluxe/icon/song_search.png
+++ b/cmake/game/themes/Classic/[icon]song_search.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[icon]song_video.png b/cmake/game/themes/Classic/[icon]song_video.png
new file mode 100644
index 00000000..4a679249
--- /dev/null
+++ b/cmake/game/themes/Classic/[icon]song_video.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[icon]stats.jpg b/cmake/game/themes/Classic/[icon]stats.jpg
deleted file mode 100644
index cd5e03fb..00000000
--- a/cmake/game/themes/Classic/[icon]stats.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[icon]stats.png b/cmake/game/themes/Classic/[icon]stats.png
new file mode 100644
index 00000000..d8e5eac1
--- /dev/null
+++ b/cmake/game/themes/Classic/[icon]stats.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[icon]video.jpg b/cmake/game/themes/Classic/[icon]video.jpg
deleted file mode 100644
index 12d71add..00000000
--- a/cmake/game/themes/Classic/[icon]video.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[icon]video.png b/cmake/game/themes/Classic/[icon]video.png
new file mode 100644
index 00000000..9bd65f86
--- /dev/null
+++ b/cmake/game/themes/Classic/[icon]video.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[interface]cursor.png b/cmake/game/themes/Classic/[interface]cursor.png
new file mode 100644
index 00000000..0fe390f0
--- /dev/null
+++ b/cmake/game/themes/Classic/[interface]cursor.png
Binary files differ
diff --git a/cmake/game/themes/Deluxe/interface/cursor_pressed.png b/cmake/game/themes/Classic/[interface]cursor_pressed.png
index 3fc36a5a..fa0056cc 100644
--- a/cmake/game/themes/Deluxe/interface/cursor_pressed.png
+++ b/cmake/game/themes/Classic/[interface]cursor_pressed.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[interface]dialog_background.png b/cmake/game/themes/Classic/[interface]dialog_background.png
new file mode 100644
index 00000000..3113cd30
--- /dev/null
+++ b/cmake/game/themes/Classic/[interface]dialog_background.png
Binary files differ
diff --git a/cmake/game/themes/Deluxe/interface/select_arrow_left.png b/cmake/game/themes/Classic/[interface]select_arrow_left.png
index e4a32d2d..e4a32d2d 100644
--- a/cmake/game/themes/Deluxe/interface/select_arrow_left.png
+++ b/cmake/game/themes/Classic/[interface]select_arrow_left.png
Binary files differ
diff --git a/cmake/game/themes/Deluxe/interface/select_arrow_right.png b/cmake/game/themes/Classic/[interface]select_arrow_right.png
index b2a29793..b2a29793 100644
--- a/cmake/game/themes/Deluxe/interface/select_arrow_right.png
+++ b/cmake/game/themes/Classic/[interface]select_arrow_right.png
Binary files differ
diff --git a/cmake/game/themes/Deluxe/interface/selectbg_search.png b/cmake/game/themes/Classic/[interface]selectbg_search.png
index 57d0ca88..57d0ca88 100644
--- a/cmake/game/themes/Deluxe/interface/selectbg_search.png
+++ b/cmake/game/themes/Classic/[interface]selectbg_search.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[main]Bar.jpg b/cmake/game/themes/Classic/[main]Bar.jpg
deleted file mode 100644
index 2453cc3b..00000000
--- a/cmake/game/themes/Classic/[main]Bar.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[main]Bar1.jpg b/cmake/game/themes/Classic/[main]Bar1.jpg
deleted file mode 100644
index 4e9693e3..00000000
--- a/cmake/game/themes/Classic/[main]Bar1.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[main]Button.jpg b/cmake/game/themes/Classic/[main]Button.jpg
deleted file mode 100644
index e6191a95..00000000
--- a/cmake/game/themes/Classic/[main]Button.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[main]Button2.jpg b/cmake/game/themes/Classic/[main]Button2.jpg
deleted file mode 100644
index e3e9679a..00000000
--- a/cmake/game/themes/Classic/[main]Button2.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[main]Button3.jpg b/cmake/game/themes/Classic/[main]Button3.jpg
deleted file mode 100644
index 3ac1f442..00000000
--- a/cmake/game/themes/Classic/[main]Button3.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[main]ButtonEditor.jpg b/cmake/game/themes/Classic/[main]ButtonEditor.jpg
deleted file mode 100644
index 32e455ef..00000000
--- a/cmake/game/themes/Classic/[main]ButtonEditor.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[main]Logo.jpg b/cmake/game/themes/Classic/[main]Logo.jpg
deleted file mode 100644
index 1902cb02..00000000
--- a/cmake/game/themes/Classic/[main]Logo.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[main]button.png b/cmake/game/themes/Classic/[main]button.png
new file mode 100644
index 00000000..978e04df
--- /dev/null
+++ b/cmake/game/themes/Classic/[main]button.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[main]buttonf.jpg b/cmake/game/themes/Classic/[main]buttonf.jpg
new file mode 100644
index 00000000..d844add5
--- /dev/null
+++ b/cmake/game/themes/Classic/[main]buttonf.jpg
Binary files differ
diff --git a/cmake/game/themes/Classic/[main]logo.png b/cmake/game/themes/Classic/[main]logo.png
new file mode 100644
index 00000000..9b559de9
--- /dev/null
+++ b/cmake/game/themes/Classic/[main]logo.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[main]mainBar.png b/cmake/game/themes/Classic/[main]mainBar.png
new file mode 100644
index 00000000..60063e63
--- /dev/null
+++ b/cmake/game/themes/Classic/[main]mainBar.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[main]playerNumberBox.png b/cmake/game/themes/Classic/[main]playerNumberBox.png
new file mode 100644
index 00000000..3336ef56
--- /dev/null
+++ b/cmake/game/themes/Classic/[main]playerNumberBox.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[main]selectbg.png b/cmake/game/themes/Classic/[main]selectbg.png
new file mode 100644
index 00000000..9917045d
--- /dev/null
+++ b/cmake/game/themes/Classic/[main]selectbg.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[main]songCover.jpg b/cmake/game/themes/Classic/[main]songCover.jpg
index 426bf22d..7cf8930b 100644
--- a/cmake/game/themes/Classic/[main]songCover.jpg
+++ b/cmake/game/themes/Classic/[main]songCover.jpg
Binary files differ
diff --git a/cmake/game/themes/Classic/[main]square.jpg b/cmake/game/themes/Classic/[main]square.jpg
deleted file mode 100644
index 8af62b71..00000000
--- a/cmake/game/themes/Classic/[main]square.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[mainbutton]Exit.jpg b/cmake/game/themes/Classic/[mainbutton]Exit.jpg
deleted file mode 100644
index 55494e65..00000000
--- a/cmake/game/themes/Classic/[mainbutton]Exit.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[mainbutton]Exit.png b/cmake/game/themes/Classic/[mainbutton]Exit.png
new file mode 100644
index 00000000..bfd79f1e
--- /dev/null
+++ b/cmake/game/themes/Classic/[mainbutton]Exit.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[mainbutton]Multi.jpg b/cmake/game/themes/Classic/[mainbutton]Multi.jpg
deleted file mode 100644
index ad5980d7..00000000
--- a/cmake/game/themes/Classic/[mainbutton]Multi.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[mainbutton]Multi.png b/cmake/game/themes/Classic/[mainbutton]Multi.png
new file mode 100644
index 00000000..caea5c2b
--- /dev/null
+++ b/cmake/game/themes/Classic/[mainbutton]Multi.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[mainbutton]Options.jpg b/cmake/game/themes/Classic/[mainbutton]Options.jpg
deleted file mode 100644
index 5e1bff71..00000000
--- a/cmake/game/themes/Classic/[mainbutton]Options.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[mainbutton]Options.png b/cmake/game/themes/Classic/[mainbutton]Options.png
new file mode 100644
index 00000000..940e37a5
--- /dev/null
+++ b/cmake/game/themes/Classic/[mainbutton]Options.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[mainbutton]Solo.jpg b/cmake/game/themes/Classic/[mainbutton]Solo.jpg
deleted file mode 100644
index a7e3d82a..00000000
--- a/cmake/game/themes/Classic/[mainbutton]Solo.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[mainbutton]Solo.png b/cmake/game/themes/Classic/[mainbutton]Solo.png
new file mode 100644
index 00000000..9f205872
--- /dev/null
+++ b/cmake/game/themes/Classic/[mainbutton]Solo.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[mainbutton]Stats.jpg b/cmake/game/themes/Classic/[mainbutton]Stats.jpg
deleted file mode 100644
index 71cc13ad..00000000
--- a/cmake/game/themes/Classic/[mainbutton]Stats.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[mainbutton]Stats.png b/cmake/game/themes/Classic/[mainbutton]Stats.png
new file mode 100644
index 00000000..588c2ce6
--- /dev/null
+++ b/cmake/game/themes/Classic/[mainbutton]Stats.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[menu]PopUpBg.JPG b/cmake/game/themes/Classic/[menu]PopUpBg.JPG
deleted file mode 100644
index 1a23a90c..00000000
--- a/cmake/game/themes/Classic/[menu]PopUpBg.JPG
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[menu]PopUpFg.JPG b/cmake/game/themes/Classic/[menu]PopUpFg.JPG
deleted file mode 100644
index 530d4cf9..00000000
--- a/cmake/game/themes/Classic/[menu]PopUpFg.JPG
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[menu]PopUpFg.png b/cmake/game/themes/Classic/[menu]PopUpFg.png
new file mode 100644
index 00000000..2c9785b4
--- /dev/null
+++ b/cmake/game/themes/Classic/[menu]PopUpFg.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[menu]jumpToBg.jpg b/cmake/game/themes/Classic/[menu]jumpToBg.jpg
deleted file mode 100644
index d0cd1da8..00000000
--- a/cmake/game/themes/Classic/[menu]jumpToBg.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[menu]jumpToBg.png b/cmake/game/themes/Classic/[menu]jumpToBg.png
new file mode 100644
index 00000000..8e3a3a00
--- /dev/null
+++ b/cmake/game/themes/Classic/[menu]jumpToBg.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[menu]songMenuBg.jpg b/cmake/game/themes/Classic/[menu]songMenuBg.jpg
deleted file mode 100644
index e4242fc5..00000000
--- a/cmake/game/themes/Classic/[menu]songMenuBg.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[menu]songMenuBg.png b/cmake/game/themes/Classic/[menu]songMenuBg.png
new file mode 100644
index 00000000..92beff8e
--- /dev/null
+++ b/cmake/game/themes/Classic/[menu]songMenuBg.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[menu]songMenuBorder.jpg b/cmake/game/themes/Classic/[menu]songMenuBorder.jpg
deleted file mode 100644
index 11dd0604..00000000
--- a/cmake/game/themes/Classic/[menu]songMenuBorder.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[menu]songMenuButtonBG.jpg b/cmake/game/themes/Classic/[menu]songMenuButtonBG.jpg
deleted file mode 100644
index 53f0da59..00000000
--- a/cmake/game/themes/Classic/[menu]songMenuButtonBG.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[menu]songMenuSelectBG.jpg b/cmake/game/themes/Classic/[menu]songMenuSelectBG.jpg
deleted file mode 100644
index cd3041e2..00000000
--- a/cmake/game/themes/Classic/[menu]songMenuSelectBG.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[menu]songMenuSelectBg.png b/cmake/game/themes/Classic/[menu]songMenuSelectBg.png
new file mode 100644
index 00000000..8ff5eef8
--- /dev/null
+++ b/cmake/game/themes/Classic/[menu]songMenuSelectBg.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]Joker.jpg b/cmake/game/themes/Classic/[party]Joker.jpg
deleted file mode 100644
index 78b66936..00000000
--- a/cmake/game/themes/Classic/[party]Joker.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]Joker.png b/cmake/game/themes/Classic/[party]Joker.png
new file mode 100644
index 00000000..ba667a9b
--- /dev/null
+++ b/cmake/game/themes/Classic/[party]Joker.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]playerButton.jpg b/cmake/game/themes/Classic/[party]playerButton.jpg
deleted file mode 100644
index 15a34c66..00000000
--- a/cmake/game/themes/Classic/[party]playerButton.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]playerButton.png b/cmake/game/themes/Classic/[party]playerButton.png
new file mode 100644
index 00000000..7232b25c
--- /dev/null
+++ b/cmake/game/themes/Classic/[party]playerButton.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]playerTeamButton.jpg b/cmake/game/themes/Classic/[party]playerTeamButton.jpg
deleted file mode 100644
index 2faf9c4b..00000000
--- a/cmake/game/themes/Classic/[party]playerTeamButton.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]playerTeamButton.png b/cmake/game/themes/Classic/[party]playerTeamButton.png
new file mode 100644
index 00000000..71aa736a
--- /dev/null
+++ b/cmake/game/themes/Classic/[party]playerTeamButton.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]playerselectbg.png b/cmake/game/themes/Classic/[party]playerselectbg.png
new file mode 100644
index 00000000..daf44ace
--- /dev/null
+++ b/cmake/game/themes/Classic/[party]playerselectbg.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]pointer.bmp b/cmake/game/themes/Classic/[party]pointer.bmp
deleted file mode 100644
index 88bbcc3d..00000000
--- a/cmake/game/themes/Classic/[party]pointer.bmp
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]pointer.png b/cmake/game/themes/Classic/[party]pointer.png
new file mode 100644
index 00000000..2292d6c1
--- /dev/null
+++ b/cmake/game/themes/Classic/[party]pointer.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]roundBG1.jpg b/cmake/game/themes/Classic/[party]roundBG1.jpg
deleted file mode 100644
index 464aabea..00000000
--- a/cmake/game/themes/Classic/[party]roundBG1.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]roundBG1.png b/cmake/game/themes/Classic/[party]roundBG1.png
new file mode 100644
index 00000000..5f40c7f5
--- /dev/null
+++ b/cmake/game/themes/Classic/[party]roundBG1.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]roundBG2.jpg b/cmake/game/themes/Classic/[party]roundBG2.jpg
deleted file mode 100644
index 3413958f..00000000
--- a/cmake/game/themes/Classic/[party]roundBG2.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]roundBG2.png b/cmake/game/themes/Classic/[party]roundBG2.png
new file mode 100644
index 00000000..02afa063
--- /dev/null
+++ b/cmake/game/themes/Classic/[party]roundBG2.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]roundBG3.jpg b/cmake/game/themes/Classic/[party]roundBG3.jpg
deleted file mode 100644
index c6b53caf..00000000
--- a/cmake/game/themes/Classic/[party]roundBG3.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]roundBG3.png b/cmake/game/themes/Classic/[party]roundBG3.png
new file mode 100644
index 00000000..8c18cf73
--- /dev/null
+++ b/cmake/game/themes/Classic/[party]roundBG3.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]roundBG4.jpg b/cmake/game/themes/Classic/[party]roundBG4.jpg
deleted file mode 100644
index 5e4da0ac..00000000
--- a/cmake/game/themes/Classic/[party]roundBG4.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]roundBG4.png b/cmake/game/themes/Classic/[party]roundBG4.png
new file mode 100644
index 00000000..94a5caa7
--- /dev/null
+++ b/cmake/game/themes/Classic/[party]roundBG4.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]roundTeamButton.jpg b/cmake/game/themes/Classic/[party]roundTeamButton.jpg
deleted file mode 100644
index 692db1bd..00000000
--- a/cmake/game/themes/Classic/[party]roundTeamButton.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]roundTeamButton.png b/cmake/game/themes/Classic/[party]roundTeamButton.png
new file mode 100644
index 00000000..08c645b1
--- /dev/null
+++ b/cmake/game/themes/Classic/[party]roundTeamButton.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]scoreBG1.jpg b/cmake/game/themes/Classic/[party]scoreBG1.jpg
deleted file mode 100644
index f558425d..00000000
--- a/cmake/game/themes/Classic/[party]scoreBG1.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]scoreBG1.png b/cmake/game/themes/Classic/[party]scoreBG1.png
new file mode 100644
index 00000000..53e68562
--- /dev/null
+++ b/cmake/game/themes/Classic/[party]scoreBG1.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]scoreBG2.jpg b/cmake/game/themes/Classic/[party]scoreBG2.jpg
deleted file mode 100644
index 47239d85..00000000
--- a/cmake/game/themes/Classic/[party]scoreBG2.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]scoreBG2.png b/cmake/game/themes/Classic/[party]scoreBG2.png
new file mode 100644
index 00000000..9b4bb52d
--- /dev/null
+++ b/cmake/game/themes/Classic/[party]scoreBG2.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]scoreDecoration.jpg b/cmake/game/themes/Classic/[party]scoreDecoration.jpg
deleted file mode 100644
index 49204e19..00000000
--- a/cmake/game/themes/Classic/[party]scoreDecoration.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]scoreDecoration.png b/cmake/game/themes/Classic/[party]scoreDecoration.png
new file mode 100644
index 00000000..388077e6
--- /dev/null
+++ b/cmake/game/themes/Classic/[party]scoreDecoration.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]teamPoints.jpg b/cmake/game/themes/Classic/[party]teamPoints.jpg
deleted file mode 100644
index 96855bc9..00000000
--- a/cmake/game/themes/Classic/[party]teamPoints.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]teamPoints.png b/cmake/game/themes/Classic/[party]teamPoints.png
new file mode 100644
index 00000000..e7c3b3cc
--- /dev/null
+++ b/cmake/game/themes/Classic/[party]teamPoints.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]winDecoration.jpg b/cmake/game/themes/Classic/[party]winDecoration.jpg
deleted file mode 100644
index 1d48ddb3..00000000
--- a/cmake/game/themes/Classic/[party]winDecoration.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]winDecoration.png b/cmake/game/themes/Classic/[party]winDecoration.png
new file mode 100644
index 00000000..f84dbc8a
--- /dev/null
+++ b/cmake/game/themes/Classic/[party]winDecoration.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]winTeamButton1.jpg b/cmake/game/themes/Classic/[party]winTeamButton1.jpg
deleted file mode 100644
index 10c8d80f..00000000
--- a/cmake/game/themes/Classic/[party]winTeamButton1.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]winTeamButton1.png b/cmake/game/themes/Classic/[party]winTeamButton1.png
new file mode 100644
index 00000000..a3e20695
--- /dev/null
+++ b/cmake/game/themes/Classic/[party]winTeamButton1.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]winTeamButton2.jpg b/cmake/game/themes/Classic/[party]winTeamButton2.jpg
deleted file mode 100644
index fbd85056..00000000
--- a/cmake/game/themes/Classic/[party]winTeamButton2.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]winTeamButton2.png b/cmake/game/themes/Classic/[party]winTeamButton2.png
new file mode 100644
index 00000000..78237c12
--- /dev/null
+++ b/cmake/game/themes/Classic/[party]winTeamButton2.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]winTeamButton3.jpg b/cmake/game/themes/Classic/[party]winTeamButton3.jpg
deleted file mode 100644
index e8dd9566..00000000
--- a/cmake/game/themes/Classic/[party]winTeamButton3.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[party]winTeamButton3.png b/cmake/game/themes/Classic/[party]winTeamButton3.png
new file mode 100644
index 00000000..0d0d2788
--- /dev/null
+++ b/cmake/game/themes/Classic/[party]winTeamButton3.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]Line.png b/cmake/game/themes/Classic/[score]Line.png
new file mode 100644
index 00000000..954caf94
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]Line.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]bar_box_dark.png b/cmake/game/themes/Classic/[score]bar_box_dark.png
new file mode 100644
index 00000000..e4fbfa41
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]bar_box_dark.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]bar_box_light.png b/cmake/game/themes/Classic/[score]bar_box_light.png
new file mode 100644
index 00000000..ddc17ed8
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]bar_box_light.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]bar_box_lightest.png b/cmake/game/themes/Classic/[score]bar_box_lightest.png
new file mode 100644
index 00000000..995bb9ef
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]bar_box_lightest.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]box.jpg b/cmake/game/themes/Classic/[score]box.jpg
deleted file mode 100644
index b37f7e46..00000000
--- a/cmake/game/themes/Classic/[score]box.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]box.png b/cmake/game/themes/Classic/[score]box.png
new file mode 100644
index 00000000..71a0cee6
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]box.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]endcap.png b/cmake/game/themes/Classic/[score]endcap.png
new file mode 100644
index 00000000..3cccd2e1
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]endcap.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]glass_box.png b/cmake/game/themes/Classic/[score]glass_box.png
new file mode 100644
index 00000000..c0cf2a9c
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]glass_box.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]level.jpg b/cmake/game/themes/Classic/[score]level.jpg
deleted file mode 100644
index e47280cb..00000000
--- a/cmake/game/themes/Classic/[score]level.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]level.png b/cmake/game/themes/Classic/[score]level.png
new file mode 100644
index 00000000..1f627560
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]level.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]levelRound.png b/cmake/game/themes/Classic/[score]levelRound.png
new file mode 100644
index 00000000..2bc7a6b8
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]levelRound.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]level_dark.png b/cmake/game/themes/Classic/[score]level_dark.png
new file mode 100644
index 00000000..da4fd407
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]level_dark.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]level_dark_round.png b/cmake/game/themes/Classic/[score]level_dark_round.png
new file mode 100644
index 00000000..de239cb2
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]level_dark_round.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]level_light.png b/cmake/game/themes/Classic/[score]level_light.png
new file mode 100644
index 00000000..1c1c8a4d
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]level_light.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]level_light_round.png b/cmake/game/themes/Classic/[score]level_light_round.png
new file mode 100644
index 00000000..641151a5
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]level_light_round.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]level_lightest.png b/cmake/game/themes/Classic/[score]level_lightest.png
new file mode 100644
index 00000000..f02fdf7b
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]level_lightest.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]level_lightest_round.png b/cmake/game/themes/Classic/[score]level_lightest_round.png
new file mode 100644
index 00000000..9f1bb09e
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]level_lightest_round.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]levelround.jpg b/cmake/game/themes/Classic/[score]levelround.jpg
deleted file mode 100644
index dbc5b5af..00000000
--- a/cmake/game/themes/Classic/[score]levelround.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]line.jpg b/cmake/game/themes/Classic/[score]line.jpg
deleted file mode 100644
index 2fd951aa..00000000
--- a/cmake/game/themes/Classic/[score]line.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]rating_0.png b/cmake/game/themes/Classic/[score]rating_0.png
new file mode 100644
index 00000000..7e836b99
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]rating_0.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]rating_1.png b/cmake/game/themes/Classic/[score]rating_1.png
new file mode 100644
index 00000000..556821cb
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]rating_1.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]rating_2.png b/cmake/game/themes/Classic/[score]rating_2.png
new file mode 100644
index 00000000..ffa23fd3
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]rating_2.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]rating_3.png b/cmake/game/themes/Classic/[score]rating_3.png
new file mode 100644
index 00000000..5204dc5f
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]rating_3.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]rating_4.png b/cmake/game/themes/Classic/[score]rating_4.png
new file mode 100644
index 00000000..f5d7267c
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]rating_4.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]rating_5.png b/cmake/game/themes/Classic/[score]rating_5.png
new file mode 100644
index 00000000..0f6a553b
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]rating_5.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]rating_6.png b/cmake/game/themes/Classic/[score]rating_6.png
new file mode 100644
index 00000000..e8127c85
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]rating_6.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[score]rating_7.png b/cmake/game/themes/Classic/[score]rating_7.png
new file mode 100644
index 00000000..6b1d30f5
--- /dev/null
+++ b/cmake/game/themes/Classic/[score]rating_7.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing.player1]lyric_active.png b/cmake/game/themes/Classic/[sing.player1]lyric_active.png
new file mode 100644
index 00000000..089c8c5e
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing.player1]lyric_active.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing.player1]lyric_inactive.png b/cmake/game/themes/Classic/[sing.player1]lyric_inactive.png
new file mode 100644
index 00000000..a349007d
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing.player1]lyric_inactive.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing.player2]lyric_active.png b/cmake/game/themes/Classic/[sing.player2]lyric_active.png
new file mode 100644
index 00000000..509767fa
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing.player2]lyric_active.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing.player2]lyric_inactive.png b/cmake/game/themes/Classic/[sing.player2]lyric_inactive.png
new file mode 100644
index 00000000..ac40ec61
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing.player2]lyric_inactive.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing.player3]lyric_active.png b/cmake/game/themes/Classic/[sing.player3]lyric_active.png
new file mode 100644
index 00000000..7b130ac5
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing.player3]lyric_active.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing.player3]lyric_inactive.png b/cmake/game/themes/Classic/[sing.player3]lyric_inactive.png
new file mode 100644
index 00000000..c5a00600
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing.player3]lyric_inactive.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing.player4]lyric_active.png b/cmake/game/themes/Classic/[sing.player4]lyric_active.png
new file mode 100644
index 00000000..993041fd
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing.player4]lyric_active.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing.player4]lyric_inactive.png b/cmake/game/themes/Classic/[sing.player4]lyric_inactive.png
new file mode 100644
index 00000000..f09669b2
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing.player4]lyric_inactive.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing.player5]lyric_active.png b/cmake/game/themes/Classic/[sing.player5]lyric_active.png
new file mode 100644
index 00000000..631dc9c3
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing.player5]lyric_active.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing.player5]lyric_inactive.png b/cmake/game/themes/Classic/[sing.player5]lyric_inactive.png
new file mode 100644
index 00000000..716071e8
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing.player5]lyric_inactive.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing.player6]lyric_active.png b/cmake/game/themes/Classic/[sing.player6]lyric_active.png
new file mode 100644
index 00000000..65133d03
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing.player6]lyric_active.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing.player6]lyric_inactive.png b/cmake/game/themes/Classic/[sing.player6]lyric_inactive.png
new file mode 100644
index 00000000..0c5f34d3
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing.player6]lyric_inactive.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]lineBonusPopUp.jpg b/cmake/game/themes/Classic/[sing]lineBonusPopUp.jpg
deleted file mode 100644
index 58d93130..00000000
--- a/cmake/game/themes/Classic/[sing]lineBonusPopUp.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]lineBonusPopUp.png b/cmake/game/themes/Classic/[sing]lineBonusPopUp.png
new file mode 100644
index 00000000..89d5e511
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing]lineBonusPopUp.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]lyricsHelpBar.bmp b/cmake/game/themes/Classic/[sing]lyricsHelpBar.bmp
deleted file mode 100644
index 24fa2b52..00000000
--- a/cmake/game/themes/Classic/[sing]lyricsHelpBar.bmp
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]lyricsHelpBar.png b/cmake/game/themes/Classic/[sing]lyricsHelpBar.png
new file mode 100644
index 00000000..59707c21
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing]lyricsHelpBar.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]notesBgLeft.bmp b/cmake/game/themes/Classic/[sing]notesBgLeft.bmp
deleted file mode 100644
index 776e567c..00000000
--- a/cmake/game/themes/Classic/[sing]notesBgLeft.bmp
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]notesBgLeft.png b/cmake/game/themes/Classic/[sing]notesBgLeft.png
new file mode 100644
index 00000000..9fe2621c
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing]notesBgLeft.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]notesBgMid.bmp b/cmake/game/themes/Classic/[sing]notesBgMid.bmp
deleted file mode 100644
index 759ac8a3..00000000
--- a/cmake/game/themes/Classic/[sing]notesBgMid.bmp
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]notesBgMid.png b/cmake/game/themes/Classic/[sing]notesBgMid.png
new file mode 100644
index 00000000..612da5d3
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing]notesBgMid.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]notesBgRight.bmp b/cmake/game/themes/Classic/[sing]notesBgRight.bmp
deleted file mode 100644
index 9b1ffc18..00000000
--- a/cmake/game/themes/Classic/[sing]notesBgRight.bmp
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]notesBgRight.png b/cmake/game/themes/Classic/[sing]notesBgRight.png
new file mode 100644
index 00000000..a6f42c33
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing]notesBgRight.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]notesLeft.bmp b/cmake/game/themes/Classic/[sing]notesLeft.bmp
deleted file mode 100644
index c819849b..00000000
--- a/cmake/game/themes/Classic/[sing]notesLeft.bmp
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]notesLeft.png b/cmake/game/themes/Classic/[sing]notesLeft.png
new file mode 100644
index 00000000..3a404b9c
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing]notesLeft.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]notesMid.bmp b/cmake/game/themes/Classic/[sing]notesMid.bmp
deleted file mode 100644
index 2fdce32d..00000000
--- a/cmake/game/themes/Classic/[sing]notesMid.bmp
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]notesMid.png b/cmake/game/themes/Classic/[sing]notesMid.png
new file mode 100644
index 00000000..8769d01a
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing]notesMid.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]notesPlainLeft.png b/cmake/game/themes/Classic/[sing]notesPlainLeft.png
new file mode 100644
index 00000000..1a94a9d8
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing]notesPlainLeft.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]notesPlainMid.png b/cmake/game/themes/Classic/[sing]notesPlainMid.png
new file mode 100644
index 00000000..7fc64282
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing]notesPlainMid.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]notesPlainRight.png b/cmake/game/themes/Classic/[sing]notesPlainRight.png
new file mode 100644
index 00000000..ff8bb502
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing]notesPlainRight.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]notesRight.bmp b/cmake/game/themes/Classic/[sing]notesRight.bmp
deleted file mode 100644
index 3241beeb..00000000
--- a/cmake/game/themes/Classic/[sing]notesRight.bmp
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]notesRight.png b/cmake/game/themes/Classic/[sing]notesRight.png
new file mode 100644
index 00000000..8dc40cc8
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing]notesRight.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]p.jpg b/cmake/game/themes/Classic/[sing]p.jpg
deleted file mode 100644
index 5217c6b1..00000000
--- a/cmake/game/themes/Classic/[sing]p.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]p.png b/cmake/game/themes/Classic/[sing]p.png
new file mode 100644
index 00000000..345c8959
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing]p.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]pause.png b/cmake/game/themes/Classic/[sing]pause.png
new file mode 100644
index 00000000..f5ab158c
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing]pause.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]scoreBg.jpg b/cmake/game/themes/Classic/[sing]scoreBg.jpg
index 01d3ca75..26ea1e87 100644
--- a/cmake/game/themes/Classic/[sing]scoreBg.jpg
+++ b/cmake/game/themes/Classic/[sing]scoreBg.jpg
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]scoreBg.png b/cmake/game/themes/Classic/[sing]scoreBg.png
new file mode 100644
index 00000000..4dc785e9
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing]scoreBg.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]singBarBack.jpg b/cmake/game/themes/Classic/[sing]singBarBack.jpg
deleted file mode 100644
index d7dcd791..00000000
--- a/cmake/game/themes/Classic/[sing]singBarBack.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]singBarBack.png b/cmake/game/themes/Classic/[sing]singBarBack.png
new file mode 100644
index 00000000..14d2ba42
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing]singBarBack.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]singBarBar.png b/cmake/game/themes/Classic/[sing]singBarBar.png
new file mode 100644
index 00000000..9c57057b
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing]singBarBar.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]singBarFront.jpg b/cmake/game/themes/Classic/[sing]singBarFront.jpg
deleted file mode 100644
index eec27b79..00000000
--- a/cmake/game/themes/Classic/[sing]singBarFront.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]singBarFront.png b/cmake/game/themes/Classic/[sing]singBarFront.png
new file mode 100644
index 00000000..42477c5a
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing]singBarFront.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]textBar.jpg b/cmake/game/themes/Classic/[sing]textBar.jpg
deleted file mode 100644
index e2734bce..00000000
--- a/cmake/game/themes/Classic/[sing]textBar.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]textBar.png b/cmake/game/themes/Classic/[sing]textBar.png
new file mode 100644
index 00000000..d2069235
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing]textBar.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]timeBar.jpg b/cmake/game/themes/Classic/[sing]timeBar.jpg
new file mode 100644
index 00000000..cc5cb552
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing]timeBar.jpg
Binary files differ
diff --git a/cmake/game/themes/Classic/[sing]timeBarBG.png b/cmake/game/themes/Classic/[sing]timeBarBG.png
new file mode 100644
index 00000000..6094fdf3
--- /dev/null
+++ b/cmake/game/themes/Classic/[sing]timeBarBG.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[song]selection.jpg b/cmake/game/themes/Classic/[song]selection.jpg
deleted file mode 100644
index b6c0065e..00000000
--- a/cmake/game/themes/Classic/[song]selection.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[song]selection.png b/cmake/game/themes/Classic/[song]selection.png
new file mode 100644
index 00000000..70022ca0
--- /dev/null
+++ b/cmake/game/themes/Classic/[song]selection.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[songs]bg.png b/cmake/game/themes/Classic/[songs]bg.png
new file mode 100644
index 00000000..0ff36589
--- /dev/null
+++ b/cmake/game/themes/Classic/[songs]bg.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[special]bar1.png b/cmake/game/themes/Classic/[special]bar1.png
new file mode 100644
index 00000000..00afb41d
--- /dev/null
+++ b/cmake/game/themes/Classic/[special]bar1.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[special]bar2.png b/cmake/game/themes/Classic/[special]bar2.png
new file mode 100644
index 00000000..c828a8e1
--- /dev/null
+++ b/cmake/game/themes/Classic/[special]bar2.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[special]bg_fade.png b/cmake/game/themes/Classic/[special]bg_fade.png
new file mode 100644
index 00000000..dc3248ef
--- /dev/null
+++ b/cmake/game/themes/Classic/[special]bg_fade.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[stat]detailBG1.jpg b/cmake/game/themes/Classic/[stat]detailBG1.jpg
deleted file mode 100644
index 120dc483..00000000
--- a/cmake/game/themes/Classic/[stat]detailBG1.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[stat]detailBG1.png b/cmake/game/themes/Classic/[stat]detailBG1.png
new file mode 100644
index 00000000..212baf74
--- /dev/null
+++ b/cmake/game/themes/Classic/[stat]detailBG1.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[stat]mainBG1.jpg b/cmake/game/themes/Classic/[stat]mainBG1.jpg
deleted file mode 100644
index a937b24a..00000000
--- a/cmake/game/themes/Classic/[stat]mainBG1.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[stat]mainBG1.png b/cmake/game/themes/Classic/[stat]mainBG1.png
new file mode 100644
index 00000000..9eadc579
--- /dev/null
+++ b/cmake/game/themes/Classic/[stat]mainBG1.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[stat]mainBG2.jpg b/cmake/game/themes/Classic/[stat]mainBG2.jpg
deleted file mode 100644
index 201d49b8..00000000
--- a/cmake/game/themes/Classic/[stat]mainBG2.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[stat]mainBG2.png b/cmake/game/themes/Classic/[stat]mainBG2.png
new file mode 100644
index 00000000..f883c7d5
--- /dev/null
+++ b/cmake/game/themes/Classic/[stat]mainBG2.png
Binary files differ
diff --git a/cmake/game/themes/Classic/[stat]mainBG3.jpg b/cmake/game/themes/Classic/[stat]mainBG3.jpg
deleted file mode 100644
index 812a8d78..00000000
--- a/cmake/game/themes/Classic/[stat]mainBG3.jpg
+++ /dev/null
Binary files differ
diff --git a/cmake/game/themes/Classic/[stat]mainBG3.png b/cmake/game/themes/Classic/[stat]mainBG3.png
new file mode 100644
index 00000000..d5bcd98e
--- /dev/null
+++ b/cmake/game/themes/Classic/[stat]mainBG3.png
Binary files differ
diff --git a/cmake/game/themes/Deluxe.ini b/cmake/game/themes/Deluxe.ini
index e128ae54..f2bafc88 100644
--- a/cmake/game/themes/Deluxe.ini
+++ b/cmake/game/themes/Deluxe.ini
@@ -7,6 +7,7 @@
Name = Deluxe
Creator = Ultrastar Deluxe Team
US_Version = USD 110
+DefaultSkin = Blue
[Colors]
White = 255 255 255
@@ -40,27 +41,51 @@ 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 = 550
+Y = 548
Color = White
Font = 0
Align = 0
-Size = 30
+Size = 24
Text = SING_LOADING
Reflection = 1
-ReflectionSpacing = 20
+ReflectionSpacing = 13
[LoadingText2]
X = 790
-Y = 550
-Color = White
+Y = 548
+Color = Black
Font = 0
-Size = 30
+Size = 24
Align = 2
Text = US_VERSION
Reflection = 1
-ReflectionSpacing = 20
+ReflectionSpacing = 13
[Main]
[MainBackground]
@@ -77,7 +102,7 @@ Type = Transparent
[MainText1]
X = 95
-Y = 190
+Y = 186
Color = White
Font = 0
Size = 54
@@ -86,7 +111,7 @@ Text = SING_MENU
[MainTextDescriptionLong]
X = 95
-Y = 230
+Y = 233
Color = ColorLightest
Font = 0
Size = 30
@@ -139,7 +164,7 @@ Size = 24
Align = 0
Text = SING_LEGEND_NAVIGATE
Reflection = 1
-ReflectionSpacing = 20
+ReflectionSpacing = 13
[MainStatic5]
X = 400
@@ -163,7 +188,7 @@ Size = 24
Align = 0
Text = SING_LEGEND_SELECT
Reflection = 1
-ReflectionSpacing = 20
+ReflectionSpacing = 13
[MainButtonSolo]
X = 95
@@ -524,7 +549,7 @@ Size = 24
Align = 0
Text = +
Reflection = 1
-ReflectionSpacing = 20
+ReflectionSpacing = 13
[SongStaticNonParty3]
X = 300
@@ -548,7 +573,7 @@ Size = 24
Align = 0
Text = SING_SONG_SELECTION_GOTO
Reflection = 1
-ReflectionSpacing = 20
+ReflectionSpacing = 13
# Menu opens with [M]
[SongStaticNonParty4]
@@ -573,7 +598,7 @@ Size = 24
Align = 0
Text = SING_SONG_SELECTION_MENU
Reflection = 1
-ReflectionSpacing = 20
+ReflectionSpacing = 13
# The so famous search, shown with [J]
[SongStaticNonParty5]
@@ -598,7 +623,7 @@ Size = 24
Align = 0
Text = SONG_JUMPTO_DESC
Reflection = 1
-ReflectionSpacing = 20
+ReflectionSpacing = 13
# [P]laylist
[SongStaticNonParty6]
@@ -623,7 +648,7 @@ Size = 24
Align = 0
Text = SING_SONG_SELECTION_PLAYLIST
Reflection = 1
-ReflectionSpacing = 20
+ReflectionSpacing = 13
#and these are the ones for partymode
[SongStaticParty1]
@@ -656,6 +681,8 @@ Font = 0
Size = 24
Align = 0
Text = SONG_MENU_NAME_PARTY_JOKER
+Reflection = 1
+ReflectionSpacing = 13
# menu
[SongStaticParty3]
@@ -677,6 +704,8 @@ Font = 0
Size = 24
Align = 0
Text = PARTY_SONG_MENU
+Reflection = 1
+ReflectionSpacing = 13
[SongStaticParty4]
X = 540
@@ -696,11 +725,13 @@ Font = 0
Size = 24
Align = 0
Text = PARTY_SONG_LEGEND_CONTINUE
+Reflection = 1
+ReflectionSpacing = 13
#Texts for Party Mode
[SongTextParty1]
X = 70
-Y = 6
+Y = 5
ColR = 0.7
ColG = 0.7
ColB = 0.7
@@ -719,11 +750,10 @@ Align = 2
Text = PARTY_SONG_WHEREAMI
#variable statics end
-
# Jokers, 5 for each team, only shown in party Mode
[SongStaticTeam1Joker1]
Tex = Joker
-X = 480
+X = 505
Y = 400
W = 40
H = 40
@@ -737,7 +767,7 @@ TexY2 = 1
[SongStaticTeam1Joker2]
Tex = Joker
-X = 530
+X = 555
Y = 400
W = 40
H = 40
@@ -751,7 +781,7 @@ TexY2 = 1
[SongStaticTeam1Joker3]
Tex = Joker
-X = 580
+X = 605
Y = 400
W = 40
H = 40
@@ -765,7 +795,7 @@ TexY2 = 1
[SongStaticTeam1Joker4]
Tex = Joker
-X = 630
+X = 655
Y = 400
W = 40
H = 40
@@ -779,7 +809,7 @@ TexY2 = 1
[SongStaticTeam1Joker5]
Tex = Joker
-X = 680
+X = 705
Y = 400
W = 40
H = 40
@@ -793,7 +823,7 @@ TexY2 = 1
[SongStaticTeam2Joker1]
Tex = Joker
-X = 480
+X = 505
Y = 450
W = 40
H = 40
@@ -807,7 +837,7 @@ TexY2 = 1
[SongStaticTeam2Joker2]
Tex = Joker
-X = 530
+X = 555
Y = 450
W = 40
H = 40
@@ -821,7 +851,7 @@ TexY2 = 1
[SongStaticTeam2Joker3]
Tex = Joker
-X = 580
+X = 605
Y = 450
W = 40
H = 40
@@ -835,7 +865,7 @@ TexY2 = 1
[SongStaticTeam2Joker4]
Tex = Joker
-X = 630
+X = 655
Y = 450
W = 40
H = 40
@@ -849,7 +879,7 @@ TexY2 = 1
[SongStaticTeam2Joker5]
Tex = Joker
-X = 680
+X = 705
Y = 450
W = 40
H = 40
@@ -863,7 +893,7 @@ TexY2 = 1
[SongStaticTeam3Joker1]
Tex = Joker
-X = 480
+X = 505
Y = 500
W = 40
H = 40
@@ -877,7 +907,7 @@ TexY2 = 1
[SongStaticTeam3Joker2]
Tex = Joker
-X = 530
+X = 555
Y = 500
W = 40
H = 40
@@ -891,7 +921,7 @@ TexY2 = 1
[SongStaticTeam3Joker3]
Tex = Joker
-X = 580
+X = 605
Y = 500
W = 40
H = 40
@@ -905,7 +935,7 @@ TexY2 = 1
[SongStaticTeam3Joker4]
Tex = Joker
-X = 630
+X = 655
Y = 500
W = 40
H = 40
@@ -919,7 +949,7 @@ TexY2 = 1
[SongStaticTeam3Joker5]
Tex = Joker
-X = 680
+X = 705
Y = 500
W = 40
H = 40
@@ -943,12 +973,12 @@ ColG=1
[SingText1]
Text = SING_TIME
-X = 20
+X = 43
Y = 577
Font = 1
Size = 18
Color = White
-Align = 0
+Align = 1
[SingStatic1]
;TextBG
@@ -979,12 +1009,12 @@ Color = White
[SingTimeText]
Text = SING_TIME
-X = 736
+X = 761
Y = 577
Font = 1
Size = 18
Color = White
-Align = 0
+Align = 1
# O N E P L A Y E R M O D E # # # # # # # # # # # # # # # # # # # #
#PlayerOne
@@ -1017,7 +1047,7 @@ Type = Colorized
[SingP1TextScore]
Text = 00000
-X = 690
+X = 698
Y = 284
Font = 0
Size = 30
@@ -1061,7 +1091,7 @@ Type = Colorized
[SingP1TwoPTextScore]
Text = 00000
-X = 690
+X = 698
Y = 104
Font = 0
Size = 30
@@ -1104,7 +1134,7 @@ Type = Colorized
[SingP2RTextScore]
Text = 00000
-X = 690
+X = 698
Y = 284
Font = 0
Size = 30
@@ -1124,7 +1154,7 @@ Tex = P
X = 16
Y = 59
W = 50
-H = 54
+H = 44
Color = P1Dark
Type = Colorized
@@ -1148,7 +1178,7 @@ Type = Colorized
[SingP1ThreePTextScore]
Text = 00000
-X = 85
+X = 93
Y = 63
Font = 0
Size = 30
@@ -1167,7 +1197,7 @@ Tex = P
X = 311
Y = 59
W = 50
-H = 54
+H = 44
Color = P2Dark
Type = Colorized
@@ -1191,7 +1221,7 @@ Type = Colorized
[SingP2MTextScore]
Text = 00000
-X = 380
+X = 388
Y = 63
Font = 0
Size = 30
@@ -1210,7 +1240,7 @@ Tex = P
X = 611
Y = 59
W = 50
-H = 54
+H = 44
Color = P3Dark
Type = Colorized
@@ -1234,7 +1264,7 @@ Type = Colorized
[SingP3RTextScore]
Text = 00000
-X = 680
+X = 688
Y = 63
Font = 0
Size = 30
@@ -1264,7 +1294,7 @@ Align = 0
[ScoreTextArtistTitle]
X = 70
-Y = 53
+Y = 59
Color = White
Font = 0
Size = 30
@@ -1322,7 +1352,7 @@ Size = 24
Align = 0
Text = SING_LEGEND_CONTINUE
Reflection = 1
-ReflectionSpacing = 20
+ReflectionSpacing = 13
#end of main stuff
# # # # # # # # # # # # # # # # # # One Player Score # # # # # # # # # # # #
@@ -1457,7 +1487,7 @@ Align = 2
Text = 0
#Total Score
-[ScorePlayer1Static3]
+[ScoreStaticPlayerIdBox1]
Tex = PlayerIDBox01
X = 200
Y = 455
@@ -1470,25 +1500,25 @@ ReflectionSpacing = 31
[ScoreTextTotal1]
X = 237
-Y = 456
+Y = 454
Color = White
Font = 0
Size = 30
Text = SING_TOTAL
Align = 0
Reflection = 1
-ReflectionSpacing = 30
+ReflectionSpacing = 26
[ScoreTextTotalSCore1]
X = 487
-Y = 448
+Y = 444
Color = White
Font = 0
Size = 42
Align = 2
Text = 0
Reflection = 1
-ReflectionSpacing = 28
+ReflectionSpacing = 24
#ScoreBar
[ScoreStaticBackLevel1]
@@ -1527,7 +1557,7 @@ H = 8
Color = P1Dark
Type = Colorized
-[ScorePlayer1Static4]
+[ScorePlayer1Static3]
Tex = ScoreEndCap
X = 499
Y = 478
@@ -1539,7 +1569,7 @@ Type = Colorized
Reflection = 1
ReflectionSpacing = 0
-[ScorePlayer1Static5]
+[ScorePlayer1Static4]
Tex = ScoreGlassBox
X = 499
Y = 148
@@ -1659,24 +1689,24 @@ Text = 0000
[ScoreTextTotal2]
X = 82
-Y = 456
+Y = 454
Color = White
Font = 0
Size = 30
Text = SING_TOTAL
Reflection = 1
-ReflectionSpacing = 30
+ReflectionSpacing = 24
[ScoreTextTotalSCore2]
X = 283
-Y = 448
+Y = 444
Color = White
Font = 0
Size = 42
Align = 2
Text = 00000
Reflection = 1
-ReflectionSpacing = 28
+ReflectionSpacing = 24
# Lines
[ScorePlayer2Static1]
@@ -1697,7 +1727,7 @@ H = 1
Type = Colorized
Color = White
-[ScorePlayer2Static5]
+[ScoreStaticPlayerIdBox2]
Tex = PlayerIDBox01
X = 45
Y = 455
@@ -1876,25 +1906,25 @@ Text = 0000
[ScoreTextTotal3]
X = 718
-Y = 456
+Y = 454
Color = White
Font = 0
Size = 30
Text = SING_TOTAL
Align = 2
Reflection = 1
-ReflectionSpacing = 30
+ReflectionSpacing = 24
[ScoreTextTotalScore3]
X = 517
-Y = 448
+Y = 444
Color = White
Font = 0
Size = 42
Align = 0
Text = 00000
Reflection = 1
-ReflectionSpacing = 28
+ReflectionSpacing = 24
#Lines
[ScorePlayer3Static1]
@@ -1915,7 +1945,7 @@ H = 1
Type = Colorized
Color = White
-[ScorePlayer3Static5]
+[ScoreStaticPlayerIdBox3]
Tex = PlayerIDBox02
X = 729
Y = 455
@@ -1994,7 +2024,14 @@ Font = 0
Size = 42
Align = 0
Text = P1
-Color = P1Dark
+Color = White
+
+# Rating
+[ScoreStaticRatingPicture4]
+X = 200
+Y = 150
+H = 60
+W = 60
[ScoreTextNotes4]
X = 20
@@ -2061,21 +2098,25 @@ Color = White
[ScoreTextTotal4]
X = 47
-Y = 373
+Y = 371
Font = 0
Size = 30
Align = 0
Text = SING_TOTAL
Color = White
+Reflection = 1
+ReflectionSpacing = -1
[ScoreTextTotalScore4]
X = 260
-Y = 364
+Y = 361
Font = 0
Size = 42
Align = 2
Text = 00000
Color = White
+Reflection = 1
+ReflectionSpacing = -3
[ScoreStaticBoxDark4]
Tex = PlayerNumberBox
@@ -2155,7 +2196,14 @@ Font = 0
Size = 42
Align = 0
Text = P2
-Color = P2Dark
+Color = White
+
+# Rating
+[ScoreStaticRatingPicture5]
+X = 460
+Y = 150
+H = 60
+W = 60
[ScoreTextNotes5]
X = 280
@@ -2222,21 +2270,25 @@ Color = White
[ScoreTextTotal5]
X = 307
-Y = 373
+Y = 371
Font = 0
Size = 30
Align = 0
Text = SING_TOTAL
Color = White
+Reflection = 1
+ReflectionSpacing = -1
[ScoreTextTotalScore5]
X = 520
-Y = 364
+Y = 361
Font = 0
Size = 42
Align = 2
Text = 00000
Color = White
+Reflection = 1
+ReflectionSpacing = -3
[ScoreStaticBoxDark5]
Tex = PlayerNumberBox
@@ -2315,7 +2367,14 @@ Font = 0
Size = 42
Align = 0
Text = P3
-Color = P3Dark
+Color = White
+
+# Rating
+[ScoreStaticRatingPicture6]
+X = 720
+Y = 150
+H = 60
+W = 60
[ScoreTextNotes6]
X = 540
@@ -2382,21 +2441,25 @@ Color = White
[ScoreTextTotal6]
X = 567
-Y = 373
+Y = 371
Font = 0
Size = 30
Align = 0
Text = SING_TOTAL
Color = White
+Reflection = 1
+ReflectionSpacing = -1
[ScoreTextTotalScore6]
X = 780
-Y = 364
+Y = 361
Font = 0
Size = 42
Align = 2
Text = 00000
Color = White
+Reflection = 1
+ReflectionSpacing = -3
[ScoreStaticBoxDark6]
Tex = PlayerNumberBox
@@ -2477,7 +2540,7 @@ Tex = OptionsBG
[OptionsStatic1]
X = 65
-Y = 150
+Y = 130
W = 25
H = 25
Color = White
@@ -2486,7 +2549,7 @@ Type = Colorized
[OptionsText1]
X = 95
-Y = 135
+Y = 115
Color = White
Font = 0
Size = 54
@@ -2495,7 +2558,7 @@ Align = 0
[OptionsText2]
X = 95
-Y = 175
+Y = 165
Color = ColorLightest
Font = 0
Size = 30
@@ -2509,7 +2572,7 @@ Color = White
Font = 0
Size = 30
Align = 0
-Text =
+Text =
[OptionsStatic2]
X = 0
@@ -2553,7 +2616,7 @@ Size = 24
Align = 0
Text = SING_LEGEND_NAVIGATE
Reflection=1
-ReflectionSpacing=20
+ReflectionSpacing=13
[OptionsStatic5]
X = 400
@@ -2575,7 +2638,7 @@ Size = 24
Align = 0
Text = SING_LEGEND_SELECT
Reflection=1
-ReflectionSpacing=20
+ReflectionSpacing=13
[OptionsStatic6]
X = 550
@@ -2597,7 +2660,7 @@ Size = 24
Align = 0
Text = SING_LEGEND_ESC
Reflection=1
-ReflectionSpacing=20
+ReflectionSpacing=13
[OptionsButtonGame]
X = 95
@@ -2702,7 +2765,7 @@ Color = White
[OptionsButtonThemes]
X = 95
-Y = 335
+Y = 345
W = 150
H = 50
Tex = Button
@@ -2728,7 +2791,7 @@ Color = White
[OptionsButtonRecord]
X = 250
-Y = 335
+Y = 345
W = 150
H = 50
Tex = Button
@@ -2755,7 +2818,7 @@ Texts = 1
[OptionsButtonAdvanced]
X = 405
-Y = 335
+Y = 345
W = 150
H = 50
Tex = Button
@@ -2782,7 +2845,7 @@ Texts = 1
[OptionsButtonExit]
X = 560
-Y = 335
+Y = 345
W = 150
H = 50
Tex = Button
@@ -2813,7 +2876,7 @@ Texts = 5
Tex = OptionsBG
[OptionsGameStatic1]
-X = 65
+X = 40
Y = 22
W = 25
H = 23
@@ -2822,22 +2885,22 @@ Tex = IconOption
Type = Transparent
[OptionsGameText1]
-X = 95
+X = 70
Y = 5
Color = White
Size = 54
Text = SING_OPTIONS
[OptionsGameText2]
-X = 95
-Y = 45
+X = 70
+Y = 55
Color = ColorLightest
Size = 30
Text = SING_OPTIONS_GAME_DESC
[OptionsGameText3]
-X = 95
-Y = 65
+X = 70
+Y = 85
Color = White
Size = 30
Text = SING_OPTIONS_GAME_WHEREAMI
@@ -2911,9 +2974,10 @@ Text = SING_OPTIONS_GAME_PLAYERS
Tex = MainBar
Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
X = 70
-Y = 85
-W = 230
+Y = 130
+W = 250
H = 40
SkipX = 10
@@ -2922,8 +2986,8 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+SBGColor = ColorDark
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
@@ -2932,9 +2996,10 @@ Text = SING_OPTIONS_GAME_DIFFICULTY
Tex = MainBar
Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
X = 70
-Y = 135
-W = 230
+Y = 180
+W = 250
H = 40
SkipX = 10
@@ -2943,8 +3008,8 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+SBGColor = ColorDark
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
@@ -2953,9 +3018,10 @@ Text = SING_OPTIONS_GAME_LANGUAGE
Tex = MainBar
Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
X = 70
-Y = 185
-W = 230
+Y = 230
+W = 250
H = 40
SkipX = 10
@@ -2964,8 +3030,8 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+SBGColor = ColorDark
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
@@ -2974,9 +3040,10 @@ Text = SING_OPTIONS_GAME_TABS
Tex = MainBar
Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
X = 70
-Y = 235
-W = 230
+Y = 280
+W = 250
H = 40
SkipX = 10
@@ -2985,8 +3052,8 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+SBGColor = ColorDark
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
@@ -2995,9 +3062,10 @@ Text = SING_OPTIONS_GAME_SORTING
Tex = MainBar
Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
X = 70
-Y = 285
-W = 230
+Y = 330
+W = 250
H = 40
SkipX = 10
@@ -3006,8 +3074,8 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+SBGColor = ColorDark
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
@@ -3016,9 +3084,10 @@ Text = SING_OPTIONS_GAME_DEBUG
Tex = MainBar
Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
X = 70
-Y = 335
-W = 230
+Y = 380
+W = 250
H = 40
SkipX = 10
@@ -3027,16 +3096,16 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+SBGColor = ColorDark
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
[OptionsGameButtonExit]
-X = 40
-Y = 415
-W = 230
-H = 70
+X = 70
+Y = 440
+W = 250
+H = 40
Tex = Button
Color = ColorLight
DColor = ColorDark
@@ -3051,7 +3120,7 @@ Texts = 5
Tex = OptionsBG
[OptionsGraphicsStatic1]
-X = 65
+X = 40
Y = 22
W = 25
H = 23
@@ -3060,22 +3129,22 @@ Tex = IconOption
Type = Transparent
[OptionsGraphicsText1]
-X = 95
+X = 70
Y = 5
Color = White
Size = 54
Text = SING_OPTIONS
[OptionsGraphicsText2]
-X = 95
-Y = 45
+X = 70
+Y = 55
Color = ColorLightest
Size = 30
Text = SING_OPTIONS_GRAPHICS_DESC
[OptionsGraphicsText3]
-X = 95
-Y = 65
+X = 70
+Y = 85
Color = White
Size = 30
Text = SING_OPTIONS_GRAPHICS_WHEREAMI
@@ -3150,9 +3219,10 @@ Text = SING_OPTIONS_GRAPHICS_RESOLUTION
Tex = MainBar
Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
X = 70
-Y = 85
-W = 230
+Y = 130
+W = 250
H = 40
SkipX = 10
@@ -3161,8 +3231,8 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+SBGColor = ColorDark
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
@@ -3171,9 +3241,10 @@ Text = SING_OPTIONS_GRAPHICS_FULLSCREEN
Tex = MainBar
Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
X = 70
-Y = 135
-W = 230
+Y = 180
+W = 250
H = 40
SkipX = 10
@@ -3182,8 +3253,8 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+SBGColor = ColorDark
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
@@ -3192,9 +3263,10 @@ Text = SING_OPTIONS_GRAPHICS_DEPTH
Tex = MainBar
Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
X = 70
-Y = 185
-W = 230
+Y = 230
+W = 250
H = 40
SkipX = 10
@@ -3203,19 +3275,20 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+SBGColor = ColorDark
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
[OptionsGraphicsSelectVisualizer]
Text = SING_OPTIONS_GRAPHICS_VISUALIZER
Tex = MainBar
-Type = Colorizedalc
+Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
X = 70
-Y = 235
-W = 230
+Y = 280
+W = 250
H = 40
SkipX = 10
@@ -3224,8 +3297,8 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+SBGColor = ColorDark
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
@@ -3234,9 +3307,10 @@ Text = SING_OPTIONS_GRAPHICS_OSCILLOSCOPE
Tex = MainBar
Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
X = 70
-Y = 285
-W = 230
+Y = 330
+W = 250
H = 40
SkipX = 10
@@ -3245,8 +3319,8 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+SBGColor = ColorDark
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
@@ -3255,9 +3329,10 @@ Text = SING_OPTIONS_GRAPHICS_MOVIE_SIZE
Tex = MainBar
Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
X = 70
-Y = 335
-W = 230
+Y = 380
+W = 250
H = 40
SkipX = 10
@@ -3266,16 +3341,16 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+SBGColor = ColorDark
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
[OptionsGraphicsButtonExit]
-X = 40
-Y = 415
-W = 230
-H = 70
+X = 70
+Y = 440
+W = 250
+H = 40
Tex = Button
Color = ColorLight
DColor = ColorDark
@@ -3290,7 +3365,7 @@ Texts = 5
Tex = OptionsBG
[OptionsSoundStatic1]
-X = 65
+X = 40
Y = 22
W = 25
H = 23
@@ -3299,22 +3374,22 @@ Tex = IconOption
Type = Transparent
[OptionsSoundText1]
-X = 95
+X = 70
Y = 5
Color = White
Size = 54
Text = SING_OPTIONS
[OptionsSoundText2]
-X = 95
-Y = 45
+X = 70
+Y = 55
Color = ColorLightest
Size = 30
Text = SING_OPTIONS_SOUND_DESC
[OptionsSoundText3]
-X = 95
-Y = 65
+X = 70
+Y = 85
Color = White
Size = 30
Text = SING_OPTIONS_SOUND_WHEREAMI
@@ -3385,169 +3460,185 @@ ReflectionSpacing = 20
[OptionsSoundSelectVoicePassthrough]
Tex = MainBar
+Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
Text = SING_OPTIONS_SOUND_VOICEPASSTHROUGH
X = 70
-Y = 85
-W = 230
-H = 40
+Y = 130
+W = 250
+H = 35
SkipX = 10
Color = ColorDark
-DColor = Gray
+DColor = ColorLight
TColor = White
TDColor = White
-SBGTex = MainBar
+
SBGColor = ColorDark
-SBGDColor = Gray
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
[OptionsSoundSelectBackgroundMusic]
Tex = MainBar
+Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
Text = SING_OPTIONS_SOUND_BACKGROUNDMUSIC
X = 70
-Y = 135
-W = 230
-H = 40
+Y = 170
+W = 250
+H = 35
SkipX = 10
Color = ColorDark
-DColor = Gray
+DColor = ColorLight
TColor = White
TDColor = White
-SBGTex = MainBar
+
SBGColor = ColorDark
-SBGDColor = Gray
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
[OptionsSoundSelectMicBoost]
Tex = MainBar
+Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
Text = SING_OPTIONS_SOUND_MIC_BOOST
X = 70
-Y = 185
-W = 230
-H = 40
+Y = 210
+W = 250
+H = 35
SkipX = 10
Color = ColorDark
-DColor = Gray
+DColor = ColorLight
TColor = White
TDColor = White
-SBGTex = MainBar
+
SBGColor = ColorDark
-SBGDColor = Gray
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
[OptionsSoundSelectClickAssist]
Tex = MainBar
+Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
Text = SING_OPTIONS_SOUND_CLICK_ASSIST
X = 70
-Y = 235
-W = 230
-H = 40
+Y = 250
+W = 250
+H = 35
SkipX = 10
Color = ColorDark
-DColor = Gray
+DColor = ColorLight
TColor = White
TDColor = White
-SBGTex = MainBar
+
SBGColor = ColorDark
-SBGDColor = Gray
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
[OptionsSoundSelectBeatClick]
Tex = MainBar
+Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
Text = SING_OPTIONS_SOUND_BEAT_CLICK
X = 70
-Y = 285
-W = 230
-H = 40
+Y = 290
+W = 250
+H = 35
SkipX = 10
Color = ColorDark
-DColor = Gray
+DColor = ColorLight
TColor = White
TDColor = White
-SBGTex = MainBar
+
SBGColor = ColorDark
-SBGDColor = Gray
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
[OptionsSoundSelectThreshold]
Tex = MainBar
+Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
Text = SING_OPTIONS_SOUND_THRESHOLD
X = 70
-Y = 335
-W = 230
-H = 40
+Y = 330
+W = 250
+H = 35
SkipX = 10
Color = ColorDark
-DColor = Gray
+DColor = ColorLight
TColor = White
TDColor = White
-SBGTex = MainBar
+
SBGColor = ColorDark
-SBGDColor = Gray
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
[OptionsSoundSelectSlidePreviewVolume]
Tex = MainBar
+Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
Text = SING_OPTIONS_SOUND_PREVIEWVOLUME
X = 70
-Y = 385
-W = 230
-H = 40
+Y = 370
+W = 250
+H = 35
SkipX = 10
Color = ColorDark
-DColor = Gray
+DColor = ColorLight
TColor = White
TDColor = White
-SBGTex = MainBar
+
SBGColor = ColorDark
-SBGDColor = Gray
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
[OptionsSoundSelectSlidePreviewFADING]
Tex = MainBar
+Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
Text = SING_OPTIONS_SOUND_PREVIEWFADING
X = 70
-Y = 435
-W = 230
-H = 40
+Y = 410
+W = 250
+H = 35
SkipX = 10
Color = ColorDark
-DColor = Gray
+DColor = ColorLight
TColor = White
TDColor = White
-SBGTex = MainBar
+
SBGColor = ColorDark
-SBGDColor = Gray
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
[OptionsSoundButtonExit]
-X = 40
-Y = 465
-W = 230
-H = 50
+X = 70
+Y = 460
+W = 250
+H = 35
Tex = Button
Color = ColorLight
DColor = ColorDark
@@ -3562,7 +3653,7 @@ Texts = 1
Tex = OptionsBG
[OptionsLyricsStatic1]
-X = 65
+X = 40
Y = 22
W = 25
H = 23
@@ -3571,22 +3662,22 @@ Tex = IconOption
Type = Transparent
[OptionsLyricsText1]
-X = 95
+X = 70
Y = 5
Color = White
Size = 54
Text = SING_OPTIONS
[OptionsLyricsText2]
-X = 95
-Y = 45
+X = 70
+Y = 55
Color = ColorLightest
Size = 30
Text = SING_OPTIONS_LYRICS_DESC
[OptionsLyricsText3]
-X = 95
-Y = 65
+X = 70
+Y = 85
Color = White
Size = 30
Text = SING_OPTIONS_LYRICS_WHEREAMI
@@ -3657,69 +3748,75 @@ ReflectionSpacing = 20
[OptionsLyricsSelectLyricsFont]
Tex = MainBar
+Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
Text = SING_OPTIONS_LYRICS_FONT
X = 70
-Y = 85
-W = 230
+Y = 130
+W = 250
H = 40
SkipX = 10
Color = ColorDark
-DColor = Gray
+DColor = ColorLight
TColor = White
TDColor = White
-SBGTex = MainBar
+
SBGColor = ColorDark
-SBGDColor = Gray
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
[OptionsLyricsSelectLyricsEffect]
Tex = MainBar
+Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
Text = SING_OPTIONS_LYRICS_EFFECT
X = 70
-Y = 135
-W = 230
+Y = 180
+W = 250
H = 40
SkipX = 10
Color = ColorDark
-DColor = Gray
+DColor = ColorLight
TColor = White
TDColor = White
-SBGTex = MainBar
+
SBGColor = ColorDark
-SBGDColor = Gray
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
[OptionsLyricsSelectNoteLines]
Tex = MainBar
+Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
Text = SING_OPTIONS_LYRICS_NOTELINES
X = 70
-Y = 185
-W = 230
+Y = 230
+W = 250
H = 40
SkipX = 10
Color = ColorDark
-DColor = Gray
+DColor = ColorLight
TColor = White
TDColor = White
-SBGTex = MainBar
+
SBGColor = ColorDark
-SBGDColor = Gray
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
[OptionsLyricsButtonExit]
-X = 40
-Y = 415
-W = 230
-H = 70
+X = 70
+Y = 290
+W = 250
+H = 40
Tex = Button
Color = ColorLight
DColor = ColorDark
@@ -3734,7 +3831,7 @@ Texts = 5
Tex = OptionsBG
[OptionsThemesStatic1]
-X = 65
+X = 40
Y = 22
W = 25
H = 23
@@ -3743,22 +3840,22 @@ Tex = IconOption
Type = Transparent
[OptionsThemesText1]
-X = 95
+X = 70
Y = 5
Color = White
Size = 54
Text = SING_OPTIONS
[OptionsThemesText2]
-X = 95
-Y = 45
+X = 70
+Y = 55
Color = ColorLightest
Size = 30
Text = SING_OPTIONS_THEMES_DESC
[OptionsThemesText3]
-X = 95
-Y = 65
+X = 70
+Y = 85
Color = White
Size = 30
Text = SING_OPTIONS_THEMES_WHEREAMI
@@ -3830,10 +3927,12 @@ Text = SING_LEGEND_ESC
[OptionsThemesSelectTheme]
Text = SING_OPTIONS_THEMES_THEME
Tex = MainBar
+Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
X = 70
-Y = 85
-W = 230
+Y = 130
+W = 250
H = 40
SkipX = 10
@@ -3842,18 +3941,20 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+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 = 135
-W = 230
+Y = 180
+W = 250
H = 40
SkipX = 10
@@ -3862,18 +3963,20 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+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 = 185
-W = 230
+Y = 230
+W = 250
H = 40
SkipX = 10
@@ -3882,16 +3985,16 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+SBGColor = ColorDark
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
[OptionsThemesButtonExit]
-X = 40
-Y = 415
-W = 230
-H = 70
+X = 70
+Y = 290
+W = 250
+H = 40
Tex = Button
Color = ColorLight
DColor = ColorDark
@@ -3906,7 +4009,7 @@ Texts = 5
Tex = OptionsBG
[OptionsRecordStatic1]
-X = 65
+X = 40
Y = 22
W = 25
H = 23
@@ -3915,22 +4018,22 @@ Tex = IconOption
Type = Transparent
[OptionsRecordText1]
-X = 95
+X = 70
Y = 5
Color = White
Size = 54
Text = SING_OPTIONS
[OptionsRecordText2]
-X = 95
-Y = 45
+X = 70
+Y = 55
Color = ColorLightest
Size = 30
Text = SING_OPTIONS_RECORD_DESC
[OptionsRecordText3]
-X = 95
-Y = 65
+X = 70
+Y = 85
Color = White
Size = 30
Text = SING_OPTIONS_RECORD_WHEREAMI
@@ -4002,10 +4105,12 @@ Text = SING_LEGEND_ESC
[OptionsRecordSelectSlideCard]
Text = SING_OPTIONS_RECORD_CARD
Tex = MainBar
+Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
X = 70
-Y = 85
-W = 230
+Y = 130
+W = 250
H = 40
SkipX = 10
@@ -4014,18 +4119,20 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+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 = 135
-W = 230
+Y = 180
+W = 250
H = 40
SkipX = 10
@@ -4034,18 +4141,20 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+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 = 185
-W = 230
+Y = 230
+W = 250
H = 40
SkipX = 10
@@ -4054,16 +4163,16 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+SBGColor = ColorDark
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
[OptionsRecordButtonExit]
-X = 40
-Y = 415
-W = 230
-H = 70
+X = 70
+Y = 390
+W = 250
+H = 40
Tex = Button
Color = ColorLight
DColor = ColorDark
@@ -4078,7 +4187,7 @@ Texts = 5
Tex = OptionsBG
[OptionsAdvancedStatic1]
-X = 65
+X = 40
Y = 22
W = 25
H = 23
@@ -4087,22 +4196,22 @@ Tex = IconOption
Type = Transparent
[OptionsAdvancedText1]
-X = 95
+X = 70
Y = 5
Color = White
Size = 54
Text = SING_OPTIONS
[OptionsAdvancedText3]
-X = 95
-Y = 45
+X = 70
+Y = 55
Color = ColorLightest
Size = 30
Text = SING_OPTIONS_ADVANCED_DESC
[OptionsAdvancedText2]
-X = 95
-Y = 65
+X = 70
+Y = 85
Color = White
Size = 30
Text = SING_OPTIONS_ADVANCED_WHEREAMI
@@ -4186,19 +4295,21 @@ Text = SING_LEGEND_ESC
#DColor = ColorLight
#TColor = White
#TDColor = White
-
-#SBGColor = DarkBlue
-#SBGDColor = LightBlue
+
+#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 = 85
-W = 230
+Y = 130
+W = 250
H = 40
SkipX = 10
@@ -4207,18 +4318,20 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+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 = 135
-W = 230
+Y = 180
+W = 250
H = 40
SkipX = 10
@@ -4227,18 +4340,20 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+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 = 185
-W = 230
+Y = 230
+W = 250
H = 40
SkipX = 10
@@ -4247,18 +4362,20 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+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 = 235
-W = 230
+Y = 280
+W = 250
H = 40
SkipX = 10
@@ -4267,18 +4384,20 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+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 = 285
-W = 230
+Y = 330
+W = 250
H = 40
SkipX = 10
@@ -4287,18 +4406,20 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+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 = 335
-W = 230
+Y = 380
+W = 250
H = 40
SkipX = 10
@@ -4307,16 +4428,16 @@ DColor = ColorLight
TColor = White
TDColor = White
-SBGColor = DarkBlue
-SBGDColor = LightBlue
+SBGColor = ColorDark
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
[OptionsAdvancedButtonExit]
-X = 40
-Y = 415
-W = 230
-H = 70
+X = 70
+Y = 440
+W = 250
+H = 40
Tex = Button
Color = ColorLight
DColor = ColorDark
@@ -4424,6 +4545,24 @@ 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
@@ -4470,7 +4609,7 @@ Align = 0
Text = 5. Player5
[Top5TextScore1]
-X = 680
+X = 560
Y = 190
Color = White
Font = 0
@@ -4479,7 +4618,7 @@ Align = 2
Text = 00000
[Top5TextScore2]
-X = 680
+X = 560
Y = 240
Color = White
Font = 0
@@ -4488,7 +4627,7 @@ Align = 2
Text = 00000
[Top5TextScore3]
-X = 680
+X = 560
Y = 290
Color = White
Font = 0
@@ -4497,7 +4636,7 @@ Align = 2
Text = 00000
[Top5TextScore4]
-X = 680
+X = 560
Y = 340
Color = White
Font = 0
@@ -4506,7 +4645,53 @@ Align = 2
Text = 00000
[Top5TextScore5]
-X = 680
+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
@@ -4651,7 +4836,7 @@ Size = 24
Align = 0
Text = SING_EDIT_NAVIGATE
Reflection = 1
-ReflectionSpacing = 20
+ReflectionSpacing = 13
# Select button text
[EditText4]
@@ -4663,7 +4848,7 @@ Size = 24
Align = 0
Text = SING_EDIT_SELECT
Reflection=1
-ReflectionSpacing=20
+ReflectionSpacing=13
# Esc button text
[EditText5]
@@ -4675,7 +4860,7 @@ Size = 24
Align = 0
Text = SING_EDIT_EXIT
Reflection=1
-ReflectionSpacing=20
+ReflectionSpacing=13
[EditTextDescription]
X = 95
@@ -4814,7 +4999,7 @@ Type = Transparent
[LevelText1]
X = 95
-Y = 190
+Y = 186
Color = White
Font = 0
Size = 54
@@ -4823,7 +5008,7 @@ Text = SING_MODE
[LevelText2]
X = 95
-Y = 230
+Y = 233
Color = ColorLightest
Font = 0
Size = 30
@@ -4883,7 +5068,7 @@ Size = 24
Align = 0
Text = SING_LEGEND_NAVIGATE
Reflection = 1
-ReflectionSpacing = 20
+ReflectionSpacing = 13
[LevelText4]
X = 440
@@ -4894,7 +5079,7 @@ Size = 24
Align = 0
Text = SING_DIFFICULTY_CONTINUE
Reflection = 1
-ReflectionSpacing = 20
+ReflectionSpacing = 13
[LevelButtonEasy]
X = 180
@@ -4997,7 +5182,7 @@ Type = Transparent
[NameText1]
X = 95
-Y = 190
+Y = 186
Color = White
Font = 0
Size = 54
@@ -5005,7 +5190,7 @@ Text = SING_MODE
[NameText2]
X = 95
-Y = 230
+Y = 233
Color = ColorLightest
Font = 0
Size = 30
@@ -5054,7 +5239,7 @@ Size = 24
Align = 0
Text = SING_LEGEND_NAVIGATE
Reflection = 1
-ReflectionSpacing = 20
+ReflectionSpacing = 13
[NameStatic5]
X = 400
@@ -5076,7 +5261,7 @@ Size = 24
Align = 0
Text = SING_PLAYER_ENTER_NAME
Reflection = 1
-ReflectionSpacing = 20
+ReflectionSpacing = 13
[NameStatic6]
X = 590
@@ -5098,7 +5283,7 @@ Size = 24
Align = 0
Text = SING_LEGEND_CONTINUE
Reflection = 1
-ReflectionSpacing = 20
+ReflectionSpacing = 13
[NameButtonPlayer1]
X = 180
@@ -5271,7 +5456,7 @@ Type = Colorized
[PartyNewRoundText1]
X = 70
-Y = 6
+Y = 5
ColR = 0.7
ColG = 0.7
ColB = 0.7
@@ -5282,7 +5467,7 @@ Text = PARTY_MODE
[PartyNewRoundText2]
X = 70
-Y = 53
+Y = 65
Color = White
Font = 0
Size = 30
@@ -6558,7 +6743,7 @@ Type = Transparent
[PartyOptionsText1]
X = 70
-Y = 6
+Y = 5
ColR = 0.7
ColG = 0.7
ColB = 0.7
@@ -6569,7 +6754,7 @@ Text = PARTY_MODE
[PartyOptionsText2]
X = 70
-Y = 53
+Y = 65
Color = White
Font = 0
Size = 30
@@ -6605,169 +6790,98 @@ Text = SING_LEGEND_CONTINUE
[PartyOptionsSelectLevel]
Tex = MainBar
+Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
Text = PARTY_DIFFICULTY
-X = 40
-Y = 85
+X = 70
+Y = 110
W = 230
-H = 70
-SkipX = 50
+H = 40
+SkipX = 10
Fields = 1
Color = ColorDark
-DColor = Gray
+DColor = ColorLight
TColor = White
TDColor = White
-SBGTex = MainBar
+
SBGColor = ColorDark
-SBGDColor = Gray
+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 = 40
-Y = 140
+X = 70
+Y = 165
W = 230
-H = 70
-SkipX = 50
+H = 40
+SkipX = 10
Fields = 1
Color = ColorDark
-DColor = Gray
+DColor = ColorLight
TColor = White
TDColor = White
-SBGTex = MainBar
+
SBGColor = ColorDark
-SBGDColor = Gray
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
[PartyOptionsSelectPlayList2]
Tex = MainBar
+Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
Text = PARTY_PLAYLIST
-X = 40
-Y = 195
+X = 70
+Y = 220
W = 230
-H = 70
-SkipX = 50
+H = 40
+SkipX = 10
Fields = 1
Color = ColorDark
-DColor = Gray
+DColor = ColorLight
TColor = White
TDColor = White
-SBGTex = MainBar
+
SBGColor = ColorDark
-SBGDColor = Gray
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
[PartyOptionsSelectRounds]
Tex = MainBar
+Type = Colorized
TexSBG = SelectBG
+TypeSBG = Colorized
Text = PARTY_ROUNDS
-X = 40
+X = 70
Y = 250
W = 230
-H = 70
-SkipX = 50
-Fields = 7
-
-Color = ColorDark
-DColor = Gray
-TColor = White
-TDColor = White
-SBGTex = MainBar
-SBGColor = ColorDark
-SBGDColor = Gray
-STColor = White
-STDColor = GrayDark
-
-[PartyOptionsSelectTeams]
-Tex = MainBar
-TexSBG = SelectBG
-Text = PARTY_TEAMS
-X = 40
-Y = 305
-W = 230
-H = 70
-SkipX = 50
-Fields = 7
-
-Color = ColorDark
-DColor = Gray
-TColor = White
-TDColor = White
-SBGTex = MainBar
-SBGColor = ColorDark
-SBGDColor = Gray
-STColor = White
-STDColor = GrayDark
-
-[PartyOptionsSelectPlayers1]
-Tex = MainBar
-TexSBG = SelectBG
-Text = PARTY_TEAMS_PLAYER1
-X = 40
-Y = 360
-W = 230
-H = 70
-SkipX = 50
-Fields = 7
-
-Color = ColorDark
-DColor = Gray
-TColor = White
-TDColor = White
-SBGTex = MainBar
-SBGColor = ColorDark
-SBGDColor = Gray
-STColor = White
-STDColor = GrayDark
-
-[PartyOptionsSelectPlayers2]
-Tex = MainBar
-TexSBG = SelectBG
-Text = PARTY_TEAMS_PLAYER2
-X = 40
-Y = 415
-W = 230
-H = 70
-SkipX = 50
+H = 40
+SkipX = 10
Fields = 7
Color = ColorDark
-DColor = Gray
+DColor = ColorLight
TColor = White
TDColor = White
-SBGTex = MainBar
-SBGColor = ColorDark
-SBGDColor = Gray
-STColor = White
-STDColor = GrayDark
-[PartyOptionsSelectPlayers3]
-Tex = MainBar
-TexSBG = SelectBG
-Text = PARTY_TEAMS_PLAYER3
-X = 40
-Y = 470
-W = 230
-H = 70
-SkipX = 50
-Fields = 7
-
-Color = ColorDark
-DColor = Gray
-TColor = White
-TDColor = White
-SBGTex = MainBar
SBGColor = ColorDark
-SBGDColor = Gray
+SBGDColor = ColorLight
STColor = White
STDColor = GrayDark
@@ -6782,6 +6896,7 @@ Tex = PartyBG
[PartyPlayerStatic1]
X = 0
Y = 545
+Z = 0.7
W = 250
H = 30
Tex = Leiste1
@@ -6793,6 +6908,7 @@ ReflectionSpacing = 2
[PartyPlayerStatic2]
X = 250
Y = 545
+Z = 0.7
W = 550
H = 30
Tex = Leiste2
@@ -6813,6 +6929,7 @@ Type = Colorized
[PartyPlayerStatic4]
X = 260
Y = 552
+Z = 0.75
W = 24
H = 23
Tex = ButtonNavi
@@ -6822,6 +6939,7 @@ Type = Transparent
[PartyPlayerStatic5]
X = 388
Y = 552
+Z = 0.75
W = 32
H = 23
Tex = ButtonAZ
@@ -6831,6 +6949,7 @@ Type = Transparent
[PartyPlayerStatic6]
X = 556
Y = 552
+Z = 0.75
W = 24
H = 23
Tex = ButtonEnter
@@ -6891,12 +7010,108 @@ Color = Black
Font = 0
Size = 21
Align = 0
-Text = PARTY_PLAYER_LEGEND_CONTINUE
+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 = 85
-Y = 100
+X = 45
+Y = 140
W = 310
H = 50
Type = Colorized
@@ -6905,7 +7120,7 @@ Color = P1Lightest
DColor = P1Dark
[PartyPlayerTeam1NameText1]
-X = 155
+X = 115
Y = 8
Font = 0
Size = 36
@@ -6915,8 +7130,8 @@ Color = White
[PartyPlayerPlayer1Name]
Tex = Button
-X = 85
-Y = 160
+X = 45
+Y = 200
W = 150
H = 50
Type = Transparent
@@ -6937,8 +7152,8 @@ Color = White
[PartyPlayerPlayer2Name]
Tex = Button
-X = 245
-Y = 160
+X = 205
+Y = 200
W = 150
H = 50
Type = Transparent
@@ -6959,8 +7174,8 @@ Color = White
[PartyPlayerPlayer3Name]
Tex = Button
-X = 405
-Y = 160
+X = 365
+Y = 200
W = 150
H = 50
Type = Transparent
@@ -6981,8 +7196,8 @@ Color = White
[PartyPlayerPlayer4Name]
Tex = Button
-X = 565
-Y = 160
+X = 525
+Y = 200
W = 150
H = 50
Type = Transparent
@@ -7003,8 +7218,8 @@ Color = White
[PartyPlayerTeam2Name]
Tex = PartyTeamButton2
-X = 85
-Y = 240
+X = 45
+Y = 280
W = 310
H = 50
Type = Colorized
@@ -7013,7 +7228,7 @@ Color = P2Lightest
DColor = P2Dark
[PartyPlayerTeam2NameText1]
-X = 155
+X = 115
Y = 8
Font = 0
Size = 36
@@ -7023,8 +7238,8 @@ Color = White
[PartyPlayerPlayer5Name]
Tex = Button
-X = 85
-Y = 300
+X = 45
+Y = 340
W = 150
H = 50
Type = Transparent
@@ -7045,8 +7260,8 @@ Color = White
[PartyPlayerPlayer6Name]
Tex = Button
-X = 245
-Y = 300
+X = 205
+Y = 340
W = 150
H = 50
Type = Transparent
@@ -7067,8 +7282,8 @@ Color = White
[PartyPlayerPlayer7Name]
Tex = Button
-X = 405
-Y = 300
+X = 365
+Y = 340
W = 150
H = 50
Type = Transparent
@@ -7089,8 +7304,8 @@ Color = White
[PartyPlayerPlayer8Name]
Tex = Button
-X = 565
-Y = 300
+X = 525
+Y = 340
W = 150
H = 50
Type = Transparent
@@ -7111,17 +7326,17 @@ Color = White
[PartyPlayerTeam3Name]
Tex = PartyTeamButton2
-X = 85
-Y = 380
+X = 45
+Y = 420
W = 310
H = 50
-Type = Transparent
+Type = Colorized
Texts = 1
Color = P3Lightest
DColor = P3Dark
[PartyPlayerTeam3NameText1]
-X = 155
+X = 115
Y = 8
Font = 0
Size = 36
@@ -7131,8 +7346,9 @@ Color = White
[PartyPlayerPlayer9Name]
Tex = Button
-X = 85
-Y = 440
+X = 45
+Y = 480
+Z = 0.6
W = 150
H = 50
Type = Transparent
@@ -7153,8 +7369,9 @@ Color = White
[PartyPlayerPlayer10Name]
Tex = Button
-X = 245
-Y = 440
+X = 205
+Y = 480
+Z = 0.6
W = 150
H = 50
Type = Transparent
@@ -7175,8 +7392,9 @@ Color = White
[PartyPlayerPlayer11Name]
Tex = Button
-X = 405
-Y = 440
+X = 365
+Y = 480
+Z = 0.6
W = 150
H = 50
Type = Transparent
@@ -7197,8 +7415,9 @@ Color = White
[PartyPlayerPlayer12Name]
Tex = Button
-X = 565
-Y = 440
+X = 525
+Y = 480
+Z = 0.6
W = 150
H = 50
Type = Transparent
@@ -7217,6 +7436,293 @@ 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]
@@ -7318,6 +7824,31 @@ 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
@@ -7325,8 +7856,8 @@ Z = 0.97
W = 220
H = 25
Tex = Rectangle
-Color = LightBlue
-DColor = DarkBlue
+Color = ColorLight
+DColor = ColorDark
Type = Colorized
Texts = 1
@@ -7340,31 +7871,6 @@ Text = SONG_MENU_CANCEL
Align = 0
Z = 0.97
-# uncommented cause it's not appearing anyways
-# TODO: why is this here?
-#[SongMenuSelectSlide1]
-#Tex = Rectangle
-#TexSBG = Top5BG
-#Text =lalalalalalalala
-#Type
-#X = 524
-#Y = 295
-#W = 0
-#H = 25
-#Z = 0.97
-#SkipX = 0
-#SBGW = 270
-#TextSize = 24
-#Color = LightBlue
-#DColor = DarkBlue
-#TColor = White
-#TDColor = White
-#SBGTex = MainBar
-#SBGColor = LightBlue
-#SBGDColor = DarkBlue
-#STColor = White
-#STDColor = GrayDark
-
[SongJumpto]
[SongJumptoBackground]
diff --git a/cmake/game/themes/Deluxe/Blue.ini b/cmake/game/themes/Deluxe/Blue.ini
index 10017fb3..3ebc04ff 100644
--- a/cmake/game/themes/Deluxe/Blue.ini
+++ b/cmake/game/themes/Deluxe/Blue.ini
@@ -12,18 +12,18 @@ Color=Blue
/**
* Interface
*/
-interface_selectbg_search = interface/selectbg_search.png
-interface_dialog_background = interface/dialog_background.png
+interface_selectbg_search = [interface]selectbg_search.png
+interface_dialog_background = [interface]dialog_background.png
-Cursor = interface/cursor.png
-Cursor_Pressed = interface/cursor_pressed.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
+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 # # #
@@ -32,8 +32,8 @@ 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
+Select_ArrowLeft = [interface]select_arrow_left.png
+Select_ArrowRight = [interface]select_arrow_right.png
#Backgrounds
LoadingBG = [bg-load]blue.jpg
@@ -48,11 +48,14 @@ 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
@@ -160,6 +163,7 @@ 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 # # #
@@ -186,6 +190,7 @@ 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 # # #
diff --git a/cmake/game/themes/Deluxe/Fall.ini b/cmake/game/themes/Deluxe/Fall.ini
index 38f25cdb..4502be61 100644
--- a/cmake/game/themes/Deluxe/Fall.ini
+++ b/cmake/game/themes/Deluxe/Fall.ini
@@ -12,18 +12,18 @@ Color=Orange
/**
* Interface
*/
-interface_selectbg_search = interface/selectbg_search.png
-interface_dialog_background = interface/dialog_background.png
+interface_selectbg_search = [interface]selectbg_search.png
+interface_dialog_background = [interface]dialog_background.png
-Cursor = interface/cursor.png
-Cursor_Pressed = interface/cursor_pressed.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
+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 # # #
@@ -32,8 +32,8 @@ 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
+Select_ArrowLeft = [interface]select_arrow_left.png
+Select_ArrowRight = [interface]select_arrow_right.png
#Backgrounds
LoadingBG = [bg-load]fall.jpg
@@ -48,11 +48,14 @@ 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
@@ -160,6 +163,7 @@ 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 # # #
@@ -186,6 +190,7 @@ 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 # # #
diff --git a/cmake/game/themes/Deluxe/Ocean.ini b/cmake/game/themes/Deluxe/Ocean.ini
index bdc90979..8af41f20 100644
--- a/cmake/game/themes/Deluxe/Ocean.ini
+++ b/cmake/game/themes/Deluxe/Ocean.ini
@@ -12,18 +12,18 @@ Color=Blue
/**
* Interface
*/
-interface_selectbg_search = interface/selectbg_search.png
-interface_dialog_background = interface/dialog_background.png
+interface_selectbg_search = [interface]selectbg_search.png
+interface_dialog_background = [interface]dialog_background.png
-Cursor = interface/cursor.png
-Cursor_Pressed = interface/cursor_pressed.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
+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 # # #
@@ -32,8 +32,8 @@ 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
+Select_ArrowLeft = [interface]select_arrow_left.png
+Select_ArrowRight = [interface]select_arrow_right.png
#Backgrounds
LoadingBG = [bg-load]blue.jpg
@@ -48,11 +48,14 @@ 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
@@ -97,9 +100,9 @@ Ball = [sing]LyricsBall.png
# # # S C O R E / T O P 5 # # #
ScoreBox = [score]box.png
-ScoreGlassBox = [score]glass_box.png
+ScoreGlassBox = [score]glass_box.png
ScoreLevel = [score]level.png
-ScoreLevelRound = [score]levelRound.png
+ScoreLevelRound = [score]levelround.png
ScoreLevel_Dark = [score]level_dark.png
ScoreLevel_Dark_Round = [score]level_dark_round.png
@@ -160,6 +163,7 @@ 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 # # #
@@ -186,6 +190,7 @@ 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 # # #
diff --git a/cmake/game/themes/Deluxe/Ribbon.ini b/cmake/game/themes/Deluxe/Ribbon.ini
index 73cae2ab..06a4dd41 100644
--- a/cmake/game/themes/Deluxe/Ribbon.ini
+++ b/cmake/game/themes/Deluxe/Ribbon.ini
@@ -1,230 +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
-IconOption = [icon]options.png
-IconEdit = [icon]options.png
-ScoreIcon = [icon]score.png
-PartyIcon = [icon]party.png
-StatIcon = [icon]stats.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
-
-
-# # # 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
-
-
-# # # 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
+;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/cmake/game/themes/Deluxe/Summer.ini b/cmake/game/themes/Deluxe/Summer.ini
index 36e9f5d7..660a5ec7 100644
--- a/cmake/game/themes/Deluxe/Summer.ini
+++ b/cmake/game/themes/Deluxe/Summer.ini
@@ -6,24 +6,24 @@
[Skin]
Theme=Deluxe
Name=Summer
-Color=Blue
+Color=Red
[Textures]
/**
* Interface
*/
-interface_selectbg_search = interface/selectbg_search.png
-interface_dialog_background = interface/dialog_background.png
+interface_selectbg_search = [interface]selectbg_search.png
+interface_dialog_background = [interface]dialog_background.png
-Cursor = interface/cursor.png
-Cursor_Pressed = interface/cursor_pressed.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
+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 # # #
@@ -32,8 +32,8 @@ 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
+Select_ArrowLeft = [interface]select_arrow_left.png
+Select_ArrowRight = [interface]select_arrow_right.png
#Backgrounds
LoadingBG = [bg-load]summer.jpg
@@ -48,11 +48,14 @@ 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
@@ -160,6 +163,7 @@ 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 # # #
@@ -186,6 +190,7 @@ 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 # # #
diff --git a/cmake/game/themes/Deluxe/Winter.ini b/cmake/game/themes/Deluxe/Winter.ini
index 72514a15..71b4dfaa 100644
--- a/cmake/game/themes/Deluxe/Winter.ini
+++ b/cmake/game/themes/Deluxe/Winter.ini
@@ -12,18 +12,18 @@ Color=Blue
/**
* Interface
*/
-interface_selectbg_search = interface/selectbg_search.png
-interface_dialog_background = interface/dialog_background.png
+interface_selectbg_search = [interface]selectbg_search.png
+interface_dialog_background = [interface]dialog_background.png
-Cursor = interface/cursor.png
-Cursor_Pressed = interface/cursor_pressed.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
+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 # # #
@@ -32,8 +32,8 @@ 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
+Select_ArrowLeft = [interface]select_arrow_left.png
+Select_ArrowRight = [interface]select_arrow_right.png
#Backgrounds
LoadingBG = [bg-load]winter.jpg
@@ -48,11 +48,14 @@ 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
@@ -160,6 +163,7 @@ 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 # # #
@@ -186,6 +190,7 @@ 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 # # #
diff --git a/cmake/game/themes/Deluxe/[icon]song_menu.png b/cmake/game/themes/Deluxe/[icon]song_menu.png
new file mode 100644
index 00000000..acf69bfb
--- /dev/null
+++ b/cmake/game/themes/Deluxe/[icon]song_menu.png
Binary files differ
diff --git a/cmake/game/themes/Deluxe/[icon]song_search.png b/cmake/game/themes/Deluxe/[icon]song_search.png
new file mode 100644
index 00000000..f5190315
--- /dev/null
+++ b/cmake/game/themes/Deluxe/[icon]song_search.png
Binary files differ
diff --git a/cmake/game/themes/Deluxe/icon/song_video.png b/cmake/game/themes/Deluxe/[icon]song_video.png
index 20170d5f..20170d5f 100644
--- a/cmake/game/themes/Deluxe/icon/song_video.png
+++ b/cmake/game/themes/Deluxe/[icon]song_video.png
Binary files differ
diff --git a/cmake/game/themes/Deluxe/[interface]cursor.png b/cmake/game/themes/Deluxe/[interface]cursor.png
new file mode 100644
index 00000000..0fe390f0
--- /dev/null
+++ b/cmake/game/themes/Deluxe/[interface]cursor.png
Binary files differ
diff --git a/cmake/game/themes/Deluxe/interface/cursor.png b/cmake/game/themes/Deluxe/[interface]cursor_pressed.png
index 6c222732..fa0056cc 100644
--- a/cmake/game/themes/Deluxe/interface/cursor.png
+++ b/cmake/game/themes/Deluxe/[interface]cursor_pressed.png
Binary files differ
diff --git a/cmake/game/themes/Deluxe/interface/dialog_background.png b/cmake/game/themes/Deluxe/[interface]dialog_background.png
index ed032349..ed032349 100644
--- a/cmake/game/themes/Deluxe/interface/dialog_background.png
+++ b/cmake/game/themes/Deluxe/[interface]dialog_background.png
Binary files differ
diff --git a/cmake/game/themes/Deluxe/[interface]select_arrow_left.png b/cmake/game/themes/Deluxe/[interface]select_arrow_left.png
new file mode 100644
index 00000000..e4a32d2d
--- /dev/null
+++ b/cmake/game/themes/Deluxe/[interface]select_arrow_left.png
Binary files differ
diff --git a/cmake/game/themes/Deluxe/[interface]select_arrow_right.png b/cmake/game/themes/Deluxe/[interface]select_arrow_right.png
new file mode 100644
index 00000000..b2a29793
--- /dev/null
+++ b/cmake/game/themes/Deluxe/[interface]select_arrow_right.png
Binary files differ
diff --git a/cmake/game/themes/Deluxe/[interface]selectbg_search.png b/cmake/game/themes/Deluxe/[interface]selectbg_search.png
new file mode 100644
index 00000000..57d0ca88
--- /dev/null
+++ b/cmake/game/themes/Deluxe/[interface]selectbg_search.png
Binary files differ
diff --git a/cmake/game/themes/Deluxe/[party]playerselectbg.png b/cmake/game/themes/Deluxe/[party]playerselectbg.png
new file mode 100644
index 00000000..cc608229
--- /dev/null
+++ b/cmake/game/themes/Deluxe/[party]playerselectbg.png
Binary files differ
diff --git a/cmake/game/visuals/.gitignore b/cmake/game/visuals/.gitignore
new file mode 100644
index 00000000..39ea0e37
--- /dev/null
+++ b/cmake/game/visuals/.gitignore
@@ -0,0 +1,2 @@
+# don't delete this file as it prevents git from removing this directory
+projectM
diff --git a/cmake/icons/rccompile-fpc.bat b/cmake/icons/rccompile-fpc.bat
deleted file mode 100644
index 30998c6d..00000000
--- a/cmake/icons/rccompile-fpc.bat
+++ /dev/null
@@ -1,4 +0,0 @@
-@set PATH=C:\Programme\lazarus\fpc\2.2.0\bin\i386-win32\;%PATH%
-@set RES_NAME=ultrastardx-icon
-windres.exe -i %RES_NAME%.rc -o %RES_NAME%.res
-
diff --git a/cmake/icons/ultrastardx-icon.rc b/cmake/icons/ultrastardx-icon.rc
deleted file mode 100644
index 3d0b43fc..00000000
--- a/cmake/icons/ultrastardx-icon.rc
+++ /dev/null
@@ -1 +0,0 @@
-MAINICON ICON "ultrastardx.ico"
diff --git a/cmake/installer/UltraStar Deluxe.nsi b/cmake/installer/UltraStar Deluxe.nsi
index a6f37e2a..13cf46d0 100644
--- a/cmake/installer/UltraStar Deluxe.nsi
+++ b/cmake/installer/UltraStar Deluxe.nsi
@@ -16,14 +16,16 @@
!define path_settings ".\settings"
!define path_languages ".\languages"
-!define path_images "..\installerdependencies\images"
-!define path_plugins "..\installerdependencies\plugins"
-!define path_gdf "$WINDIR\gdf.dll"
+!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}\GameExplorer.nsh"
!include "${path_settings}\functions.nsh"
; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
@@ -31,10 +33,12 @@
; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
SetCompress Auto
-SetCompressor /SOLID lzma
+SetCompressor lzma
SetCompressorDictSize 32
SetDatablockOptimize On
+CRCCheck on
+
XPStyle on
Name "${name} v.${version}"
@@ -42,6 +46,7 @@ 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:
@@ -53,8 +58,8 @@ RequestExecutionLevel admin
; Icons:
-!define MUI_ICON "${path_images}\${img_install}"
-!define MUI_UNICON "${path_images}\${img_uninstall}"
+!define MUI_ICON "${img_install}"
+!define MUI_UNICON "${img_uninstall}"
; Header and Side Images:
@@ -79,6 +84,8 @@ RequestExecutionLevel admin
; Pages Installation Routine Settings
; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
+!define MUI_CUSTOMFUNCTION_GUIINIT bgmusic
+
; Welcome Page:
!define MUI_WELCOMEPAGE_TITLE_3LINES
@@ -133,7 +140,7 @@ var ICONS_GROUP
!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 "${PRODUCT_STARTMENU_REGVAL}"
+!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${name}"
!insertmacro MUI_PAGE_STARTMENU Application $ICONS_GROUP
!insertmacro MUI_PAGE_INSTFILES
@@ -144,94 +151,70 @@ Page custom Settings
Function Settings
-!insertmacro MUI_HEADER_TEXT " " "$(page_settings_subtitle)"
+!insertmacro INSTALLOPTIONS_WRITE "Settings-$LANGUAGE" "Field 18" "State" "$INSTDIR\songs"
- !insertmacro INSTALLOPTIONS_DISPLAY "Settings-$LANGUAGE"
+!insertmacro MUI_HEADER_TEXT " " "$(page_settings_subtitle)"
+!insertmacro INSTALLOPTIONS_DISPLAY "Settings-$LANGUAGE"
; Get all the variables:
-Var /GLOBAL CHECKBOX
-Var /GLOBAL checkbox_state
+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 animations
+var /GLOBAL sorting
+var /GLOBAL songdir
- !insertmacro INSTALLOPTIONS_READ $fullscreen "Settings-$LANGUAGE" "Field 6" "State"
- !insertmacro INSTALLOPTIONS_READ $language2 "Settings-$LANGUAGE" "Field 7" "State"
- !insertmacro INSTALLOPTIONS_READ $resolution "Settings-$LANGUAGE" "Field 8" "State"
- !insertmacro INSTALLOPTIONS_READ $tabs "Settings-$LANGUAGE" "Field 9" "State"
- !insertmacro INSTALLOPTIONS_READ $animations "Settings-$LANGUAGE" "Field 10" "State"
+ !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"
; Write all variables to config.ini
-FileOpen $0 '$INSTDIR\config.ini' w
-FileWrite $0 '[Game]$\r$\n'
-FileClose $0
-
-${If} $language2 != ""
-
-${WriteToConfig} "Language=$language2$\r$\n" "$INSTDIR\config.ini"
-
-${EndIf}
-
-${If} $tabs != ""
-
-${WriteToConfig} "Tabs=$tabs$\r$\n" "$INSTDIR\config.ini"
-
-${EndIf}
-
-${WriteToConfig} "[Graphics]$\r$\n" "$INSTDIR\config.ini"
-
-${If} $fullscreen != ""
-
-${WriteToConfig} "FullScreen=$fullscreen$\r$\n" "$INSTDIR\config.ini"
-
-${EndIf}
-
-${If} $resolution != ""
-
-${WriteToConfig} "Resolution=$resolution$\r$\n" "$INSTDIR\config.ini"
-
-${EndIf}
-
-${WriteToConfig} "[Sound]$\r$\n" "$INSTDIR\config.ini"
-${WriteToConfig} "PreviewFading=3 Secs$\r$\n" "$INSTDIR\config.ini"
-
-; Animations On / Off Tasks
-
-${If} $animations == "Off"
-
-${WriteToConfig} "[Advanced]$\r$\n" "$INSTDIR\config.ini"
-
-${WriteToConfig} "LoadAnimation=Off$\r$\n" "$INSTDIR\config.ini"
-
-${WriteToConfig} "EffectSing=Off$\r$\n" "$INSTDIR\config.ini"
-
-${WriteToConfig} "ScreenFade=Off$\r$\n" "$INSTDIR\config.ini"
-
-${WriteToConfig} "LineBonus=At Notes$\r$\n" "$INSTDIR\config.ini"
+var /GLOBAL path_config
+var /GLOBAL path_configini
+${If} ${AtLeastWinVista}
+ SetShellVarContext current
+ StrCpy $path_config "$APPDATA\ultrastardx"
+ SetShellVarContext all
+${Else}
+ StrCpy $path_config "$INSTDIR"
${EndIf}
-${WriteToConfig} "[Lyrics]$\r$\n" "$INSTDIR\config.ini"
-${WriteToConfig} "LyricsFont=Plain$\r$\n" "$INSTDIR\config.ini"
-${WriteToConfig} "LyricsEffect=Slide$\r$\n" "$INSTDIR\config.ini"
+StrCpy $path_configini "$path_config\config.ini"
-${If} $animations != "Off"
+WriteINIStr "$path_configini" "Game" "Language" "$language2"
+WriteINIStr "$path_configini" "Game" "Tabs" "$tabs"
+WriteINIStr "$path_configini" "Game" "Sorting" "$sorting"
-${WriteToConfig} "[Advanced]$\r$\n" "$INSTDIR\config.ini"
-
-${WriteToConfig} "LineBonus=At Notes$\r$\n" "$INSTDIR\config.ini"
+WriteINIStr "$path_configini" "Graphics" "FullScreen" "$fullscreen"
+WriteINIStr "$path_configini" "Graphics" "Resolution" "$resolution"
+${If} $songdir != "$INSTDIR\songs"
+WriteINIStr "$path_configini" "Directories" "SongDir1" "$songdir"
${EndIf}
-
FunctionEnd ; Settings page End
-
!insertmacro MUI_PAGE_FINISH
; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
@@ -248,10 +231,32 @@ Function un.AskDelete
nsDialogs::Create /NOUNLOAD 1018
- ${NSD_CreateCheckbox} 0 -150 100% 8u "$(delete_all)"
- Pop $CHECKBOX
+ ${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
- nsDialogs::OnClick /NOUNLOAD $CHECKBOX $0
+ ${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
@@ -260,19 +265,53 @@ FunctionEnd
Function un.DeleteAll
-${NSD_GetState} $CHECKBOX $checkbox_state
+${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} $checkbox_state == "1"
+${If} $CB_CONFIG_State == "1" ; Remove config
+ SetShellVarContext current
+ Delete "$APPDATA\ultrastardx\config.ini"
+ SetShellVarContext all
+ Delete "$INSTDIR\config.ini"
+${EndIf}
- RMDir /r "$INSTDIR\Songs"
- RMDir /r "$INSTDIR\Covers"
+${If} $CB_SCORES_State == "1" ; Remove highscores
+ SetShellVarContext current
+ Delete "$APPDATA\ultrastardx\Ultrastar.db"
+ SetShellVarContext all
Delete "$INSTDIR\Ultrastar.db"
+${EndIf}
-${Else}
-
-; If checkbox_state = 0
+${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}
@@ -296,62 +335,31 @@ Section $(name_section1) Section1
!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_documentation).lnk" "$INSTDIR\documentation.pdf"
CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\$(sm_website).lnk" "http://www.ultrastardeluxe.org/"
- CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\$(sm_readme).lnk" "$INSTDIR\ReadMe.txt"
- CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\$(sm_license).lnk" "$INSTDIR\License.txt"
+ CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\$(sm_songs).lnk" "$INSTDIR\songs"
CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\$(sm_uninstall).lnk" "$INSTDIR\Uninstall.exe"
- !insertmacro MUI_STARTMENU_WRITE_END
+!insertmacro MUI_STARTMENU_WRITE_END
; Vista Game Explorer:
-
-${If} ${AtLeastWinVista}
-
-${GameExplorer_GenerateGUID}
-Pop $0
-
-${GameExplorer_AddGame} all "${path_gdf}" $WINDIR $INSTDIR\${exe}.exe $0
-
-CreateDirectory $APPDATA\Microsoft\Windows\GameExplorer\$0\PlayTasks\1
-CreateShortcut "$APPDATA\Microsoft\Windows\GameExplorer\$0\PlayTasks\1\Benchmark.lnk" \
- "$INSTDIR\${exe}.exe" "-Benchmark"
-
-CreateDirectory $APPDATA\Microsoft\Windows\GameExplorer\$0\PlayTasks\2
-CreateShortcut "$APPDATA\Microsoft\Windows\GameExplorer\$0\PlayTasks\2\Joypad.lnk" \
- "$INSTDIR\${exe}.exe" "-Joypad"
-
-CreateDirectory $APPDATA\Microsoft\Windows\GameExplorer\$0\PlayTasks\3
-CreateShortcut "$APPDATA\Microsoft\Windows\GameExplorer\$0\PlayTasks\3\Fullscreen.lnk" \
- "$INSTDIR\${exe}.exe" "-FullScreen"
-
-CreateDirectory $APPDATA\Microsoft\Windows\GameExplorer\$0\PlayTasks\3
-CreateShortcut "$APPDATA\Microsoft\Windows\GameExplorer\$0\PlayTasks\3\Dual Screen.lnk" \
- "$INSTDIR\${exe}.exe" "-Screens 2"
-
-CreateDirectory $APPDATA\Microsoft\Windows\GameExplorer\$0\SupportTasks\0
-CreateShortcut "$APPDATA\Microsoft\Windows\GameExplorer\$0\SupportTasks\0\Support Forum.lnk" \
- "http://forum.ultrastardeluxe.org"
-
-${EndIf}
+; (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}"
@@ -365,1024 +373,14 @@ SectionEnd
; OPTIONAL SONGS (Section 2)
;------------------------------------
-SectionGroup $(name_section2) Section2
-
-Section /o "Bodo Wartke - Liebeslied (Love Song)" g2Section1
-
- AddSize 10342
- SetOverwrite try
- SetOutPath "$INSTDIR\Songs\"
-
-; Download song:
- NSISdl::download /TIMEOUT=50000 ${download_song1} $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 "$TEMP\Song-BodoWartke-LoveSong.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-I-18.zip" "$INSTDIR\Songs\Dead Smiling Pirates - I 18\"
-
- Delete "$TEMP\Song-I-18.zip"
-
- SetOutPath "$INSTDIR"
-
-SectionEnd
-
-;
-; Jonathan Coulton Songs
-;
-
-SectionGroup $(name_s2_sub1) s2_sub1
-
-Section /o "Monkey Shines" s2_sub1_Section1
-
- AddSize 1455
- SetOverwrite try
- SetOutPath "$INSTDIR\Songs\"
-
-; Download song:
- NSISdl::download /TIMEOUT=50000 ${download_sub1_song1} $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 "$TEMP\Song-JC-MS.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-JC-ICE.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-JC-NAY.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-JC-MFP.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-JC-BBWO.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-JC-Flickr.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-JC-MBB.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-JC-TFS.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-JC-Ikea.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-JC-FOL.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-JC-CM.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-JC-IYM.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-JC-FOM.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-JC-DSJD.zip" "$INSTDIR\Songs\"
-
- Delete "$TEMP\Song-JC-DSJD.zip"
-
- SetOutPath "$INSTDIR"
-
-SectionEnd
-
-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} $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 "$TEMP\Song-JC-ATWG.zip" "$INSTDIR\Songs\"
-
- Delete "$TEMP\Song-JC-ATWG.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} $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 "$TEMP\Song-JC-CD.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-JC-TSDNA.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-JC-WYG.zip" "$INSTDIR\Songs\"
-
- Delete "$TEMP\Song-JC-WYG.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} $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 "$TEMP\Song-JC-Better.zip" "$INSTDIR\Songs\"
-
- Delete "$TEMP\Song-JC-Better.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} $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 "$TEMP\Song-JC-SV.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-JC-IFF.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-JC-ReYB.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-JC-SCM.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-JC-CBP.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-On-the-run.zip" "$INSTDIR\Songs\Joshua Morin - On The Run\"
-
- Delete "$TEMP\Song-On-the-run.zip"
-
- SetOutPath "$INSTDIR"
-
-SectionEnd
-
-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} $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 "$TEMP\Song-Space-Invaders.zip" "$INSTDIR\Songs\Pornophonique - Space Invaders\"
-
- Delete "$TEMP\Song-Space-Invaders.zip"
-
- SetOutPath "$INSTDIR"
-
-SectionEnd
-
-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} $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 "$TEMP\Song-Shearer-69.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-Shearer-69-Kar.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-Shearer-CSI.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-Shearer-CSI-Kar.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-Shearer-IMH.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-Shearer-MS.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-Shearer-MS-Kar.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-Shearer-SWM.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-Shearer-SWM-Kar.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-Northern-Star.zip" "$INSTDIR\Songs\Steven Dunston - Northern Star\"
-
- Delete "$TEMP\Song-Northern-Star.zip"
-
- SetOutPath "$INSTDIR"
-
-SectionEnd
-
-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} $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 "$TEMP\Song-WiseGuys-LUKUS.zip" "$INSTDIR\Songs\"
-
- Delete "$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} $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 "$TEMP\Song-WiseGuys-MWBD.zip" "$INSTDIR\Songs\"
-
- Delete "$TEMP\Song-WiseGuys-MWBD.zip"
-
- SetOutPath "$INSTDIR"
-
-SectionEnd
-
-SectionGroupEnd
-
-SectionGroupEnd
+ !include "${path_settings}\files_opt_songs.nsh"
;------------------------------------
; OPTIONAL THEMES (Section 3)
;------------------------------------
-SectionGroup $(name_section3) Section3
-
- Section /o "Orange" g3Section1
- AddSize 1291
-
-; Download theme orange:
- NSISdl::download /TIMEOUT=50000 ${download_theme1} $TEMP\Theme-Orange.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 "$TEMP\Theme-Orange.zip" "$INSTDIR\"
-
- Delete "$TEMP\Theme-Orange.zip"
-
- SetOutPath "$INSTDIR"
-
-SectionEnd
-
- Section /o "Streetlight" g3Section2
- AddSize 1905
-
-; Download theme Streetlight:
- NSISdl::download /TIMEOUT=50000 ${download_theme2} $TEMP\Theme-Streetlight.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 "$TEMP\Theme-Streetlight.zip" "$INSTDIR\"
-
- Delete "$TEMP\Theme-Streetlight.zip"
-
- SetOutPath "$INSTDIR"
-
-SectionEnd
-
- Section /o "Vistar" g3Section3
- AddSize 1936
-
-; Download theme Vistar:
-
- NSISdl::download /TIMEOUT=50000 ${download_theme3} $TEMP\Theme-Vistar.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 "$TEMP\Theme-Vistar.zip" "$INSTDIR\"
-
- Delete "$TEMP\Theme-Vistar.zip"
-
- SetOutPath "$INSTDIR"
-
-SectionEnd
-
- Section /o "BlueSensation" g3Section4
- AddSize 2109
-
-; Download theme BlueSensation:
-
- NSISdl::download /TIMEOUT=50000 ${download_theme4} $TEMP\Theme-BlueSensation.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 "$TEMP\Theme-BlueSensation.zip" "$INSTDIR\"
-
- Delete "$TEMP\Theme-BlueSensation.zip"
-
- SetOutPath "$INSTDIR"
-
-SectionEnd
-
-
- Section /o "WhiteSensation" g3Section5
- AddSize 1168
-
-; Download theme WhiteSensation:
-
- NSISdl::download /TIMEOUT=50000 ${download_theme7} $TEMP\Theme-WhiteSensation.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 "$TEMP\Theme-WhiteSensation.zip" "$INSTDIR\"
-
- Delete "$TEMP\Theme-WhiteSensation.zip"
-
- SetOutPath "$INSTDIR"
-
-SectionEnd
-
- Section /o "WiiStar" g3Section6
- AddSize 850
-
-; Download theme WiiStar:
-
- NSISdl::download /TIMEOUT=50000 ${download_theme5} $TEMP\Theme-WiiStar.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 "$TEMP\Theme-WiiStar.zip" "$INSTDIR\"
-
- Delete "$TEMP\Theme-WiiStar.zip"
-
- SetOutPath "$INSTDIR"
-
-SectionEnd
-
- Section /o "iStar" g3Section7
- AddSize 1588
-
-; Download theme iStar:
-
- NSISdl::download /TIMEOUT=50000 ${download_theme6} $TEMP\Theme-iStar.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 "$TEMP\Theme-iStar.zip" "$INSTDIR\"
-
- Delete "$TEMP\Theme-iStar.zip"
-
- SetOutPath "$INSTDIR"
-
-SectionEnd
-
-SectionGroupEnd
+; No additional themes available
+; for current version of ultrastardx
;------------------------------------
; UNINSTALL (Section 4)
@@ -1397,14 +395,7 @@ Section Uninstall
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
; Unregister from Windows Vista Game Explorer
-
-${If} ${AtLeastWinVista}
-
-${GameExplorer_RemoveGame} $0
-
-${EndIf}
-
-
+; (removed due to incompatibility with Windows 7)
SectionEnd
@@ -1420,13 +411,15 @@ SectionEnd
!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 ${Section3} $(DESC_Section3)
+ !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)
@@ -1465,14 +458,7 @@ SectionEnd
!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 ${g3Section1} $(DESC_g3Section1)
- !insertmacro MUI_DESCRIPTION_TEXT ${g3Section2} $(DESC_g3Section2)
- !insertmacro MUI_DESCRIPTION_TEXT ${g3Section3} $(DESC_g3Section3)
- !insertmacro MUI_DESCRIPTION_TEXT ${g3Section4} $(DESC_g3Section4)
- !insertmacro MUI_DESCRIPTION_TEXT ${g3Section5} $(DESC_g3Section5)
- !insertmacro MUI_DESCRIPTION_TEXT ${g3Section6} $(DESC_g3Section6)
- !insertmacro MUI_DESCRIPTION_TEXT ${g3Section7} $(DESC_g3Section7)
+ !insertmacro MUI_DESCRIPTION_TEXT ${s2_sub3_Section3} $(DESC_s2_sub3_Section3)
!insertmacro MUI_FUNCTION_DESCRIPTION_END
@@ -1482,18 +468,30 @@ SectionEnd
!insertmacro MUI_LANGUAGE "English"
!insertmacro MUI_LANGUAGE "German"
+!insertmacro MUI_LANGUAGE "Hungarian"
!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
var /GLOBAL version
-StrCpy $version "1.1a"
+StrCpy $version "1.1beta"
- System::Call 'kernel32::CreateMutexA(i 0, i 0, t "USdx Installer.exe") ?e'
+ System::Call 'kernel32::CreateMutexA(i 0, i 0, t "USdx Installer.exe") ?e'
Pop $R0
@@ -1506,28 +504,34 @@ StrCpy $version "1.1a"
${If} $R0 == $version
MessageBox MB_YESNO|MB_ICONEXCLAMATION \
"${name} v.$R0 $(oninit_alreadyinstalled). $\n$\n $(oninit_installagain)" \
- IDYES done
+ IDYES continue
Abort
${EndIf}
- ReadRegStr $R1 HKLM \
- "Software\Microsoft\Windows\CurrentVersion\Uninstall\${name}" \
- "UninstallString"
+ 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 done
+ 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"
FunctionEnd
@@ -1537,10 +541,18 @@ Function un.onInit
StrCmp $R0 0 0 +2
MessageBox MB_YESNO|MB_ICONEXCLAMATION '$(oninit_closeusdx)' IDYES closeit IDNO end
- closeit:
+ 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
diff --git a/cmake/installer/dependencies/dll/put game dlls here b/cmake/installer/dependencies/dll/put game dlls here
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/cmake/installer/dependencies/dll/put game dlls here
diff --git a/cmake/installerdependencies/documents/documentation.pdf b/cmake/installer/dependencies/documents/documentation.pdf
index 16267bb9..16267bb9 100644
--- a/cmake/installerdependencies/documents/documentation.pdf
+++ b/cmake/installer/dependencies/documents/documentation.pdf
Binary files differ
diff --git a/cmake/installerdependencies/documents/license.txt b/cmake/installer/dependencies/documents/license.txt
index 4964fc70..66f35b98 100644
--- a/cmake/installerdependencies/documents/license.txt
+++ b/cmake/installer/dependencies/documents/license.txt
@@ -1,125 +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.
+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/cmake/installerdependencies/images/header.bmp b/cmake/installer/dependencies/images/header.bmp
index 058eafd3..058eafd3 100644
--- a/cmake/installerdependencies/images/header.bmp
+++ b/cmake/installer/dependencies/images/header.bmp
Binary files differ
diff --git a/cmake/installerdependencies/images/side.bmp b/cmake/installer/dependencies/images/side.bmp
index 3883fa09..3883fa09 100644
--- a/cmake/installerdependencies/images/side.bmp
+++ b/cmake/installer/dependencies/images/side.bmp
Binary files differ
diff --git a/cmake/installer/dependencies/loop.wav b/cmake/installer/dependencies/loop.wav
new file mode 100644
index 00000000..8a252921
--- /dev/null
+++ b/cmake/installer/dependencies/loop.wav
Binary files differ
diff --git a/cmake/installerdependencies/plugins/NSISdl.dll b/cmake/installer/dependencies/plugins/NSISdl.dll
index a3675054..a3675054 100644
--- a/cmake/installerdependencies/plugins/NSISdl.dll
+++ b/cmake/installer/dependencies/plugins/NSISdl.dll
Binary files differ
diff --git a/cmake/installerdependencies/plugins/ZipDLL.dll b/cmake/installer/dependencies/plugins/ZipDLL.dll
index 5925d591..5925d591 100644
--- a/cmake/installerdependencies/plugins/ZipDLL.dll
+++ b/cmake/installer/dependencies/plugins/ZipDLL.dll
Binary files differ
diff --git a/cmake/installerdependencies/plugins/nsProcess.dll b/cmake/installer/dependencies/plugins/nsProcess.dll
index 064097a3..064097a3 100644
--- a/cmake/installerdependencies/plugins/nsProcess.dll
+++ b/cmake/installer/dependencies/plugins/nsProcess.dll
Binary files differ
diff --git a/cmake/installer/install.ico b/cmake/installer/install.ico
new file mode 100644
index 00000000..fc1d0797
--- /dev/null
+++ b/cmake/installer/install.ico
Binary files differ
diff --git a/cmake/installer/languages/English.nsh b/cmake/installer/languages/English.nsh
index 63901b87..a3325d5b 100644
--- a/cmake/installer/languages/English.nsh
+++ b/cmake/installer/languages/English.nsh
@@ -9,13 +9,20 @@ LangString oninit_installagain ${LANG_ENGLISH} "Are you sure you want to install
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_all ${LANG_ENGLISH} "Also delete Songs, Highscores and Covers ?"
+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."
@@ -26,10 +33,8 @@ LangString update_check_failed ${LANG_ENGLISH} "The check for a new version fail
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:
@@ -54,6 +59,7 @@ 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"
@@ -66,63 +72,60 @@ 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_section3 ${LANG_ENGLISH} "Themes"
+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 installed."
+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_Section3 ${LANG_ENGLISH} "You can choose which optional themes should be installed."
-
-LangString DESC_g2Section2 ${LANG_ENGLISH} "This will install the song 'Dead Smiling Pirates - I 18' (CC by-nc-nd 2.5)."
-LangString DESC_g2Section3 ${LANG_ENGLISH} "This will install the song 'Joshua Morin - On The Run' (CC by-sa 2.5)."
-LangString DESC_g2Section4 ${LANG_ENGLISH} "This will install the song 'Pornophonique - Space Invaders' (CC by-nc-nd 2.0)."
-LangString DESC_g2Section5 ${LANG_ENGLISH} "This will install the song 'Steven Dunston - Northern Star' (CC by-nc-sa 2.5)."
-LangString DESC_g2Section1 ${LANG_ENGLISH} "This will install the song 'Bodo Wartke - Liebeslied (Love Song)'."
-
-LangString DESC_s2_sub1_Section1 ${LANG_ENGLISH} "This will install the song 'Monkey Shines'."
-LangString DESC_s2_sub1_Section2 ${LANG_ENGLISH} "This will install the song 'I Crush Everything'."
-LangString DESC_s2_sub1_Section3 ${LANG_ENGLISH} "This will install the song 'Not About You'."
-LangString DESC_s2_sub1_Section4 ${LANG_ENGLISH} "This will install the song 'Mr. Fancy Pants'."
-LangString DESC_s2_sub1_Section5 ${LANG_ENGLISH} "This will install the song 'Big Bad World One'."
-LangString DESC_s2_sub1_Section6 ${LANG_ENGLISH} "This will install the song 'Flickr [incl. video]'."
-LangString DESC_s2_sub1_Section7 ${LANG_ENGLISH} "This will install the song 'My Beige Bear'."
-LangString DESC_s2_sub1_Section8 ${LANG_ENGLISH} "This will install the song 'The Future Soon'."
-LangString DESC_s2_sub1_Section9 ${LANG_ENGLISH} "This will install the song 'Ikea'."
-LangString DESC_s2_sub1_Section10 ${LANG_ENGLISH} "This will install the song 'Furry Old Lobster'."
-LangString DESC_s2_sub1_Section11 ${LANG_ENGLISH} "This will install the song 'Code Monkey [incl. video]'."
-LangString DESC_s2_sub1_Section12 ${LANG_ENGLISH} "This will install the song 'I´m Your Moon'."
-LangString DESC_s2_sub1_Section13 ${LANG_ENGLISH} "This will install the song 'First Of May'."
-LangString DESC_s2_sub1_Section14 ${LANG_ENGLISH} "This will install the song 'Dance, Soterios Johnson, Dance'."
-LangString DESC_s2_sub1_Section15 ${LANG_ENGLISH} "This will install the song 'A Talk With George'."
-LangString DESC_s2_sub1_Section16 ${LANG_ENGLISH} "This will install the song 'Creepy Doll [incl. video]'."
-LangString DESC_s2_sub1_Section17 ${LANG_ENGLISH} "This will install the song 'That Spells DNA'."
-LangString DESC_s2_sub1_Section18 ${LANG_ENGLISH} "This will install the song 'When You Go'."
-LangString DESC_s2_sub1_Section19 ${LANG_ENGLISH} "This will install the song 'Better'."
-LangString DESC_s2_sub1_Section20 ${LANG_ENGLISH} "This will install the song 'Shop Vac'."
-LangString DESC_s2_sub1_Section21 ${LANG_ENGLISH} "This will install the song 'I Feel Fantastic'."
-LangString DESC_s2_sub1_Section22 ${LANG_ENGLISH} "This will install the song 'Re: Your Brains'."
-LangString DESC_s2_sub1_Section23 ${LANG_ENGLISH} "This will install the song 'Skullcrusher Mountain'."
-LangString DESC_s2_sub1_Section24 ${LANG_ENGLISH} "This will install the song 'Chiron Beta Prime [incl. video]'."
-
-LangString DESC_s2_sub2_Section1 ${LANG_ENGLISH} "This will install the song '69'."
-LangString DESC_s2_sub2_Section2 ${LANG_ENGLISH} "This will install the song '69 (Karaoke)'."
-LangString DESC_s2_sub2_Section3 ${LANG_ENGLISH} "This will install the song 'Can't stop it'."
-LangString DESC_s2_sub2_Section4 ${LANG_ENGLISH} "This will install the song 'Can't stop it (Karaoke)'."
-LangString DESC_s2_sub2_Section5 ${LANG_ENGLISH} "This will install the song 'In My Hand'."
-LangString DESC_s2_sub2_Section6 ${LANG_ENGLISH} "This will install the song 'Man Song'."
-LangString DESC_s2_sub2_Section7 ${LANG_ENGLISH} "This will install the song 'Man Song (Karaoke)'."
-LangString DESC_s2_sub2_Section8 ${LANG_ENGLISH} "This will install the song 'Stay with me'."
-LangString DESC_s2_sub2_Section9 ${LANG_ENGLISH} "This will install the song 'Stay with me (Karaoke)'."
-
-LangString DESC_s2_sub3_Section1 ${LANG_ENGLISH} "This will install the song 'Lebendig und kräftig und schärfer'."
-LangString DESC_s2_sub3_Section2 ${LANG_ENGLISH} "This will install the song 'Mensch, wo bist du?'."
-
-LangString DESC_g3Section1 ${LANG_ENGLISH} "This will install the optional theme 'Orange' by Skar"
-LangString DESC_g3Section2 ${LANG_ENGLISH} "This will install the optional theme 'Streetlight' by Skar"
-LangString DESC_g3Section3 ${LANG_ENGLISH} "This will install the optional theme 'Vistar' by Skar"
-LangString DESC_g3Section4 ${LANG_ENGLISH} "This will install the optional theme 'BlueSensation v5.1' by Charis"
-LangString DESC_g3Section6 ${LANG_ENGLISH} "This will install the optional theme 'WiiStar' by MasterPhW"
-LangString DESC_g3Section7 ${LANG_ENGLISH} "This will install the optional theme 'iStar' by MezzoX"
-LangString DESC_g3Section5 ${LANG_ENGLISH} "This will install the optional theme 'WhiteSensation' by Charis" \ No newline at end of file
+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/cmake/installer/languages/German.nsh b/cmake/installer/languages/German.nsh
index 7f438e9d..56507ec5 100644
--- a/cmake/installer/languages/German.nsh
+++ b/cmake/installer/languages/German.nsh
@@ -2,20 +2,27 @@
; UltraStar Deluxe Installer - Language file: German
; ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~ ~+~
-LangString abort_install ${LANG_GERMAN} "Wollen Sie die Installation wirklich abbrechen?"
-LangString abort_uninstall ${LANG_GERMAN} "Wollen Sie die Deinstallation wirklich abbrechen?"
+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} "Sind Sie sicher, dass Sie es erneut installieren möchten?"
+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öchten Sie das Programm aktualisieren von"
+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_all ${LANG_GERMAN} "Lieder, Highscores und Cover auch löschen?"
+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."
@@ -25,16 +32,16 @@ LangString update_check_failed ${LANG_GERMAN} "Die Aktualisierungsprüfung ist fe
; 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 Sie 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_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 Sie 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_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} "Schieben Sie den Mauszeiger über die Komponente um Details einzusehen"
+LangString page_components_info ${LANG_GERMAN} "Schiebe den Mauszeiger über die Komponente um Details einzusehen"
; Custom Page
@@ -43,17 +50,18 @@ LangString page_settings_subtitle ${LANG_GERMAN} "Lege deine favorisierten Einst
; Finish Page:
-LangString page_finish_txt ${LANG_GERMAN} "UltraStar Deluxe wurde erfolgreich auf Ihrem System installiert.$\n$\r$\n$\rBesuchen Sie unsere Projektwebseite um die neusten Updates und News zu erhalten."
+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} "Internetseite"
+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"
@@ -66,63 +74,57 @@ 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_section3 ${LANG_GERMAN} "Designs"
+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 Installieren gewählt werden."
-LangString DESC_Section2_sub1 ${LANG_GERMAN} "Hier können Jonathan Coulton Songs (CC by-nc 3.0) zum Installieren gewählt werden."
-LangString DESC_Section2_sub2 ${LANG_GERMAN} "Hier können Shearer Songs (CC by-nc-sa 2.0 / 3.0) zum Installieren gewählt werden."
-LangString DESC_Section2_sub3 ${LANG_GERMAN} "Hier können Wise Guys Songs zum Installieren gewählt werden."
-LangString DESC_Section3 ${LANG_GERMAN} "Hier können alternative Motive zum Installieren gewählt werden."
-
-LangString DESC_g2Section2 ${LANG_GERMAN} "Installiert das Lied 'Dead Smiling Pirates - I 18' (CC by-nc-nd 2.5)."
-LangString DESC_g2Section3 ${LANG_GERMAN} "Installiert das Lied 'Joshua Morin - On The Run' (CC by-sa 2.5)."
-LangString DESC_g2Section4 ${LANG_GERMAN} "Installiert das Lied 'Pornophonique - Space Invaders' (CC by-nc-nd 2.0)."
-LangString DESC_g2Section5 ${LANG_GERMAN} "Installiert das Lied 'Steven Dunston - Northern Star' (CC by-nc-sa 2.5)."
-LangString DESC_g2Section1 ${LANG_GERMAN} "Installiert das Lied 'Bodo Wartke - Liebeslied (Love Song)'."
-
-LangString DESC_s2_sub1_Section1 ${LANG_GERMAN} "Installiert das Lied 'Monkey Shines'."
-LangString DESC_s2_sub1_Section2 ${LANG_GERMAN} "Installiert das Lied 'I Crush Everything'."
-LangString DESC_s2_sub1_Section3 ${LANG_GERMAN} "Installiert das Lied 'Not About You'."
-LangString DESC_s2_sub1_Section4 ${LANG_GERMAN} "Installiert das Lied 'Mr. Fancy Pants'."
-LangString DESC_s2_sub1_Section5 ${LANG_GERMAN} "Installiert das Lied 'Big Bad World One'."
-LangString DESC_s2_sub1_Section6 ${LANG_GERMAN} "Installiert das Lied 'Flickr [inkl. Video]'."
-LangString DESC_s2_sub1_Section7 ${LANG_GERMAN} "Installiert das Lied 'My Beige Bear'."
-LangString DESC_s2_sub1_Section8 ${LANG_GERMAN} "Installiert das Lied 'The Future Soon'."
-LangString DESC_s2_sub1_Section9 ${LANG_GERMAN} "Installiert das Lied 'Ikea'."
-LangString DESC_s2_sub1_Section10 ${LANG_GERMAN} "Installiert das Lied 'Furry Old Lobster'."
-LangString DESC_s2_sub1_Section11 ${LANG_GERMAN} "Installiert das Lied 'Code Monkey [inkl. Video]'."
-LangString DESC_s2_sub1_Section12 ${LANG_GERMAN} "Installiert das Lied 'I´m Your Moon'."
-LangString DESC_s2_sub1_Section13 ${LANG_GERMAN} "Installiert das Lied 'First Of May'."
-LangString DESC_s2_sub1_Section14 ${LANG_GERMAN} "Installiert das Lied 'Dance, Soterios Johnson, Dance'."
-LangString DESC_s2_sub1_Section15 ${LANG_GERMAN} "Installiert das Lied 'A Talk With George'."
-LangString DESC_s2_sub1_Section16 ${LANG_GERMAN} "Installiert das Lied 'Creepy Doll [inkl. Video]'."
-LangString DESC_s2_sub1_Section17 ${LANG_GERMAN} "Installiert das Lied 'That Spells DNA'."
-LangString DESC_s2_sub1_Section18 ${LANG_GERMAN} "Installiert das Lied 'When You Go'."
-LangString DESC_s2_sub1_Section19 ${LANG_GERMAN} "Installiert das Lied 'Better'."
-LangString DESC_s2_sub1_Section20 ${LANG_GERMAN} "Installiert das Lied 'Shop Vac'."
-LangString DESC_s2_sub1_Section21 ${LANG_GERMAN} "Installiert das Lied 'I Feel Fantastic'."
-LangString DESC_s2_sub1_Section22 ${LANG_GERMAN} "Installiert das Lied 'Re: Your Brains'."
-LangString DESC_s2_sub1_Section23 ${LANG_GERMAN} "Installiert das Lied 'Skullcrusher Mountain'."
-LangString DESC_s2_sub1_Section24 ${LANG_GERMAN} "Installiert das Lied 'Chiron Beta Prime [inkl. Video]'."
-
-LangString DESC_s2_sub2_Section1 ${LANG_GERMAN} "Installiert das Lied '69'."
-LangString DESC_s2_sub2_Section2 ${LANG_GERMAN} "Installiert das Lied '69 (Karaoke)'."
-LangString DESC_s2_sub2_Section3 ${LANG_GERMAN} "Installiert das Lied 'Can't stop it'."
-LangString DESC_s2_sub2_Section4 ${LANG_GERMAN} "Installiert das Lied 'Can't stop it (Karaoke)'."
-LangString DESC_s2_sub2_Section5 ${LANG_GERMAN} "Installiert das Lied 'In My Hand'."
-LangString DESC_s2_sub2_Section6 ${LANG_GERMAN} "Installiert das Lied 'Man Song'."
-LangString DESC_s2_sub2_Section7 ${LANG_GERMAN} "Installiert das Lied 'Man Song (Karaoke)'."
-LangString DESC_s2_sub2_Section8 ${LANG_GERMAN} "Installiert das Lied 'Stay with me'."
-LangString DESC_s2_sub2_Section9 ${LANG_GERMAN} "Installiert das Lied 'Stay with me (Karaoke)'."
-
-LangString DESC_s2_sub3_Section1 ${LANG_GERMAN} "Installiert das Lied 'Lebendig und kräftig und schärfer'."
-LangString DESC_s2_sub3_Section2 ${LANG_GERMAN} "Installiert das Lied 'Mensch, wo bist du?'."
-
-LangString DESC_g3Section1 ${LANG_GERMAN} "Installiert das Motiv 'Orange' von Skar"
-LangString DESC_g3Section2 ${LANG_GERMAN} "Installiert das Motiv 'Streetlight' von Skar"
-LangString DESC_g3Section3 ${LANG_GERMAN} "Installiert das Motiv 'Vistar' von Skar"
-LangString DESC_g3Section4 ${LANG_GERMAN} "Installiert das Motiv 'BlueSensation v5.1' von Charis"
-LangString DESC_g3Section6 ${LANG_GERMAN} "Installiert das Motiv 'WiiStar' von MasterPhW"
-LangString DESC_g3Section7 ${LANG_GERMAN} "Installiert das Motiv 'iStar' von MezzoX"
-LangString DESC_g3Section5 ${LANG_GERMAN} "Installiert das Motiv 'WhiteSensation' von Charis" \ No newline at end of file
+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/cmake/installer/languages/Hungarian.nsh b/cmake/installer/languages/Hungarian.nsh
new file mode 100644
index 00000000..198251f6
--- /dev/null
+++ b/cmake/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/cmake/installer/languages/translations.txt b/cmake/installer/languages/translations.txt
new file mode 100644
index 00000000..9d5946e8
--- /dev/null
+++ b/cmake/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/cmake/installer/settings/GameExplorer.nsh b/cmake/installer/settings/GameExplorer.nsh
deleted file mode 100644
index d5056661..00000000
--- a/cmake/installer/settings/GameExplorer.nsh
+++ /dev/null
@@ -1,198 +0,0 @@
-# user interface
-
-!define GameExplorer_GenerateGUID '!insertmacro GameExplorer_GenerateGUID'
-!define GameExplorer_AddGame '!insertmacro GameExplorer_AddGame'
-!define GameExplorer_UpdateGame '!insertmacro GameExplorer_UpdateGame'
-!define GameExplorer_RemoveGame '!insertmacro GameExplorer_RemoveGame'
-
-# internal stuff
-
-!define CLSCTX_INPROC_SERVER 1
-!define IID_IGameExplorer {E7B2FB72-D728-49B3-A5F2-18EBF5F1349E}
-!define CLSID_GameExplorer {9A5EA990-3034-4D6F-9128-01F3C61022BC}
-
-!define GIS_CURRENT_USER 2
-!define GIS_ALL_USERS 3
-
-!define IGameExplorer_QueryInterface 0
-!define IGameExplorer_AddRef 1
-!define IGameExplorer_Release 2
-!define IGameExplorer_AddGame 3
-!define IGameExplorer_RemoveGame 4
-!define IGameExplorer_UpdateGame 5
-!define IGameExplorer_VerifyAccess 6
-
-# includes
-
-!include LogicLib.nsh
-
-# the actual code
-
-!macro GameExplorer_GenerateGUID
-
- System::Call 'ole32::CoCreateGuid(g .s)'
-
-!macroend
-
-!macro GameExplorer_AddGame CONTEXT GDF INSTDIR EXE GUID
-
- !define __GAME_EXPLORER_UNIQUE "${__LINE__}${__FILE__}"
-
- Push $0
- Push $1
-
- Push $R0
- Push $R1
- Push $R2
- Push $R3
-
- Push "${EXE}"
- Push "${GUID}"
- Push "${INSTDIR}"
- Push "${GDF}"
-
- Pop $R0 # == ${GDF}
- Pop $R1 # == ${INSTDIR}
- Pop $R2 # == ${GUID}
- Pop $R3 # == ${EXE}
-
- ClearErrors
-
- System::Call "ole32::CoCreateInstance( \
- g '${CLSID_GameExplorer}', i 0, \
- i ${CLSCTX_INPROC_SERVER}, \
- g '${IID_IGameExplorer}', *i .r1) i .r0"
-
- ${If} $0 != 0 # S_OK
-
- SetErrors
- Goto "done_${__GAME_EXPLORER_UNIQUE}"
-
- ${EndIf}
-
- !if ${CONTEXT} == all
-
- System::Call "$1->${IGameExplorer_AddGame}(w R0, w R1, i ${GIS_ALL_USERS}, g R2) i .r0"
-
- !else if ${CONTEXT} == user
-
- System::Call "$1->${IGameExplorer_AddGame}(w R1, w R0, i ${GIS_CURRENT_USER}, g R2) i .r0"
-
- !else
-
- !error "Invalid CONTEXT passed to GameExplorer_AddGame! Must be `user` or `all`."
-
- !endif
-
- ${If} $0 != 0 # S_OK
-
- SetErrors
-
- ${Else}
-
- # Create play task
-
- !if ${CONTEXT} == all
-
- SetShellVarContext all
-
- !else if if ${CONTEXT} == user
-
- SetShellVarContext user
-
- !endif
-
- CreateDirectory $APPDATA\Microsoft\Windows\GameExplorer\$R2\PlayTasks\0
- CreateShortcut $APPDATA\Microsoft\Windows\GameExplorer\$R2\PlayTasks\0\Play.lnk $R3
-
- ${EndIf}
-
- System::Call "$1->${IGameExplorer_Release}()"
-
- "done_${__GAME_EXPLORER_UNIQUE}:"
-
- Pop $R3
- Pop $R2
- Pop $R1
- Pop $R0
-
- Pop $1
- Pop $0
-
- !undef __GAME_EXPLORER_UNIQUE
-
-!macroend
-
-!macro _GameExplorer_GUID_Function Function GUID
-
- !define __GAME_EXPLORER_UNIQUE "${__LINE__}${__FILE__}"
-
- Push $0
- Push $1
- Push $2
- Push $3
- Push $4
- Push $5
-
- Push $R0
-
- Push "${GUID}"
-
- Pop $R0 # == ${GUID}
-
- System::Alloc 16
- Exch $R0
- System::Call "ole32::CLSIDFromString(w s, i R0)"
- System::Call "*$R0(i .r2, i .r3, i .r4, i .r5)"
- System::Free $R0
-
- ClearErrors
-
- System::Call "ole32::CoCreateInstance( \
- g '${CLSID_GameExplorer}', i 0, \
- i ${CLSCTX_INPROC_SERVER}, \
- g '${IID_IGameExplorer}', *i .r1) i .r0"
-
- ${If} $0 != 0 # S_OK
-
- SetErrors
- Goto "done_${__GAME_EXPLORER_UNIQUE}"
-
- ${EndIf}
-
- System::Call "$1->${Function}(i r2, i r3, i r4, i r5) i .r0"
-
- ${If} $0 != 0 # S_OK
-
- SetErrors
-
- ${EndIf}
-
- System::Call "$1->${IGameExplorer_Release}()"
-
- "done_${__GAME_EXPLORER_UNIQUE}:"
-
- Pop $R0
-
- Pop $5
- Pop $4
- Pop $3
- Pop $2
- Pop $1
- Pop $0
-
- !undef __GAME_EXPLORER_UNIQUE
-
-!macroend
-
-!macro GameExplorer_UpdateGame GUID
-
- !insertmacro _GameExplorer_GUID_Function ${IGameExplorer_UpdateGame} "${GUID}"
-
-!macroend
-
-!macro GameExplorer_RemoveGame GUID
-
- !insertmacro _GameExplorer_GUID_Function ${IGameExplorer_RemoveGame} "${GUID}"
-
-!macroend \ No newline at end of file
diff --git a/cmake/installer/settings/files_main_install.nsh b/cmake/installer/settings/files_main_install.nsh
index c2cdf727..a79d4991 100644
--- a/cmake/installer/settings/files_main_install.nsh
+++ b/cmake/installer/settings/files_main_install.nsh
@@ -2,55 +2,89 @@
; 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\Songs
-CreateDirectory $INSTDIR\Screenshots
-CreateDirectory $INSTDIR\Playlists
-CreateDirectory $INSTDIR\Covers
+CreateDirectory $INSTDIR\plugins
+CreateDirectory $INSTDIR\covers
+CreateDirectory $INSTDIR\songs
-SetOutPath "$INSTDIR"
+${If} ${AtLeastWinVista}
+
+ ; Create folders in appdata for current user
+ SetShellVarContext current
+ CreateDirectory $APPDATA\ultrastardx
+ CreateDirectory $APPDATA\ultrastardx\screenshots
+ CreateDirectory $APPDATA\ultrastardx\playlists
+
+ SetOutPath "$INSTDIR"
+
+ CreateShortCut "screenshots.lnk" "$APPDATA\ultrastardx\screenshots"
+ CreateShortCut "playlists.lnk" "$APPDATA\ultrastardx\playlists"
+ CreateShortCut "config.ini.lnk" "$APPDATA\ultrastardx\config.ini"
+
+ SetShellVarContext all
+${EndIf}
; themes, languages, sounds, fonts, visuals dir
-File /r ..\game\themes
-File /r ..\game\languages
-File /r ..\game\sounds
-File /r ..\game\fonts
-File /r ..\installerdependencies\visuals
+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 ..\installerdependencies\dll\*.dll
+File .\dependencies\dll\*.dll
File ..\ChangeLog.txt
-File ..\ChangeLog.german.txt
+File ..\ChangeLog.GERMAN.txt
+File ..\game\LuaCommands.odt
File ..\README.txt
-File ..\installerdependencies\documents\documentation.pdf
-File ..\installerdependencies\documents\license.txt
+File .\dependencies\documents\license.txt
+File .\dependencies\documents\documentation.pdf
-File "..\ScoreConverter.exe"
File "..\${exe}.exe"
; Covers dir:
-SetOutPath "$INSTDIR\Covers"
+SetOutPath "$INSTDIR\covers"
IfFileExists $INSTDIR\covers\covers.ini +2 0
-File ..\game\covers\Covers.ini
+File ..\game\covers\covers.ini
File ..\game\covers\NoCover.jpg
; Plugins dir:
-SetOutPath "$INSTDIR\Plugins\"
- File "..\Plugins\*.dll"
-
-${If} ${AtLeastWinVista}
-
- SetOutPath "$WINDIR"
- File "..\installerdependencies\plugins\gdf.dll"
-
-${EndIf}
+SetOutPath "$INSTDIR\plugins\"
+File "..\game\plugins\*.*"
-SetOutPath "$INSTDIR"
+SetOutPath "$INSTDIR" \ No newline at end of file
diff --git a/cmake/installer/settings/files_main_uninstall.nsh b/cmake/installer/settings/files_main_uninstall.nsh
index af61cb0b..ed2259bf 100644
--- a/cmake/installer/settings/files_main_uninstall.nsh
+++ b/cmake/installer/settings/files_main_uninstall.nsh
@@ -2,17 +2,16 @@
; 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
@@ -21,32 +20,41 @@
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\ChangeLog.GERMAN.txt"
+ Delete "$INSTDIR\ChangeLog.txt"
+ Delete "$INSTDIR\LuaCommands.odt"
Delete "$INSTDIR\documentation.pdf"
- Delete "$INSTDIR\License.txt"
- Delete "$INSTDIR\config.ini"
+ 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\covers.cache"
+ Delete "$INSTDIR\Benchmark.log"
Delete "$INSTDIR\cover.db"
- Delete "$INSTDIR\avcodec-51.dll"
- Delete "$INSTDIR\avformat-50.dll"
- Delete "$INSTDIR\avutil-49.dll"
+ 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\libfreetype-6.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"
@@ -54,29 +62,46 @@
Delete "$INSTDIR\SDL_image.dll"
Delete "$INSTDIR\SDL_ttf.dll"
Delete "$INSTDIR\sqlite3.dll"
+ Delete "$INSTDIR\swscale-0.dll"
Delete "$INSTDIR\zlib1.dll"
-${If} ${AtLeastWinVista}
- Delete "$WINDIR\gdf.dll"
-${EndIf}
+ StrCpy $0 "$INSTDIR\songs"
+ Call un.DeleteIfEmpty
+ StrCpy $0 "$INSTDIR\covers"
+ Call un.DeleteIfEmpty
- RMDir "$INSTDIR\songs\Dead Smiling Pirates - I 18"
- RMDir "$INSTDIR\songs\Joshua Morin - On The Run"
- RMDir "$INSTDIR\songs\Pornophonique - Space Invaders"
- RMDir "$INSTDIR\songs\Steven Dunston - Northern Star"
+ StrCpy $0 "$INSTDIR\screenshots"
+ Call un.DeleteIfEmpty
- StrCpy $0 "$INSTDIR\songs"
+ StrCpy $0 "$INSTDIR\playlists"
Call un.DeleteIfEmpty
- Delete "$INSTDIR\covers\NoCover.jpg"
+ ; Clean up AppData
- StrCpy $0 "$INSTDIR\screenshots"
+ 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 "$INSTDIR\playlists"
+ 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"
diff --git a/cmake/installer/settings/files_opt_songs.nsh b/cmake/installer/settings/files_opt_songs.nsh
new file mode 100644
index 00000000..d8d4ef28
--- /dev/null
+++ b/cmake/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/cmake/installer/settings/functions.nsh b/cmake/installer/settings/functions.nsh
index bbd4fea2..d437c9e1 100644
--- a/cmake/installer/settings/functions.nsh
+++ b/cmake/installer/settings/functions.nsh
@@ -2,11 +2,8 @@
; checked on Finish Page
Function CreateDesktopShortCuts
-
SetOutPath "$INSTDIR"
-
-CreateShortcut "$Desktop\$(sm_shortcut).lnk" "$INSTDIR\USdx.exe"
-
+CreateShortcut "$Desktop\$(sm_shortcut).lnk" "$INSTDIR\ultrastardx.exe"
FunctionEnd
; Deletes only empty dirs which are
@@ -27,30 +24,6 @@ Function un.DeleteIfEmpty
FindClose $R0
FunctionEnd
-; This is used to write a
-; string to config.ini
-
-Function WriteToConfig
- Exch $0
- Exch
- Exch $1
-
- FileOpen $0 $0 a
- FileSeek $0 0 END
- FileWrite $0 $1
- FileClose $0
-
- Pop $1
- Pop $0
-FunctionEnd
-
-!macro WriteToConfig String File
- Push "${String}"
- Push "${File}"
- Call WriteToConfig
-!macroend
-!define WriteToConfig "!insertmacro WriteToConfig"
-
; Finds UltraStar Deluxe process
;
@@ -74,126 +47,4 @@ FunctionEnd
!macro nsProcess::Unload
nsProcess::_Unload
-!macroend
-
-Function OnCheckbox
- GetDlgItem $R0 $HWNDPARENT 1
- Pop $0 # HWND
- ${NSD_GetState} $0 $1
- IntCmp $1 1 _Next _Close
- _Next:
- SendMessage $R0 ${WM_SETTEXT} 0 "STR:$(button_next)"
- goto _done
- _Close:
- SendMessage $R0 ${WM_SETTEXT} 0 "STR:$(button_close)"
- _done:
-FunctionEnd
-
-Function VersionCompare
- !define VersionCompare `!insertmacro VersionCompareCall`
-
- !macro VersionCompareCall _VER1 _VER2 _RESULT
- Push `${_VER1}`
- Push `${_VER2}`
- Call VersionCompare
- Pop ${_RESULT}
- !macroend
-
- Exch $1
- Exch
- Exch $0
- Exch
- Push $2
- Push $3
- Push $4
- Push $5
- Push $6
- Push $7
-
- begin:
- StrCpy $2 -1
- IntOp $2 $2 + 1
- StrCpy $3 $0 1 $2
- StrCmp $3 '' +2
- StrCmp $3 '.' 0 -3
- StrCpy $4 $0 $2
- IntOp $2 $2 + 1
- StrCpy $0 $0 '' $2
-
- StrCpy $2 -1
- IntOp $2 $2 + 1
- StrCpy $3 $1 1 $2
- StrCmp $3 '' +2
- StrCmp $3 '.' 0 -3
- StrCpy $5 $1 $2
- IntOp $2 $2 + 1
- StrCpy $1 $1 '' $2
-
- StrCmp $4$5 '' equal
-
- StrCpy $6 -1
- IntOp $6 $6 + 1
- StrCpy $3 $4 1 $6
- StrCmp $3 '0' -2
- StrCmp $3 '' 0 +2
- StrCpy $4 0
-
- StrCpy $7 -1
- IntOp $7 $7 + 1
- StrCpy $3 $5 1 $7
- StrCmp $3 '0' -2
- StrCmp $3 '' 0 +2
- StrCpy $5 0
-
- StrCmp $4 0 0 +2
- StrCmp $5 0 begin newer2
- StrCmp $5 0 newer1
- IntCmp $6 $7 0 newer1 newer2
-
- StrCpy $4 '1$4'
- StrCpy $5 '1$5'
- IntCmp $4 $5 begin newer2 newer1
-
- equal:
- StrCpy $0 0
- goto end
- newer1:
- StrCpy $0 1
- goto end
- newer2:
- StrCpy $0 2
-
- end:
- Pop $7
- Pop $6
- Pop $5
- Pop $4
- Pop $3
- Pop $2
- Pop $1
- Exch $0
-FunctionEnd
-
-Function ReadFileLine
-Exch $0 ;file
-Exch
-Exch $1 ;line number
-Push $2
-Push $3
-
- FileOpen $2 $0 r
- StrCpy $3 0
-
-Loop:
- IntOp $3 $3 + 1
- ClearErrors
- FileRead $2 $0
- IfErrors +2
- StrCmp $3 $1 0 loop
- FileClose $2
-
-Pop $3
-Pop $2
-Pop $1
-Exch $0
-FunctionEnd \ No newline at end of file
+!macroend \ No newline at end of file
diff --git a/cmake/installer/settings/settings-1031.ini b/cmake/installer/settings/settings-1031.ini
index 9e588fcb..7f9573a1 100644
--- a/cmake/installer/settings/settings-1031.ini
+++ b/cmake/installer/settings/settings-1031.ini
@@ -1,136 +1,161 @@
[Settings]
-NumFields=16
+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=0
-Right=53
-Top=27
-Bottom=35
+Left=5
+Right=58
+Top=30
+Bottom=38
[Field 2]
Type=Label
Text="Sprache:"
-Left=0
-Right=53
-Top=51
-Bottom=59
+Left=5
+Right=58
+Top=47
+Bottom=55
[Field 3]
Type=Label
Text="Auflösung:"
-Left=0
-Right=53
-Top=73
-Bottom=81
+Left=5
+Right=58
+Top=64
+Bottom=72
[Field 4]
Type=Label
Text="Ordnerstruktur:"
-Left=0
-Right=53
-Top=97
-Bottom=105
+Left=5
+Right=58
+Top=82
+Bottom=90
[Field 5]
-Type=Label
-Text="Animationen/Effekte:"
-Left=0
-Right=70
-Top=124
-Bottom=132
-
-[Field 6]
-Type=Droplist
+Type=DropList
ListItems=On|Off
State=On
-Left=71
-Right=161
-Top=25
-Bottom=38
+Left=62
+Right=152
+Top=28
+Bottom=39
-[Field 7]
-Type=Droplist
-ListItems=Catalan|Croatian|Danish|Dutch|English|Euskara|French|German|Italian|Norwegian|Polish|Portuguese|Serbian|Slovak|Spanish|Swedish
+[Field 6]
+Type=DropList
+ListItems=Catalan|Croatian|Dutch|English|Euskara|Finnish|French|German|Greek|Icelandic|Italian|Japanese|Luxembourgish|Portuguese|Spanish|Swedish
State=German
-Left=71
-Right=161
-Top=48
-Bottom=62
+Left=62
+Right=152
+Top=45
+Bottom=56
-[Field 8]
-Type=Droplist
+[Field 7]
+Type=DropList
ListItems=320x200|640x480|800x600|1024x768|1280x1024|1440x900|1680x1050|1920x1200
State=800x600
-Left=71
-Right=161
-Top=72
-Bottom=86
+Left=62
+Right=152
+Top=62
+Bottom=73
-[Field 9]
-Type=Droplist
+[Field 8]
+Type=DropList
ListItems=On|Off
State=Off
-Left=71
-Right=161
-Top=96
-Bottom=110
+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=Droplist
-ListItems=On|Off
-State=On
-Left=71
-Right=161
-Top=121
-Bottom=136
+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="Wähle aus, ob das Spiel im Fenster oder \r\nals Vollbild gestartet werden soll."
-Left=170
-Right=315
-Top=24
-Bottom=44
+Text=Passe die Sprache des Menüs an.
+Left=158
+Right=300
+Top=46
+Bottom=55
[Field 12]
Type=Label
-Text="Hier können einige Einstellungen für UltraStar Deluxe vorgenommen werden.\r\nAlle Einstellungen können später im Spielmenü geändert werden."
-Left=0
-Right=315
-Top=3
-Bottom=20
+Text=Wähle die Auflösung/Fenstergröße aus.
+Left=157
+Right=300
+Top=64
+Bottom=72
[Field 13]
Type=Label
-Text="Wähle deine favorisierte Sprache, in der UltraStar Deluxe angezeigt werden soll."
-Left=170
-Right=315
-Top=46
-Bottom=68
+Text=Eine virtuelle Ordnerstruktur zum Anzeigen der Lieder verwenden?
+Left=158
+Right=300
+Top=78
+Bottom=94
[Field 14]
Type=Label
-Text="Wähle deine, dem Monitor angepasste, bevorzugte Auflösung."
-Left=170
-Right=315
-Top=70
-Bottom=96
+Left=5
+Top=100
+Right=58
+Bottom=109
+Text=Sortierung:
[Field 15]
-Type=Label
-Text="Wähle aus, ob UltraStar Deluxe eine Ordnerstruktur zum Anzeigen der Lieder verwenden soll."
-Left=170
-Right=315
-Top=92
-Bottom=116
+Type=DropList
+Left=62
+Top=100
+Right=152
+Bottom=111
+State=Artist
+ListItems=Edition|Genre|Language|Folder|Title|Artist
[Field 16]
Type=Label
-Text="Wähle, ob Spezialeffekte und \r\nAnimationen benutzt werden sollen."
-Left=170
-Right=315
+Left=157
+Top=101
+Right=300
+Bottom=110
+Text=Kriterium zum Sortieren der Lieder wählen.
+
+[Field 18]
+Type=DirRequest
+Left=5
Top=121
-Bottom=137
+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/cmake/installer/settings/settings-1033.ini b/cmake/installer/settings/settings-1033.ini
index 17a08a8c..5e6b6055 100644
--- a/cmake/installer/settings/settings-1033.ini
+++ b/cmake/installer/settings/settings-1033.ini
@@ -1,136 +1,161 @@
[Settings]
-NumFields=16
+NumFields=19
+
+; Background Group of Settings Box
+[Field 17]
+Type=GroupBox
+Left=1
+Top=1
+Right=300
+Bottom=140
+Text=UltraStar Deluxe Konfiguration (Optional)
[Field 1]
Type=Label
Text="Fullscreen Mode:"
-Left=0
-Right=50
-Top=27
-Bottom=35
+Left=5
+Right=58
+Top=30
+Bottom=38
[Field 2]
Type=Label
Text="Language:"
-Left=0
-Right=50
-Top=51
-Bottom=59
+Left=5
+Right=58
+Top=47
+Bottom=55
[Field 3]
Type=Label
Text="Resolution:"
-Left=0
-Right=50
-Top=73
-Bottom=81
+Left=5
+Right=58
+Top=64
+Bottom=72
[Field 4]
Type=Label
Text="Tabs:"
-Left=0
-Right=50
-Top=100
-Bottom=108
+Left=5
+Right=58
+Top=82
+Bottom=90
[Field 5]
-Type=Label
-Text="Animations/Effects:"
-Left=0
-Right=67
-Top=124
-Bottom=132
-
-[Field 6]
-Type=Droplist
+Type=DropList
ListItems=On|Off
State=On
-Left=70
-Right=160
-Top=24
-Bottom=36
+Left=62
+Right=152
+Top=28
+Bottom=39
-[Field 7]
-Type=Droplist
-ListItems=Catalan|Croatian|Danish|Dutch|English|Euskara|French|German|Italian|Norwegian|Polish|Portuguese|Serbian|Slovak|Spanish|Swedish
-State=English
-Left=70
-Right=160
-Top=48
-Bottom=60
+[Field 6]
+Type=DropList
+ListItems=Catalan|Croatian|Dutch|English|Euskara|Finnish|French|German|Greek|Icelandic|Italian|Japanese|Luxembourgish|Portuguese|Spanish|Swedish
+State=German
+Left=62
+Right=152
+Top=45
+Bottom=56
-[Field 8]
-Type=Droplist
+[Field 7]
+Type=DropList
ListItems=320x200|640x480|800x600|1024x768|1280x1024|1440x900|1680x1050|1920x1200
State=800x600
-Left=70
-Right=160
-Top=72
-Bottom=86
+Left=62
+Right=152
+Top=62
+Bottom=73
-[Field 9]
-Type=Droplist
+[Field 8]
+Type=DropList
ListItems=On|Off
State=Off
-Left=70
-Right=160
-Top=99
-Bottom=113
+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=Droplist
-ListItems=On|Off
-State=On
-Left=70
-Right=160
-Top=123
-Bottom=137
+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="Choose if you want to run UltraStar Deluxe in a window or fullscreen."
-Left=170
-Right=305
-Top=25
-Bottom=46
+Text=Adjust the GUI language.
+Left=158
+Right=300
+Top=46
+Bottom=55
[Field 12]
Type=Label
-Text="Choose your favorite language, in that UltraStar Deluxe should be displayed."
-Left=170
-Right=305
-Top=48
-Bottom=70
+Text=Choose screen resolution/window size.
+Left=157
+Right=300
+Top=64
+Bottom=72
[Field 13]
Type=Label
-Text="Choose your favorite screen resolution for UltraStar Deluxe adjusted to your display device."
-Left=170
-Right=305
-Top=72
-Bottom=97
+Text=Employ a virtual folder structure to show songs?
+Left=158
+Right=300
+Top=78
+Bottom=94
[Field 14]
Type=Label
-Text="Choose whether you would like to view folders in UltraStar Deluxe or not."
-Left=170
-Right=305
-Top=99
-Bottom=122
+Left=5
+Top=100
+Right=58
+Bottom=109
+Text=Sorting:
[Field 15]
-Type=Label
-Text="Here you can define some settings for UltraStar Deluxe. The settings can\r\nalso be changed in the GUI later."
-Left=0
-Right=289
-Top=3
-Bottom=20
+Type=DropList
+Left=62
+Top=100
+Right=152
+Bottom=111
+State=Artist
+ListItems=Edition|Genre|Language|Folder|Title|Artist
[Field 16]
Type=Label
-Text="Choose if special effects or animations should be used by UltraStar Deluxe. Recommended: On"
-Left=170
-Right=305
-Top=123
-Bottom=139
+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/cmake/installer/settings/settings-1038.ini b/cmake/installer/settings/settings-1038.ini
new file mode 100644
index 00000000..62994a1f
--- /dev/null
+++ b/cmake/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 Konfiguration (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|Dutch|English|Euskara|Finnish|French|German|Greek|Icelandic|Italian|Japanese|Luxembourgish|Portuguese|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=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/cmake/installer/settings/variables.nsh b/cmake/installer/settings/variables.nsh
index db98d89f..5d79e115 100644
--- a/cmake/installer/settings/variables.nsh
+++ b/cmake/installer/settings/variables.nsh
@@ -4,17 +4,18 @@
; Product Information:
-!define version "1.1a" ; Make sure version is also set in onInit
+!define version "1.1beta" ; 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 "USdx"
+!define exe "ultrastardx"
-!define license "..\installerdependencies\documents\license.txt"
+!define license ".\dependencies\documents\license.txt"
; Icons
@@ -34,15 +35,16 @@
!define PRODUCT_WEB_SITE "${homepage}"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${name}"
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
-!define PRODUCT_STARTMENU_REGVAL "NSIS:StartMenuDir"
; 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_song1 "http://downloads.sourceforge.net/ultrastardx/usdx_song-bodo_wartke_-_liebeslied.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"
@@ -81,11 +83,7 @@
!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"
-!define download_theme1 "http://downloads.sourceforge.net/ultrastardx/usdx_skin-orange_by_Skar.zip"
-!define download_theme2 "http://downloads.sourceforge.net/ultrastardx/usdx_skin-Streetlight_by_Skar.zip"
-!define download_theme3 "http://downloads.sourceforge.net/ultrastardx/usdx_skin-Vistar_by_Skar.zip"
-!define download_theme4 "http://downloads.sourceforge.net/ultrastardx/usdx_skin-bluesensationV5.1_by_Charis.zip"
-!define download_theme6 "http://downloads.sourceforge.net/ultrastardx/usdx_skin-WiiStar_by_MasterPhW.zip"
-!define download_theme7 "http://downloads.sourceforge.net/ultrastardx/usdx_skin-istar_by_MezzoX.zip"
-!define download_theme5 "http://downloads.sourceforge.net/ultrastardx/usdx_skin-whitesensationV101_by_Charis.zip" \ No newline at end of file
+; THEMES
+; (removed theme section - currently no additional skins available for this usdx version) \ No newline at end of file
diff --git a/cmake/installerdependencies/images/uninstall.ico b/cmake/installer/uninstall.ico
index 1c72432a..1c72432a 100644
--- a/cmake/installerdependencies/images/uninstall.ico
+++ b/cmake/installer/uninstall.ico
Binary files differ
diff --git a/cmake/installerdependencies/images/install.ico b/cmake/installerdependencies/images/install.ico
deleted file mode 100644
index af1b9372..00000000
--- a/cmake/installerdependencies/images/install.ico
+++ /dev/null
Binary files differ
diff --git a/cmake/installerdependencies/plugins/gdf.dll b/cmake/installerdependencies/plugins/gdf.dll
deleted file mode 100644
index e3400051..00000000
--- a/cmake/installerdependencies/plugins/gdf.dll
+++ /dev/null
Binary files differ
diff --git a/cmake/plugins/5000Points/CMakeLists.txt b/cmake/plugins/5000Points/CMakeLists.txt
deleted file mode 100644
index ecc89b00..00000000
--- a/cmake/plugins/5000Points/CMakeLists.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-# $URL$
-# $Id$
-pascal_add_module(until5000 Until5000.dpr OUTPUT_DIR ${USDX_PLUGIN_DIR} EXCLUDE_FROM_ALL)
-add_dependencies(plugins until5000)
diff --git a/cmake/plugins/5000Points/Until5000.dpr b/cmake/plugins/5000Points/Until5000.dpr
deleted file mode 100644
index 83bc1007..00000000
--- a/cmake/plugins/5000Points/Until5000.dpr
+++ /dev/null
@@ -1,104 +0,0 @@
-library Until5000;
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-uses
- ModiSDK in '..\SDK\ModiSDK.pas';
-
-// give the plugin's info
-procedure PluginInfo (var Info: TPluginInfo); {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-begin
- Info.Name := 'PLUGIN_UNTIL5000_NAME';
-
- Info.Creator := 'Whiteshark';
- Info.PluginDesc := 'PLUGIN_UNTIL5000_DESC';
-
- // set to party modus plugin
- Info.Typ := 8;
-
- Info.NumPlayers := 31;
- // options
- Info.LoadSong := true; // whether or not a song should be loaded
- // only when song is loaded:
- Info.ShowScore := true; // whether or not the score should be shown
- Info.ShowNotes := true; // whether the note lines should be displayed
- Info.LoadVideo := true; // should the video be loaded?
- Info.LoadBack := true; // should the background be loaded?
-
- Info.BGShowFull := false; // whether the background or the video should be shown full size
- Info.BGShowFull_O := true; // whether the background or the video should be shown full size
-
- Info.ShowRateBar := true; // whether the bar that shows how good the player was should be displayed
- Info.ShowRateBar_O := true; // load from ini whether the bar should be displayed
-
- Info.EnLineBonus := false; // whether line bonus should be enabled
- Info.EnLineBonus_O := true; // load from ini whether line bonus should be enabled
-
- // options even when song is not loaded
- Info.ShowBars := false; // whether the white bars on top and bottom should be drawn
- Info.TeamModeOnly := false; // if true the plugin can only be played in team mode
- Info.GetSoundData := false; // if true the rdata procedure is called when new sound data is available
- Info.Dummy := false; // should be set to false... for updateing plugin interface
-end;
-
-// executed on game start; if true game begins, else failure
-function Init (const TeamInfo: TTeamInfo;
- var Playerinfo: TPlayerinfo;
- const Sentences: TSentences;
- const Methods: TMethodRec)
- : boolean; {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-begin
- Result := true;
-end;
-
-// executed everytime the screen is drawn; if false the game finishes
-function Draw (var Playerinfo: TPlayerinfo;
- const CurSentence: cardinal)
- : boolean; {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-var
- Index: integer;
-begin
- Result := false;
- for Index := 0 to PlayerInfo.NumPlayers-1 do
- begin
- PlayerInfo.Playerinfo[Index].Bar := PlayerInfo.Playerinfo[Index].Score div 50;
- PlayerInfo.Playerinfo[Index].Percentage := PlayerInfo.Playerinfo[Index].Bar;
- if (PlayerInfo.Playerinfo[Index].Score >= 5000) then
- Exit;
- end;
- Result := true;
-end;
-
-// is executed on finish, returns the player number of the winner
-function Finish (var Playerinfo: TPlayerinfo): byte; {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-var
- Index: integer;
-begin
- Result := 0;
- for Index := 0 to PlayerInfo.NumPlayers-1 do
- begin
- if (PlayerInfo.Playerinfo[Index].Score >= 5000) then
- begin
- case Index of
- 0: Result := Result or 1;
- 1: Result := Result or 2;
- 2: Result := Result or 4;
- 3: Result := Result or 8;
- 4: Result := Result or 16;
- 5: Result := Result or 32;
- end;
- end;
- end;
-end;
-
-exports
- PluginInfo,
- Init,
- Draw,
- Finish;
-
-begin
-
-end. \ No newline at end of file
diff --git a/cmake/plugins/Blind/Blind.dpr b/cmake/plugins/Blind/Blind.dpr
deleted file mode 100644
index 3c68374c..00000000
--- a/cmake/plugins/Blind/Blind.dpr
+++ /dev/null
@@ -1,112 +0,0 @@
-library Blind;
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-uses
- ModiSDK in '..\SDK\ModiSDK.pas';
-
-// give the plugin's info
-procedure PluginInfo (var Info: TPluginInfo); {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-begin
- Info.Name := 'PLUGIN_BLIND_NAME';
- Info.Creator := 'Whiteshark';
- Info.PluginDesc := 'PLUGIN_BLIND_DESC';
-
- // set to party modus plugin
- Info.Typ := 8;
-
- Info.NumPlayers := 31;
-
- // options
- Info.LoadSong := true; // whether or not a song should be loaded
- // only when song is loaded:
- Info.ShowScore := true; // whether or not the score should be shown
- Info.ShowNotes := false; // whether the note lines should be displayed
- Info.LoadVideo := true; // should the video be loaded?
- Info.LoadBack := true; // should the background be loaded?
-
- Info.BGShowFull := false; // whether the background or the video should be shown in full size
- Info.BGShowFull_O := true; // whether the background or the video should be shown in full size
-
- Info.ShowRateBar := false; // whether the bar that shows how good the player was should be displayed
- Info.ShowRateBar_O := true; // load from ini whether the bar should be displayed
-
- Info.EnLineBonus := false; // whether line bonus should be enabled
- Info.EnLineBonus_O := true; // load from ini whether line bonus should be enabled
-
- // options even when song is not loaded
- Info.ShowBars := false; // whether the white bars on top and bottom should be drawn
- Info.TeamModeOnly := false; // if true the plugin can only be played in team mode
- Info.GetSoundData := false; // if true the rdata procedure is called when new sound data is available
- Info.Dummy := false; // should be set to false... for updating plugin interface
-end;
-
-// executed on game start. if true game begins, else failure
-function Init (const TeamInfo: TTeamInfo;
- var Playerinfo: TPlayerinfo;
- const Sentences: TSentences;
- const Methods: TMethodRec)
- : boolean; {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-begin
- Result := true;
-end;
-
-// executed every time the screen is drawn. if false the game finishes
-function Draw (var Playerinfo: TPlayerinfo;
- const CurSentence: cardinal)
- : boolean; {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-begin
- Result := true;
-end;
-
-// is executed on finish, returns the player number of the winner
-function Finish (var Playerinfo: TPlayerinfo): byte; {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-var
- Index: integer;
- MaxScore: word;
-begin
- Result := 0;
- MaxScore := 0;
- for Index := 0 to PlayerInfo.NumPlayers - 1 do
- begin
- PlayerInfo.Playerinfo[Index].Percentage := PlayerInfo.Playerinfo[Index].Score div 9999;
- if (PlayerInfo.Playerinfo[Index].Score > MaxScore) then
- begin
- MaxScore := PlayerInfo.Playerinfo[Index].Score;
- case Index of
- 0: Result := 1;
- 1: Result := 2;
- 2: Result := 4;
- 3: Result := 8;
- 4: Result := 16;
- 5: Result := 32;
- end;
- end
- else if (PlayerInfo.Playerinfo[Index].Score = MaxScore) and (PlayerInfo.Playerinfo[Index].Score <> 0) then
- begin
- case Index of
- 0: Result := Result or 1;
- 1: Result := Result or 2;
- 2: Result := Result or 4;
- 3: Result := Result or 8;
- 4: Result := Result or 16;
- 5: Result := Result or 32;
- end;
- end;
- end;
- // if everybody has 0 points nobody wins
- if (MaxScore = 0) then
- Result := 0;
-end;
-
-exports
- PluginInfo,
- Init,
- Draw,
- Finish;
-
-begin
-
-end. \ No newline at end of file
diff --git a/cmake/plugins/Blind/CMakeLists.txt b/cmake/plugins/Blind/CMakeLists.txt
deleted file mode 100644
index 350ba13e..00000000
--- a/cmake/plugins/Blind/CMakeLists.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-# $URL$
-# $Id$
-pascal_add_module(blind Blind.dpr OUTPUT_DIR ${USDX_PLUGIN_DIR} EXCLUDE_FROM_ALL)
-add_dependencies(plugins blind)
diff --git a/cmake/plugins/CMakeLists.txt b/cmake/plugins/CMakeLists.txt
deleted file mode 100644
index d7cd8ae6..00000000
--- a/cmake/plugins/CMakeLists.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-# $URL$
-# $Id$
-
-# create an option to exclude plugins target from ALL target
-option(BUILD_PLUGINS "Build UltraStar Deluxe party-mode plugins." ON)
-set(plugins_tgt_all)
-if(BUILD_PLUGINS)
- set(plugins_tgt_all ALL)
-endif(BUILD_PLUGINS)
-# create a plugins target
-add_custom_target(plugins ${plugins_tgt_all})
-
-# add plugins to target
-add_subdirectory(5000Points)
-add_subdirectory(Blind)
-add_subdirectory(Duell)
-add_subdirectory(Dont_Get_Worse)
-add_subdirectory(Team_Duell)
diff --git a/cmake/plugins/Dont_Get_Worse/CMakeLists.txt b/cmake/plugins/Dont_Get_Worse/CMakeLists.txt
deleted file mode 100644
index 5a3f6c24..00000000
--- a/cmake/plugins/Dont_Get_Worse/CMakeLists.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-# $URL$
-# $Id$
-pascal_add_module(hold_the_line Hold_The_Line.dpr
- OUTPUT_DIR ${USDX_PLUGIN_DIR}
- PACKAGES sdl opengl
- EXCLUDE_FROM_ALL
-)
-add_dependencies(plugins hold_the_line)
diff --git a/cmake/plugins/Dont_Get_Worse/Hold_The_Line.bdsproj b/cmake/plugins/Dont_Get_Worse/Hold_The_Line.bdsproj
deleted file mode 100644
index 8694fb50..00000000
--- a/cmake/plugins/Dont_Get_Worse/Hold_The_Line.bdsproj
+++ /dev/null
@@ -1,175 +0,0 @@
-<?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">{06A9B812-7EBB-46A7-A56A-6DE18E64E79D}</Option>
- </Option>
- </PersonalityInfo>
- <Delphi.Personality>
- <Source>
- <Source Name="MainSource">Hold_The_Line.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">..\..\src\lib\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/cmake/plugins/Dont_Get_Worse/Hold_The_Line.dpr b/cmake/plugins/Dont_Get_Worse/Hold_The_Line.dpr
deleted file mode 100644
index a7828f8e..00000000
--- a/cmake/plugins/Dont_Get_Worse/Hold_The_Line.dpr
+++ /dev/null
@@ -1,227 +0,0 @@
-library Hold_The_Line;
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-uses
- SysUtils,
- ModiSDK in '..\SDK\ModiSDK.pas',
- gl in '..\..\src\lib\JEDI-SDL\OpenGL\Pas\gl.pas';
-
-var
- PointerTex: TSmallTexture;
- CountSentences: cardinal;
- Limit: byte;
- MethodRec: TMethodRec;
-// Frame: integer;
- PlayerTimes: array[0..5] of integer;
- LastTick: cardinal;
- PointerVisible: boolean;
-
- DismissedSound: cardinal;
-
-// Give the plugin's info
-procedure PluginInfo (var Info: TPluginInfo); {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-begin
- Info.Name := 'PLUGIN_HDL_NAME';
-
- Info.Creator := 'Whiteshark';
- Info.PluginDesc := 'PLUGIN_HDL_DESC';
-
- // Set to Party Modi Plugin
- Info.Typ := 8;
-
- Info.NumPlayers := 31;
- // Options
- Info.LoadSong := true; // Whether or not a song should be loaded
- // Only when song is loaded:
- Info.ShowScore := true; // Whether or not the score should be shown
- Info.ShowNotes := true; // Whether the note lines should be displayed
- Info.LoadVideo := true; // Should the video be loaded?
- Info.LoadBack := true; // Should the background be loaded?
-
- Info.BGShowFull := false; // Whether the background or the video should be shown full size
- Info.BGShowFull_O := true; // Whether the Background or the Video should be shown full size
-
- Info.ShowRateBar := true; // Whether the bar that shows how good the player was should be displayed
- Info.ShowRateBar_O := false; // Load from ini whether the bar should be displayed
-
- Info.EnLineBonus := false; // Whether line bonus should be enabled
- Info.EnLineBonus_O := true; // Load from ini whether line bonus should be enabled
-
- // Options even when song is not loaded
- Info.ShowBars := false; // Whether the white bars on top and bottom should be drawn
- Info.TeamModeOnly := false; // if true the plugin can only be played in team mode
- Info.GetSoundData := false; // if true the rdata procedure is called when new sound data is available
- Info.Dummy := false; // Should be set to false... for updating plugin interface
-end;
-
-// executed on game start. if true game begins, else failure
-function Init (const TeamInfo: TTeamInfo;
- var Playerinfo: TPlayerinfo;
- const Sentences: TSentences;
- const Methods: TMethodRec)
- : boolean; {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-
-const
- TextureName : PChar = 'HDL_Pointer';
- SoundName : PChar = 'dismissed.mp3';
-var
- Index: integer;
-// Texname: PChar;
- TexType: TTextureType;
-begin
-{
- TexName := CreateStr(PChar('HDL_Pointer'));
- TexType := TEXTURE_TYPE_TRANSPARENT;
- PointerTex := Methods.LoadTex(TexName, TexType);
-
- FreeStr(TexName);
-
- TexName := CreateStr(PChar('dismissed.mp3'));
- DismissedSound := Methods.LoadSound (TexName);
- FreeStr(TexName);
-}
- TexType := TEXTURE_TYPE_TRANSPARENT;
- PointerTex := Methods.LoadTex(TextureName, TexType);
-
- DismissedSound := Methods.LoadSound (SoundName);
-
- CountSentences := Sentences.High;
- Limit := 0;
-// Frame := 0;
-
- MethodRec := Methods;
-
- for Index := 0 to PlayerInfo.NumPlayers-1 do
- begin
- PlayerInfo.Playerinfo[Index].Enabled := true;
- PlayerInfo.Playerinfo[Index].Percentage := 100;
- PlayerTimes[Index] := 0;
- end;
-
- Result := true;
-end;
-
-function Draw (var Playerinfo: TPlayerinfo;
- const CurSentence: cardinal)
- : boolean; {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-const
- SoundName : PChar = 'PARTY_DISMISSED';
-var
- Index: integer;
- L: byte;
- C: byte;
- Tick: cardinal;
-begin
- // activate blink
- if (CurSentence = CountSentences div 5 * 2 - 1) or (CurSentence = CountSentences div 3 * 2 - 1) then
- begin
- Tick := round(TimeStampToMSecs(DateTimeToTimeStamp(Now))) div 400;
- if (Tick <> LastTick) then
- begin
- LastTick := Tick;
- PointerVisible := not PointerVisible;
- end;
- end
- else
- PointerVisible := true;
-
- // inc limit
- if (Limit = 0) and (CurSentence >= CountSentences div 5 * 2) then
- Inc(Limit)
- else if (Limit = 1) and (CurSentence >= CountSentences div 3 * 2) then
- Inc(Limit);
-
- case Limit of
- 0: L := 20;
- 1: L := 50;
- 2: L := 75;
- end;
-
- C:= 0;
-
- Result := true;
-
- for Index := 0 to PlayerInfo.NumPlayers-1 do
- begin
- if PlayerInfo.Playerinfo[Index].Enabled then
- begin
- if PlayerInfo.Playerinfo[Index].Bar < L then
- begin
- PlayerInfo.Playerinfo[Index].Enabled := false;
- Inc(C);
- PlayerTimes[Index] := CurSentence; // Save Time of Dismission
- // PlaySound
- MethodRec.PlaySound (DismissedSound);
- end;
-
- // Draw pointer
- if (PointerVisible) then
- begin
- glColor4f (0.2, 0.8, 0.1, 1);
-
- glEnable(GL_TEXTURE_2D);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- glBindTexture(GL_TEXTURE_2D, PointerTex.TexNum);
-
- glBegin(GL_QUADS);
- glTexCoord2f(1/32, 0); glVertex2f(PlayerInfo.Playerinfo[Index].PosX + L - 3, PlayerInfo.Playerinfo[Index].PosY - 4);
- glTexCoord2f(1/32, 1); glVertex2f(PlayerInfo.Playerinfo[Index].PosX + L - 3, PlayerInfo.Playerinfo[Index].PosY + 12);
- glTexCoord2f(31/32, 1); glVertex2f(PlayerInfo.Playerinfo[Index].PosX+ L + 3, PlayerInfo.Playerinfo[Index].PosY + 12);
- glTexCoord2f(31/32, 0); glVertex2f(PlayerInfo.Playerinfo[Index].PosX+ L + 3, PlayerInfo.Playerinfo[Index].PosY - 4);
- glEnd;
-
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_BLEND);
- end;
-
- end
- else
- begin
- Inc(C);
- // Draw dismissed
- glColor4f (0.8, 0.8, 0.8, 1);
- MethodRec.Print (1, 18, PlayerInfo.Playerinfo[Index].PosX, PlayerInfo.Playerinfo[Index].PosY-8, SoundName);
- end;
- end;
- if (C >= PlayerInfo.NumPlayers-1) then
- Result := false;
-end;
-
-// is executed on finish, returns the player number of the winner
-function Finish (var Playerinfo: TPlayerinfo): byte; {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-var
- Index: integer;
-begin
- Result := 0;
- for Index := 0 to PlayerInfo.NumPlayers-1 do
- begin
- PlayerInfo.Playerinfo[Index].Percentage := (PlayerTimes[Index] * 100) div CountSentences;
- if (PlayerInfo.Playerinfo[Index].Enabled) then
- begin
- PlayerInfo.Playerinfo[Index].Percentage := 100;
- case Index of
- 0: Result := Result or 1;
- 1: Result := Result or 2;
- 2: Result := Result or 4;
- 3: Result := Result or 8;
- 4: Result := Result or 16;
- 5: Result := Result or 32;
- end;
- end;
- end;
-end;
-
-exports
- PluginInfo,
- Init,
- Draw,
- Finish;
-
-begin
-
-end.
diff --git a/cmake/plugins/Dont_Get_Worse/Hold_The_Line.lpi b/cmake/plugins/Dont_Get_Worse/Hold_The_Line.lpi
deleted file mode 100644
index bb21d5d9..00000000
--- a/cmake/plugins/Dont_Get_Worse/Hold_The_Line.lpi
+++ /dev/null
@@ -1,108 +0,0 @@
-<?xml version="1.0"?>
-<CONFIG>
- <ProjectOptions>
- <PathDelim Value="\"/>
- <Version Value="6"/>
- <General>
- <Flags>
- <MainUnitHasUsesSectionForAllUnits Value="False"/>
- <MainUnitHasCreateFormStatements Value="False"/>
- <MainUnitHasTitleStatement Value="False"/>
- </Flags>
- <MainUnit Value="0"/>
- <TargetFileExt Value=".exe"/>
- <Title Value="Hold_The_Line"/>
- <ActiveEditorIndexAtStart Value="2"/>
- </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>
- <Units Count="4">
- <Unit0>
- <Filename Value="Hold_The_Line.dpr"/>
- <IsPartOfProject Value="True"/>
- <UnitName Value="Hold_The_Line"/>
- <CursorPos X="22" Y="1"/>
- <TopLine Value="1"/>
- <EditorIndex Value="0"/>
- <UsageCount Value="20"/>
- <Loaded Value="True"/>
- </Unit0>
- <Unit1>
- <Filename Value="..\SDK\StrUtils.pas"/>
- <UnitName Value="StrUtils"/>
- <CursorPos X="4" Y="13"/>
- <TopLine Value="1"/>
- <EditorIndex Value="2"/>
- <UsageCount Value="10"/>
- <Loaded Value="True"/>
- </Unit1>
- <Unit2>
- <Filename Value="..\..\src\lib\JEDI-SDL\OpenGL\Pas\gl.pas"/>
- <UnitName Value="gl"/>
- <CursorPos X="1" Y="1"/>
- <TopLine Value="1"/>
- <UsageCount Value="10"/>
- </Unit2>
- <Unit3>
- <Filename Value="..\SDK\ModiSDK.pas"/>
- <UnitName Value="ModiSDK"/>
- <CursorPos X="1" Y="8"/>
- <TopLine Value="1"/>
- <EditorIndex Value="1"/>
- <UsageCount Value="10"/>
- <Loaded Value="True"/>
- </Unit3>
- </Units>
- <JumpHistory Count="1" HistoryIndex="0">
- <Position1>
- <Filename Value="..\SDK\StrUtils.pas"/>
- <Caret Line="1" Column="1" TopLine="1"/>
- </Position1>
- </JumpHistory>
- </ProjectOptions>
- <CompilerOptions>
- <Version Value="8"/>
- <PathDelim Value="\"/>
- <SearchPaths>
- <IncludeFiles Value="..\..\src\lib\JEDI-SDL\SDL\Pas\"/>
- </SearchPaths>
- <Parsing>
- <SyntaxOptions>
- <CStyleOperator Value="False"/>
- </SyntaxOptions>
- </Parsing>
- <Linking>
- <Options>
- <ExecutableType Value="Library"/>
- </Options>
- </Linking>
- <Other>
- <CompilerPath Value="$(CompPath)"/>
- </Other>
- </CompilerOptions>
- <Debugging>
- <Exceptions Count="2">
- <Item1>
- <Name Value="ECodetoolError"/>
- </Item1>
- <Item2>
- <Name Value="EFOpenError"/>
- </Item2>
- </Exceptions>
- </Debugging>
-</CONFIG>
diff --git a/cmake/plugins/Dont_Get_Worse/dismissed.mp3 b/cmake/plugins/Dont_Get_Worse/dismissed.mp3
deleted file mode 100644
index f478e7a3..00000000
--- a/cmake/plugins/Dont_Get_Worse/dismissed.mp3
+++ /dev/null
Binary files differ
diff --git a/cmake/plugins/Duell/CMakeLists.txt b/cmake/plugins/Duell/CMakeLists.txt
deleted file mode 100644
index d1a40730..00000000
--- a/cmake/plugins/Duell/CMakeLists.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-# $URL$
-# $Id$
-pascal_add_module(duell Duell.dpr OUTPUT_DIR ${USDX_PLUGIN_DIR} EXCLUDE_FROM_ALL)
-add_dependencies(plugins duell)
diff --git a/cmake/plugins/Duell/Duell.dpr b/cmake/plugins/Duell/Duell.dpr
deleted file mode 100644
index f54edea8..00000000
--- a/cmake/plugins/Duell/Duell.dpr
+++ /dev/null
@@ -1,106 +0,0 @@
-library Duell;
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-uses
- ModiSDK in '..\SDK\ModiSDK.pas';
-
-//Gave the Plugins Info
-procedure PluginInfo (var Info: TPluginInfo); {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-begin
- Info.Name := 'PLUGIN_DUELL_NAME';
-
- Info.Creator := 'Whiteshark';
- Info.PluginDesc := 'PLUGIN_DUELL_DESC';
-
- Info.Typ := 8;
-
- Info.NumPlayers := 31;
- //Options
- Info.LoadSong := True; //Whether or not a Song should be Loaded
- //Only When Song is Loaded:
- Info.ShowScore := True; //Whether or not the Score should be shown
- Info.ShowNotes := True; //Whether the Note Lines should be displayed
- Info.LoadVideo := True; //Should the Video be loaded ?
- Info.LoadBack := True; //Should the Background be loaded ?
-
- Info.BGShowFull := False; //Whether the Background or the Video should be shown Fullsize
- Info.BGShowFull_O := True; //Whether the Background or the Video should be shown Fullsize
-
- Info.ShowRateBar := False; //Whether the Bar that shows how good the player was sould be displayed
- Info.ShowRateBar_O := True; //Load from Ini whether the Bar should be Displayed
-
- Info.EnLineBonus := False; //Whether LineBonus Should be enabled
- Info.EnLineBonus_O := True; //Load from Ini whether LineBonus Should be enabled
-
- //Options even when song is Not loaded
- Info.ShowBars := False; //Whether the White Bars on Top and Bottom should be Drawn
- Info.TeamModeOnly := False; //If True the Plugin can only be Played in Team Mode
- Info.GetSoundData := False; //If True the RData Procedure is called when new SoundData is available
- Info.Dummy := False; //Should be Set to False... for Updateing Plugin Interface
-end;
-
-//Executed on Game Start //If True Game begins, else Failure
-function Init (const TeamInfo: TTeamInfo; var Playerinfo: TPlayerinfo; const Sentences: TSentences; const Methods: TMethodRec): boolean; {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-begin
- Result := True;
-end;
-
-//Executed everytime the Screen is Drawed //If False The Game finishes
-function Draw (var Playerinfo: TPlayerinfo; const CurSentence: Cardinal): boolean; {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-begin
- Result := True;
-end;
-
-//Is Executed on Finish, Returns the Playernum of the Winner
-function Finish (var Playerinfo: TPlayerinfo): byte; {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-var
- I: Integer;
- MaxScore: Word;
-begin
- Result := 0;
- MaxScore := 0;
- for I := 0 to PlayerInfo.NumPlayers-1 do
- begin
- PlayerInfo.Playerinfo[I].Percentage := PlayerInfo.Playerinfo[I].Score div 9999;
- if (PlayerInfo.Playerinfo[I].Score > MaxScore) then
- begin
- MaxScore := PlayerInfo.Playerinfo[I].Score;
- Case I of
- 0: Result := 1;
- 1: Result := 2;
- 2: Result := 4;
- 3: Result := 8;
- 4: Result := 16;
- 5: Result := 32;
- end;
- end
- else if (PlayerInfo.Playerinfo[I].Score = MaxScore) AND (PlayerInfo.Playerinfo[I].Score <> 0) then
- begin
- Case I of
- 0: Result := Result OR 1;
- 1: Result := Result OR 2;
- 2: Result := Result OR 4;
- 3: Result := Result OR 8;
- 4: Result := Result OR 16;
- 5: Result := Result OR 32;
- end;
- end;
- end;
-
- //When nobody has Points -> Everybody loose
- if (MaxScore = 0) then
- Result := 0;
-end;
-
-exports
- PluginInfo,
- Init,
- Draw,
- Finish;
-
-begin
-
-end. \ No newline at end of file
diff --git a/cmake/plugins/README(Plugins Status).txt b/cmake/plugins/README(Plugins Status).txt
deleted file mode 100644
index a6756832..00000000
--- a/cmake/plugins/README(Plugins Status).txt
+++ /dev/null
@@ -1,12 +0,0 @@
-All plugins are cleared off the SDL stuff (basically SDL_GetTicks), the StrUtils and moduleloader unit and should work on all platforms.
-2009-May-23 KMS
-
-Mac OS X:
-The following plugins can be compiled and used after being put in to the plugins folder: Blind, 5000Points, Duell
-
-2009-Apr-8 KMS
-
-The plugins are currently disabled until the party mode is working again.
-This applies to all platforms supported (Windows, Linux, Mac OS X, FreeBSD).
-
-2009-Jan-20 Karl-Michael Schindler aka Mischi.
diff --git a/cmake/plugins/SDK/ModiSDK.pas b/cmake/plugins/SDK/ModiSDK.pas
deleted file mode 100644
index e0b52a81..00000000
--- a/cmake/plugins/SDK/ModiSDK.pas
+++ /dev/null
@@ -1,164 +0,0 @@
-unit ModiSDK;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-type // PluginInfo, for init
- TPluginInfo = record
- // Info
- Name: array [0..32] of char; // modus to register for the plugin
- Creator: array [0..32] of char; // name of the author
- PluginDesc: array [0..64] of char; // plugin description
-
- // plugin type, atm: 8 only for partymode modus
- Case Typ: byte of
- 8: (
- // Options
- LoadSong: boolean; // Whether or not a song should be loaded
- // Only when song is loaded:
- ShowNotes: boolean; // Whether the note lines should be displayed
- LoadVideo: boolean; // Should the video be loaded?
- LoadBack: boolean; // Should the background be loaded?
-
- ShowRateBar: boolean; // Whether the bar that shows how good the player was sould be displayed
- ShowRateBar_O: boolean; // Load from ini whether the bar should be displayed
-
- EnLineBonus: boolean; // Whether line bonus should be enabled
- EnLineBonus_O: boolean; // Load from ini whether line bonus should be enabled
-
- BGShowFull: boolean; // Whether the background or the video should be shown full size
- BGShowFull_O: boolean; // Whether the background or the video should be shown full size
-
- // Options -> everytime
- ShowScore: boolean; // Whether or not the score should be shown
- ShowBars: boolean; // Whether the white bars on top and bottom should be drawn
- TeamModeOnly: boolean; // If true the plugin can only be played in team mode
- GetSoundData: boolean; // If true the rdata procedure is called when new sound data is available
- Dummy: boolean; // Should be set to false... for updating plugin interface
-
- NumPlayers: byte // Number of available players for modus
- // Set different bits
- // 1 -> one player
- // 2 -> two players
- // 4 -> three players
- // 8 -> four players
- // 16-> six players
- // e.g. : 10 -> playable with 2 and 4 players
- );
-
- end;
-
- TPlayerInfo = record
- NumPlayers: byte;
- Playerinfo: array[0..5] of record
- Name: PChar; // Name of the player
- Score: word; // Player's score
- Bar: byte; // Percentage of the singbar filled
- PosX: real; // PosX of player's singbar
- PosY: real; // PosY "
- Enabled: boolean; // Whether the player could get points
- Percentage: byte; // Percentage shown on the score screen
- end;
- end;
-
- TTeamInfo = record
- NumTeams: byte;
- Teaminfo: array[0..5] of record
- Name: PChar;
- Score: word;
- Joker: byte;
- CurPlayer: byte;
- NumPlayers: byte;
- Playerinfo: array[0..3] of record
- Name: PChar;
- TimesPlayed: byte;
- end;
- end;
- end;
-
- TsmallTexture = record
- TexNum: integer;
- W: real;
- H: real;
- end;
-
- TSentences = record
- Current: integer; // current part of a line
- High: integer;
- Number: integer;
- Resolution: integer;
- NotesGAP: integer;
- TotalLength: integer;
- Sentence: array of record
- Start: integer;
- StartNote: integer;
- Lyric: string;
- LyricWidth: real;
- End_: integer;
- BaseNote: integer;
- HighNote: integer;
- IlNut: integer;
- TotalNotes: integer;
- Note: array of record
- Color: integer;
- Start: integer;
- Length: integer;
- Tone: integer;
- //Text: string;
- FreeStyle: boolean;
- Typ: integer; // normal note x1, golden note x2
- end;
- end;
- end;
-
- dword = longword;
- hstream = dword;
-
- 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
- );
-
- // Routines to give to the plugin
- fModi_LoadTex = function (const Name: PChar; Typ: TTextureType): TsmallTexture; // Pointer to texture loader
- {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
- //fModi_Translate = function (const Name, Translation: AChar): integer; // Pointer to translator
- // {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-
- fModi_Print = procedure (const Style, Size: byte; const X, Y: real; const Text: PChar); // Procedure to print text // Now translated automatically
- {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
- fModi_LoadSound = function (const Name: PChar): cardinal; // Procedure that loads a custom sound
- {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
- pModi_PlaySound = procedure (const Index: cardinal); // Plays a custom sound
- {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-
- TMethodRec = record
- LoadTex: fModi_LoadTex;
- Print: fModi_Print;
- LoadSound: fModi_LoadSound;
- PlaySound: pModi_PlaySound;
- end;
- // DLL functions
- // Give the plugins info
- pModi_PluginInfo = procedure (var Info: TPluginInfo);
- {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
- // Executed on game start // if true game begins, else failure
- fModi_Init = function (const TeamInfo: TTeamInfo; var Playerinfo: TPlayerinfo; const Sentences: TSentences; const Methods: TMethodRec): boolean;
- {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
- // Executed everytime the screen is drawn // if false the game finishes
- fModi_Draw = function (var Playerinfo: TPlayerinfo; const CurSentence: cardinal): boolean;
- {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
- // Is executed on finish, returns the player num of the winner
- fModi_Finish = function (var Playerinfo: TPlayerinfo): byte;
- {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
- // Procedure called when new sound data is available
- pModi_RData = procedure (handle: hstream; buffer: pointer; len: dword; user: dword);
- {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-
-implementation
-
-end.
diff --git a/cmake/plugins/SDK/USDXStrUtils.pas b/cmake/plugins/SDK/USDXStrUtils.pas
deleted file mode 100644
index 94e5f65f..00000000
--- a/cmake/plugins/SDK/USDXStrUtils.pas
+++ /dev/null
@@ -1,79 +0,0 @@
-unit USDXStrUtils;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-uses ModiSDK;
-
-//function StrToAChar(Str: String): AChar;
-function CreateStr(Str: PChar): PChar;
-procedure FreeStr(Str: PChar);
-
-implementation
-
-{$IFDEF FPC}
- {$ASMMODE Intel}
-{$ENDIF}
-
-{function StrToAChar(Str: String): AChar;
-var
- L, I: Integer;
-begin
- L := Length(Str);
- For I := 0 to L-1 do
- AChar[I] := Str[I+1];
-
- For I := L to 254 do
- AChar[I] := #0;
-end; }
-
-function StrCopy(Dest, Source: PChar): PChar; assembler;
-asm
- PUSH EDI
- PUSH ESI
- MOV ESI,EAX
- MOV EDI,EDX
- MOV ECX,0FFFFFFFFH
- XOR AL,AL
- REPNE SCASB
- NOT ECX
- MOV EDI,ESI
- MOV ESI,EDX
- MOV EDX,ECX
- MOV EAX,EDI
- SHR ECX,2
- REP MOVSD
- MOV ECX,EDX
- AND ECX,3
- REP MOVSB
- POP ESI
- POP EDI
-end;
-
-function StrLen(Str: PChar): Cardinal; assembler;
-asm
- MOV EDX,EDI
- MOV EDI,EAX
- MOV ECX,0FFFFFFFFH
- XOR AL,AL
- REPNE SCASB
- MOV EAX,0FFFFFFFEH
- SUB EAX,ECX
- MOV EDI,EDX
-end;
-
-function CreateStr(Str: PChar): PChar;
-begin
- GetMem(Result, StrLen(Str) + 1);
- StrCopy(Result, Str);
-end;
-
-procedure FreeStr(Str: PChar);
-begin
- FreeMem(Str);
-end;
-
-end.
diff --git a/cmake/plugins/Team_Duell/CMakeLists.txt b/cmake/plugins/Team_Duell/CMakeLists.txt
deleted file mode 100644
index 7201f471..00000000
--- a/cmake/plugins/Team_Duell/CMakeLists.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-# $URL$
-# $Id$
-pascal_add_module(team_duell TeamDuell.dpr
- OUTPUT_DIR ${USDX_PLUGIN_DIR}
- PACKAGES sdl opengl
- EXCLUDE_FROM_ALL
-)
-add_dependencies(plugins team_duell)
diff --git a/cmake/plugins/Team_Duell/TeamDuell.dpr b/cmake/plugins/Team_Duell/TeamDuell.dpr
deleted file mode 100644
index 1371c95d..00000000
--- a/cmake/plugins/Team_Duell/TeamDuell.dpr
+++ /dev/null
@@ -1,274 +0,0 @@
-library TeamDuell ;
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-uses
- SysUtils,
- ModiSDK in '..\SDK\ModiSDK.pas',
- gl in '..\..\src\lib\JEDI-SDL\OpenGL\Pas\gl.pas';
-
-var
- TeamPlayer: array of array of string;
- StartPoints: array of integer;
- CurSinger, NextSinger: array[0..2] of integer;
- MethodRec: TMethodRec;
- SPT, PlayerSelected: array[0..2] of integer;
- TimeToNextChange, starttick, endtick, ChangeOnSentence: cardinal;
- bps, RTimeToNextChange: double;
- firsttime, secondtime: boolean;
-
-function GetTicks: cardinal;
-// returns a time stamp in milliseconds
-begin
- GetTicks := round(TimeStampToMSecs(DateTimeToTimeStamp(Now)));
-end;
-
-// Give the plugin's info
-procedure PluginInfo (var Info: TPluginInfo); {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-begin
- Info.Name := 'PLUGIN_TEAMDUELL_NAME';
-
- Info.Creator := 'jekatt';
- Info.PluginDesc := 'PLUGIN_TEAMDUELL_DESC';
-
- Info.Typ := 8;
-
- Info.NumPlayers := 31;
- // Options
- Info.LoadSong := true; // Whether or not a song should be loaded
- // Only when song is loaded:
- Info.ShowScore := true; // Whether or not the score should be shown
- Info.ShowNotes := true; // Whether the note lines should be displayed
- Info.LoadVideo := true; // Should the video be loaded ?
- Info.LoadBack := true; // Should the background be loaded ?
-
- Info.BGShowFull := false; // Whether the background or the video should be shown full size
- Info.BGShowFull_O := true; // Whether the background or the video should be shown full size
-
- Info.ShowRateBar := true; // Whether the bar that shows how good the player was should be displayed
- Info.ShowRateBar_O := false; // Load from ini whether the bar should be displayed
-
- Info.EnLineBonus := false; // Whether line bonus should be enabled
- Info.EnLineBonus_O := true; // Load from ini whether line bonus should be enabled
-
- // Options even when song is not loaded
- Info.ShowBars := false; // Whether the white bars on top and bottom should be drawn
- Info.TeamModeOnly := true; // if true the plugin can only be played in team mode
- Info.GetSoundData := false; // if true the rdata procedure is called when new sounddata is available
- Info.Dummy := false; // Should be set to false... for updating plugin interface
-end;
-
-// executed on game start. if true game begins, else failure
-function Init (const TeamInfo: TTeamInfo;
- var Playerinfo: TPlayerinfo;
- const Sentences: TSentences;
- const Methods: TMethodRec)
- : boolean; {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-var
- Index, J: integer;
-begin
-// Get beginning of sentences
- for Index := 0 to Sentences.High do
- begin
- SetLength(Startpoints, Index+1);
- Startpoints[Index]:=Sentences.Sentence[Index].Start;
- end;
- // Get teams and players
- for Index := 0 to TeamInfo.NumTeams-1 do
- begin
- SetLength(TeamPlayer, Index+1);
- for J := 0 to TeamInfo.Teaminfo[Index].NumPlayers-1 do
- begin
- SetLength(TeamPlayer[Index], J+1);
- TeamPlayer[Index,J] := Copy(string(TeamInfo.Teaminfo[Index].Playerinfo[J].Name), 1, 8);
- if (not(TeamPlayer[Index,J] = (string(TeamInfo.Teaminfo[Index].Playerinfo[J].Name)))) then
- TeamPlayer[Index,J] := TeamPlayer[Index,J]+'.';
- SPT[Index]:=J+1;
- end;
- CurSinger[Index] := TeamInfo.Teaminfo[Index].CurPlayer;
- repeat
- NextSinger[Index] := random(SPT[Index]);
- until not(NextSinger[Index] = CurSinger[Index]) or (SPT[Index] = 1);
- end;
- ChangeOnSentence := 8;
- starttick := GetTicks;
- firsttime := true;
- secondtime := true;
- bps := 1;
- MethodRec := Methods;
- Result := true;
-end;
-
-// Executed every time the screen is drawn; if false the game finishes
-function Draw (var Playerinfo: TPlayerinfo;
- const CurSentence: cardinal)
- : boolean; {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-var
- Index, timeline, x, y: integer;
- display: PChar;
- TimeString: PChar;
- start: boolean;
-begin
- // TickCount(firstSentence) (not zero!)
- if (CurSentence = ChangeOnSentence - 7) and (firsttime) then
- begin
- firsttime := false;
- starttick := GetTicks;
- end;
- start := false;
- // show first singer for 5 sec
- if (CurSentence < 1) and ((starttick + 5000) > GetTicks) then
- start := true;
-
- // TickCount(thirdSentence)
- if (CurSentence = 3) and (secondtime) then
- begin
- secondtime := false;
- firsttime := true;
- endtick := GetTicks;
- bps := (Startpoints[3]-Startpoints[1]) * 1000 / (endtick-starttick); // BeatsPerSecond
- end;
-
- // Time to next change
- RTimeToNextChange := ((Startpoints[ChangeOnSentence]-Startpoints[ChangeOnSentence - 7]) / bps) - ((GetTicks - starttick) / 1000);
- TimeToNextChange := Trunc(RTimeToNextChange) + 1;
-
- // Next singer for team I
- for Index := 0 to High(TeamPlayer) do
- begin
- if (CurSentence = ChangeOnSentence) and not(PlayerSelected[Index] = CurSentence) then
- begin
- PlayerSelected[Index] := CurSentence;
- CurSinger[Index] := NextSinger[Index];
- repeat
- NextSinger[Index] := random(SPT[Index]);
- until not(NextSinger[Index] = CurSinger[Index]) or (SPT[Index] = 1) ;
- end;
-
- // display background
- glColor4f (0.8, 0.8, 0.8, 1);
- display := PChar(TeamPlayer[Index,CurSinger[Index]]);
- if (TimeToNextChange <= 11) or (start = true) then
- begin
- glEnable(GL_TEXTURE_2D);
- glDisable(GL_BLEND);
- glColor4f(0, 0, 0, 1);
- glBegin(GL_QUADS);
- glVertex2f(PlayerInfo.Playerinfo[Index].PosX, PlayerInfo.Playerinfo[Index].PosY + 8);
- glVertex2f(PlayerInfo.Playerinfo[Index].PosX, PlayerInfo.Playerinfo[Index].PosY + 30);
- glVertex2f(PlayerInfo.Playerinfo[Index].PosX + 100, PlayerInfo.Playerinfo[Index].PosY + 30);
- glVertex2f(PlayerInfo.Playerinfo[Index].PosX + 100, PlayerInfo.Playerinfo[Index].PosY + 8);
- glEnd;
- display := 'Next Singer';
-
- // timeline
- x := 270;
- y := 472;
- if (TimeToNextChange <= 5) and (RTimeToNextChange > 0) then
- begin
- timeline := Trunc(RTimeToNextChange*50);
- glColor3f(0, 0, 0);
- glBegin(GL_QUADS);
- glVertex2f(x, y);
- glVertex2f(x, y + 18);
- glVertex2f(x + 6 + 250, y + 18);
- glVertex2f(x + 6 + 250, y);
- glEnd;
- glColor3f(0.2, 0.2, 0.2);
- glBegin(GL_QUADS);
- glVertex2f(x + 3, y + 3);
- glVertex2f(x + 3, y + 15);
- glVertex2f(x + 3 + 250, y + 15);
- glVertex2f(x + 3 + 250, y + 3);
- glEnd;
- glColor3f(0.8, 0.2, 0.2);
- glBegin(GL_QUADS);
- glColor3f(0.9, 0, 0); glVertex2f(x + 3, y + 3);
- glColor3f(0.8, 0.3, 0.3); glVertex2f(x + 3, y + 15);
- glColor3f(0.8, 0.3, 0.3); glVertex2f(x + 3 + timeline, y + 15);
- glColor3f(0.9, 0, 0); glVertex2f(x + 3 + timeline, y + 3);
- glEnd;
- end;
- glDisable(GL_TEXTURE_2D);
- end;
-
- // Names, Timer
- if (TimeToNextChange <= 9) then
- begin display := PChar(TeamPlayer[Index,NextSinger[Index]]);
- glColor4f(0.8, 0.1, 0.2, 1);
-// KMS aka Mischi:
-// try to replace the use of the unit USDXStrUtils
-// original:
-// MethodRec.Print (1, 18, PlayerInfo.Playerinfo[Index].PosX+85, PlayerInfo.Playerinfo[Index].PosY+10, CreateStr(PChar(IntToStr(Trunc(TimeToNextChange)))));
-// replacement: Is this correct?
- TimeString := PChar(IntToStr(Trunc(TimeToNextChange)));
- MethodRec.Print (1, 18, PlayerInfo.Playerinfo[Index].PosX+85, PlayerInfo.Playerinfo[Index].PosY+10, TimeString);
- end;
- glColor4f(0.8, 0.8, 0.8, 1);
- if (CurSentence = 0) then
- display := PChar(TeamPlayer[Index,CurSinger[Index]]);
- if (TimeToNextChange <= 11) or (start) then
- MethodRec.Print (1, 18, PlayerInfo.Playerinfo[Index].PosX+5, PlayerInfo.Playerinfo[Index].PosY+10, display);
- end;
- if (CurSentence = ChangeOnSentence) then
- begin
- ChangeOnSentence := CurSentence + 7;
- firsttime := true;
- end;
- Result := true;
-end;
-
-// is executed on finish, returns the player number of the winner
-function Finish (var Playerinfo: TPlayerinfo): byte; {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-var
- Index: integer;
- MaxScore: word;
-begin
- Result := 0;
- MaxScore := 0;
- for Index := 0 to PlayerInfo.NumPlayers-1 do
- begin
- PlayerInfo.Playerinfo[Index].Percentage := PlayerInfo.Playerinfo[Index].Score div 9999;
- if (PlayerInfo.Playerinfo[Index].Score > MaxScore) then
- begin
- MaxScore := PlayerInfo.Playerinfo[Index].Score;
- case Index of
- 0: Result := 1;
- 1: Result := 2;
- 2: Result := 4;
- 3: Result := 8;
- 4: Result := 16;
- 5: Result := 32;
- end;
- end
- else if (PlayerInfo.Playerinfo[Index].Score = MaxScore) and (PlayerInfo.Playerinfo[Index].Score <> 0) then
- begin
- case Index of
- 0: Result := Result or 1;
- 1: Result := Result or 2;
- 2: Result := Result or 4;
- 3: Result := Result or 8;
- 4: Result := Result or 16;
- 5: Result := Result or 32;
- end;
- end;
- end;
-
- // When nobody has points -> everybody looses
- if (MaxScore = 0) then
- Result := 0;
-end;
-
-exports
- PluginInfo,
- Init,
- Draw,
- Finish;
-
-begin
-
-end.
-
-
diff --git a/cmake/icons/rccompile-delphi.bat b/cmake/res/rccompile-delphi.bat
index 32f209a7..cb429f86 100644
--- a/cmake/icons/rccompile-delphi.bat
+++ b/cmake/res/rccompile-delphi.bat
@@ -1,2 +1,2 @@
-@set RES_NAME=ultrastardx-icon
-BRC32 -r -fo%RES_NAME%.res %RES_NAME%.rc
+@set RES_NAME=ultrastardx
+BRC32 -r -fo%RES_NAME%.res %RES_NAME%.rc
diff --git a/cmake/res/rccompile-fpc.bat b/cmake/res/rccompile-fpc.bat
new file mode 100644
index 00000000..fc31fd4d
--- /dev/null
+++ b/cmake/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/cmake/res/ultrastardx.exe.manifest b/cmake/res/ultrastardx.exe.manifest
new file mode 100644
index 00000000..a6481875
--- /dev/null
+++ b/cmake/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/cmake/res/ultrastardx.rc b/cmake/res/ultrastardx.rc
new file mode 100644
index 00000000..7c3dea60
--- /dev/null
+++ b/cmake/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/cmake/icons/ultrastardx-icon.res b/cmake/res/ultrastardx.res
index d79a3d0f..813282ba 100644
--- a/cmake/icons/ultrastardx-icon.res
+++ b/cmake/res/ultrastardx.res
Binary files differ
diff --git a/cmake/src/.gitignore b/cmake/src/.gitignore
new file mode 100644
index 00000000..1c20f512
--- /dev/null
+++ b/cmake/src/.gitignore
@@ -0,0 +1,8 @@
+*.cfg
+*.local
+*.bdsproj
+*.identcache
+clean.bat
+config-linux.inc
+paths.inc
+ultrastardx-*.lp[i|s]
diff --git a/cmake/src/base/TextGL.pas b/cmake/src/base/TextGL.pas
index c8de4e28..c354a500 100644
--- a/cmake/src/base/TextGL.pas
+++ b/cmake/src/base/TextGL.pas
@@ -33,304 +33,189 @@ interface
{$I switches.inc}
-// as long as the transition to freetype is not finished
-// use the old implementation
-{$IFDEF UseFreetype}
- {$INCLUDE TextGLFreetype.pas}
-{$ELSE}
uses
gl,
+ glext,
SDL,
+ Classes,
UTexture,
+ UFont,
+ UPath,
ULog;
-procedure BuildFont; // build our bitmap font
-procedure KillFont; // delete the font
-function glTextWidth(const text: string): real; // returns text width
-procedure glPrint(const text: string); // custom GL "Print" routine
+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 SetFontAspectW(Aspect: real);
procedure SetFontReflection(Enable:boolean;Spacing: real); // enables/disables text reflection
-//function NextPowerOfTwo(Value: integer): integer;
-// Checks if the ttf exists, if yes then a SDL_ttf is returned
-//function LoadFont(FileName: PAnsiChar; PointSize: integer):PTTF_Font;
-// Does the renderstuff, color is in $ffeecc style
-//function RenderText(font: PTTF_Font; Text:PAnsiChar; Color: Cardinal):PSDL_Surface;
-
-type
- TTextGL = record
- X: real;
- Y: real;
- Z: real;
- Text: string;
- Size: real;
- ColR: real;
- ColG: real;
- ColB: real;
- end;
-
- PFont = ^TFont;
- TFont = record
- Tex: TTexture;
- Width: array[0..255] of byte;
- AspectW: real;
- Centered: boolean;
- Outline: real;
- Italic: boolean;
- Reflection: boolean;
- ReflectionSpacing: real;
- end;
-
-
-var
- Fonts: array of TFont;
- ActFont: integer;
-
-
implementation
uses
- Classes,
+ UTextEncoding,
SysUtils,
IniFiles,
UCommon,
- UGraphic,
UMain,
- UPath;
-
-var
- // Colours for the reflection
- TempColor: array[0..3] of GLfloat;
+ UPathUtils;
{**
- * Load font info.
- * FontFile is the name of the image (.png) not the data (.dat) file
+ * Returns either Filename if it is absolute or a path relative to FontPath.
*}
-procedure LoadFontInfo(FontID: integer; const FontFile: string);
-var
- Stream: TFileStream;
- DatFile: string;
+function FindFontFile(const Filename: string): IPath;
begin
- DatFile := ChangeFileExt(FontFile, '.dat');
- FillChar(Fonts[FontID].Width[0], Length(Fonts[FontID].Width), 0);
+ Result := FontPath.Append(Filename);
+ // if path does not exist, try as an absolute path
+ if (not Result.IsFile) then
+ Result := Path(Filename);
+end;
- Stream := nil;
- try
- Stream := TFileStream.Create(DatFile, fmOpenRead);
- Stream.Read(Fonts[FontID].Width, 256);
- except
- Log.LogError('Error while reading font['+ inttostr(FontID) +']', 'LoadFontInfo');
+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;
- Stream.Free;
end;
-// Builds bitmap fonts
-procedure BuildFont;
+const
+ FONT_NAMES: array [0..3] of string = (
+ 'Normal', 'Bold', 'Outline1', 'Outline2'
+ );
+
+procedure BuildFonts;
var
- Count: integer;
+ I: integer;
FontIni: TMemIniFile;
- FontFile: string; // filename of the image (with .png/... ending)
+ FontFile: IPath;
+ Outline: single;
+ Embolden: single;
+ OutlineFont: TFTScalableOutlineFont;
+ SectionName: string;
begin
ActFont := 0;
- SetLength(Fonts, 4);
- FontIni := TMemIniFile.Create(FontPath + 'fonts.ini');
-
- // Normal
-
- FontFile := FontPath + FontIni.ReadString('Normal', 'File', '');
-
- Fonts[0].Tex := Texture.LoadTexture(true, FontFile, TEXTURE_TYPE_TRANSPARENT, 0);
- Fonts[0].Tex.H := 30;
- Fonts[0].AspectW := 0.9;
- Fonts[0].Outline := 0;
-
- LoadFontInfo(0, FontFile);
-
- // Bold
-
- FontFile := FontPath + FontIni.ReadString('Bold', 'File', '');
-
- Fonts[1].Tex := Texture.LoadTexture(true, FontFile, TEXTURE_TYPE_TRANSPARENT, 0);
- Fonts[1].Tex.H := 30;
- Fonts[1].AspectW := 1;
- Fonts[1].Outline := 0;
-
- LoadFontInfo(1, FontFile);
- for Count := 0 to 255 do
- Fonts[1].Width[Count] := Fonts[1].Width[Count] div 2;
-
- // Outline1
-
- FontFile := FontPath + FontIni.ReadString('Outline1', 'File', '');
-
- Fonts[2].Tex := Texture.LoadTexture(true, FontFile, TEXTURE_TYPE_TRANSPARENT, 0);
- Fonts[2].Tex.H := 30;
- Fonts[2].AspectW := 0.95;
- Fonts[2].Outline := 5;
-
- LoadFontInfo(2, FontFile);
- for Count := 0 to 255 do
- Fonts[2].Width[Count] := Fonts[2].Width[Count] div 2 + 2;
-
- // Outline2
+ SetLength(Fonts, Length(FONT_NAMES));
- FontFile := FontPath + FontIni.ReadString('Outline2', 'File', '');
-
- Fonts[3].Tex := Texture.LoadTexture(true, FontFile, TEXTURE_TYPE_TRANSPARENT, 0);
- Fonts[3].Tex.H := 30;
- Fonts[3].AspectW := 0.95;
- Fonts[3].Outline := 4;
-
- LoadFontInfo(3, FontFile);
- for Count := 0 to 255 do
- Fonts[3].Width[Count] := Fonts[3].Width[Count] + 1;
+ 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);
+ 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);
+ 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 KillFont;
-begin
- // delete all characters
- //glDeleteLists(..., 256);
-end;
-function glTextWidth(const text: string): real;
+// Deletes the font
+procedure KillFonts;
var
- Letter: char;
- i: integer;
- Font: PFont;
+ I: integer;
begin
- Result := 0;
- Font := @Fonts[ActFont];
-
- for i := 1 to Length(text) do
- begin
- Letter := Text[i];
- Result := Result + Font.Width[Ord(Letter)] * Font.Tex.H / 30 * Font.AspectW;
- end;
-
- if ((Result > 0) and Font.Italic) then
- Result := Result + 12 * Font.Tex.H / 60 * Font.AspectW;
+ for I := 0 to High(Fonts) do
+ Fonts[I].Font.Free;
end;
-procedure glPrintLetter(Letter: char);
+function glTextWidth(const text: UTF8String): real;
var
- TexX, TexY: real;
- TexR, TexB: real;
- TexHeight: real;
- FWidth: real;
- PL, PT: real;
- PR, PB: real;
- XItal: real; // X shift for italic type letter
- ReflectionSpacing: real; // Distance of the reflection
- Font: PFont;
- Tex: PTexture;
+ Bounds: TBoundsDbl;
begin
- Font := @Fonts[ActFont];
- Tex := @Font.Tex;
-
- FWidth := Font.Width[Ord(Letter)];
-
- Tex.W := FWidth * (Tex.H/30) * Font.AspectW;
-
- // set texture positions
- TexX := (ord(Letter) mod 16) * 1/16 + 1/32 - FWidth/1024 - Font.Outline/1024;
- TexY := (ord(Letter) div 16) * 1/16 + 2/1024;
- TexR := (ord(Letter) mod 16) * 1/16 + 1/32 + FWidth/1024 + Font.Outline/1024;
- TexB := (1 + ord(Letter) div 16) * 1/16 - 2/1024;
-
- TexHeight := TexB - TexY;
-
- // set vector positions
- PL := Tex.X - Font.Outline * (Tex.H/30) * Font.AspectW /2;
- PT := Tex.Y;
- PR := PL + Tex.W + Font.Outline * (Tex.H/30) * Font.AspectW;
- PB := PT + Tex.H;
-
- if (not Font.Italic) then
- XItal := 0
- else
- XItal := 12;
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, Tex.TexNum);
-
- glBegin(GL_QUADS);
- glTexCoord2f(TexX, TexY); glVertex2f(PL+XItal, PT);
- glTexCoord2f(TexX, TexB); glVertex2f(PL, PB);
- glTexCoord2f(TexR, TexB); glVertex2f(PR, PB);
- glTexCoord2f(TexR, TexY); glVertex2f(PR+XItal, PT);
- glEnd;
-
- // <mog> Reflection
- // Yes it would make sense to put this in an extra procedure,
- // but this works, doesn't take much lines, and is almost lightweight
- if Font.Reflection then
- begin
- ReflectionSpacing := Font.ReflectionSpacing + Tex.H/2;
-
- glDepthRange(0, 10);
- glDepthFunc(GL_LEQUAL);
- glEnable(GL_DEPTH_TEST);
-
- glBegin(GL_QUADS);
- glColor4f(TempColor[0], TempColor[1], TempColor[2], 0);
- glTexCoord2f(TexX, TexY + TexHeight/2);
- glVertex3f(PL, PB + ReflectionSpacing - Tex.H/2, Tex.z);
-
- glColor4f(TempColor[0], TempColor[1], TempColor[2], Tex.Alpha-0.3);
- glTexCoord2f(TexX, TexB );
- glVertex3f(PL + XItal, PT + ReflectionSpacing, Tex.z);
-
- glTexCoord2f(TexR, TexB );
- glVertex3f(PR + XItal, PT + ReflectionSpacing, Tex.z);
-
- glColor4f(TempColor[0], TempColor[1], TempColor[2], 0);
- glTexCoord2f(TexR, TexY + TexHeight/2);
- glVertex3f(PR, PB + ReflectionSpacing - Tex.H/2, Tex.z);
- glEnd;
-
- glDisable(GL_DEPTH_TEST);
- end; // reflection
-
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_BLEND);
-
- Tex.X := Tex.X + Tex.W;
-
- //write the colour back
- glColor4fv(@TempColor);
+ Bounds := Fonts[ActFont].Font.BBox(Text, true);
+ Result := Bounds.Right - Bounds.Left;
end;
// Custom GL "Print" Routine
-procedure glPrint(const Text: string);
+procedure glPrint(const Text: UTF8String);
var
- Pos: integer;
+ GLFont: PGLFont;
begin
// if there is no text do nothing
if (Text = '') then
Exit;
- //Save the actual color and alpha (for reflection)
- glGetFloatv(GL_CURRENT_COLOR, @TempColor);
+ GLFont := @Fonts[ActFont];
- for Pos := 1 to Length(Text) do
- begin
- glPrintLetter(Text[Pos]);
- end;
+ glPushMatrix();
+ // set font position
+ glTranslatef(GLFont.X, GLFont.Y + GLFont.Font.Ascender, GLFont.Z);
+ // draw string
+ GLFont.Font.Print(Text);
+ glPopMatrix();
end;
procedure ResetFont();
@@ -343,18 +228,18 @@ end;
procedure SetFontPos(X, Y: real);
begin
- Fonts[ActFont].Tex.X := X;
- Fonts[ActFont].Tex.Y := Y;
+ Fonts[ActFont].X := X;
+ Fonts[ActFont].Y := Y;
end;
procedure SetFontZ(Z: real);
begin
- Fonts[ActFont].Tex.Z := Z;
+ Fonts[ActFont].Z := Z;
end;
procedure SetFontSize(Size: real);
begin
- Fonts[ActFont].Tex.H := Size;
+ Fonts[ActFont].Font.Height := Size;
end;
procedure SetFontStyle(Style: integer);
@@ -364,21 +249,19 @@ end;
procedure SetFontItalic(Enable: boolean);
begin
- Fonts[ActFont].Italic := Enable;
-end;
-
-procedure SetFontAspectW(Aspect: real);
-begin
- Fonts[ActFont].AspectW := Aspect;
+ 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
- Fonts[ActFont].Reflection := Enable;
- Fonts[ActFont].ReflectionSpacing := Spacing;
+ 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.
-
-{$ENDIF}
-
diff --git a/cmake/src/base/TextGLFreetype.pas b/cmake/src/base/TextGLFreetype.pas
deleted file mode 100644
index 61b26693..00000000
--- a/cmake/src/base/TextGLFreetype.pas
+++ /dev/null
@@ -1,222 +0,0 @@
-{* 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/src/base/TextGL.pas $
- * $Id: TextGL.pas 1483 2008-10-28 19:01:20Z tobigun $
- *}
-
-(*
-unit TextGL;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-*)
-
-uses
- gl,
- glext,
- SDL,
- UTexture,
- UFont,
- Classes,
- ULog;
-
-type
- PGLFont = ^TGLFont;
- TGLFont = record
- Font: TScalableFont;
- X, Y, Z: real;
- end;
-
-var
- Fonts: array of TGLFont;
- ActFont: integer;
-
-procedure BuildFont; // build our bitmap font
-procedure KillFont; // delete the font
-function glTextWidth(const text: string): real; // returns text width
-procedure glPrint(const text: string); // 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
- UMain,
- UCommon,
- UTextEncoding,
- SysUtils,
- IniFiles;
-
-function FindFontFile(FontIni: TCustomIniFile; Font: string): string;
-var
- Filename: string;
-begin
- Filename := FontIni.ReadString(Font, 'File', '');
- Result := FontPath + Filename;
- // if path does not exist, try as an absolute path
- if (not FileExists(Result)) then
- Result := Filename;
-end;
-
-procedure BuildFont;
-var
- FontIni: TMemIniFile;
- //BitmapFont: TBitmapFont;
- FontFile: string;
-begin
- ActFont := 0;
-
- SetLength(Fonts, 4);
- FontIni := TMemIniFile.Create(FontPath + 'fontsTTF.ini');
- //FontIni := TMemIniFile.Create(FontPath + 'fonts.ini');
-
- try
-
- // Normal
- FontFile := FindFontFile(FontIni, 'Normal');
- Fonts[0].Font := TFTScalableFont.Create(FontFile, 64);
- //Fonts[0].Font.GlyphSpacing := 1.4;
- //Fonts[0].Font.Aspect := 1.2;
-
- {
- BitmapFont := TBitmapFont.Create(FontFile, 0, 19, 35, -10);
- BitmapFont.CorrectWidths(2, 0);
- Fonts[0].Font := TScalableFont.Create(BitmapFont, false);
- }
-
- //Fonts[0].Font.Aspect := 0.9;
-
- // Bold
- FontFile := FindFontFile(FontIni, 'Bold');
- Fonts[1].Font := TFTScalableFont.Create(FontFile, 64);
-
- // Outline1
- FontFile := FindFontFile(FontIni, 'Outline1');
- Fonts[2].Font := TFTScalableOutlineFont.Create(FontFile, 64, 0.06);
- //TFTScalableOutlineFont(Fonts[2].Font).SetOutlineColor(0.3, 0.3, 0.3);
-
- // Outline2
- FontFile := FindFontFile(FontIni, 'Outline2');
- Fonts[3].Font := TFTScalableOutlineFont.Create(FontFile, 64, 0.08);
-
- except on E: Exception do
- Log.LogCritical(E.Message, 'BuildFont');
- end;
-
- // close ini-file
- FontIni.Free;
-end;
-
-
-// Deletes the font
-procedure KillFont;
-begin
- // delete all characters
- //glDeleteLists(..., 256);
-end;
-
-function glTextWidth(const text: string): real;
-var
- Bounds: TBoundsDbl;
-begin
- // FIXME: remove conversion
- Bounds := Fonts[ActFont].Font.BBox(RecodeString(Text, encCP1252), true);
- Result := Bounds.Right - Bounds.Left;
-end;
-
-// Custom GL "Print" Routine
-procedure glPrint(const Text: string);
-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
- // FIXME: remove conversion
- GLFont.Font.Print(RecodeString(Text, encCP1252));
- 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/cmake/src/base/UBeatTimer.pas b/cmake/src/base/UBeatTimer.pas
index a47a06f9..bc03de76 100644
--- a/cmake/src/base/UBeatTimer.pas
+++ b/cmake/src/base/UBeatTimer.pas
@@ -1,170 +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: https://ultrastardx.svn.sourceforge.net/svnroot/ultrastardx/trunk/src/base/USingNotes.pas $
- * $Id: USingNotes.pas 1406 2008-09-23 21:43:52Z k-m_schindler $
- *}
+{* 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;
-unit UBeatTimer;
+ // 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;
-interface
+ {$IFDEF LOG_SYNC}
+ //Log.LogError(Format('TimeDiff: %.3f', [TimeDiff]));
+ {$ENDIF}
-{$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
- Timer: TRelativeTimer; // keeps track of the current time
- 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();
- procedure Pause();
- procedure Resume();
-
- procedure Reset();
- procedure UpdateBeats();
-
- (**
- * current song time (in seconds) used as base-timer for lyrics etc.
- *)
- function GetCurrentTime(): real;
- procedure SetCurrentTime(Time: real);
- end;
-
-implementation
-uses UNote, Math;
-
-
-constructor TLyricsState.Create();
-begin
- // create a triggered timer, so we can Pause() it, set the time
- // and Resume() it afterwards for better synching.
- Timer := TRelativeTimer.Create(true);
-
- // reset state
- Reset();
-end;
-
-procedure TLyricsState.Pause();
-begin
- Timer.Pause();
-end;
-
-procedure TLyricsState.Resume();
-begin
- Timer.Resume();
-end;
-
-procedure TLyricsState.SetCurrentTime(Time: real);
-begin
- // do not start the timer (if not started already),
- // after setting the current time
- Timer.SetTime(Time, false);
-end;
-
-function TLyricsState.GetCurrentTime(): real;
-begin
- Result := Timer.GetTime();
+ // 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;
-
-(**
- * 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
- Pause();
- SetCurrentTime(0);
-
- 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;
-
+
+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/cmake/src/base/UCatCovers.pas b/cmake/src/base/UCatCovers.pas
index 6ef81b68..85cb850f 100644
--- a/cmake/src/base/UCatCovers.pas
+++ b/cmake/src/base/UCatCovers.pas
@@ -24,10 +24,6 @@
*}
unit UCatCovers;
-/////////////////////////////////////////////////////////////////////////
-// UCatCovers by Whiteshark //
-// Class for listing and managing the Category Covers //
-/////////////////////////////////////////////////////////////////////////
interface
@@ -38,20 +34,21 @@ interface
{$I switches.inc}
uses
- UIni;
+ UIni,
+ UPath;
type
TCatCovers = class
protected
- cNames: array [0..high(ISorting)] of array of string;
- cFiles: array [0..high(ISorting)] of array of string;
+ 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: string);
- procedure Add(Sorting: integer; Name, Filename: string); //Add a Cover
- function CoverExists(Sorting: integer; Name: string): boolean; //Returns True when a cover with the given Name exists
- function GetCover(Sorting: integer; Name: string): string; //Returns the Filename of a Cover
+ 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
@@ -63,10 +60,11 @@ uses
IniFiles,
SysUtils,
Classes,
- // UFiles,
+ UFilesystem,
ULog,
UMain,
- UPath;
+ UUnicodeUtils,
+ UPathUtils;
constructor TCatCovers.Create;
begin
@@ -79,90 +77,96 @@ var
I: integer;
begin
for I := 0 to CoverPaths.Count-1 do
- LoadPath(CoverPaths[I]);
+ LoadPath(CoverPaths[I] as IPath);
end;
(**
* Load Cover from Cover.ini and Cover Folder
*)
-procedure TCatCovers.LoadPath(const CoversPath: string);
+procedure TCatCovers.LoadPath(const CoversPath: IPath);
var
Ini: TMemIniFile;
- SR: TSearchRec;
List: TStringlist;
- I, J: Integer;
- Name, Filename, Temp: string;
+ 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 + 'covers.ini');
+ Ini := TMemIniFile.Create(CoversPath.Append('covers.ini').ToNative);
List := TStringlist.Create;
//Add every Cover in Covers Ini for Every Sorting option
- for I := 0 to High(ISorting) do
+ for SortType := Low(TSortingType) to High(TSortingType) do
begin
- Ini.ReadSection(ISorting[I], List);
+ Ini.ReadSection(ISorting[Ord(SortType)], List);
- for J := 0 to List.Count - 1 do
- Add(I, List.Strings[J], CoversPath + Ini.ReadString(ISorting[I], List.Strings[J], 'NoCover.jpg'));
+ 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;
- try
- //Add Covers from Folder
- if (FindFirst (CoversPath + '*.jpg', faAnyFile, SR) = 0) then
- repeat
- //Add Cover if it doesn't exist for every Section
- Name := SR.Name;
- Filename := CoversPath + Name;
- Delete (Name, length(Name) - 3, 4);
-
- for I := 0 to high(ISorting) do
- begin
- Temp := Name;
- if ((I = sTitle) or (I = sTitle2)) and (Pos ('Title', Temp) <> 0) then
- Delete (Temp, Pos ('Title', Temp), 5)
- else if (I = sArtist) or (I = sArtist2) and (Pos ('Artist', Temp) <> 0) then
- Delete (Temp, Pos ('Artist', Temp), 6);
-
- if not CoverExists(I, Temp) then
- Add (I, Temp, Filename);
- end;
- until FindNext (SR) <> 0;
- finally
- FindClose (SR);
+ //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: integer; Name, Filename: string);
+procedure TCatCovers.Add(Sorting: TSortingType; const Name: UTF8String; const Filename: IPath);
begin
- if FileExists (Filename) then //If Exists -> Add
+ if Filename.IsFile then //If Exists -> Add
begin
- SetLength (CNames[Sorting], Length(CNames[Sorting]) + 1);
- SetLength (CFiles[Sorting], Length(CNames[Sorting]) + 1);
+ SetLength(CNames[Sorting], Length(CNames[Sorting]) + 1);
+ SetLength(CFiles[Sorting], Length(CNames[Sorting]) + 1);
- CNames[Sorting][high(cNames[Sorting])] := Uppercase(Name);
+ 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: integer; Name: string): boolean;
+function TCatCovers.CoverExists(Sorting: TSortingType; const Name: UTF8String): boolean;
var
I: Integer;
+ UpperName: UTF8String;
begin
Result := False;
- Name := Uppercase(Name); //Case Insensitiv
+ UpperName := UTF8Uppercase(Name); //Case Insensitiv
for I := 0 to high(cNames[Sorting]) do
begin
- if (cNames[Sorting][I] = Name) then //Found Name
+ if (cNames[Sorting][I] = UpperName) then //Found Name
begin
Result := true;
break; //Break For Loop
@@ -171,16 +175,18 @@ begin
end;
//Returns the Filename of a Cover
-function TCatCovers.GetCover(Sorting: integer; Name: string): string;
+function TCatCovers.GetCover(Sorting: TSortingType; const Name: UTF8String): IPath;
var
I: Integer;
+ UpperName: UTF8String;
+ NoCoverPath: IPath;
begin
- Result := '';
- Name := Uppercase(Name);
+ Result := PATH_NONE;
+ UpperName := UTF8Uppercase(Name);
for I := 0 to high(cNames[Sorting]) do
begin
- if cNames[Sorting][I] = Name then
+ if cNames[Sorting][I] = UpperName then
begin
Result := cFiles[Sorting][I];
Break;
@@ -188,17 +194,18 @@ begin
end;
//No Cover
- if (Result = '') then
+ if (Result.IsUnset) then
begin
for I := 0 to CoverPaths.Count-1 do
begin
- if (FileExists(CoverPaths[I] + 'NoCover.jpg')) then
+ NoCoverPath := (CoverPaths[I] as IPath).Append('NoCover.jpg');
+ if (NoCoverPath.IsFile) then
begin
- Result := CoverPaths[I] + 'NoCover.jpg';
+ Result := NoCoverPath;
Break;
end;
end;
end;
end;
-end.
+end. \ No newline at end of file
diff --git a/cmake/src/base/UCommandLine.pas b/cmake/src/base/UCommandLine.pas
index 281a480d..ac0db2c2 100644
--- a/cmake/src/base/UCommandLine.pas
+++ b/cmake/src/base/UCommandLine.pas
@@ -33,6 +33,9 @@ interface
{$I switches.inc}
+uses
+ UPath;
+
type
TScreenMode = (scmDefault, scmFullscreen, scmWindowed);
@@ -64,9 +67,9 @@ type
Screens: integer;
// some strings set when reading infos {Length=0: Not Set}
- SongPath: string;
- ConfigFile: string;
- ScoreFile: string;
+ SongPath: IPath;
+ ConfigFile: IPath;
+ ScoreFile: IPath;
// pseudo integer values
property Language: integer read GetLanguage;
@@ -144,9 +147,9 @@ begin
Screens := -1;
// some strings set when reading infos {Length=0 Not Set}
- SongPath := '';
- ConfigFile := '';
- ScoreFile := '';
+ SongPath := PATH_NONE;
+ ConfigFile := PATH_NONE;
+ ScoreFile := PATH_NONE;
end;
{**
@@ -248,7 +251,7 @@ begin
if (PCount > I) then
begin
// write value to string
- SongPath := ParamStr(I + 1);
+ SongPath := Path(ParamStr(I + 1));
end;
end
@@ -258,11 +261,11 @@ begin
if (PCount > I) then
begin
// write value to string
- ConfigFile := ParamStr(I + 1);
+ ConfigFile := Path(ParamStr(I + 1));
// is this a relative path -> then add gamepath
- if Not ((Length(ConfigFile) > 2) AND (ConfigFile[2] = ':')) then
- ConfigFile := ExtractFilePath(ParamStr(0)) + Configfile;
+ if (not ConfigFile.IsAbsolute) then
+ ConfigFile := Platform.GetExecutionDir().Append(ConfigFile);
end;
end
@@ -272,7 +275,7 @@ begin
if (PCount > I) then
begin
// write value to string
- ScoreFile := ParamStr(I + 1);
+ ScoreFile := Path(ParamStr(I + 1));
end;
end;
diff --git a/cmake/src/base/UCommon.pas b/cmake/src/base/UCommon.pas
index d729b6dd..18022337 100644
--- a/cmake/src/base/UCommon.pas
+++ b/cmake/src/base/UCommon.pas
@@ -39,9 +39,29 @@ uses
{$IFDEF MSWINDOWS}
Windows,
{$ENDIF}
- sdl,
UConfig,
- ULog;
+ 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);
@@ -50,49 +70,27 @@ procedure ShowMessage(const msg: string; msgType: TMessageType = mtInfo);
procedure ConsoleWriteLn(const msg: string);
-function RWopsFromStream(Stream: TStream): PSDL_RWops;
-
{$IFDEF FPC}
function RandomRange(aMin: integer; aMax: integer): integer;
{$ENDIF}
-function StringReplaceW(text: WideString; search, rep: WideChar): WideString;
-function AdaptFilePaths(const aPath: WideString): WideString;
-
procedure DisableFloatingPointExceptions();
procedure SetDefaultNumericLocale();
procedure RestoreNumericLocale();
{$IFNDEF MSWINDOWS}
- procedure ZeroMemory(Destination: pointer; Length: dword);
- function MakeLong(a, b: word): longint;
- (*
- #define LOBYTE(a) (BYTE)(a)
- #define HIBYTE(a) (BYTE)((a)>>8)
- #define LOWORD(a) (WORD)(a)
- #define HIWORD(a) (WORD)((a)>>16)
- #define MAKEWORD(a,b) (WORD)(((a)&0xff)|((b)<<8))
- *)
+procedure ZeroMemory(Destination: pointer; Length: dword);
+function MakeLong(a, b: word): longint;
{$ENDIF}
-function FileExistsInsensitive(var FileName: string): boolean;
-
-(*
- * Character classes
- *)
-
-function IsAlphaChar(ch: WideChar): boolean;
-function IsNumericChar(ch: WideChar): boolean;
-function IsAlphaNumericChar(ch: WideChar): boolean;
-function IsPunctuationChar(ch: WideChar): boolean;
-function IsControlChar(ch: WideChar): boolean;
-
// 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
@@ -101,8 +99,63 @@ uses
{$IFDEF Delphi}
Dialogs,
{$ENDIF}
- UMain;
+ 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)}
@@ -224,39 +277,6 @@ begin
exOverflow, exUnderflow, exPrecision]);
end;
-function StringReplaceW(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;
-
-function AdaptFilePaths(const aPath: WideString): WideString;
-begin
- result := StringReplaceW(aPath, '\', PathDelim);//, [rfReplaceAll]);
-end;
-
-
{$IFNDEF MSWINDOWS}
procedure ZeroMemory(Destination: pointer; Length: dword);
begin
@@ -268,135 +288,8 @@ begin
Result := (LongInt(B) shl 16) + A;
end;
-(*
-function QueryPerformanceCounter(lpPerformanceCount:TLARGEINTEGER): Bool;
-
- // From http://en.wikipedia.org/wiki/RDTSC
- function RDTSC: Int64; register;
- asm
- rdtsc
- end;
-
-begin
- // Use clock_gettime(CLOCK_REALTIME, ...) here (but not from the libc unit)
- lpPerformanceCount := RDTSC();
- result := true;
-end;
-
-function QueryPerformanceFrequency(lpFrequency:TLARGEINTEGER):Bool;
-begin
- // clock_getres(CLOCK_REALTIME, ...)
- lpFrequency := 0;
- result := true;
-end;
-*)
{$ENDIF}
-// Checks if a regular files or directory with the given name exists.
-// The comparison is case insensitive.
-function FileExistsInsensitive(var FileName: string): boolean;
-var
- FilePath, LocalFileName: string;
- SearchInfo: TSearchRec;
-begin
-{$IF Defined(Linux) or Defined(FreeBSD)}
- // speed up standard case
- if FileExists(FileName) then
- begin
- Result := true;
- exit;
- end;
-
- Result := false;
-
- FilePath := ExtractFilePath(FileName);
- if (FindFirst(FilePath + '*', faAnyFile, SearchInfo) = 0) then
- begin
- LocalFileName := ExtractFileName(FileName);
- repeat
- if (AnsiSameText(LocalFileName, SearchInfo.Name)) then
- begin
- FileName := FilePath + SearchInfo.Name;
- Result := true;
- break;
- end;
- until (FindNext(SearchInfo) <> 0);
- end;
- FindClose(SearchInfo);
-{$ELSE}
- // Windows and Mac OS X do not have case sensitive file systems
- Result := FileExists(FileName);
-{$IFEND}
-end;
-
-// +++++++++++++++++++++ helpers for RWOpsFromStream() +++++++++++++++
-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 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;
-// -----------------------------------------------
-
-(*
- * Creates an SDL_RWops handle from a TStream.
- * The stream and RWops must be freed by the user after usage.
- * Use SDL_FreeRW(...) to free the RWops data-struct.
- *)
-function RWopsFromStream(Stream: TStream): PSDL_RWops;
-begin
- Result := SDL_AllocRW();
- if (Result = nil) then
- Exit;
-
- // set RW-callbacks
- with Result^ do
- begin
- unknown := TUnknown(Stream);
- seek := SDLStreamSeek;
- read := SDLStreamRead;
- write := nil;
- close := SDLStreamClose;
- type_ := 2;
- end;
-end;
-
{$IFDEF FPC}
function RandomRange(aMin: integer; aMax: integer): integer;
begin
@@ -541,59 +434,6 @@ begin
{$IFEND}
end;
-function IsAlphaChar(ch: WideChar): boolean;
-begin
- // TODO: add chars > 255 when unicode-fonts work?
- 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;
-end;
-
-function IsNumericChar(ch: WideChar): boolean;
-begin
- case ch of
- '0'..'9':
- Result := true;
- else
- Result := false;
- end;
-end;
-
-function IsAlphaNumericChar(ch: WideChar): boolean;
-begin
- Result := (IsAlphaChar(ch) or IsNumericChar(ch));
-end;
-
-function IsPunctuationChar(ch: WideChar): boolean;
-begin
- // TODO: add chars outside of Latin1 basic (0..127)?
- case ch of
- ' '..'/',':'..'@','['..'`','{'..'~':
- Result := true;
- else
- Result := false;
- end;
-end;
-
-function IsControlChar(ch: WideChar): boolean;
-begin
- case ch of
- #0..#31,
- #127..#159:
- Result := true;
- else
- Result := false;
- end;
-end;
-
(*
* Recursive part of the MergeSort algorithm.
* OutList will be either InList or TempList and will be swapped in each
@@ -677,6 +517,28 @@ begin
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()
diff --git a/cmake/src/base/UConfig.pas b/cmake/src/base/UConfig.pas
index dfb51d54..c0980de4 100644
--- a/cmake/src/base/UConfig.pas
+++ b/cmake/src/base/UConfig.pas
@@ -58,7 +58,7 @@ unit UConfig;
// not possible to use the version-numbers in this uses-clause.
// Example:
// interface
-// uses
+// uses
// versions, // include this file
// {$IF USE_UNIT_XYZ}xyz;{$IFEND} // Error: USE_UNIT_XYZ not defined
// const
@@ -68,13 +68,13 @@ unit UConfig;
//
// 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
+// 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
+// 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.
+// 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.
@@ -88,9 +88,9 @@ interface
{$ENDIF}
{$I switches.inc}
-
+
uses
- Sysutils;
+ SysUtils;
const
// IMPORTANT:
@@ -107,7 +107,7 @@ const
// include config-file (defines + constants)
{$IF Defined(MSWindows)}
- {$I config-win.inc}
+ {$I ..\config-win.inc}
{$ELSEIF Defined(Linux)}
{$I config-linux.inc}
{$ELSEIF Defined(FreeBSD)}
@@ -130,7 +130,7 @@ const
USDX_VERSION_MAJOR = 1;
USDX_VERSION_MINOR = 1;
USDX_VERSION_RELEASE = 0;
- USDX_VERSION_STATE = 'Alpha';
+ USDX_VERSION_STATE = 'Beta';
USDX_STRING = 'UltraStar Deluxe';
(*
@@ -151,11 +151,17 @@ const
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}
@@ -179,13 +185,13 @@ const
{$ENDIF}
- {$IFDEF HaveProjectM}
+ {$IFDEF HaveProjectM}
PROJECTM_VERSION = (PROJECTM_VERSION_MAJOR * VERSION_MAJOR) +
(PROJECTM_VERSION_MINOR * VERSION_MINOR) +
(PROJECTM_VERSION_RELEASE * VERSION_RELEASE);
{$ENDIF}
- {$IFDEF HavePortaudio}
+ {$IFDEF HavePortaudio}
PORTAUDIO_VERSION = (PORTAUDIO_VERSION_MAJOR * VERSION_MAJOR) +
(PORTAUDIO_VERSION_MINOR * VERSION_MINOR) +
(PORTAUDIO_VERSION_RELEASE * VERSION_RELEASE);
@@ -223,4 +229,4 @@ begin
' Build';
end;
-end.
+end. \ No newline at end of file
diff --git a/cmake/src/base/UCovers.pas b/cmake/src/base/UCovers.pas
index a1705674..6c7c9e48 100644
--- a/cmake/src/base/UCovers.pas
+++ b/cmake/src/base/UCovers.pas
@@ -50,7 +50,8 @@ uses
SysUtils,
Classes,
UImage,
- UTexture;
+ UTexture,
+ UPath;
type
ECoverDBException = class(Exception)
@@ -59,9 +60,9 @@ type
TCover = class
private
ID: int64;
- Filename: WideString;
+ Filename: IPath;
public
- constructor Create(ID: int64; Filename: WideString);
+ constructor Create(ID: int64; Filename: IPath);
function GetPreviewTexture(): TTexture;
function GetTexture(): TTexture;
end;
@@ -76,19 +77,19 @@ type
private
DB: TSQLiteDatabase;
procedure InitCoverDatabase();
- function CreateThumbnail(const Filename: WideString; var Info: TThumbnailInfo): PSDL_Surface;
+ function CreateThumbnail(const Filename: IPath; var Info: TThumbnailInfo): PSDL_Surface;
function LoadCover(CoverID: int64): TTexture;
procedure DeleteCover(CoverID: int64);
- function FindCoverIntern(const Filename: WideString): 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: WideString): TCover;
- function FindCover(const Filename: WideString): TCover;
- function CoverExists(const Filename: WideString): boolean;
+ 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;
@@ -111,7 +112,7 @@ uses
DateUtils;
const
- COVERDB_FILENAME = 'cover.db';
+ COVERDB_FILENAME: UTF8String = 'cover.db';
COVERDB_VERSION = 01; // 0.1
COVER_TBL = 'Cover';
COVER_THUMBNAIL_TBL = 'CoverThumbnail';
@@ -141,7 +142,7 @@ end;
{ TCover }
-constructor TCover.Create(ID: int64; Filename: WideString);
+constructor TCover.Create(ID: int64; Filename: IPath);
begin
Self.ID := ID;
Self.Filename := Filename;
@@ -210,11 +211,11 @@ end;
procedure TCoverDatabase.Open();
var
Version: integer;
- Filename: string;
+ Filename: IPath;
begin
- Filename := UTF8Encode(Platform.GetGameUserPath() + COVERDB_FILENAME);
+ Filename := Platform.GetGameUserPath().Append(COVERDB_FILENAME);
- DB := TSQLiteDatabase.Create(Filename);
+ DB := TSQLiteDatabase.Create(Filename.ToUTF8());
Version := GetVersion();
// check version, if version is too old/new, delete database file
@@ -223,10 +224,10 @@ begin
Log.LogInfo('Outdated cover-database file found', 'TCoverDatabase.Open');
// close and delete outdated file
DB.Free;
- if (not DeleteFile(Filename)) then
- raise ECoverDBException.Create('Could not delete ' + Filename);
+ if (not Filename.DeleteFile()) then
+ raise ECoverDBException.Create('Could not delete ' + Filename.ToNative);
// reopen
- DB := TSQLiteDatabase.Create(Filename);
+ DB := TSQLiteDatabase.Create(Filename.ToUTF8());
Version := 0;
end;
@@ -266,14 +267,14 @@ begin
')');
end;
-function TCoverDatabase.FindCoverIntern(const Filename: WideString): int64;
+function TCoverDatabase.FindCoverIntern(const Filename: IPath): int64;
begin
Result := DB.GetTableValue('SELECT [ID] FROM ['+COVER_TBL+'] ' +
'WHERE [Filename] = ?',
- [UTF8Encode(Filename)]);
+ [Filename.ToUTF8]);
end;
-function TCoverDatabase.FindCover(const Filename: WideString): TCover;
+function TCoverDatabase.FindCover(const Filename: IPath): TCover;
var
CoverID: int64;
begin
@@ -287,7 +288,7 @@ begin
end;
end;
-function TCoverDatabase.CoverExists(const Filename: WideString): boolean;
+function TCoverDatabase.CoverExists(const Filename: IPath): boolean;
begin
Result := false;
try
@@ -297,7 +298,7 @@ begin
end;
end;
-function TCoverDatabase.AddCover(const Filename: WideString): TCover;
+function TCoverDatabase.AddCover(const Filename: IPath): TCover;
var
CoverID: int64;
Thumbnail: PSDL_Surface;
@@ -329,7 +330,7 @@ begin
DB.ExecSQL('INSERT INTO ['+COVER_TBL+'] ' +
'([Filename], [Date], [Width], [Height]) VALUES' +
'(?, ?, ?, ?)',
- [UTF8Encode(Filename), DateTimeToUnixTime(FileDate),
+ [Filename.ToUTF8, DateTimeToUnixTime(FileDate),
Info.CoverWidth, Info.CoverHeight]);
// get auto-generated cover ID
@@ -358,7 +359,7 @@ var
PixelFmt: TImagePixelFmt;
Data: PChar;
DataSize: integer;
- Filename: WideString;
+ Filename: IPath;
Table: TSQLiteUniTable;
begin
Table := nil;
@@ -371,7 +372,7 @@ begin
'USING(ID) ' +
'WHERE [ID] = %d', [CoverID]));
- Filename := UTF8Decode(Table.FieldAsString(0));
+ Filename := Path(Table.FieldAsString(0));
PixelFmt := TImagePixelFmt(Table.FieldAsInteger(1));
Width := Table.FieldAsInteger(2);
Height := Table.FieldAsInteger(3);
@@ -384,6 +385,9 @@ begin
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
@@ -403,7 +407,7 @@ end;
* Returns a pointer to an array of bytes containing the texture data in the
* requested size
*)
-function TCoverDatabase.CreateThumbnail(const Filename: WideString; var Info: TThumbnailInfo): PSDL_Surface;
+function TCoverDatabase.CreateThumbnail(const Filename: IPath; var Info: TThumbnailInfo): PSDL_Surface;
var
//TargetAspect, SourceAspect: double;
//TargetWidth, TargetHeight: integer;
@@ -417,7 +421,7 @@ begin
Thumbnail := LoadImage(Filename);
if (not assigned(Thumbnail)) then
begin
- Log.LogError('Could not load cover: "'+ Filename +'"', 'TCoverDatabase.AddCover');
+ Log.LogError('Could not load cover: "'+ Filename.ToNative +'"', 'TCoverDatabase.AddCover');
Exit;
end;
diff --git a/cmake/src/base/UDLLManager.pas b/cmake/src/base/UDLLManager.pas
deleted file mode 100644
index 3faa15bf..00000000
--- a/cmake/src/base/UDLLManager.pas
+++ /dev/null
@@ -1,292 +0,0 @@
-{* 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 UDLLManager;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-
-uses
- ModiSDK,
- UFiles;
-
-type
- TDLLMan = class
- private
- hLib: THandle;
- P_Init: fModi_Init;
- P_Draw: fModi_Draw;
- P_Finish: fModi_Finish;
- P_RData: pModi_RData;
- public
- Plugins: array of TPluginInfo;
- PluginPaths: array of string;
- Selected: ^TPluginInfo;
-
- constructor Create;
-
- procedure GetPluginList;
- procedure ClearPluginInfo(No: cardinal);
- function LoadPluginInfo(Filename: string; No: cardinal): boolean;
-
- function LoadPlugin(No: cardinal): boolean;
- procedure UnLoadPlugin;
-
- function PluginInit (const TeamInfo: TTeamInfo;
- var Playerinfo: TPlayerinfo;
- const Sentences: TSentences;
- const LoadTex: fModi_LoadTex;
- const Print: fModi_Print;
- LoadSound: fModi_LoadSound;
- PlaySound: pModi_PlaySound)
- : boolean;
- function PluginDraw (var Playerinfo: TPlayerinfo; const CurSentence: cardinal): boolean;
- function PluginFinish (var Playerinfo: TPlayerinfo): byte;
- procedure PluginRData (handle: HSTREAM; buffer: Pointer; len: dword; user: dword);
- end;
-
-var
- DLLMan: TDLLMan;
-
-const
-{$IF Defined(MSWINDOWS)}
- DLLExt = '.dll';
-{$ELSEIF Defined(DARWIN)}
- DLLExt = '.dylib';
-{$ELSEIF Defined(UNIX)}
- DLLExt = '.so';
-{$IFEND}
-
-implementation
-
-uses
- {$IFDEF MSWINDOWS}
- windows,
- {$ELSE}
- dynlibs,
- {$ENDIF}
- UPath,
- ULog,
- SysUtils;
-
-
-constructor TDLLMan.Create;
-begin
- inherited;
- SetLength(Plugins, 0);
- SetLength(PluginPaths, Length(Plugins));
- GetPluginList;
-end;
-
-procedure TDLLMan.GetPluginList;
-var
- SearchRecord: TSearchRec;
-begin
-
- if FindFirst(PluginPath + '*' + DLLExt, faAnyFile, SearchRecord) = 0 then
- begin
- repeat
- SetLength(Plugins, Length(Plugins)+1);
- SetLength(PluginPaths, Length(Plugins));
-
- if LoadPluginInfo(SearchRecord.Name, High(Plugins)) then // loaded succesful
- begin
- PluginPaths[High(PluginPaths)] := SearchRecord.Name;
- end
- else // error loading
- begin
- SetLength(Plugins, Length(Plugins)-1);
- SetLength(PluginPaths, Length(Plugins));
- end;
-
- until FindNext(SearchRecord) <> 0;
- FindClose(SearchRecord);
- end;
-end;
-
-procedure TDLLMan.ClearPluginInfo(No: cardinal);
-begin
-// set to party modi plugin
- Plugins[No].Typ := 8;
-
- Plugins[No].Name := 'unknown';
- Plugins[No].NumPlayers := 0;
-
- Plugins[No].Creator := 'Nobody';
- Plugins[No].PluginDesc := 'NO_PLUGIN_DESC';
-
- Plugins[No].LoadSong := true;
- Plugins[No].ShowScore := true;
- Plugins[No].ShowBars := true;
- Plugins[No].ShowNotes := true;
- Plugins[No].LoadVideo := true;
- Plugins[No].LoadBack := true;
-
- Plugins[No].TeamModeOnly := true;
- Plugins[No].GetSoundData := true;
- Plugins[No].Dummy := true;
-
-
- Plugins[No].BGShowFull := true;
- Plugins[No].BGShowFull_O := true;
-
- Plugins[No].ShowRateBar := true;
- Plugins[No].ShowRateBar_O := true;
-
- Plugins[No].EnLineBonus := true;
- Plugins[No].EnLineBonus_O := true;
-end;
-
-function TDLLMan.LoadPluginInfo(Filename: string; No: cardinal): boolean;
-var
- hLibg: THandle;
- Info: pModi_PluginInfo;
-// I: integer;
-begin
- Result := true;
-// clear plugin info
- ClearPluginInfo(No);
-
-{
-// workaround plugins loaded 2 times
- for i := low(pluginpaths) to high(pluginpaths) do
- if (pluginpaths[i] = filename) then
- exit;
-}
-
-// load libary
- hLibg := LoadLibrary(PChar(PluginPath + Filename));
-// if loaded
- if (hLibg <> 0) then
- begin
-// load info procedure
- @Info := GetProcAddress(hLibg, PChar('PluginInfo'));
-
-// if loaded
- if (@Info <> nil) then
- begin
-// load plugininfo
- Info(Plugins[No]);
- Result := true;
- end
- else
- Log.LogError('Could not load plugin "' + Filename + '": Info procedure not found');
-
- FreeLibrary (hLibg);
- end
- else
- Log.LogError('Could not load plugin "' + Filename + '": Libary not loaded');
-end;
-
-function TDLLMan.LoadPlugin(No: cardinal): boolean;
-begin
- Result := true;
-// load libary
- hLib := LoadLibrary(PChar(PluginPath + PluginPaths[No]));
-// if loaded
- if (hLib <> 0) then
- begin
-// load info procedure
- @P_Init := GetProcAddress (hLib, 'Init');
- @P_Draw := GetProcAddress (hLib, 'Draw');
- @P_Finish := GetProcAddress (hLib, 'Finish');
-
-// if loaded
- if (@P_Init <> nil) and (@P_Draw <> nil) and (@P_Finish <> nil) then
- begin
- Selected := @Plugins[No];
- Result := true;
- end
- else
- begin
- Log.LogError('Could not load plugin "' + PluginPaths[No] + '": Procedures not found');
- end;
- end
- else
- Log.LogError('Could not load plugin "' + PluginPaths[No] + '": Libary not loaded');
-end;
-
-procedure TDLLMan.UnLoadPlugin;
-begin
- if (hLib <> 0) then
- FreeLibrary (hLib);
-
-// Selected := nil;
- @P_Init := nil;
- @P_Draw := nil;
- @P_Finish := nil;
- @P_RData := nil;
-end;
-
-function TDLLMan.PluginInit (const TeamInfo: TTeamInfo;
- var Playerinfo: TPlayerinfo;
- const Sentences: TSentences;
- const LoadTex: fModi_LoadTex;
- const Print: fModi_Print;
- LoadSound: fModi_LoadSound;
- PlaySound: pModi_PlaySound)
- : boolean;
-var
- Methods: TMethodRec;
-begin
- Methods.LoadTex := LoadTex;
- Methods.Print := Print;
- Methods.LoadSound := LoadSound;
- Methods.PlaySound := PlaySound;
-
- if (@P_Init <> nil) then
- Result := P_Init (TeamInfo, PlayerInfo, Sentences, Methods)
- else
- Result := true
-end;
-
-function TDLLMan.PluginDraw (var Playerinfo: TPlayerinfo; const CurSentence: cardinal): boolean;
-begin
- if (@P_Draw <> nil) then
- Result := P_Draw (PlayerInfo, CurSentence)
- else
- Result := true
-end;
-
-function TDLLMan.PluginFinish (var Playerinfo: TPlayerinfo): byte;
-begin
- if (@P_Finish <> nil) then
- Result := P_Finish (PlayerInfo)
- else
- Result := 0;
-end;
-
-procedure TDLLMan.PluginRData (handle: HStream; buffer: Pointer; len: dword; user: dword);
-begin
-if (@P_RData <> nil) then
- P_RData (handle, buffer, len, user);
-end;
-
-end.
diff --git a/cmake/src/base/UDataBase.pas b/cmake/src/base/UDataBase.pas
index 0f9d88a7..cccedc69 100644
--- a/cmake/src/base/UDataBase.pas
+++ b/cmake/src/base/UDataBase.pas
@@ -34,20 +34,22 @@ interface
{$I switches.inc}
uses
- USongs,
- USong,
Classes,
- SQLiteTable3;
+ SQLiteTable3,
+ UPath,
+ USong,
+ USongs,
+ UTextEncoding;
//--------------------
-//DataBaseSystem - Class including all DB Methods
+//DataBaseSystem - Class including all DB methods
//--------------------
type
TStatType = (
- stBestScores, // Best Scores
- stBestSingers, // Best Singers
- stMostSungSong, // Most sung Songs
- stMostPopBand // Most popular Band
+ stBestScores, // Best scores
+ stBestSingers, // Best singers
+ stMostSungSong, // Most sung songs
+ stMostPopBand // Most popular band
);
// abstract super-class for statistic results
@@ -58,54 +60,57 @@ type
TStatResultBestScores = class(TStatResult)
public
- Singer: WideString;
- Score: Word;
- Difficulty: Byte;
- SongArtist: WideString;
- SongTitle: WideString;
+ Singer: UTF8String;
+ Score: word;
+ Difficulty: byte;
+ SongArtist: UTF8String;
+ SongTitle: UTF8String;
+ Date: UTF8String;
end;
TStatResultBestSingers = class(TStatResult)
public
- Player: WideString;
- AverageScore: Word;
+ Player: UTF8String;
+ AverageScore: word;
end;
TStatResultMostSungSong = class(TStatResult)
public
- Artist: WideString;
- Title: WideString;
- TimesSung: Word;
+ Artist: UTF8String;
+ Title: UTF8String;
+ TimesSung: word;
end;
TStatResultMostPopBand = class(TStatResult)
public
- ArtistName: WideString;
- TimesSungTot: Word;
+ ArtistName: UTF8String;
+ TimesSungTot: word;
end;
-
+
TDataBaseSystem = class
private
- ScoreDB: TSQLiteDatabase;
- fFilename: string;
+ ScoreDB: TSQLiteDatabase;
+ fFilename: IPath;
function GetVersion(): integer;
procedure SetVersion(Version: integer);
public
- property Filename: string read fFilename;
+ property Filename: IPath read fFilename;
destructor Destroy; override;
- procedure Init(const Filename: string);
+ procedure Init(const Filename: IPath);
+ procedure ConvertFrom101To110();
procedure ReadScore(Song: TSong);
- procedure AddScore(Song: TSong; Level: integer; const Name: WideString; Score: integer);
+ 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;
+ function GetStats(Typ: TStatType; Count: byte; Page: cardinal; Reversed: boolean): TList;
procedure FreeStats(StatList: TList);
- function GetTotalEntrys(Typ: TStatType): Cardinal;
+ function GetTotalEntrys(Typ: TStatType): cardinal;
function GetStatReset: TDateTime;
+ function FormatDate(time_stamp: integer): UTF8String;
end;
var
@@ -114,53 +119,72 @@ var
implementation
uses
- ULog,
DateUtils,
+ ULanguage,
StrUtils,
- SysUtils;
-
+ 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';
+ cUS_Statistics_Info = 'us_statistics_info';
(**
- * Opens Database and Create Tables if not Exist
+ * Open database and create tables if they do not exist
*)
-procedure TDataBaseSystem.Init(const Filename: string);
+procedure TDataBaseSystem.Init(const Filename: IPath);
var
- Version: integer;
+ Version: integer;
+ finalizeConversion: boolean;
begin
if Assigned(ScoreDB) then
Exit;
- Log.LogStatus('Initializing database: "'+Filename+'"', 'TDataBaseSystem.Init');
+ Log.LogStatus('Initializing database: "' + Filename.ToNative + '"', 'TDataBaseSystem.Init');
try
-
- // Open Database
- ScoreDB := TSQLiteDatabase.Create(Filename);
+
+ // open database
+ ScoreDB := TSQLiteDatabase.Create(Filename.ToUTF8);
fFilename := Filename;
- // Close and delete outdated file
Version := GetVersion();
- if ((Version <> 0) and (Version <> cDBVersion)) then
+
+ // 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 cover-database file found', 'TDataBaseSystem.Init');
- // Close and delete outdated file
- ScoreDB.Free;
- if (not DeleteFile(Filename)) then
- raise Exception.Create('Could not delete ' + Filename);
- // Reopen
- ScoreDB := TSQLiteDatabase.Create(Filename);
- Version := 0;
+ 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,
@@ -169,30 +193,44 @@ begin
// 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+'] (' +
+ 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' +
+ '[Score] INTEGER NOT NULL, ' +
+ '[Date] INTEGER NULL' +
');');
- ScoreDB.ExecSQL('CREATE TABLE IF NOT EXISTS ['+cUS_Songs+'] (' +
+ 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' +
+ '[TimesPlayed] INTEGER NOT NULL, ' +
+ '[Rating] INTEGER NULL' +
');');
- if not ScoreDB.TableExists(cUS_Statistics_Info) then
+ //add column date to cUS-Scores
+ if not ScoreDB.ContainsColumn(cUS_Scores, 'Date') then
begin
- 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())]));
+ 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
@@ -206,6 +244,115 @@ begin
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 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;
@@ -216,33 +363,55 @@ begin
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;
+ 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] FROM ['+cUS_Scores+'] ' +
+ 'SELECT [Difficulty], [Player], [Score], [Date] FROM [' + cUS_Scores + '] ' +
'WHERE [SongID] = (' +
- 'SELECT [ID] FROM ['+cUS_Songs+'] ' +
+ 'SELECT [ID] FROM [' + cUS_Songs + '] ' +
'WHERE [Artist] = ? AND [Title] = ? ' +
'LIMIT 1) ' +
- 'ORDER BY [Score] DESC LIMIT 15',
- [UTF8Encode(Song.Artist), UTF8Encode(Song.Title)]);
+ 'ORDER BY [Score] DESC;', //no LIMIT! see filter below!
+ [Song.Artist, Song.Title]);
// Empty Old Scores
- SetLength(Song.Score[0], 0);
- SetLength(Song.Score[1], 0);
- SetLength(Song.Score[2], 0);
+ 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
@@ -252,12 +421,31 @@ begin
if ((Difficulty >= 0) and (Difficulty <= 2)) and
(Length(Song.Score[Difficulty]) < 5) then
begin
- SetLength(Song.Score[Difficulty], Length(Song.Score[Difficulty]) + 1);
+ //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 :=
- UTF8Decode(TableData.FieldByName['Player']);
- Song.Score[Difficulty, High(Song.Score[Difficulty])].Score :=
+ 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;
@@ -277,70 +465,43 @@ end;
(**
* Adds one new score to DB
*)
-procedure TDataBaseSystem.AddScore(Song: TSong; Level: integer; const Name: WideString; Score: integer);
+procedure TDataBaseSystem.AddScore(Song: TSong; Level: integer; const Name: UTF8String; Score: integer);
var
- ID: Integer;
+ ID: integer;
TableData: TSQLiteTable;
begin
if not Assigned(ScoreDB) then
Exit;
- // Prevent 0 Scores from being added
- if (Score <= 0) 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+'] ' +
+ 'SELECT [ID] FROM [' + cUS_Songs + '] ' +
'WHERE [Artist] = ? AND [Title] = ?',
- [UTF8Encode(Song.Artist), UTF8Encode(Song.Title)]);
+ [Song.Artist, Song.Title]);
if (ID = 0) then
begin
// Create song if it does not exist
ScoreDB.ExecSQL(
- 'INSERT INTO ['+cUS_Songs+'] ' +
+ 'INSERT INTO [' + cUS_Songs + '] ' +
'([ID], [Artist], [Title], [TimesPlayed]) VALUES ' +
'(NULL, ?, ?, 0);',
- [UTF8Encode(Song.Artist), UTF8Encode(Song.Title)]);
+ [Song.Artist, Song.Title]);
// Get song-ID
ID := ScoreDB.GetLastInsertRowID();
end;
// Create new entry
ScoreDB.ExecSQL(
- 'INSERT INTO ['+cUS_Scores+'] ' +
- '([SongID] ,[Difficulty], [Player], [Score]) VALUES ' +
- '(?, ?, ?, ?);',
- [ID, Level, UTF8Encode(Name), Score]);
-
- // Delete last position when there are more than 5 entrys.
- // Fixes crash when there are > 5 ScoreEntrys
- // Note: GetUniTable is not applicable here, as the results are used while
- // table entries are deleted.
- TableData := ScoreDB.GetTable(
- 'SELECT [Player], [Score] FROM ['+cUS_Scores+'] ' +
- 'WHERE [SongID] = ' + InttoStr(ID) + ' AND ' +
- '[Difficulty] = ' + InttoStr(Level) +' ' +
- 'ORDER BY [Score] DESC LIMIT -1 OFFSET 5');
-
- while (not TableData.EOF) do
- begin
- // Note: Score is an int-value, so in contrast to Player, we do not bind
- // this value. Otherwise we had to convert the string to an int to avoid
- // an automatic cast of this field to the TEXT type (although it might even
- // work that way).
- ScoreDB.ExecSQL(
- 'DELETE FROM ['+cUS_Scores+'] ' +
- 'WHERE [SongID] = ' + InttoStr(ID) + ' AND ' +
- '[Difficulty] = ' + InttoStr(Level) +' AND ' +
- '[Player] = ? AND ' +
- '[Score] = ' + TableData.FieldByName['Score'],
- [TableData.FieldByName['Player']]);
-
- TableData.Next;
- end;
+ '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');
@@ -350,21 +511,21 @@ begin
end;
(**
- * Not needed with new System.
- * Used for increment played count
+ * 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+'] ' +
+ 'UPDATE [' + cUS_Songs + '] ' +
'SET [TimesPlayed] = [TimesPlayed] + 1 ' +
'WHERE [Title] = ? AND [Artist] = ?;',
- [UTF8Encode(Song.Title), UTF8Encode(Song.Artist)]);
+ [Song.Title, Song.Artist]);
except on E: Exception do
Log.LogError(E.Message, 'TDataBaseSystem.WriteScore');
end;
@@ -376,11 +537,11 @@ end;
* 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;
+function TDataBaseSystem.GetStats(Typ: TStatType; Count: byte; Page: cardinal; Reversed: boolean): TList;
var
- Query: String;
+ Query: string;
TableData: TSQLiteUniTable;
- Stat: TStatResult;
+ Stat: TStatResult;
begin
Result := nil;
@@ -392,19 +553,19 @@ begin
// Create query
case Typ of
stBestScores: begin
- Query := 'SELECT [Player], [Difficulty], [Score], [Artist], [Title] FROM ['+cUS_Scores+'] ' +
- 'INNER JOIN ['+cUS_Songs+'] ON ([SongID] = [ID]) ORDER BY [Score]';
+ 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+'] ' +
+ 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+'] ' +
+ Query := 'SELECT [Artist], [Title], [TimesPlayed] FROM [' + cUS_Songs + '] ' +
'ORDER BY [TimesPlayed]';
end;
stMostPopBand: begin
- Query := 'SELECT [Artist], SUM([TimesPlayed]) FROM ['+cUS_Songs+'] ' +
+ Query := 'SELECT [Artist], SUM([TimesPlayed]) FROM [' + cUS_Songs + '] ' +
'GROUP BY [Artist] ORDER BY SUM([TimesPlayed])';
end;
end;
@@ -437,18 +598,19 @@ begin
Stat := TStatResultBestScores.Create;
with TStatResultBestScores(Stat) do
begin
- Singer := UTF8Decode(TableData.Fields[0]);
+ Singer := TableData.Fields[0];
Difficulty := TableData.FieldAsInteger(1);
Score := TableData.FieldAsInteger(2);
- SongArtist := UTF8Decode(TableData.Fields[3]);
- SongTitle := UTF8Decode(TableData.Fields[4]);
+ 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 := UTF8Decode(TableData.Fields[0]);
+ Player := TableData.Fields[0];
AverageScore := TableData.FieldAsInteger(1);
end;
end;
@@ -456,8 +618,8 @@ begin
Stat := TStatResultMostSungSong.Create;
with TStatResultMostSungSong(Stat) do
begin
- Artist := UTF8Decode(TableData.Fields[0]);
- Title := UTF8Decode(TableData.Fields[1]);
+ Artist := TableData.Fields[0];
+ Title := TableData.Fields[1];
TimesSung := TableData.FieldAsInteger(2);
end;
end;
@@ -465,7 +627,7 @@ begin
Stat := TStatResultMostPopBand.Create;
with TStatResultMostPopBand(Stat) do
begin
- ArtistName := UTF8Decode(TableData.Fields[0]);
+ ArtistName := TableData.Fields[0];
TimesSungTot := TableData.FieldAsInteger(1);
end;
end
@@ -484,21 +646,21 @@ end;
procedure TDataBaseSystem.FreeStats(StatList: TList);
var
- I: integer;
+ Index: integer;
begin
if (StatList = nil) then
Exit;
- for I := 0 to StatList.Count-1 do
- TStatResult(StatList[I]).Free;
+ 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;
+function TDataBaseSystem.GetTotalEntrys(Typ: TStatType): cardinal;
var
- Query: String;
+ Query: string;
begin
Result := 0;
@@ -509,13 +671,13 @@ begin
// Create query
case Typ of
stBestScores:
- Query := 'SELECT COUNT([SongID]) FROM ['+cUS_Scores+'];';
+ Query := 'SELECT COUNT([SongID]) FROM [' + cUS_Scores + '];';
stBestSingers:
- Query := 'SELECT COUNT(DISTINCT [Player]) FROM ['+cUS_Scores+'];';
+ Query := 'SELECT COUNT(DISTINCT [Player]) FROM [' + cUS_Scores + '];';
stMostSungSong:
- Query := 'SELECT COUNT([ID]) FROM ['+cUS_Songs+'];';
+ Query := 'SELECT COUNT([ID]) FROM [' + cUS_Songs + '];';
stMostPopBand:
- Query := 'SELECT COUNT(DISTINCT [Artist]) FROM ['+cUS_Songs+'];';
+ Query := 'SELECT COUNT(DISTINCT [Artist]) FROM [' + cUS_Songs + '];';
end;
Result := ScoreDB.GetTableValue(Query);
@@ -538,7 +700,7 @@ begin
Exit;
try
- Query := 'SELECT [ResetTime] FROM ['+cUS_Statistics_Info+'];';
+ Query := 'SELECT [ResetTime] FROM [' + cUS_Statistics_Info + '];';
Result := UnixToDateTime(ScoreDB.GetTableValue(Query));
except on E: Exception do
Log.LogError(E.Message, 'TDataBaseSystem.GetStatReset');
diff --git a/cmake/src/base/UDraw.pas b/cmake/src/base/UDraw.pas
index 1783986f..308526b8 100644
--- a/cmake/src/base/UDraw.pas
+++ b/cmake/src/base/UDraw.pas
@@ -35,11 +35,9 @@ interface
uses
UThemes,
- ModiSDK,
UGraphicClasses;
procedure SingDraw;
-procedure SingModiDraw (PlayerInfo: TPlayerInfo);
procedure SingDrawBackground;
procedure SingDrawOscilloscope(X, Y, W, H: real; NrSound: integer);
procedure SingDrawNoteLines(Left, Top, Right: real; Space: integer);
@@ -86,7 +84,6 @@ uses
Math,
gl,
TextGL,
- UDLLManager,
UDrawTexture,
UGraphic,
UIni,
@@ -96,7 +93,6 @@ uses
UMusic,
URecord,
UScreenSing,
- UScreenSingModi,
UTexture;
procedure SingDrawBackground;
@@ -258,19 +254,21 @@ begin
// 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;
+ PlayerNumber := NrLines + 1; // Player 1 is 0
+ NrLines := 0;
-// exploit done
+ // exploit done
- glColor3f(1, 1, 1);
- glEnable(GL_TEXTURE_2D);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ 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);
+ 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
@@ -285,16 +283,17 @@ begin
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
+
+ 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
+ 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;
@@ -309,35 +308,35 @@ begin
glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
glEnd;
- //We keep the postion of the top left corner b4 it's overwritten
+ //We keep the postion of the top left corner b4 it's overwritten
GoldenStarPos := Rec.Left;
- //done
+ //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;
+ // 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;
+ 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;
+ 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
@@ -345,13 +344,14 @@ begin
GoldenRec.SaveGoldenStarsRec(GoldenStarPos, Rec.Top, Rec.Right, Rec.Bottom);
end;
- end; // if not FreeStyle
- end; // with
- end; // for
- end; // with
+ end; // if not FreeStyle
+ end; // with
+ end; // for
+ end; // with
- glDisable(GL_BLEND);
- glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+ glDisable(GL_TEXTURE_2D);
+ end;
end;
// draw sung notes
@@ -481,7 +481,7 @@ var
W, H: real;
lTmpA, lTmpB: real;
begin
- if (Player[PlayerIndex].ScoreTotalInt >= 0) then
+ 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);
@@ -683,20 +683,25 @@ begin
// draw note-lines
- if (PlayersPlay = 1) and (Ini.NoteLines = 1) then
+ // 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
- SingDrawNoteLines(NR.Left + 10*ScreenX, Skin_P1_NotesB - 105, NR.Right + 10*ScreenX, 15);
- SingDrawNoteLines(NR.Left + 10*ScreenX, Skin_P2_NotesB - 105, NR.Right + 10*ScreenX, 15);
+ 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
- SingDrawNoteLines(NR.Left + 10*ScreenX, 120, NR.Right + 10*ScreenX, 12);
- SingDrawNoteLines(NR.Left + 10*ScreenX, 245, NR.Right + 10*ScreenX, 12);
- SingDrawNoteLines(NR.Left + 10*ScreenX, 370, NR.Right + 10*ScreenX, 12);
+ 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
@@ -895,259 +900,6 @@ begin
glDisable(GL_TEXTURE_2D);
end;
-// q'n'd for using the game mode dll's
-procedure SingModiDraw (PlayerInfo: TPlayerInfo);
-var
- NR: TRecR;
-begin
- // positions
- if Ini.SingWindow = 0 then
- begin
- NR.Left := 120;
- end
- else
- begin
- NR.Left := 20;
- end;
-
- NR.Right := 780;
- NR.Width := NR.Right - NR.Left;
- NR.WMid := NR.Width / 2;
- NR.Mid := NR.Left + NR.WMid;
-
- // time bar
- SingDrawTimeBar();
-
- if DLLMan.Selected.ShowNotes then
- begin
- if PlayersPlay = 1 then
- SingDrawNoteLines(NR.Left + 10*ScreenX, Skin_P2_NotesB - 105, NR.Right + 10*ScreenX, 15);
- if (PlayersPlay = 2) or (PlayersPlay = 4) then
- begin
- SingDrawNoteLines(NR.Left + 10*ScreenX, Skin_P1_NotesB - 105, NR.Right + 10*ScreenX, 15);
- SingDrawNoteLines(NR.Left + 10*ScreenX, Skin_P2_NotesB - 105, NR.Right + 10*ScreenX, 15);
- end;
-
- if (PlayersPlay = 3) or (PlayersPlay = 6) then
- begin
- SingDrawNoteLines(NR.Left + 10*ScreenX, 120, NR.Right + 10*ScreenX, 12);
- SingDrawNoteLines(NR.Left + 10*ScreenX, 245, NR.Right + 10*ScreenX, 12);
- SingDrawNoteLines(NR.Left + 10*ScreenX, 370, NR.Right + 10*ScreenX, 12);
- end;
- end;
-
- // Draw Lyrics
- ScreenSingModi.Lyrics.Draw(LyricsState.MidBeat);
- // TODO: Lyrics helper
-
- // oscilloscope | the thing that moves when you yell into your mic (imho)
- if (((Ini.Oscilloscope = 1) and (DLLMan.Selected.ShowRateBar_O)) and (not DLLMan.Selected.ShowRateBar)) then
- begin
- if PlayersPlay = 1 then
- if PlayerInfo.Playerinfo[0].Enabled then
- SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0);
-
- if PlayersPlay = 2 then
- begin
- if PlayerInfo.Playerinfo[0].Enabled then
- SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0);
- if PlayerInfo.Playerinfo[1].Enabled then
- SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 1);
- end;
-
- if PlayersPlay = 4 then
- begin
- if ScreenAct = 1 then
- begin
- if PlayerInfo.Playerinfo[0].Enabled then
- SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0);
- if PlayerInfo.Playerinfo[1].Enabled then
- SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 1);
- end;
- if ScreenAct = 2 then
- begin
- if PlayerInfo.Playerinfo[2].Enabled then
- SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 2);
- if PlayerInfo.Playerinfo[3].Enabled then
- SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 3);
- end;
- end;
-
- if PlayersPlay = 3 then
- begin
- if PlayerInfo.Playerinfo[0].Enabled then
- SingDrawOscilloscope( 75 + 10*ScreenX, 95, 100, 20, 0);
- if PlayerInfo.Playerinfo[1].Enabled then
- SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 1);
- if PlayerInfo.Playerinfo[2].Enabled then
- SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 2);
- end;
-
- if PlayersPlay = 6 then
- begin
- if ScreenAct = 1 then
- begin
- if PlayerInfo.Playerinfo[0].Enabled then
- SingDrawOscilloscope( 75 + 10*ScreenX, 95, 100, 20, 0);
- if PlayerInfo.Playerinfo[1].Enabled then
- SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 1);
- if PlayerInfo.Playerinfo[2].Enabled then
- SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 2);
- end;
- if ScreenAct = 2 then
- begin
- if PlayerInfo.Playerinfo[3].Enabled then
- SingDrawOscilloscope( 75 + 10*ScreenX, 95, 100, 20, 3);
- if PlayerInfo.Playerinfo[4].Enabled then
- SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 4);
- if PlayerInfo.Playerinfo[5].Enabled then
- SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 5);
- end;
- end;
-
- end;
-
-// resize the notes 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;
-
- if (DLLMAn.Selected.ShowNotes and DLLMan.Selected.LoadSong) then
- begin
- if (PlayersPlay = 1) and PlayerInfo.Playerinfo[0].Enabled then
- begin
- SingDrawPlayerBGLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 0, 0, 15);
- SingDrawLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 0, 15);
- SingDrawPlayerLine(NR.Left + 20, Skin_P2_NotesB, NR.Width - 40, 0, 15);
- end;
-
- if PlayersPlay = 2 then
- begin
- if PlayerInfo.Playerinfo[0].Enabled then
- begin
- SingDrawPlayerBGLine(NR.Left + 20, Skin_P1_NotesB, NR.Right - 20, 0, 0, 15);
- SingDrawLine(NR.Left + 20, Skin_P1_NotesB, NR.Right - 20, 0, 15);
- SingDrawPlayerLine(NR.Left + 20, Skin_P1_NotesB, NR.Width - 40, 0, 15);
- end;
- if PlayerInfo.Playerinfo[1].Enabled then
- begin
- SingDrawPlayerBGLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 0, 1, 15);
- SingDrawLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 0, 15);
- SingDrawPlayerLine(NR.Left + 20, Skin_P2_NotesB, NR.Width - 40, 1, 15);
- end;
-
- end;
-
- if PlayersPlay = 3 then
- begin
- NotesW := NotesW * 0.8;
- NotesH := NotesH * 0.8;
-
- if PlayerInfo.Playerinfo[0].Enabled then
- begin
- SingDrawPlayerBGLine(NR.Left + 20, 120+95, NR.Right - 20, 0, 0, 12);
- SingDrawLine(NR.Left + 20, 120+95, NR.Right - 20, 0, 12);
- SingDrawPlayerLine(NR.Left + 20, 120+95, NR.Width - 40, 0, 12);
- end;
-
- if PlayerInfo.Playerinfo[1].Enabled then
- begin
- SingDrawPlayerBGLine(NR.Left + 20, 245+95, NR.Right - 20, 0, 1, 12);
- SingDrawLine(NR.Left + 20, 245+95, NR.Right - 20, 0, 12);
- SingDrawPlayerLine(NR.Left + 20, 245+95, NR.Width - 40, 1, 12);
- end;
-
- if PlayerInfo.Playerinfo[2].Enabled then
- begin
- SingDrawPlayerBGLine(NR.Left + 20, 370+95, NR.Right - 20, 0, 2, 12);
- SingDrawLine(NR.Left + 20, 370+95, NR.Right - 20, 0, 12);
- SingDrawPlayerLine(NR.Left + 20, 370+95, NR.Width - 40, 2, 12);
- end;
- 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;
-
- SingDrawLine(NR.Left + 20, Skin_P1_NotesB, NR.Right - 20, 0, 15);
- SingDrawLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 0, 15);
-
- 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;
-
- SingDrawLine(NR.Left + 20, 120+95, NR.Right - 20, 0, 12);
- SingDrawLine(NR.Left + 20, 245+95, NR.Right - 20, 0, 12);
- SingDrawLine(NR.Left + 20, 370+95, NR.Right - 20, 0, 12);
-
- 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;
- end;
-
- glDisable(GL_BLEND);
- glDisable(GL_TEXTURE_2D);
-end;
-
{//SingBar Mod
procedure SingDrawSingbar(X, Y, W, H: real; Percent: integer);
var
diff --git a/cmake/src/base/UEditorLyrics.pas b/cmake/src/base/UEditorLyrics.pas
index ef9d8dd6..0eacd1f9 100644
--- a/cmake/src/base/UEditorLyrics.pas
+++ b/cmake/src/base/UEditorLyrics.pas
@@ -74,7 +74,7 @@ type
procedure SetSize(Value: real);
procedure SetSelected(Value: integer);
procedure SetFontStyle(Value: integer);
- procedure AddWord(Text: string);
+ procedure AddWord(Text: UTF8String);
procedure Refresh;
public
ColR: real;
@@ -179,7 +179,7 @@ begin
FontStyleI := Value;
end;
-procedure TEditorLyrics.AddWord(Text: string);
+procedure TEditorLyrics.AddWord(Text: UTF8String);
var
WordNum: integer;
begin
diff --git a/cmake/src/base/UFiles.pas b/cmake/src/base/UFiles.pas
index 0495dfbb..5a258e3e 100644
--- a/cmake/src/base/UFiles.pas
+++ b/cmake/src/base/UFiles.pas
@@ -34,24 +34,23 @@ interface
uses
SysUtils,
+ Classes,
ULog,
UMusic,
USongs,
- USong;
+ USong,
+ UPath;
procedure ResetSingTemp;
-function SaveSong(Song: TSong; Lines: TLines; Name: string; Relative: boolean): boolean;
+type
+ TSaveSongResult = (ssrOK, ssrFileError, ssrEncodingError);
-var
- SongFile: TextFile; // all procedures in this unit operates on this file
- FileLineNo: integer; //Line which is readed at Last, for error reporting
-
- // variables available for all procedures
- Base : array[0..1] of integer;
- Rel : array[0..1] of integer;
- Mult : integer = 1;
- MultBPM : integer = 4;
+{**
+ * 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
@@ -59,7 +58,9 @@ uses
TextGL,
UIni,
UNote,
- UPlatform;
+ UPlatform,
+ UUnicodeUtils,
+ UTextEncoding;
//--------------------
// Resets the temporary Sentence Arrays for each Player and some other Variables
@@ -77,101 +78,135 @@ begin
Player[Count].LengthNote := 0;
Player[Count].HighNote := -1;
end;
-
- (* FIXME
- //Reset Path and Filename Values to Prevent Errors in Editor
- if assigned( CurrentSong ) then
- begin
- SetLength(CurrentSong.BPM, 0);
- CurrentSong.Path := '';
- CurrentSong.FileName := '';
- end;
- *)
-
-// CurrentSong := nil;
end;
-
//--------------------
// Saves a Song
//--------------------
-function SaveSong(Song: TSong; Lines: TLines; Name: string; Relative: boolean): boolean;
+function SaveSong(const Song: TSong; const Lines: TLines; const Name: IPath; Relative: boolean): TSaveSongResult;
var
C: integer;
N: integer;
- S: string;
+ S: AnsiString;
B: integer;
- RelativeSubTime: integer;
- NoteState: String;
+ RelativeSubTime: integer;
+ NoteState: AnsiString;
+ SongFile: TTextFileStream;
-begin
-// Relative := true; // override (idea - use shift+S to save with relative)
- AssignFile(SongFile, Name);
- Rewrite(SongFile);
-
- Writeln(SongFile, '#TITLE:' + Song.Title + '');
- Writeln(SongFile, '#ARTIST:' + Song.Artist);
-
- if Song.Creator <> '' then Writeln(SongFile, '#CREATOR:' + Song.Creator);
- if Song.Edition <> 'Unknown' then Writeln(SongFile, '#EDITION:' + Song.Edition);
- if Song.Genre <> 'Unknown' then Writeln(SongFile, '#GENRE:' + Song.Genre);
- if Song.Language <> 'Unknown' then Writeln(SongFile, '#LANGUAGE:' + Song.Language);
-
- Writeln(SongFile, '#MP3:' + Song.Mp3);
-
- if Song.Cover <> '' then Writeln(SongFile, '#COVER:' + Song.Cover);
- if Song.Background <> '' then Writeln(SongFile, '#BACKGROUND:' + Song.Background);
- if Song.Video <> '' then Writeln(SongFile, '#VIDEO:' + Song.Video);
- if Song.VideoGAP <> 0 then Writeln(SongFile, '#VIDEOGAP:' + FloatToStr(Song.VideoGAP));
- if Song.Resolution <> 4 then Writeln(SongFile, '#RESOLUTION:' + IntToStr(Song.Resolution));
- if Song.NotesGAP <> 0 then Writeln(SongFile, '#NOTESGAP:' + IntToStr(Song.NotesGAP));
- if Song.Start <> 0 then Writeln(SongFile, '#START:' + FloatToStr(Song.Start));
- if Song.Finish <> 0 then Writeln(SongFile, '#END:' + IntToStr(Song.Finish));
- if Relative then Writeln(SongFile, '#RELATIVE:yes');
-
- Writeln(SongFile, '#BPM:' + FloatToStr(Song.BPM[0].BPM / 4));
- Writeln(SongFile, '#GAP:' + FloatToStr(Song.GAP));
-
- RelativeSubTime := 0;
- for B := 1 to High(CurrentSong.BPM) do
- Writeln(SongFile, 'B ' + FloatToStr(CurrentSong.BPM[B].StartBeat) + ' ' + FloatToStr(CurrentSong.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) + ' ' + Text;
-
-
- Writeln(SongFile, S);
- end; // with
- end; // N
-
- if C < Lines.High then begin // don't write end of last sentence
- 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;
- Writeln(SongFile, S);
- end;
+ function EncodeToken(const Str: UTF8String): RawByteString;
+ var
+ Success: boolean;
+ begin
+ Success := EncodeStringUTF8(Str, Result, Song.Encoding);
+ if (not Success) then
+ SaveSong := ssrEncodingError;
+ end;
- end; // C
+ 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;
- Writeln(SongFile, 'E');
- CloseFile(SongFile);
+ end;
- Result := true;
+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);
+
+ 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/cmake/src/base/UFilesystem.pas b/cmake/src/base/UFilesystem.pas
new file mode 100644
index 00000000..805bcfe5
--- /dev/null
+++ b/cmake/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/cmake/src/base/UFont.pas b/cmake/src/base/UFont.pas
index a72bca21..49a19a1a 100644
--- a/cmake/src/base/UFont.pas
+++ b/cmake/src/base/UFont.pas
@@ -41,18 +41,23 @@ interface
{$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}
- Math,
- Classes,
- SysUtils;
+ UPath;
type
@@ -60,7 +65,7 @@ type
TGLubyteArray = array[0 .. (MaxInt div SizeOf(GLubyte))-1] of GLubyte;
TGLubyteDynArray = array of GLubyte;
- TWideStringArray = array of WideString;
+ TUCS4StringArray = array of UCS4String;
TGLColor = packed record
case byte of
@@ -86,6 +91,8 @@ type
Width, Height: integer;
end;
+ EFontError = class(Exception);
+
{**
* Abstract base class representing a glyph.
*}
@@ -117,6 +124,7 @@ type
procedure ResetIntern();
protected
+ fFilename: IPath;
fStyle: TFontStyle;
fUseKerning: boolean;
fLineSpacing: single; // must be inited by subclass
@@ -126,34 +134,34 @@ type
{**
* Splits lines in Text seperated by newline (char-code #13).
- * @param Text UTF-8 encoded string
- * @param Lines splitted WideString lines
+ * @param Text UCS-4 encoded string
+ * @param Lines splitted UCS4String lines
*}
- procedure SplitLines(const Text: UTF8String; var Lines: TWideStringArray);
+ procedure SplitLines(const Text: UCS4String; var Lines: TUCS4StringArray);
{**
- * Print an array of WideStrings. Each array-item is a line of text.
+ * 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: TWideStringArray); overload; virtual;
+ procedure Print(const Text: TUCS4StringArray); overload; virtual;
{**
* Draws an underline.
*}
- procedure DrawUnderline(const Text: WideString); virtual;
+ procedure DrawUnderline(const Text: UCS4String); virtual;
{**
* Renders (one) line of text.
*}
- procedure Render(const Text: WideString); virtual; abstract;
+ 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: TWideStringArray; Advance: boolean): TBoundsDbl; overload; virtual; abstract;
+ function BBox(const Text: TUCS4StringArray; Advance: boolean): TBoundsDbl; overload; virtual; abstract;
{**
* Resets all user settings to default values.
@@ -182,15 +190,17 @@ type
property ReflectionPass: boolean read fReflectionPass write SetReflectionPass;
public
- constructor Create();
+ 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: string); overload;
+ procedure Print(const Text: UTF8String); overload;
{**
* Calculates the bounding box (width and height) around Text.
@@ -203,10 +213,18 @@ type
* 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 }
@@ -223,6 +241,8 @@ type
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
@@ -242,16 +262,16 @@ type
procedure ResetIntern();
protected
- fScale: single; //**< current height to base-font height ratio
- fAspect: single; //**< width to height aspect
+ 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: WideString); override;
- procedure Print(const Text: TWideStringArray); override;
- function BBox(const Text: TWideStringArray; Advance: boolean): TBoundsDbl; override;
+ 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.
@@ -280,8 +300,8 @@ type
procedure SetHeight(Height: single); virtual;
function GetHeight(): single; override;
- procedure SetAspect(Aspect: single); virtual;
- function GetAspect(): single; virtual;
+ procedure SetStretch(Stretch: single); virtual;
+ function GetStretch(): single; virtual;
function GetAscender(): single; override;
function GetDescender(): single; override;
procedure SetLineSpacing(Spacing: single); override;
@@ -316,13 +336,13 @@ type
{** Font height }
property Height: single read GetHeight write SetHeight;
- {** Factor for font stretching (NewWidth = Width*Aspect), 1.0 by default }
- property Aspect: single read GetAspect write SetAspect;
+ {** 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 WideChar
+ * Used for the second cache level. Indexed by the LSB of the UCS4Char
* char-code.
*}
PGlyphTable = ^TGlyphTable;
@@ -332,7 +352,7 @@ type
* 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 WideChar character code
+ * 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.
@@ -359,22 +379,22 @@ type
* Add glyph Glyph with char-code ch to the cache.
* @returns @true on success, @false otherwise
*}
- function AddGlyph(ch: WideChar; const Glyph: TGlyph): boolean;
+ function AddGlyph(ch: UCS4Char; const Glyph: TGlyph): boolean;
{**
* Removes the glyph with char-code ch from the cache.
*}
- procedure DeleteGlyph(ch: WideChar);
+ procedure DeleteGlyph(ch: UCS4Char);
{**
* Removes the glyph with char-code ch from the cache.
*}
- function GetGlyph(ch: WideChar): TGlyph;
+ function GetGlyph(ch: UCS4Char): TGlyph;
{**
* Checks if a glyph with char-code ch is cached.
*}
- function HasGlyph(ch: WideChar): boolean;
+ function HasGlyph(ch: UCS4Char): boolean;
{**
* Remove and free all cached glyphs. If KeepBaseSet is set to
@@ -408,16 +428,16 @@ type
* 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: WideChar): TGlyph;
+ function GetGlyph(ch: UCS4Char): TGlyph;
{**
* Callback to create (load) a glyph with char-code ch.
* Implemented by subclasses.
*}
- function LoadGlyph(ch: WideChar): TGlyph; virtual; abstract;
+ function LoadGlyph(ch: UCS4Char): TGlyph; virtual; abstract;
public
- constructor Create();
+ constructor Create(const Filename: IPath);
destructor Destroy(); override;
{**
@@ -431,11 +451,55 @@ type
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
@@ -458,13 +522,13 @@ type
* The bitmap must be 2* pixels wider and higher than the
* original glyph's bitmap with the latter centered in it.
*}
- procedure Extrude(var TexBuffer: TGLubyteDynArray; Outset: single);
+ 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 Exception if the glyph could not be initialized
+ * @raises EFontError if the glyph could not be initialized
*}
procedure CreateTexture(LoadFlags: FT_Int32);
@@ -477,7 +541,7 @@ type
* Creates a glyph with char-code ch from font Font.
* @param LoadFlags flags passed to FT_Load_Glyph()
*}
- constructor Create(Font: TFTFont; ch: WideChar; Outset: single;
+ constructor Create(Font: TFTFont; ch: UCS4Char; Outset: single;
LoadFlags: FT_Int32);
destructor Destroy(); override;
@@ -488,29 +552,36 @@ type
{** 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
- fFilename: string; //**< filename of the font-file
+ fFace: TFTFontFace; //**< Default font face
fSize: integer; //**< Font base size (in pixels)
fOutset: single; //**< size of outset extrusion (in pixels)
- fFace: FT_Face; //**< Holds the height of the font
fLoadFlags: FT_Int32; //**< FT glpyh load-flags
- fFontUnitScale: TPositionDbl; //**< FT font-units to pixel ratio
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: WideChar): TGlyph; override;
+ function LoadGlyph(ch: UCS4Char): TGlyph; override;
- procedure Render(const Text: WideString); override;
- function BBox(const Text: TWideStringArray; Advance: boolean): TBoundsDbl; override;
+ procedure Render(const Text: UCS4String); override;
+ function BBox(const Text: TUCS4StringArray; Advance: boolean): TBoundsDbl; override;
function GetHeight(): single; override;
function GetAscender(): single; override;
@@ -518,17 +589,15 @@ type
function GetUnderlinePosition(): single; override;
function GetUnderlineThickness(): single; override;
- property Face: FT_Face read fFace;
-
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 Exception if the font-file could not be loaded
+ * @raises EFontError if the font-file could not be loaded
*}
- constructor Create(const Filename: string;
+ constructor Create(const Filename: IPath;
Size: integer; Outset: single = 0.0;
LoadFlags: FT_Int32 = FT_LOAD_DEFAULT);
@@ -539,11 +608,19 @@ type
{** @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)
@@ -557,11 +634,27 @@ type
* 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: string;
+ constructor Create(const Filename: IPath;
Size: integer; OutsetAmount: single = 0.0;
UseMipmaps: boolean = true);
+ procedure AddFallback(const Filename: IPath); override;
+
{** @seealso TGlyphCache.FlushCache }
procedure FlushCache(KeepBaseSet: boolean);
@@ -576,7 +669,6 @@ type
*}
TFTOutlineFont = class(TFont)
private
- fFilename: string;
fSize: integer;
fOutset: single;
fInnerFont, fOutlineFont: TFTFont;
@@ -585,9 +677,9 @@ type
procedure ResetIntern();
protected
- procedure DrawUnderline(const Text: WideString); override;
- procedure Render(const Text: WideString); override;
- function BBox(const Text: TWideStringArray; Advance: boolean): TBoundsDbl; override;
+ 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;
@@ -603,7 +695,7 @@ type
procedure SetReflectionPass(Enable: boolean); override;
public
- constructor Create(const Filename: string;
+ constructor Create(const Filename: IPath;
Size: integer; Outset: single;
LoadFlags: FT_Int32 = FT_LOAD_DEFAULT);
destructor Destroy; override;
@@ -618,6 +710,8 @@ type
{** @seealso TGlyphCache.FlushCache }
procedure FlushCache(KeepBaseSet: boolean);
+ procedure AddFallback(const Filename: IPath); override;
+
{** @seealso TFont.Reset }
procedure Reset(); override;
@@ -637,7 +731,7 @@ type
function CreateMipmap(Level: integer; Scale: single): TFont; override;
public
- constructor Create(const Filename: string;
+ constructor Create(const Filename: IPath;
Size: integer; OutsetAmount: single;
UseMipmaps: boolean = true);
@@ -647,6 +741,8 @@ type
{** @seealso TGlyphCache.FlushCache }
procedure FlushCache(KeepBaseSet: boolean);
+ procedure AddFallback(const Filename: IPath); override;
+
{** Outset size }
property Outset: single read GetOutset;
end;
@@ -672,18 +768,18 @@ type
procedure ResetIntern();
- procedure RenderChar(ch: WideChar; var AdvanceX: real);
+ procedure RenderChar(ch: UCS4Char; var AdvanceX: real);
{**
* Load font widths from an info file.
* @param InfoFile the name of the info (.dat) file
- * @raises Exception if the file is corrupted
+ * @raises EFontError if the file is corrupted
*}
- procedure LoadFontInfo(const InfoFile: string);
+ procedure LoadFontInfo(const InfoFile: IPath);
protected
- procedure Render(const Text: WideString); override;
- function BBox(const Text: TWideStringArray; Advance: boolean): TBoundsDbl; override;
+ procedure Render(const Text: UCS4String); override;
+ function BBox(const Text: TUCS4StringArray; Advance: boolean): TBoundsDbl; override;
function GetHeight(): single; override;
function GetAscender(): single; override;
@@ -699,7 +795,7 @@ type
* (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: string; Outline: integer;
+ constructor Create(const Filename: IPath; Outline: integer;
Baseline, Ascender, Descender: integer);
destructor Destroy(); override;
@@ -711,6 +807,8 @@ type
{** @seealso TFont.Reset }
procedure Reset(); override;
+
+ procedure AddFallback(const Filename: IPath); override;
end;
{$ENDIF BITMAP_FONT}
@@ -720,7 +818,7 @@ type
{**
* Returns a pointer to the freetype library singleton.
* If non exists, freetype will be initialized.
- * @raises Exception if initialization failed
+ * @raises EFontError if initialization failed
*}
class function GetLibrary(): FT_Library;
class procedure FreeLibrary();
@@ -773,9 +871,10 @@ end;
* TFont
*}
-constructor TFont.Create();
+constructor TFont.Create(const Filename: IPath);
begin
- inherited;
+ inherited Create();
+ fFilename := Filename;
ResetIntern();
end;
@@ -801,37 +900,61 @@ begin
ResetIntern();
end;
-procedure TFont.SplitLines(const Text: UTF8String; var Lines: TWideStringArray);
+procedure TFont.SplitLines(const Text: UCS4String; var Lines: TUCS4StringArray);
var
- LineList: TStringList;
- LineIndex: integer;
+ CharIndex: integer;
+ LineStart: integer;
+ LineLength: integer;
+ EOT: boolean; // End-Of-Text
begin
- // split lines on newline (there is no WideString version of ExtractStrings)
- LineList := TStringList.Create();
- ExtractStrings([#13], [], PChar(Text), LineList);
+ // split lines on newline
+ SetLength(Lines, 0);
+ EOT := false;
+ LineStart := 0;
- // create an array of WideStrins from the UTF-8 string-list
- SetLength(Lines, LineList.Count);
- for LineIndex := 0 to LineList.Count-1 do
- Lines[LineIndex] := UTF8Decode(LineList[LineIndex]);
- LineList.Free();
+ 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: UTF8String; Advance: boolean): TBoundsDbl;
+function TFont.BBox(const Text: UCS4String; Advance: boolean): TBoundsDbl;
var
- LineArray: TWideStringArray;
+ 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(UTF8Encode(Text), Advance);
+ Result := BBox(WideStringToUCS4String(Text), Advance);
end;
-procedure TFont.Print(const Text: TWideStringArray);
+procedure TFont.Print(const Text: TUCS4StringArray);
var
LineIndex: integer;
begin
@@ -912,21 +1035,26 @@ begin
glPopAttrib();
end;
-procedure TFont.Print(const Text: string);
+procedure TFont.Print(const Text: UCS4String);
var
- LineArray: TWideStringArray;
+ 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(UTF8Encode(Text));
+ Print(WideStringToUCS4String(Text));
end;
-procedure TFont.DrawUnderline(const Text: WideString);
+procedure TFont.DrawUnderline(const Text: UCS4String);
var
UnderlineY1, UnderlineY2: single;
Bounds: TBoundsDbl;
@@ -1001,7 +1129,7 @@ constructor TScalableFont.Create(Font: TFont; UseMipmaps: boolean);
var
MipmapLevel: integer;
begin
- inherited Create();
+ inherited Create(Font.Filename);
fBaseFont := Font;
fMipmapFonts[0] := Font;
@@ -1033,7 +1161,7 @@ end;
procedure TScalableFont.ResetIntern();
begin
fScale := 1.0;
- fAspect := 1.0;
+ fStretch := 1.0;
end;
procedure TScalableFont.Reset();
@@ -1049,7 +1177,7 @@ end;
{**
* Returns the mipmap level to use with regard to the current projection
- * and modelview matrix, font scale and aspect.
+ * and modelview matrix, font scale and stretch.
*
* Note:
* - for Freetype fonts, hinting and grid-fitting must be disabled, otherwise
@@ -1088,7 +1216,7 @@ var
ModelMatrix, ProjMatrix: T16dArray;
WinCoords: array[0..2, 0..2] of GLdouble;
ViewPortArray: TViewPortArray;
- Dist, Dist2: double;
+ Dist, Dist2, DistSum: double;
WidthScale, HeightScale: double;
const
// width/height of square used for determining the scale
@@ -1128,12 +1256,24 @@ begin
// projected width ||(x1, y1) - (x2, y1)||
Dist := (WinCoords[0][0] - WinCoords[1][0]);
Dist2 := (WinCoords[0][1] - WinCoords[1][1]);
- WidthScale := cTestSize / Sqrt(Dist*Dist + Dist2*Dist2);
+
+ 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 := cTestSize / Sqrt(Dist*Dist + Dist2*Dist2);
+
+ HeightScale := 1;
+ DistSum := Dist*Dist + Dist2*Dist2;
+ if (DistSum > 0) then
+ begin
+ HeightScale := cTestSize / Sqrt(DistSum);
+ end;
//writeln(Format('Scale %f, %f', [WidthScale, HeightScale]));
@@ -1194,12 +1334,12 @@ begin
glScalef(MipmapScale, MipmapScale, 0);
end;
-procedure TScalableFont.Print(const Text: TWideStringArray);
+procedure TScalableFont.Print(const Text: TUCS4StringArray);
begin
glPushMatrix();
// set scale and stretching
- glScalef(fScale * fAspect, fScale, 0);
+ glScalef(fScale * fStretch, fScale, 0);
// print text
if (fUseMipmaps) then
@@ -1210,16 +1350,16 @@ begin
glPopMatrix();
end;
-procedure TScalableFont.Render(const Text: WideString);
+procedure TScalableFont.Render(const Text: UCS4String);
begin
Assert(false, 'Unused TScalableFont.Render() was called');
end;
-function TScalableFont.BBox(const Text: TWideStringArray; Advance: boolean): TBoundsDbl;
+function TScalableFont.BBox(const Text: TUCS4StringArray; Advance: boolean): TBoundsDbl;
begin
Result := fBaseFont.BBox(Text, Advance);
- Result.Left := Result.Left * fScale * fAspect;
- Result.Right := Result.Right * fScale * fAspect;
+ Result.Left := Result.Left * fScale * fStretch;
+ Result.Right := Result.Right * fScale * fStretch;
Result.Top := Result.Top * fScale;
Result.Bottom := Result.Bottom * fScale;
end;
@@ -1234,14 +1374,14 @@ begin
Result := fBaseFont.GetHeight() * fScale;
end;
-procedure TScalableFont.SetAspect(Aspect: single);
+procedure TScalableFont.SetStretch(Stretch: single);
begin
- fAspect := Aspect;
+ fStretch := Stretch;
end;
-function TScalableFont.GetAspect(): single;
+function TScalableFont.GetStretch(): single;
begin
- Result := fAspect;
+ Result := fStretch;
end;
function TScalableFont.GetAscender(): single;
@@ -1287,7 +1427,7 @@ var
Level: integer;
begin
for Level := 0 to High(fMipmapFonts) do
- if (fMipmapFonts[Level] <> nil) then
+ if ((fMipmapFonts[Level] <> nil) AND (GetMipmapScale(Level) > 0)) then
fMipmapFonts[Level].SetReflectionSpacing(Spacing / GetMipmapScale(Level));
end;
@@ -1334,9 +1474,9 @@ end;
* TCachedFont
*}
-constructor TCachedFont.Create();
+constructor TCachedFont.Create(const Filename: IPath);
begin
- inherited;
+ inherited Create(Filename);
fCache := TGlyphCache.Create();
end;
@@ -1346,7 +1486,7 @@ begin
inherited;
end;
-function TCachedFont.GetGlyph(ch: WideChar): TGlyph;
+function TCachedFont.GetGlyph(ch: UCS4Char): TGlyph;
begin
Result := fCache.GetGlyph(ch);
if (Result = nil) then
@@ -1362,60 +1502,155 @@ begin
fCache.FlushCache(KeepBaseSet);
end;
+{*
+ * TFTFontFaceCache
+ *}
{*
- * TFTFont
+ * TFTFontFace
*}
-constructor TFTFont.Create(
- const Filename: string;
- Size: integer; Outset: single;
- LoadFlags: FT_Int32);
-var
- i: WideChar;
+constructor TFTFontFace.Create(const Filename: IPath; Size: integer);
begin
inherited Create();
fFilename := Filename;
fSize := Size;
- fOutset := Outset;
- fLoadFlags := LoadFlags;
- fUseDisplayLists := true;
// load font information
- if (FT_New_Face(TFreeType.GetLibrary(), PChar(Filename), 0, fFace) <> 0) then
- raise Exception.Create('FT_New_Face: Could not load font ''' + Filename + '''');
+ 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 Exception.Create('Font is not scalable');
+ raise EFontError.Create('Font is not scalable');
if (FT_Set_Pixel_Sizes(fFace, 0, Size) <> 0) then
- raise Exception.Create('FT_Set_Pixel_Sizes failes');
+ 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;
+ LoadFlags: FT_Int32);
+var
+ ch: UCS4Char;
+begin
+ inherited Create(Filename);
+
+ fSize := Size;
+ fOutset := Outset;
+ fLoadFlags := LoadFlags;
+ fUseDisplayLists := true;
+ fPart := fpNone;
+
+ fFace := GetFaceCache.LoadFace(Filename, Size);
ResetIntern();
// pre-cache some commonly used glyphs (' ' - '~')
- for i := #32 to #126 do
- fCache.AddGlyph(i, TFTGlyph.Create(Self, i, Outset, LoadFlags));
+ for ch := 32 to 126 do
+ fCache.AddGlyph(ch, TFTGlyph.Create(Self, ch, Outset, LoadFlags));
end;
destructor TFTFont.Destroy();
+var
+ I: integer;
begin
- // free face
- FT_Done_Face(fFace);
+ // 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.height * fFontUnitScale.Y;
- fReflectionSpacing := -2*fFace.descender * fFontUnitScale.Y;
+ fLineSpacing := fFace.Data.height * fFace.FontUnitScale.Y;
+ fReflectionSpacing := -2*fFace.Data.descender * fFace.FontUnitScale.Y;
end;
procedure TFTFont.Reset();
@@ -1424,15 +1659,24 @@ begin
ResetIntern();
end;
-function TFTFont.LoadGlyph(ch: WideChar): TGlyph;
+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: TWideStringArray; Advance: boolean): TBoundsDbl;
+function TFTFont.BBox(const Text: TUCS4StringArray; Advance: boolean): TBoundsDbl;
var
Glyph, PrevGlyph: TFTGlyph;
- TextLine: WideString;
+ TextLine: UCS4String;
LineYOffset: single;
LineIndex, CharIndex: integer;
LineBounds: TBoundsDbl;
@@ -1462,17 +1706,17 @@ begin
LineBounds.Top := 0;
// for each glyph image, compute its bounding box
- for CharIndex := 1 to Length(TextLine) do
+ 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) and (PrevGlyph <> nil)) then
+ if (fUseKerning and FT_HAS_KERNING(fFace.Data) and (PrevGlyph <> nil)) then
begin
- FT_Get_Kerning(fFace, PrevGlyph.CharIndex, Glyph.CharIndex,
+ FT_Get_Kerning(fFace.Data, PrevGlyph.CharIndex, Glyph.CharIndex,
FT_KERNING_UNSCALED, KernDelta);
- LineBounds.Right := LineBounds.Right + KernDelta.x * fFontUnitScale.X;
+ LineBounds.Right := LineBounds.Right + KernDelta.x * fFace.FontUnitScale.X;
end;
// update left bound (must be done before right bound is updated)
@@ -1480,9 +1724,9 @@ begin
LineBounds.Left := LineBounds.Right + Glyph.Bounds.Left;
// update right bound
- if (CharIndex < Length(TextLine)) or // not the last character
- (TextLine[CharIndex] = ' ') or // on space char (Bounds.Right = 0)
- Advance then // or in advance mode
+ 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
@@ -1534,13 +1778,13 @@ begin
end;
// if left or bottom bound was not set, set them to 0
- if (Result.Left = Infinity) then
+ if (IsInfinite(Result.Left)) then
Result.Left := 0.0;
- if (Result.Bottom = Infinity) then
+ if (IsInfinite(Result.Bottom)) then
Result.Bottom := 0.0;
end;
-procedure TFTFont.Render(const Text: WideString);
+procedure TFTFont.Render(const Text: UCS4String);
var
CharIndex: integer;
Glyph, PrevGlyph: TFTGlyph;
@@ -1550,17 +1794,17 @@ begin
PrevGlyph := nil;
// draw current line
- for CharIndex := 1 to Length(Text) do
+ 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) and (PrevGlyph <> nil)) then
+ if (fUseKerning and FT_HAS_KERNING(fFace.Data) and (PrevGlyph <> nil)) then
begin
- FT_Get_Kerning(fFace, PrevGlyph.CharIndex, Glyph.CharIndex,
+ FT_Get_Kerning(fFace.Data, PrevGlyph.CharIndex, Glyph.CharIndex,
FT_KERNING_UNSCALED, KernDelta);
- glTranslatef(KernDelta.x * fFontUnitScale.X, 0, 0);
+ glTranslatef(KernDelta.x * fFace.FontUnitScale.X, 0, 0);
end;
if (ReflectionPass) then
@@ -1582,23 +1826,23 @@ end;
function TFTFont.GetAscender(): single;
begin
- Result := fFace.ascender * fFontUnitScale.Y + Outset*2;
+ 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.descender * fFontUnitScale.Y;
+ Result := fFace.Data.descender * fFace.FontUnitScale.Y;
end;
function TFTFont.GetUnderlinePosition(): single;
begin
- Result := fFace.underline_position * fFontUnitScale.Y - Outset;
+ Result := fFace.Data.underline_position * fFace.FontUnitScale.Y - Outset;
end;
function TFTFont.GetUnderlineThickness(): single;
begin
- Result := fFace.underline_thickness * fFontUnitScale.Y + Outset*2;
+ Result := fFace.Data.underline_thickness * fFace.FontUnitScale.Y + Outset*2;
end;
@@ -1606,7 +1850,7 @@ end;
* TFTScalableFont
*}
-constructor TFTScalableFont.Create(const Filename: string;
+constructor TFTScalableFont.Create(const Filename: IPath;
Size: integer; OutsetAmount: single;
UseMipmaps: boolean);
var
@@ -1637,8 +1881,8 @@ begin
// do not create mipmap fonts < 8 pixels
if (ScaledSize < 8) then
Exit;
- Result := TFTFont.Create(BaseFont.fFilename,
- ScaledSize, BaseFont.fOutset * Scale,
+ Result := TFTFont.Create(BaseFont.Filename,
+ ScaledSize, BaseFont.Outset * Scale,
FT_LOAD_DEFAULT or FT_LOAD_NO_HINTING);
end;
@@ -1647,6 +1891,15 @@ 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;
@@ -1662,18 +1915,19 @@ end;
*}
constructor TFTOutlineFont.Create(
- const Filename: string;
+ const Filename: IPath;
Size: integer; Outset: single;
LoadFlags: FT_Int32);
begin
- inherited Create();
+ inherited Create(Filename);
- fFilename := Filename;
fSize := Size;
fOutset := Outset;
fInnerFont := TFTFont.Create(Filename, Size, 0.0, LoadFlags);
+ fInnerFont.Part := fpInner;
fOutlineFont := TFTFont.Create(Filename, Size, Outset, LoadFlags);
+ fOutlineFont.Part := fpOutline;
ResetIntern();
end;
@@ -1705,7 +1959,7 @@ begin
ResetIntern();
end;
-procedure TFTOutlineFont.DrawUnderline(const Text: WideString);
+procedure TFTOutlineFont.DrawUnderline(const Text: UCS4String);
var
CurrentColor: TGLColor;
OutlineColor: TGLColor;
@@ -1730,7 +1984,7 @@ begin
glPopMatrix();
end;
-procedure TFTOutlineFont.Render(const Text: WideString);
+procedure TFTOutlineFont.Render(const Text: UCS4String);
var
CurrentColor: TGLColor;
OutlineColor: TGLColor;
@@ -1770,7 +2024,13 @@ begin
fInnerFont.FlushCache(KeepBaseSet);
end;
-function TFTOutlineFont.BBox(const Text: TWideStringArray; Advance: boolean): TBoundsDbl;
+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;
@@ -1852,7 +2112,7 @@ end;
*}
constructor TFTScalableOutlineFont.Create(
- const Filename: string;
+ const Filename: IPath;
Size: integer; OutsetAmount: single;
UseMipmaps: boolean);
var
@@ -1906,6 +2166,15 @@ begin
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
@@ -1935,82 +2204,119 @@ const
*}
cTexSmoothBorder = 1;
-procedure TFTGlyph.Extrude(var TexBuffer: TGLubyteDynArray; Outset: single);
+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!');
- procedure SetToMax(var Val1: GLubyte; Val2: GLubyte); {$IFDEF HasInline}inline;{$ENDIF}
+ FT_Stroker_GetBorderCounts(OuterStroker, OuterBorder, OuterNumPoints, OuterNumContours);
+
+ { extrude inner border (= stencil) }
+
+ if (UseStencil) then
begin
- if (Val1 < Val2) then
- Val1 := Val2;
+ 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;
-var
- I, X, Y: integer;
- SrcBuffer,TmpBuffer: TGLubyteDynArray;
- TexLine, TexLinePrev, TexLineNext: PGLubyteArray;
- SrcLine: PGLubyteArray;
- AlphaScale: single;
- Value, ValueNeigh, ValueDiag: GLubyte;
-const
- // square-root of 2 used for diagonal neighbor pixels
- cSqrt2 = 1.4142;
- // number of ignored pixels on each edge of the bitmap. Consists of:
- // - border used for font smoothing and
- // - outer (extruded) bitmap pixel (because it is just written but never read)
- cBorder = cTexSmoothBorder + 1;
-begin
- // allocate memory for temporary buffer
- SetLength(SrcBuffer, Length(TexBuffer));
- FillChar(SrcBuffer[0], Length(TexBuffer), 0);
-
- // extrude pixel by pixel
- for I := 1 to Ceil(Outset) do
- begin
- // swap arrays
- TmpBuffer := TexBuffer;
- TexBuffer := SrcBuffer;
- SrcBuffer := TmpBuffer;
-
- // as long as we add an entire pixel of outset, use a solid color.
- // If the fractional part is reached blend, e.g. outline=3.2 -> 3 solid
- // pixels and one blended with alpha=0.2.
- // For the fractional part I = Ceil(Outset) is always true.
- if (I <= Outset) then
- AlphaScale := 1
- else
- AlphaScale := Outset - Trunc(Outset);
-
- // copy data to the expanded bitmap.
- for Y := cBorder to fTexSize.Height - 2*cBorder do
- begin
- TexLine := @TexBuffer[Y*fTexSize.Width];
- TexLinePrev := @TexBuffer[(Y-1)*fTexSize.Width];
- TexLineNext := @TexBuffer[(Y+1)*fTexSize.Width];
- SrcLine := @SrcBuffer[Y*fTexSize.Width];
+ { combine borders (subtract: OuterBorder - InnerBorder) }
- // expand current line's pixels
- for X := cBorder to fTexSize.Width - 2*cBorder do
- begin
- Value := SrcLine[X];
- ValueNeigh := Round(Value * AlphaScale);
- ValueDiag := Round(ValueNeigh / cSqrt2);
+ GlyphNumPoints := InnerNumPoints + OuterNumPoints;
+ GlyphNumContours := InnerNumContours + OuterNumContours;
- SetToMax(TexLine[X], Value);
- SetToMax(TexLine[X-1], ValueNeigh);
- SetToMax(TexLine[X+1], ValueNeigh);
+ // save flags before deletion (TODO: set them on the resulting outline)
+ OutlineFlags := Outline.flags;
- SetToMax(TexLinePrev[X], ValueNeigh);
- SetToMax(TexLinePrev[X-1], ValueDiag);
- SetToMax(TexLinePrev[X+1], ValueDiag);
+ // 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!');
- SetToMax(TexLineNext[X], ValueNeigh);
- SetToMax(TexLineNext[X-1], ValueDiag);
- SetToMax(TexLineNext[X+1], ValueDiag);
- end;
- end;
- end;
+ Outline.n_points := 0;
+ Outline.n_contours := 0;
- TmpBuffer := nil;
- SetLength(SrcBuffer, 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);
@@ -2025,17 +2331,26 @@ var
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(fFont.Face, fCharIndex, LoadFlags) <> 0) then
- raise Exception.Create('FT_Load_Glyph failed');
+ 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(fFont.Face^.glyph, Glyph) <> 0) then
- raise Exception.Create('FT_Get_Glyph failed');
+ 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 := fFont.Face^.glyph^.advance.x / 64 + fOutset*2;
- fAdvance.Y := fFont.Face^.glyph^.advance.y / 64 + fOutset*2;
+ 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);
@@ -2114,9 +2429,6 @@ begin
end;
end;
- if (fOutset > 0) then
- Extrude(TexBuffer, fOutset);
-
// allocate resources for textures and display lists
glGenTextures(1, @fTexture);
@@ -2151,16 +2463,36 @@ begin
FT_Done_Glyph(Glyph);
end;
-constructor TFTGlyph.Create(Font: TFTFont; ch: WideChar; Outset: single;
+constructor TFTGlyph.Create(Font: TFTFont; ch: UCS4Char; Outset: single;
LoadFlags: FT_Int32);
+var
+ I: integer;
begin
inherited Create();
fFont := Font;
fOutset := Outset;
+ fCharCode := ch;
- // get the Freetype char-index (use default UNICODE charmap)
- fCharIndex := FT_Get_Char_Index(Font.fFace, FT_ULONG(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;
@@ -2336,7 +2668,7 @@ begin
InsertPos := fHash.Count;
end;
-function TGlyphCache.AddGlyph(ch: WideChar; const Glyph: TGlyph): boolean;
+function TGlyphCache.AddGlyph(ch: UCS4Char; const Glyph: TGlyph): boolean;
var
BaseCode: cardinal;
GlyphCode: integer;
@@ -2346,7 +2678,7 @@ var
begin
Result := false;
- BaseCode := cardinal(ch) shr 8;
+ BaseCode := Ord(ch) shr 8;
GlyphTable := FindGlyphTable(BaseCode, InsertPos);
if (GlyphTable = nil) then
begin
@@ -2356,7 +2688,7 @@ begin
end;
// get glyph table offset
- GlyphCode := cardinal(ch) and $FF;
+ GlyphCode := Ord(ch) and $FF;
// insert glyph into table if not present
if (GlyphTable[GlyphCode] = nil) then
begin
@@ -2365,19 +2697,19 @@ begin
end;
end;
-procedure TGlyphCache.DeleteGlyph(ch: WideChar);
+procedure TGlyphCache.DeleteGlyph(ch: UCS4Char);
var
Table: PGlyphTable;
TableIndex, GlyphIndex: integer;
TableEmpty: boolean;
begin
// find table
- Table := FindGlyphTable(cardinal(ch) shr 8, TableIndex);
+ Table := FindGlyphTable(Ord(ch) shr 8, TableIndex);
if (Table = nil) then
Exit;
// find glyph
- GlyphIndex := cardinal(ch) and $FF;
+ GlyphIndex := Ord(ch) and $FF;
if (Table[GlyphIndex] <> nil) then
begin
// destroy glyph
@@ -2402,19 +2734,19 @@ begin
end;
end;
-function TGlyphCache.GetGlyph(ch: WideChar): TGlyph;
+function TGlyphCache.GetGlyph(ch: UCS4Char): TGlyph;
var
InsertPos: integer;
Table: PGlyphTable;
begin
- Table := FindGlyphTable(cardinal(ch) shr 8, InsertPos);
+ Table := FindGlyphTable(Ord(ch) shr 8, InsertPos);
if (Table = nil) then
Result := nil
else
- Result := Table[cardinal(ch) and $FF];
+ Result := Table[Ord(ch) and $FF];
end;
-function TGlyphCache.HasGlyph(ch: WideChar): boolean;
+function TGlyphCache.HasGlyph(ch: UCS4Char): boolean;
begin
Result := (GetGlyph(ch) <> nil);
end;
@@ -2464,7 +2796,7 @@ begin
begin
// initialize freetype
if (FT_Init_FreeType(LibraryInst) <> 0) then
- raise Exception.Create('FT_Init_FreeType failed');
+ raise EFontError.Create('FT_Init_FreeType failed');
end;
Result := LibraryInst;
end;
@@ -2482,10 +2814,10 @@ end;
* TBitmapFont
*}
-constructor TBitmapFont.Create(const Filename: string; Outline: integer;
+constructor TBitmapFont.Create(const Filename: IPath; Outline: integer;
Baseline, Ascender, Descender: integer);
begin
- inherited Create();
+ inherited Create(Filename);
fTex := Texture.LoadTexture(true, Filename, TEXTURE_TYPE_TRANSPARENT, 0);
fTexSize := 1024;
@@ -2494,7 +2826,7 @@ begin
fAscender := Ascender;
fDescender := Descender;
- LoadFontInfo(ChangeFileExt(Filename, '.dat'));
+ LoadFontInfo(Filename.SetExtension('.dat'));
ResetIntern();
end;
@@ -2516,6 +2848,11 @@ begin
ResetIntern();
end;
+procedure TBitmapFont.AddFallback(const Filename: IPath);
+begin
+ // no support for fallbacks
+end;
+
procedure TBitmapFont.CorrectWidths(WidthMult: real; WidthAdd: integer);
var
Count: integer;
@@ -2524,27 +2861,27 @@ begin
fWidths[Count] := Round(fWidths[Count] * WidthMult) + WidthAdd;
end;
-procedure TBitmapFont.LoadFontInfo(const InfoFile: string);
+procedure TBitmapFont.LoadFontInfo(const InfoFile: IPath);
var
- Stream: TFileStream;
+ Stream: TStream;
begin
FillChar(fWidths[0], Length(fWidths), 0);
Stream := nil;
try
- Stream := TFileStream.Create(InfoFile, fmOpenRead);
+ Stream := TBinaryFileStream.Create(InfoFile, fmOpenRead);
Stream.Read(fWidths, 256);
except
- raise Exception.Create('Could not read font info file ''' + InfoFile + '''');
+ raise EFontError.Create('Could not read font info file ''' + InfoFile.ToNative + '''');
end;
Stream.Free;
end;
-function TBitmapFont.BBox(const Text: TWideStringArray; Advance: boolean): TBoundsDbl;
+function TBitmapFont.BBox(const Text: TUCS4StringArray; Advance: boolean): TBoundsDbl;
var
LineIndex, CharIndex: integer;
CharCode: cardinal;
- Line: WideString;
+ Line: UCS4String;
LineWidth: double;
begin
Result.Left := 0;
@@ -2556,7 +2893,7 @@ begin
begin
Line := Text[LineIndex];
LineWidth := 0;
- for CharIndex := 1 to Length(Line) do
+ for CharIndex := 0 to LengthUCS4(Line)-1 do
begin
CharCode := Ord(Line[CharIndex]);
if (CharCode < Length(fWidths)) then
@@ -2567,7 +2904,7 @@ begin
end;
end;
-procedure TBitmapFont.RenderChar(ch: WideChar; var AdvanceX: real);
+procedure TBitmapFont.RenderChar(ch: UCS4Char; var AdvanceX: real);
var
TexX, TexY: real;
TexR, TexB: real;
@@ -2659,20 +2996,20 @@ begin
AdvanceX := AdvanceX + GlyphWidth;
end;
-procedure TBitmapFont.Render(const Text: WideString);
+procedure TBitmapFont.Render(const Text: UCS4String);
var
CharIndex: integer;
AdvanceX: real;
begin
// if there is no text do nothing
- if (Text = '') then
+ 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 := 1 to Length(Text) do
+ for CharIndex := 0 to LengthUCS4(Text)-1 do
begin
RenderChar(Text[CharIndex], AdvanceX);
end;
diff --git a/cmake/src/base/UGraphic.pas b/cmake/src/base/UGraphic.pas
index 818e49aa..4f0c8c77 100644
--- a/cmake/src/base/UGraphic.pas
+++ b/cmake/src/base/UGraphic.pas
@@ -45,7 +45,6 @@ uses
UImage,
UMusic,
UScreenLoading,
- UScreenWelcome,
UScreenMain,
UScreenName,
UScreenLevel,
@@ -71,12 +70,12 @@ uses
UScreenSongMenu,
UScreenSongJumpto,
{Party Screens}
- UScreenSingModi,
UScreenPartyNewRound,
UScreenPartyScore,
UScreenPartyOptions,
UScreenPartyWin,
UScreenPartyPlayer,
+ UScreenPartyRounds,
{Stats Screens}
UScreenStatMain,
UScreenStatDetail,
@@ -107,7 +106,6 @@ var
ScreenX: integer;
ScreenLoading: TScreenLoading;
- ScreenWelcome: TScreenWelcome;
ScreenMain: TScreenMain;
ScreenName: TScreenName;
ScreenLevel: TScreenLevel;
@@ -133,12 +131,13 @@ var
ScreenSongJumpto: TScreenSongJumpto;
//Party Screens
- ScreenSingModi: TScreenSingModi;
+ //ScreenSingModi: TScreenSingModi;
ScreenPartyNewRound: TScreenPartyNewRound;
ScreenPartyScore: TScreenPartyScore;
ScreenPartyWin: TScreenPartyWin;
ScreenPartyOptions: TScreenPartyOptions;
ScreenPartyPlayer: TScreenPartyPlayer;
+ ScreenPartyRounds: TScreenPartyRounds;
//StatsScreens
ScreenStatMain: TScreenStatMain;
@@ -150,11 +149,12 @@ var
//popup mod
ScreenPopupCheck: TScreenPopupCheck;
ScreenPopupError: TScreenPopupError;
+ ScreenPopupInfo: TScreenPopupInfo;
//Notes
- Tex_Left: array[0..6] of TTexture; //rename to tex_note_left
- Tex_Mid: array[0..6] of TTexture; //rename to tex_note_mid
- Tex_Right: array[0..6] of TTexture; //rename to tex_note_right
+ 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
@@ -206,6 +206,10 @@ var
// textures for software mouse cursor
Tex_Cursor_Unpressed: TTexture;
Tex_Cursor_Pressed: TTexture;
+
+
+ PboSupported: boolean;
+
const
Skin_BGColorR = 1;
Skin_BGColorG = 1;
@@ -261,6 +265,7 @@ const
Skin_P2_ScoreL = 640;
procedure Initialize3D (Title: string);
+procedure Finalize3D;
procedure Reinitialize3D;
procedure SwapBuffers;
@@ -268,7 +273,7 @@ procedure LoadTextures;
procedure InitializeScreen;
procedure LoadLoadingScreen;
procedure LoadScreens;
-procedure UnLoadScreens;
+procedure UnloadScreens;
function LoadingThreadFunction: integer;
@@ -281,12 +286,18 @@ uses
UIni,
UDisplay,
UCommandLine,
- UPath;
+ UPathUtils;
procedure LoadFontTextures;
begin
Log.LogStatus('Building Fonts', 'LoadTextures');
- BuildFont;
+ BuildFonts;
+end;
+
+procedure UnloadFontTextures;
+begin
+ Log.LogStatus('Kill Fonts', 'UnloadFontTextures');
+ KillFonts;
end;
procedure LoadTextures;
@@ -298,15 +309,6 @@ var
begin
Log.LogStatus('Loading Textures', 'LoadTextures');
- // FIXME: do we need this? (REMOVE otherwise)
- Tex_Left[0] := Texture.LoadTexture(Skin.GetTextureFileName('GrayLeft'), TEXTURE_TYPE_TRANSPARENT, 0);
- // FIXME: do we need this? (REMOVE otherwise)
- Tex_Mid[0] := Texture.LoadTexture(Skin.GetTextureFileName('GrayMid'), TEXTURE_TYPE_PLAIN, 0);
- // FIXME: do we need this? (REMOVE otherwise)
- Tex_Right[0] := Texture.LoadTexture(Skin.GetTextureFileName('GrayRight'), TEXTURE_TYPE_TRANSPARENT, 0);
-
- Log.LogStatus('Loading Textures - A', 'LoadTextures');
-
// P1-6
// TODO... do it once for each player... this is a bit crappy !!
// can we make it any better !?
@@ -314,7 +316,29 @@ begin
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);
@@ -340,7 +364,7 @@ begin
Tex_Cursor_Unpressed := Texture.LoadTexture(Skin.GetTextureFileName('Cursor'), TEXTURE_TYPE_TRANSPARENT, 0);
- if (Skin.GetTextureFileName('Cursor_Pressed') <> '') then
+ 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;
@@ -389,14 +413,14 @@ begin
End;
Col := $10000 * Round(R*255) + $100 * Round(G*255) + Round(B*255);
- Tex_SingLineBonusBack[P] := Texture.LoadTexture(pchar(Skin.GetTextureFileName('LineBonusBack')), TEXTURE_TYPE_COLORIZED, Col);
+ 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(pchar(Skin.GetTextureFileName('ScoreBG')), TEXTURE_TYPE_COLORIZED, Col);
+ Tex_ScoreBG[P] := Texture.LoadTexture(Skin.GetTextureFileName('ScoreBG'), TEXTURE_TYPE_COLORIZED, Col);
end;
@@ -411,23 +435,23 @@ 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(pchar(Skin.GetTextureFileName('ScoreLevel_Dark')), TEXTURE_TYPE_COLORIZED, Col);
- Tex_Score_NoteBarRound_Dark[P] := Texture.LoadTexture(pchar(Skin.GetTextureFileName('ScoreLevel_Dark_Round')), TEXTURE_TYPE_COLORIZED, Col);
+ 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(pchar(Skin.GetTextureFileName('ScoreLevel_Light')), TEXTURE_TYPE_COLORIZED, Col);
- Tex_Score_NoteBarRound_Light[P] := Texture.LoadTexture(pchar(Skin.GetTextureFileName('ScoreLevel_Light_Round')), TEXTURE_TYPE_COLORIZED, Col);
+ 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(pchar(Skin.GetTextureFileName('ScoreLevel_Lightest')), TEXTURE_TYPE_COLORIZED, Col);
- Tex_Score_NoteBarRound_Lightest[P] := Texture.LoadTexture(pchar(Skin.GetTextureFileName('ScoreLevel_Lightest_Round')), TEXTURE_TYPE_COLORIZED, Col);
+ 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(pchar(Skin.GetTextureFileName('Rating_'+IntToStr(P))), TEXTURE_TYPE_TRANSPARENT, 0);
+ Tex_Score_Ratings[P] := Texture.LoadTexture(Skin.GetTextureFileName('Rating_'+IntToStr(P)), TEXTURE_TYPE_TRANSPARENT, 0);
end;
Log.LogStatus('Loading Textures - Done', 'LoadTextures');
@@ -448,6 +472,12 @@ begin
// 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
@@ -464,12 +494,17 @@ begin
end;
// load icon image (must be 32x32 for win32)
- Icon := LoadImage(ResourcesPath + WINDOW_ICON);
+ Icon := LoadImage(ResourcesPath.Append(WINDOW_ICON));
if (Icon <> nil) then
- SDL_WM_SetIcon(Icon, 0);
+ 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;
@@ -573,6 +608,13 @@ begin
glMatrixMode(GL_MODELVIEW);
end;
+procedure Finalize3D;
+begin
+ // TODO: finalize other stuff
+ UnloadFontTextures;
+ SDL_QuitSubSystem(SDL_INIT_VIDEO);
+end;
+
procedure Reinitialize3D;
begin
InitializeScreen;
@@ -667,7 +709,7 @@ end;
procedure LoadLoadingScreen;
begin
ScreenLoading := TScreenLoading.Create;
- ScreenLoading.onShow;
+ ScreenLoading.OnShow;
Display.CurrentScreen := @ScreenLoading;
@@ -682,15 +724,13 @@ end;
procedure LoadScreens;
begin
{ ScreenLoading := TScreenLoading.Create;
- ScreenLoading.onShow;
+ ScreenLoading.OnShow;
Display.CurrentScreen := @ScreenLoading;
ScreenLoading.Draw;
Display.Draw;
SwapBuffers;
}
Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Loading', 3); Log.BenchmarkStart(3);
-{ ScreenWelcome := TScreenWelcome.Create; //'BG', 4, 3);
- Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Welcome', 3); Log.BenchmarkStart(3);}
ScreenMain := TScreenMain.Create;
Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Main', 3); Log.BenchmarkStart(3);
ScreenName := TScreenName.Create;
@@ -733,8 +773,8 @@ begin
// 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);
+ //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;
@@ -743,6 +783,8 @@ begin
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;
@@ -753,6 +795,8 @@ begin
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;
@@ -768,39 +812,41 @@ begin
Result:= 1;
end;
-procedure UnLoadScreens;
+procedure UnloadScreens;
begin
- ScreenMain.Destroy;
- ScreenName.Destroy;
- ScreenLevel.Destroy;
- ScreenSong.Destroy;
- ScreenSing.Destroy;
- ScreenScore.Destroy;
- ScreenTop5.Destroy;
- ScreenOptions.Destroy;
- ScreenOptionsGame.Destroy;
- ScreenOptionsGraphics.Destroy;
- ScreenOptionsSound.Destroy;
- ScreenOptionsLyrics.Destroy;
-// ScreenOptionsThemes.Destroy;
- ScreenOptionsRecord.Destroy;
- ScreenOptionsAdvanced.Destroy;
- ScreenEditSub.Destroy;
- ScreenEdit.Destroy;
- ScreenEditConvert.Destroy;
- ScreenOpen.Destroy;
- ScreenSingModi.Destroy;
- ScreenSongMenu.Destroy;
- ScreenSongJumpto.Destroy;
- ScreenPopupCheck.Destroy;
- ScreenPopupError.Destroy;
- ScreenPartyNewRound.Destroy;
- ScreenPartyScore.Destroy;
- ScreenPartyWin.Destroy;
- ScreenPartyOptions.Destroy;
- ScreenPartyPlayer.Destroy;
- ScreenStatMain.Destroy;
- ScreenStatDetail.Destroy;
+ 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/cmake/src/base/UImage.pas b/cmake/src/base/UImage.pas
index 60b0a3a2..1866316e 100644
--- a/cmake/src/base/UImage.pas
+++ b/cmake/src/base/UImage.pas
@@ -34,7 +34,8 @@ interface
{$I switches.inc}
uses
- SDL;
+ SDL,
+ UPath;
{$DEFINE HavePNG}
{$DEFINE HaveBMP}
@@ -131,20 +132,20 @@ type
*******************************************************)
{$IFDEF HavePNG}
-function WritePNGImage(const FileName: string; Surface: PSDL_Surface): boolean;
+function WritePNGImage(const FileName: IPath; Surface: PSDL_Surface): boolean;
{$ENDIF}
{$IFDEF HaveBMP}
-function WriteBMPImage(const FileName: string; Surface: PSDL_Surface): boolean;
+function WriteBMPImage(const FileName: IPath; Surface: PSDL_Surface): boolean;
{$ENDIF}
{$IFDEF HaveJPG}
-function WriteJPGImage(const FileName: string; Surface: PSDL_Surface; Quality: integer): boolean;
+function WriteJPGImage(const FileName: IPath; Surface: PSDL_Surface; Quality: integer): boolean;
{$ENDIF}
(*******************************************************
* Image loading
*******************************************************)
-function LoadImage(const Filename: string): PSDL_Surface;
+function LoadImage(const Filename: IPath): PSDL_Surface;
(*******************************************************
* Image manipulation
@@ -181,6 +182,7 @@ uses
zlib,
sdl_image,
sdlutils,
+ sdlstreams,
UCommon,
ULog;
@@ -282,26 +284,26 @@ end;
procedure user_read_data(png_ptr: png_structp; data: png_bytep; length: png_size_t); cdecl;
var
- inFile: TFileStream;
+ inFile: TStream;
begin
- inFile := TFileStream(png_get_io_ptr(png_ptr));
+ 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: TFileStream;
+ outFile: TStream;
begin
- outFile := TFileStream(png_get_io_ptr(png_ptr));
+ outFile := TStream(png_get_io_ptr(png_ptr));
outFile.Write(data^, length);
end;
procedure user_flush_data(png_ptr: png_structp); cdecl;
//var
-// outFile: TFileStream;
+// outFile: TStream;
begin
// binary files are flushed automatically, Flush() works with Text-files only
- //outFile := TFileStream(png_get_io_ptr(png_ptr));
+ //outFile := TStream(png_get_io_ptr(png_ptr));
//outFile.Flush();
end;
@@ -323,11 +325,11 @@ end;
(*
* ImageData must be in RGB-format
*)
-function WritePNGImage(const FileName: string; Surface: PSDL_Surface): boolean;
+function WritePNGImage(const FileName: IPath; Surface: PSDL_Surface): boolean;
var
png_ptr: png_structp;
info_ptr: png_infop;
- pngFile: TFileStream;
+ pngFile: TStream;
row: integer;
rowData: array of png_bytep;
// rowStride: integer;
@@ -339,9 +341,9 @@ begin
// open file for writing
try
- pngFile := TFileStream.Create(FileName, fmCreate);
+ pngFile := TBinaryFileStream.Create(FileName, fmCreate);
except
- Log.LogError('Could not open file: "' + FileName + '"', 'WritePngImage');
+ Log.LogError('Could not open file: "' + FileName.ToNative + '"', 'WritePngImage');
Exit;
end;
@@ -500,9 +502,9 @@ type
(*
* ImageData must be in BGR-format
*)
-function WriteBMPImage(const FileName: string; Surface: PSDL_Surface): boolean;
+function WriteBMPImage(const FileName: IPath; Surface: PSDL_Surface): boolean;
var
- bmpFile: TFileStream;
+ bmpFile: TStream;
FileInfo: BITMAPINFOHEADER;
FileHeader: BITMAPFILEHEADER;
Converted: boolean;
@@ -513,9 +515,9 @@ begin
// open file for writing
try
- bmpFile := TFileStream.Create(FileName, fmCreate);
+ bmpFile := TBinaryFileStream.Create(FileName, fmCreate);
except
- Log.LogError('Could not open file: "' + FileName + '"', 'WriteBMPImage');
+ Log.LogError('Could not open file: "' + FileName.ToNative + '"', 'WriteBMPImage');
Exit;
end;
@@ -579,7 +581,7 @@ begin
Result := true;
finally
- Log.LogError('Could not write file: "' + FileName + '"', 'WriteBMPImage');
+ Log.LogError('Could not write file: "' + FileName.ToNative + '"', 'WriteBMPImage');
end;
if (Converted) then
@@ -597,20 +599,21 @@ end;
{$IFDEF HaveJPG}
-function WriteJPGImage(const FileName: string; Surface: PSDL_Surface; Quality: integer): boolean;
+function WriteJPGImage(const FileName: IPath; Surface: PSDL_Surface; Quality: integer): boolean;
var
{$IFDEF Delphi}
- Bitmap: TBitmap;
+ Bitmap: TBitmap;
BitmapInfo: TBitmapInfo;
- Jpeg: TJpegImage;
- row: integer;
+ Jpeg: TJpegImage;
+ row: integer;
+ FileStream: TBinaryFileStream;
{$ELSE}
cinfo: jpeg_compress_struct;
jerr : jpeg_error_mgr;
- jpgFile: TFileStream;
+ jpgFile: TBinaryFileStream;
rowPtr: array[0..0] of JSAMPROW;
{$ENDIF}
- converted: boolean;
+ converted: boolean;
begin
Result := false;
@@ -669,19 +672,32 @@ begin
SDL_UnlockSurface(Surface);
// assign Bitmap to JPEG and store the latter
- Jpeg := TJPEGImage.Create;
- Jpeg.Assign(Bitmap);
- Bitmap.Free;
- Jpeg.CompressionQuality := Quality;
try
- // compress image (don't forget this line, otherwise it won't be compressed)
- Jpeg.Compress();
- Jpeg.SaveToFile(FileName);
+ // 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 + '"', 'WriteJPGImage');
+ Log.LogError('Could not save file: "' + FileName.ToNative + '"', 'WriteJPGImage');
Exit;
end;
- Jpeg.Free;
{$ELSE}
// based on example.pas in FPC's packages/base/pasjpeg directory
@@ -703,9 +719,9 @@ begin
// open file for writing
try
- jpgFile := TFileStream.Create(FileName, fmCreate);
+ jpgFile := TBinaryFileStream.Create(FileName, fmCreate);
except
- Log.LogError('Could not open file: "' + FileName + '"', 'WriteJPGImage');
+ Log.LogError('Could not open file: "' + FileName.ToNative + '"', 'WriteJPGImage');
Exit;
end;
@@ -763,27 +779,29 @@ end;
(*
* Loads an image from the given file
*)
-function LoadImage(const Filename: string): PSDL_Surface;
+function LoadImage(const Filename: IPath): PSDL_Surface;
var
- FilenameFound: string;
+ FilenameCaseAdj: IPath;
+ FileStream: TBinaryFileStream;
+ SDLStream: PSDL_RWops;
begin
- Result := nil;
+ Result := nil;
- // FileExistsInsensitive() requires a var-arg
- FilenameFound := Filename;
-
- // try to find the file case insensitive
- if (not FileExistsInsensitive(FilenameFound)) then
+ // 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 "'+FilenameFound+'"', 'LoadImage');
+ Log.LogError('Image-File does not exist "' + FilenameCaseAdj.ToNative + '"', 'LoadImage');
Exit;
end;
// load from file
try
- Result := IMG_Load(PChar(FilenameFound));
+ 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 "'+FilenameFound+'"', 'LoadImage');
+ Log.LogError('Could not load from file "' + FilenameCaseAdj.ToNative + '"', 'LoadImage');
Exit;
end;
end;
@@ -794,17 +812,13 @@ end;
function PixelFormatEquals(fmt1, fmt2: PSDL_PixelFormat): boolean;
begin
- if (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)
- then
- Result := true
- else
- Result := false;
+ 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);
@@ -885,7 +899,7 @@ begin
end;
*)
-procedure ColorizeImage(ImgSurface: PSDL_Surface; NewColor: cardinal);
+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
@@ -893,7 +907,7 @@ procedure ColorizeImage(ImgSurface: PSDL_Surface; NewColor: cardinal);
// 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 longwords, shifted by 10 bits to keep
+ // replaced by division of longints, shifted by 10 bits to keep
// digits.
// The use of longwards leeds to some type size mismatch warnings
@@ -904,8 +918,8 @@ procedure ColorizeImage(ImgSurface: PSDL_Surface; NewColor: cardinal);
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: longword;
- Min, Max, Delta: longword;
+ Red, Green, Blue: longint;
+ Min, Max, Delta: longint;
Hue: double;
begin
// extract the colors
@@ -933,6 +947,8 @@ procedure ColorizeImage(ImgSurface: PSDL_Surface; NewColor: cardinal);
// 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;
@@ -940,6 +956,8 @@ procedure ColorizeImage(ImgSurface: PSDL_Surface; NewColor: cardinal);
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;
@@ -952,6 +970,8 @@ var
Min, Max, Delta: longword;
HueInteger: longword;
f, p, q, t: longword;
+ GreyReal: real;
+ Grey: byte;
begin
Pixel := ImgSurface^.Pixels;
@@ -965,8 +985,48 @@ begin
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
+ 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
@@ -1036,9 +1096,9 @@ begin
// 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;
+ 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.
diff --git a/cmake/src/base/UIni.pas b/cmake/src/base/UIni.pas
index 2bcc7305..a4c85a3b 100644
--- a/cmake/src/base/UIni.pas
+++ b/cmake/src/base/UIni.pas
@@ -36,8 +36,12 @@ interface
uses
Classes,
IniFiles,
+ SysUtils,
+ UCommon,
ULog,
- SysUtils;
+ UTextEncoding,
+ UFilesystem,
+ UPath;
type
// TInputDeviceConfig stores the configuration for an input device.
@@ -59,9 +63,13 @@ type
TInputDeviceConfig = record
Name: string;
Input: integer;
+ Latency: integer; //**< latency in ms, or LATENCY_AUTODETECT for default
ChannelToPlayerMap: array of integer;
end;
+const
+ LATENCY_AUTODETECT = -1;
+
type
//Options
@@ -70,11 +78,9 @@ type
TBackgroundMusicOption = (bmoOff, bmoOn);
TIni = class
private
- function RemoveFileExt(FullName: string): string;
function ExtractKeyIndex(const Key, Prefix, Suffix: string): integer;
function GetMaxKeyIndex(Keys: TStringList; const Prefix, Suffix: string): integer;
- function GetArrayIndex(const SearchArray: array of string; Value: string; CaseInsensitiv: boolean = false): integer;
- function ReadArrayIndex(const SearchArray: array of string; IniFile: TCustomIniFile;
+ function ReadArrayIndex(const SearchArray: array of UTF8String; IniFile: TCustomIniFile;
IniSection: string; IniProperty: string; Default: integer): integer;
procedure TranslateOptionValues;
@@ -85,14 +91,14 @@ type
procedure LoadScreenModes(IniFile: TCustomIniFile);
public
- Name: array[0..11] of string;
+ Name: array[0..11] of UTF8String;
// Templates for Names Mod
- NameTeam: array[0..2] of string;
- NameTemplate: array[0..11] of string;
+ NameTeam: array[0..2] of UTF8String;
+ NameTemplate: array[0..11] of UTF8String;
//Filename of the opened iniFile
- Filename: string;
+ Filename: IPath;
// Game
Players: integer;
@@ -125,6 +131,8 @@ type
AudioOutputBufferSizeIndex: integer;
VoicePassthrough: integer;
+ SyncTo: integer;
+
//Song Preview
PreviewVolume: integer;
PreviewFading: integer;
@@ -132,7 +140,6 @@ type
// Lyrics
LyricsFont: integer;
LyricsEffect: integer;
- Solmization: integer;
NoteLines: integer;
// Themes
@@ -165,173 +172,205 @@ type
var
Ini: TIni;
- IResolution: array of string;
- ILanguage: array of string;
- ITheme: array of string;
- ISkin: array of string;
+ IResolution: TUTF8StringDynArray;
+ ILanguage: TUTF8StringDynArray;
+ ITheme: TUTF8StringDynArray;
+ ISkin: TUTF8StringDynArray;
+
+{*
+ * Options
+ *}
const
- IPlayers: array[0..4] of string = ('1', '2', '3', '4', '6');
- IPlayersVals: array[0..4] of integer = ( 1 , 2 , 3 , 4 , 6 );
+ 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 string = ('Easy', 'Medium', 'Hard');
- ITabs: array[0..1] of string = ('Off', 'On');
+ IDifficulty: array[0..2] of UTF8String = ('Easy', 'Medium', 'Hard');
+ ITabs: array[0..1] of UTF8String = ('Off', 'On');
- ISorting: array[0..7] of string = ('Edition', 'Genre', 'Language', 'Folder', 'Title', 'Artist', 'Title2', 'Artist2');
- sEdition = 0;
- sGenre = 1;
- sLanguage = 2;
- sFolder = 3;
- sTitle = 4;
- sArtist = 5;
- sTitle2 = 6;
- sArtist2 = 7;
+const
+ ISorting: array[0..6] of UTF8String = ('Edition', 'Genre', 'Language', 'Folder', 'Title', 'Artist', 'Artist2');
+type
+ TSortingType = (sEdition, sGenre, sLanguage, sFolder, sTitle, sArtist, sArtist2);
- IDebug: array[0..1] of string = ('Off', 'On');
+const
+ IDebug: array[0..1] of UTF8String = ('Off', 'On');
- IScreens: array[0..1] of string = ('1', '2');
- IFullScreen: array[0..1] of string = ('Off', 'On');
- IDepth: array[0..1] of string = ('16 bit', '32 bit');
- IVisualizer: array[0..2] of string = ('Off', 'WhenNoVideo','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 string = ('Off', 'On');
+ IBackgroundMusic: array[0..1] of UTF8String = ('Off', 'On');
- ITextureSize: array[0..3] of string = ('64', '128', '256', '512');
- ITextureSizeVals: array[0..3] of integer = ( 64, 128, 256, 512);
+ 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 string = ('Small', 'Big');
+ ISingWindow: array[0..1] of UTF8String = ('Small', 'Big');
//SingBar Mod
- IOscilloscope: array[0..1] of string = ('Off', 'On');
+ IOscilloscope: array[0..1] of UTF8String = ('Off', 'On');
- ISpectrum: array[0..1] of string = ('Off', 'On');
- ISpectrograph: array[0..1] of string = ('Off', 'On');
- IMovieSize: array[0..2] of string = ('Half', 'Full [Vid]', 'Full [BG+Vid]');
+ 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]');
- IClickAssist: array[0..1] of string = ('Off', 'On');
- IBeatClick: array[0..1] of string = ('Off', 'On');
- ISavePlayback: array[0..1] of string = ('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 string = ('5%', '10%', '15%', '20%');
+ 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 string = ('Off', 'On');
+ IVoicePassthrough: array[0..1] of UTF8String = ('Off', 'On');
+
+const
+ ISyncTo: array[0..2] of UTF8String = ('Music', 'Lyrics', 'Off');
+type
+ TSyncToType = (stMusic, stLyrics, stOff);
- IAudioOutputBufferSize: array[0..9] of string = ('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 );
+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 string = ('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 );
+ 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 string = ('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 );
+ 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 string = ('Off', '1 Sec', '2 Secs', '3 Secs', '4 Secs', '5 Secs');
- IPreviewFadingVals: array[0..5] of integer = ( 0, 1, 2, 3, 4, 5 );
+ 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 string = ('Plain', 'OLine1', 'OLine2');
- ILyricsEffect: array[0..4] of string = ('Simple', 'Zoom', 'Slide', 'Ball', 'Shift');
- ISolmization: array[0..3] of string = ('Off', 'Euro', 'Jap', 'American');
- INoteLines: array[0..1] of string = ('Off', 'On');
+ 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 string = ('Blue', 'Green', 'Pink', 'Red', 'Violet', 'Orange', 'Yellow', 'Brown', 'Black');
+ IColor: array[0..8] of UTF8String = ('Blue', 'Green', 'Pink', 'Red', 'Violet', 'Orange', 'Yellow', 'Brown', 'Black');
// Advanced
- ILoadAnimation: array[0..1] of string = ('Off', 'On');
- IEffectSing: array[0..1] of string = ('Off', 'On');
- IScreenFade: array[0..1] of string = ('Off', 'On');
- IAskbeforeDel: array[0..1] of string = ('Off', 'On');
- IOnSongClick: array[0..2] of string = ('Sing', 'Select Players', 'Open Menu');
- ILineBonus: array[0..1] of string = ('Off', 'On');
- IPartyPopup: array[0..1] of string = ('Off', 'On');
+ 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 string = ('Off', 'On');
- IMouse: array[0..2] of string = ('Off', 'Hardware Cursor', 'Software Cursor');
+ 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 string = ('Off', '1', '2', '3', '4', '5', '6');
- IMicBoost: array[0..3] of string = ('Off', '+6dB', '+12dB', '+18dB');
+ 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
- IDifficultyTranslated: array[0..2] of string = ('Easy', 'Medium', 'Hard');
- ITabsTranslated: array[0..1] of string = ('Off', 'On');
+ ILanguageTranslated: array of UTF8String;
- ISortingTranslated: array[0..7] of string = ('Edition', 'Genre', 'Language', 'Folder', 'Title', 'Artist', 'Title2', 'Artist2');
+ IDifficultyTranslated: array[0..2] of UTF8String = ('Easy', 'Medium', 'Hard');
+ ITabsTranslated: array[0..1] of UTF8String = ('Off', 'On');
- IDebugTranslated: array[0..1] of string = ('Off', 'On');
+ ISortingTranslated: array[0..6] of UTF8String = ('Edition', 'Genre', 'Language', 'Folder', 'Title', 'Artist', 'Artist2');
- IFullScreenTranslated: array[0..1] of string = ('Off', 'On');
- IVisualizerTranslated: array[0..2] of string = ('Off', 'WhenNoVideo','On');
+ IDebugTranslated: array[0..1] of UTF8String = ('Off', 'On');
- IBackgroundMusicTranslated: array[0..1] of string = ('Off', 'On');
- ISingWindowTranslated: array[0..1] of string = ('Small', 'Big');
+ 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 string = ('Off', 'On');
+ 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]');
- ISpectrumTranslated: array[0..1] of string = ('Off', 'On');
- ISpectrographTranslated: array[0..1] of string = ('Off', 'On');
- IMovieSizeTranslated: array[0..2] of string = ('Half', 'Full [Vid]', 'Full [BG+Vid]');
+ IClickAssistTranslated: array[0..1] of UTF8String = ('Off', 'On');
+ IBeatClickTranslated: array[0..1] of UTF8String = ('Off', 'On');
+ ISavePlaybackTranslated: array[0..1] of UTF8String = ('Off', 'On');
- IClickAssistTranslated: array[0..1] of string = ('Off', 'On');
- IBeatClickTranslated: array[0..1] of string = ('Off', 'On');
- ISavePlaybackTranslated: array[0..1] of string = ('Off', 'On');
+ IVoicePassthroughTranslated: array[0..1] of UTF8String = ('Off', 'On');
- IVoicePassthroughTranslated: array[0..1] of string = ('Off', 'On');
+ ISyncToTranslated: array[0..2] of UTF8String = ('Music', 'Lyrics', 'Off');
//Song Preview
- IPreviewVolumeTranslated: array[0..10] of string = ('Off', '10%', '20%', '30%', '40%', '50%', '60%', '70%', '80%', '90%', '100%');
+ IPreviewVolumeTranslated: array[0..10] of UTF8String = ('Off', '10%', '20%', '30%', '40%', '50%', '60%', '70%', '80%', '90%', '100%');
- IAudioOutputBufferSizeTranslated: array[0..9] of string = ('Auto', '256', '512', '1024', '2048', '4096', '8192', '16384', '32768', '65536');
+ IAudioOutputBufferSizeTranslated: array[0..9] of UTF8String = ('Auto', '256', '512', '1024', '2048', '4096', '8192', '16384', '32768', '65536');
- IAudioInputBufferSizeTranslated: array[0..9] of string = ('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 string = ('Off', '1 Sec', '2 Secs', '3 Secs', '4 Secs', '5 Secs');
+ IPreviewFadingTranslated: array[0..5] of UTF8String = ('Off', '1 Sec', '2 Secs', '3 Secs', '4 Secs', '5 Secs');
- ILyricsFontTranslated: array[0..2] of string = ('Plain', 'OLine1', 'OLine2');
- ILyricsEffectTranslated: array[0..4] of string = ('Simple', 'Zoom', 'Slide', 'Ball', 'Shift');
- ISolmizationTranslated: array[0..3] of string = ('Off', 'Euro', 'Jap', 'American');
- INoteLinesTranslated: array[0..1] of string = ('Off', 'On');
+ 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 string = ('Blue', 'Green', 'Pink', 'Red', 'Violet', 'Orange', 'Yellow', 'Brown', 'Black');
+ IColorTranslated: array[0..8] of UTF8String = ('Blue', 'Green', 'Pink', 'Red', 'Violet', 'Orange', 'Yellow', 'Brown', 'Black');
// Advanced
- ILoadAnimationTranslated: array[0..1] of string = ('Off', 'On');
- IEffectSingTranslated: array[0..1] of string = ('Off', 'On');
- IScreenFadeTranslated: array[0..1] of string = ('Off', 'On');
- IAskbeforeDelTranslated: array[0..1] of string = ('Off', 'On');
- IOnSongClickTranslated: array[0..2] of string = ('Sing', 'Select Players', 'Open Menu');
- ILineBonusTranslated: array[0..1] of string = ('Off', 'On');
- IPartyPopupTranslated: array[0..1] of string = ('Off', 'On');
+ 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 string = ('Off', 'On');
- IMouseTranslated: array[0..2] of string = ('Off', 'Hardware Cursor', 'Software Cursor');
+ 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 string = ('Off', '1', '2', '3', '4', '5', '6');
- IMicBoostTranslated: array[0..3] of string = ('Off', '+6dB', '+12dB', '+18dB');
+ 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,
- UMain,
SDL,
+ UCommandLine,
ULanguage,
UPlatform,
- USkins,
+ UMain,
URecord,
- UCommandLine,
- UPath;
+ USkins,
+ UThemes,
+ UPathUtils,
+ UUnicodeUtils;
(**
* Translate and set the values of options, which need translation.
*)
procedure TIni.TranslateOptionValues;
+var
+ I: integer;
begin
- ULanguage.Language.ChangeLanguage(ILanguage[Language]);
-
+ // 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');
@@ -345,8 +384,7 @@ begin
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_TITLE2');
- ISortingTranslated[7] := ULanguage.Language.Translate('OPTION_VALUE_ARTIST2');
+ ISortingTranslated[6] := ULanguage.Language.Translate('OPTION_VALUE_ARTIST2');
IDebugTranslated[0] := ULanguage.Language.Translate('OPTION_VALUE_OFF');
IDebugTranslated[1] := ULanguage.Language.Translate('OPTION_VALUE_ON');
@@ -389,6 +427,10 @@ begin
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');
@@ -399,11 +441,6 @@ begin
ILyricsEffectTranslated[3] := ULanguage.Language.Translate('OPTION_VALUE_BALL');
ILyricsEffectTranslated[4] := ULanguage.Language.Translate('OPTION_VALUE_SHIFT');
- ISolmizationTranslated[0] := ULanguage.Language.Translate('OPTION_VALUE_OFF');
- ISolmizationTranslated[1] := ULanguage.Language.Translate('OPTION_VALUE_EURO');
- ISolmizationTranslated[2] := ULanguage.Language.Translate('OPTION_VALUE_JAPAN');
- ISolmizationTranslated[3] := ULanguage.Language.Translate('OPTION_VALUE_AMERICAN');
-
INoteLinesTranslated[0] := ULanguage.Language.Translate('OPTION_VALUE_OFF');
INoteLinesTranslated[1] := ULanguage.Language.Translate('OPTION_VALUE_ON');
@@ -415,7 +452,7 @@ begin
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_BALCK');
+ IColorTranslated[8] := ULanguage.Language.Translate('OPTION_VALUE_BLACK');
// Advanced
ILoadAnimationTranslated[0] := ULanguage.Language.Translate('OPTION_VALUE_OFF');
@@ -508,14 +545,6 @@ begin
end;
(**
- * Returns the filename without its fileextension
- *)
-function TIni.RemoveFileExt(FullName: string): string;
-begin
- Result := ChangeFileExt(FullName, '');
-end;
-
-(**
* Extracts an index of a key that is surrounded by a Prefix/Suffix pair.
* Example: ExtractKeyIndex('MyKey[1]', '[', ']') will return 1.
*)
@@ -562,34 +591,12 @@ begin
end;
(**
- * Returns the index of Value in SearchArray
- * or -1 if Value is not in SearchArray.
- *)
-function TIni.GetArrayIndex(const SearchArray: array of string; 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 (UpperCase(SearchArray[i]) = UpperCase(Value))) then
- begin
- Result := i;
- Break;
- end;
- 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 string; IniFile: TCustomIniFile;
+function TIni.ReadArrayIndex(const SearchArray: array of UTF8String; IniFile: TCustomIniFile;
IniSection: string; IniProperty: string; Default: integer): integer;
var
StrValue: string;
@@ -625,7 +632,7 @@ begin
if (DeviceIndex >= 0) then
begin
if not IniFile.ValueExists('Record', Format('DeviceName[%d]', [DeviceIndex])) then
- break;
+ Continue;
// resize list
SetLength(InputDeviceConfig, Length(InputDeviceConfig)+1);
@@ -637,6 +644,7 @@ begin
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]));
@@ -675,6 +683,8 @@ begin
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
@@ -702,9 +712,9 @@ begin
// Load song-paths
for I := 0 to PathStrings.Count-1 do
begin
- if (AnsiStartsText('SongDir', PathStrings[I])) then
+ if (Pos('SONGDIR', UpperCase(PathStrings[I])) = 1) then
begin
- AddSongPath(IniFile.ReadString('Directories', PathStrings[I], ''));
+ AddSongPath(Path(IniFile.ReadString('Directories', PathStrings[I], '')));
end;
end;
@@ -712,38 +722,7 @@ begin
end;
procedure TIni.LoadThemes(IniFile: TCustomIniFile);
-var
- SearchResult: TSearchRec;
- ThemeIni: TMemIniFile;
- ThemeName: string;
- I: integer;
begin
- // Theme
- SetLength(ITheme, 0);
- Log.LogStatus('Searching for Theme : ' + ThemePath + '*.ini', 'Theme');
-
- FindFirst(ThemePath + '*.ini',faAnyFile, SearchResult);
- Repeat
- Log.LogStatus('Found Theme: ' + SearchResult.Name, 'Theme');
-
- //Read Themename from Theme
- ThemeIni := TMemIniFile.Create(SearchResult.Name);
- ThemeName := UpperCase(ThemeIni.ReadString('Theme','Name', RemoveFileExt(SearchResult.Name)));
- ThemeIni.Free;
-
- //Search for Skins for this Theme
- for I := Low(Skin.Skin) to High(Skin.Skin) do
- begin
- if UpperCase(Skin.Skin[I].Theme) = ThemeName then
- begin
- SetLength(ITheme, Length(ITheme)+1);
- ITheme[High(ITheme)] := RemoveFileExt(SearchResult.Name);
- break;
- end;
- end;
- until FindNext(SearchResult) <> 0;
- FindClose(SearchResult);
-
// No Theme Found
if (Length(ITheme) = 0) then
begin
@@ -757,13 +736,22 @@ begin
// Skin
Skin.onThemeChange;
- SkinNo := GetArrayIndex(ISkin, IniFile.ReadString('Themes', 'Skin', ISkin[0]));
+ 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: string);
+ procedure swap(var s1, s2: UTF8String);
var
s3: string;
begin
@@ -800,17 +788,25 @@ begin
else if (Modes = PPSDL_Rect(-1)) then
begin
// Fallback to some standard resolutions
- SetLength(IResolution, 10);
+ SetLength(IResolution, 18);
IResolution[0] := '640x480';
IResolution[1] := '800x600';
IResolution[2] := '1024x768';
- IResolution[3] := '1152x864';
- IResolution[4] := '1280x800';
- IResolution[5] := '1280x960';
- IResolution[6] := '1400x1050';
- IResolution[7] := '1440x900';
- IResolution[8] := '1600x1200';
- IResolution[9] := '1680x1050';
+ 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
@@ -872,19 +868,15 @@ var
begin
GamePath := Platform.GetGameUserPath;
- Log.LogStatus( 'GamePath : ' +GamePath , '' );
+ Log.LogStatus( 'GamePath : ' +GamePath.ToNative , '' );
- if (Params.ConfigFile <> '') then
- try
- FileName := Params.ConfigFile;
- except
- FileName := GamePath + 'config.ini';
- end
+ if (Params.ConfigFile.IsSet) then
+ FileName := Params.ConfigFile
else
- FileName := GamePath + 'config.ini';
+ FileName := GamePath.Append('config.ini');
- Log.LogStatus( 'Using config : ' + FileName , 'Ini');
- IniFile := TMemIniFile.Create( FileName );
+ Log.LogStatus('Using config : ' + FileName.ToNative, 'Ini');
+ IniFile := TMemIniFile.Create(FileName.ToNative);
// Name
for I := 0 to 11 do
@@ -904,22 +896,24 @@ begin
// Language
Language := GetArrayIndex(ILanguage, IniFile.ReadString('Game', 'Language', 'English'));
- //Language.ChangeLanguage(ILanguage[Language]);
// 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[0]));
+ Sorting := GetArrayIndex(ISorting, IniFile.ReadString('Game', 'Sorting', ISorting[Ord(sEdition)]));
// Debug
Debug := GetArrayIndex(IDebug, IniFile.ReadString('Game', 'Debug', IDebug[0]));
LoadScreenModes(IniFile);
- // TextureSize
- TextureSize := GetArrayIndex(ITextureSize, IniFile.ReadString('Graphics', 'TextureSize', ITextureSize[1]));
+ // TextureSize (aka CachedCoverSize)
+ // Note: a default cached cover size of 128 pixels is big enough,
+ // 256 pixels are already noticeably slow with 180 covers in the song-screen
+ // displayed at once. In additon the covers.db will be too big.
+ TextureSize := GetArrayIndex(ITextureSize, IniFile.ReadString('Graphics', 'TextureSize', '128'));
// SingWindow
SingWindow := GetArrayIndex(ISingWindow, IniFile.ReadString('Graphics', 'SingWindow', 'Big'));
@@ -961,19 +955,13 @@ begin
LyricsFont := GetArrayIndex(ILyricsFont, IniFile.ReadString('Lyrics', 'LyricsFont', ILyricsFont[0]));
// Lyrics Effect
- LyricsEffect := GetArrayIndex(ILyricsEffect, IniFile.ReadString('Lyrics', 'LyricsEffect', ILyricsEffect[2]));
-
- // Solmization
- Solmization := GetArrayIndex(ISolmization, IniFile.ReadString('Lyrics', 'Solmization', ISolmization[0]));
+ LyricsEffect := GetArrayIndex(ILyricsEffect, IniFile.ReadString('Lyrics', 'LyricsEffect', ILyricsEffect[4]));
// NoteLines
NoteLines := GetArrayIndex(INoteLines, IniFile.ReadString('Lyrics', 'NoteLines', INoteLines[1]));
LoadThemes(IniFile);
- // Color
- Color := GetArrayIndex(IColor, IniFile.ReadString('Themes', 'Color', IColor[0]));
-
LoadInputDeviceCfg(IniFile);
// LoadAnimation
@@ -993,7 +981,7 @@ begin
{**
* Background music
*}
- BackgroundMusicOption := GetArrayIndex(IBackgroundMusic, IniFile.ReadString('Sound', 'BackgroundMusic', 'Off'));
+ BackgroundMusicOption := GetArrayIndex(IBackgroundMusic, IniFile.ReadString('Sound', 'BackgroundMusic', 'On'));
// EffectSing
EffectSing := GetArrayIndex(IEffectSing, IniFile.ReadString('Advanced', 'EffectSing', 'On'));
@@ -1010,6 +998,9 @@ begin
// 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]));
@@ -1027,13 +1018,13 @@ procedure TIni.Save;
var
IniFile: TIniFile;
begin
- if (FileExists(Filename) and FileIsReadOnly(Filename)) then
+ if (Filename.IsFile and Filename.IsReadOnly) then
begin
Log.LogError('Config-file is read-only', 'TIni.Save');
Exit;
end;
- IniFile := TIniFile.Create(Filename);
+ IniFile := TIniFile.Create(Filename.ToNative);
// Players
IniFile.WriteString('Game', 'Players', IPlayers[Players]);
@@ -1116,9 +1107,6 @@ begin
// Lyrics Effect
IniFile.WriteString('Lyrics', 'LyricsEffect', ILyricsEffect[LyricsEffect]);
- // Solmization
- IniFile.WriteString('Lyrics', 'Solmization', ISolmization[Solmization]);
-
// NoteLines
IniFile.WriteString('Lyrics', 'NoteLines', INoteLines[NoteLines]);
@@ -1154,6 +1142,9 @@ begin
//Party Popup
IniFile.WriteString('Advanced', 'PartyPopup', IPartyPopup[PartyPopup]);
+ //SyncTo
+ IniFile.WriteString('Advanced', 'SyncTo', ISyncTo[SyncTo]);
+
// Joypad
IniFile.WriteString('Controller', 'Joypad', IJoypad[Joypad]);
@@ -1173,17 +1164,17 @@ var
IniFile: TIniFile;
I: integer;
begin
- if not FileIsReadOnly(Filename) then
+ if not Filename.IsReadOnly() then
begin
- IniFile := TIniFile.Create(Filename);
+ IniFile := TIniFile.Create(Filename.ToNative);
//Name Templates for Names Mod
- for I := 1 to 12 do
- IniFile.WriteString('Name', 'P' + IntToStr(I), Name[I-1]);
- for I := 1 to 3 do
- IniFile.WriteString('NameTeam', 'T' + IntToStr(I), NameTeam[I-1]);
- for I := 1 to 12 do
- IniFile.WriteString('NameTemplate', 'Name' + IntToStr(I), NameTemplate[I-1]);
+ 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;
@@ -1193,9 +1184,9 @@ procedure TIni.SaveLevel;
var
IniFile: TIniFile;
begin
- if not FileIsReadOnly(Filename) then
+ if not Filename.IsReadOnly() then
begin
- IniFile := TIniFile.Create(Filename);
+ IniFile := TIniFile.Create(Filename.ToNative);
// Difficulty
IniFile.WriteString('Game', 'Difficulty', IDifficulty[Difficulty]);
diff --git a/cmake/src/base/ULanguage.pas b/cmake/src/base/ULanguage.pas
index 02cd7712..5f8a2692 100644
--- a/cmake/src/base/ULanguage.pas
+++ b/cmake/src/base/ULanguage.pas
@@ -33,33 +33,41 @@ interface
{$I switches.inc}
+uses
+ UUnicodeUtils;
+
type
TLanguageEntry = record
- ID: string;
- Text: string;
+ ID: AnsiString; //**< identifier (ASCII)
+ Text: UTF8String; //**< translation (UTF-8)
end;
TLanguageList = record
- Name: string;
- {FileName: string; }
+ Name: AnsiString; //**< language name (ASCII)
end;
+ TLanguageEntryArray = array of TLanguageEntry;
+
TLanguage = class
- public
- Entry: array of TLanguageEntry; //Entrys of Chosen Language
- SEntry: array of TLanguageEntry; //Entrys of Standard Language
- CEntry: array of TLanguageEntry; //Constant Entrys e.g. Version
- Implode_Glue1, Implode_Glue2: String;
- public
+ private
List: array of TLanguageList;
- constructor Create;
+ 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 Translate(Text: String): String;
- procedure ChangeLanguage(Language: String);
- procedure AddConst(ID, Text: String);
- procedure ChangeConst(ID, Text: String);
- function Implode(Pieces: Array of String): String;
+ 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
@@ -69,20 +77,18 @@ implementation
uses
UMain,
- // UFiles,
UIni,
IniFiles,
Classes,
SysUtils,
- {$IFDEF win32}
- Windows,
- {$ENDIF}
ULog,
- UPath;
+ UPath,
+ UFilesystem,
+ UPathUtils;
-//----------
-//Create - Construct Class then LoadList + Standard Language + Set Standard Implode Glues
-//----------
+{**
+ * LoadList, set default language, set standard implode glues
+ *}
constructor TLanguage.Create;
var
I, J: Integer;
@@ -107,9 +113,9 @@ begin
begin
ChangeLanguage('English');
- SetLength(SEntry, Length(Entry));
- for J := low(Entry) to high(Entry) do
- SEntry[J] := Entry[J];
+ SetLength(EntryDefault, Length(Entry));
+ for J := 0 to high(Entry) do
+ EntryDefault[J] := Entry[J];
SetLength(Entry, 0);
@@ -123,41 +129,44 @@ begin
end;
-//----------
-//LoadList - Parse the Language Dir searching Translations
-//----------
+{**
+ * Parse the Language Dir searching Translations
+ *}
procedure TLanguage.LoadList;
var
- SR: TSearchRec; // for parsing directory
+ Iter: IFileIterator;
+ IniInfo: TFileInfo;
+ LangName: string;
begin
SetLength(List, 0);
SetLength(ILanguage, 0);
- if FindFirst(LanguagesPath + '*.ini', 0, SR) = 0 then begin
- repeat
- SetLength(List, Length(List)+1);
- SetLength(ILanguage, Length(ILanguage)+1);
- SR.Name := ChangeFileExt(SR.Name, '');
+ Iter := FileSystem.FileFind(LanguagesPath.Append('*.ini'), 0);
+ while(Iter.HasNext) do
+ begin
+ IniInfo := Iter.Next;
+
+ LangName := IniInfo.Name.SetExtension('').ToUTF8;
- List[High(List)].Name := SR.Name;
- ILanguage[High(ILanguage)] := SR.Name;
+ SetLength(List, Length(List)+1);
+ List[High(List)].Name := LangName;
- until FindNext(SR) <> 0;
- SysUtils.FindClose(SR);
- end; // if FindFirst
+ SetLength(ILanguage, Length(ILanguage)+1);
+ ILanguage[High(ILanguage)] := LangName;
+ end;
end;
-//----------
-//ChangeLanguage - Load the specified LanguageFile
-//----------
-procedure TLanguage.ChangeLanguage(Language: String);
+{**
+ * Load the specified LanguageFile
+ *}
+procedure TLanguage.ChangeLanguage(const Language: AnsiString);
var
- IniFile: TIniFile;
+ IniFile: TUnicodeMemIniFile;
E: integer; // entry
S: TStringList;
begin
SetLength(Entry, 0);
- IniFile := TIniFile.Create(LanguagesPath + Language + '.ini');
+ IniFile := TUnicodeMemIniFile.Create(LanguagesPath.Append(Language + '.ini'));
S := TStringList.Create;
IniFile.ReadSectionValues('Text', S);
@@ -177,80 +186,107 @@ begin
IniFile.Free;
end;
-//----------
-//Translate - Translate the Text
-//----------
-Function TLanguage.Translate(Text: String): String;
+{**
+ * 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
+ E: integer; // entry
+ ID: AnsiString;
+ EntryIndex: integer;
begin
+ // fallback result in case Text is not a known ID
Result := Text;
- Text := Uppercase(Result);
+
+ // normalize ID case
+ ID := UpperCase(Text);
+
+ // Check if ID exists
//Const Mod
- for E := 0 to high(CEntry) do
- if Text = CEntry[E].ID then
- begin
- Result := CEntry[E].Text;
- exit;
- end;
- //Const Mod End
+ EntryIndex := FindID(ID, EntryConst);
+ if (EntryIndex >= 0) then
+ begin
+ Result := EntryConst[EntryIndex].Text;
+ Exit;
+ end;
- for E := 0 to high(Entry) do
- if Text = Entry[E].ID then
- begin
- Result := Entry[E].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
- for E := low(SEntry) to high(SEntry) do
- if Text = SEntry[E].ID then
- begin
- Result := SEntry[E].Text;
- Break;
- end;
- //Standard Language END
+ EntryIndex := FindID(ID, EntryDefault);
+ if (EntryIndex >= 0) then
+ begin
+ Result := EntryDefault[EntryIndex].Text;
+ Exit;
+ end;
end;
-//----------
-//AddConst - Add a Constant ID that will be Translated but not Loaded from the LanguageFile
-//----------
-procedure TLanguage.AddConst (ID, Text: String);
+{**
+ * 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 (CEntry, Length(CEntry) + 1);
- CEntry[high(CEntry)].ID := ID;
- CEntry[high(CEntry)].Text := Text;
+ SetLength (EntryConst, Length(EntryConst) + 1);
+ EntryConst[high(EntryConst)].ID := ID;
+ EntryConst[high(EntryConst)].Text := Text;
end;
-//----------
-//ChangeConst - Change a Constant Value by ID
-//----------
-procedure TLanguage.ChangeConst(ID, Text: String);
+{**
+ * Change a Constant Value by ID
+ *}
+procedure TLanguage.ChangeConst(const ID: AnsiString; const Text: UTF8String);
var
I: Integer;
begin
- for I := 0 to high(CEntry) do
+ for I := 0 to high(EntryConst) do
begin
- if CEntry[I].ID = ID then
+ if EntryConst[I].ID = ID then
begin
- CEntry[I].Text := Text;
+ EntryConst[I].Text := Text;
Break;
end;
end;
end;
-//----------
-//Implode - Connect an Array of Strings with ' and ' or ', ' to one String
-//----------
-function TLanguage.Implode(Pieces: Array of String): String;
+{**
+ * 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 := low(Pieces) to high(Pieces) do
+ for I := 0 to high(Pieces) do
begin
//Add Value
Result := Result + Pieces[I];
diff --git a/cmake/src/base/ULog.pas b/cmake/src/base/ULog.pas
index a872729a..e4ff4862 100644
--- a/cmake/src/base/ULog.pas
+++ b/cmake/src/base/ULog.pas
@@ -34,7 +34,8 @@ interface
{$I switches.inc}
uses
- Classes;
+ Classes,
+ UPath;
(*
* LOG_LEVEL_[TYPE] defines the "minimum" index for logs of type TYPE. Each
@@ -115,7 +116,7 @@ type
// voice
procedure LogVoice(SoundNr: integer);
// buffer
- procedure LogBuffer(const buf : Pointer; const bufLength : Integer; const filename : string);
+ procedure LogBuffer(const buf : Pointer; const bufLength : Integer; const filename : IPath);
end;
procedure DebugWriteln(const aString: String);
@@ -133,7 +134,7 @@ uses
UTime,
UCommon,
UCommandLine,
- UPath;
+ UPathUtils;
(*
* Write to console if in debug mode (Thread-safe).
@@ -198,7 +199,7 @@ begin
if not BenchmarkFileOpened then
begin
BenchmarkFileOpened := true;
- AssignFile(BenchmarkFile, LogPath + 'Benchmark.log');
+ AssignFile(BenchmarkFile, LogPath.Append('Benchmark.log').ToNative);
{$I-}
Rewrite(BenchmarkFile);
if IOResult = 0 then
@@ -270,7 +271,7 @@ procedure TLog.LogToFile(const Text: string);
begin
if (FileOutputEnabled and not LogFileOpened) then
begin
- AssignFile(LogFile, LogPath + 'Error.log');
+ AssignFile(LogFile, LogPath.Append('Error.log').ToNative);
{$I-}
Rewrite(LogFile);
if IOResult = 0 then
@@ -399,20 +400,19 @@ end;
procedure TLog.LogVoice(SoundNr: integer);
var
- FS: TFileStream;
- FileName: string;
+ FS: TBinaryFileStream;
+ Prefix: string;
+ FileName: IPath;
Num: integer;
begin
for Num := 1 to 9999 do begin
- FileName := IntToStr(Num);
- while Length(FileName) < 4 do
- FileName := '0' + FileName;
- FileName := LogPath + 'Voice' + FileName + '.raw';
- if not FileExists(FileName) then
+ Prefix := Format('Voice%.4d', [Num]);
+ FileName := LogPath.Append(Prefix + '.raw');
+ if not FileName.Exists() then
break
end;
- FS := TFileStream.Create(FileName, fmCreate);
+ FS := TBinaryFileStream.Create(FileName, fmCreate);
AudioInputProcessor.Sound[SoundNr].LogBuffer.Seek(0, soBeginning);
FS.CopyFrom(AudioInputProcessor.Sound[SoundNr].LogBuffer, AudioInputProcessor.Sound[SoundNr].LogBuffer.Size);
@@ -420,21 +420,19 @@ begin
FS.Free;
end;
-procedure TLog.LogBuffer(const buf: Pointer; const bufLength: Integer; const filename: string);
+procedure TLog.LogBuffer(const buf: Pointer; const bufLength: Integer; const filename: IPath);
var
- f : TFileStream;
+ f : TBinaryFileStream;
begin
- f := nil;
-
try
- f := TFileStream.Create( filename, fmCreate);
- f.Write( buf^, bufLength);
- f.Free;
- except
- on e : Exception do begin
- Log.LogError('TLog.LogBuffer: Failed to log buffer into file "' + filename + '". ErrMsg: ' + e.Message);
+ 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;
diff --git a/cmake/src/base/ULyrics.pas b/cmake/src/base/ULyrics.pas
index 82982981..3f62db9c 100644
--- a/cmake/src/base/ULyrics.pas
+++ b/cmake/src/base/ULyrics.pas
@@ -52,14 +52,14 @@ type
Width: real; // width
Start: cardinal; // start of the word in quarters (beats)
Length: cardinal; // length of the word in quarters
- Text: string; // text
+ Text: UTF8String; // text
Freestyle: boolean; // is freestyle?
end;
TLyricWordArray = array of TLyricWord;
TLyricLine = class
public
- Text: string; // text
+ Text: UTF8String; // text
Width: real; // width
Height: real; // height
Words: TLyricWordArray; // words in this line
diff --git a/cmake/src/base/UMain.pas b/cmake/src/base/UMain.pas
index 275510fc..0d479420 100644
--- a/cmake/src/base/UMain.pas
+++ b/cmake/src/base/UMain.pas
@@ -37,13 +37,9 @@ uses
SysUtils,
SDL;
-var
- Done: boolean;
- Restart: boolean;
-
procedure Main;
procedure MainLoop;
-procedure CheckEvents;
+function CheckEvents: boolean;
type
TMainThreadExecProc = procedure(Data: Pointer);
@@ -73,22 +69,30 @@ uses
UCovers,
UDataBase,
UDisplay,
- UDLLManager,
UGraphic,
UGraphicClasses,
UIni,
UJoystick,
ULanguage,
ULog,
- UPath,
+ UPathUtils,
UPlaylist,
UMusic,
+ URecord,
UBeatTimer,
UPlatform,
USkins,
USongs,
UThemes,
UParty,
+ ULuaCore,
+ UHookableEvent,
+ ULuaGl,
+ ULuaLog,
+ ULuaTexture,
+ ULuaTextGL,
+ ULuaParty,
+ ULuaScreenSing,
UTime;
procedure Main;
@@ -124,6 +128,10 @@ begin
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;
@@ -148,15 +156,6 @@ begin
Log.BenchmarkEnd(1);
Log.LogBenchmark('Loading Language', 1);
-{
- // SDL_ttf (Not used yet, maybe in version 1.5)
- Log.BenchmarkStart(1);
- Log.LogStatus('Initialize SDL_ttf', 'Initialization');
- TTF_Init();
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Initializing SDL_ttf', 1);
-}
-
// Skin
Log.BenchmarkStart(1);
Log.LogStatus('Loading Skin List', 'Initialization');
@@ -164,6 +163,12 @@ begin
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');
@@ -174,12 +179,6 @@ begin
Log.LogStatus('Write Ini', 'Initialization');
Ini.Save;
- // Load Languagefile
- if (Params.Language <> -1) then
- Language.ChangeLanguage(ILanguage[Params.Language])
- else
- Language.ChangeLanguage(ILanguage[Ini.Language]);
-
Log.BenchmarkEnd(1);
Log.LogBenchmark('Loading Ini', 1);
@@ -195,10 +194,10 @@ begin
// Theme
Log.BenchmarkStart(1);
- Log.LogStatus('Load Themes', 'Initialization');
- Theme := TTheme.Create(ThemePath + ITheme[Ini.Theme] + '.ini', Ini.Color);
+ Log.LogStatus('Load Theme', 'Initialization');
+ Theme.LoadTheme(Ini.Theme, Ini.Color);
Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading Themes', 1);
+ Log.LogBenchmark('Loading Theme', 1);
// Covers Cache
Log.BenchmarkStart(1);
@@ -226,20 +225,6 @@ begin
Log.BenchmarkEnd(1);
Log.LogBenchmark('Loading Songs', 1);
- // PluginManager
- Log.BenchmarkStart(1);
- Log.LogStatus('PluginManager', 'Initialization');
- DLLMan := TDLLMan.Create; // Load PluginList
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading PluginManager', 1);
-
- // Party Mode Manager
- Log.BenchmarkStart(1);
- Log.LogStatus('PartySession Manager', 'Initialization');
- PartySession := TPartySession.Create; //Load PartySession
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading PartySession Manager', 1);
-
// Graphics
Log.BenchmarkStart(1);
Log.LogStatus('Initialize 3D', 'Initialization');
@@ -252,10 +237,10 @@ begin
Log.LogStatus('DataBase System', 'Initialization');
DataBase := TDataBaseSystem.Create;
- if (Params.ScoreFile = '') then
- DataBase.Init (Platform.GetGameUserPath + 'Ultrastar.db')
+ if (Params.ScoreFile.IsUnset) then
+ DataBase.Init(Platform.GetGameUserPath.Append('Ultrastar.db'))
else
- DataBase.Init (Params.ScoreFile);
+ DataBase.Init(Params.ScoreFile);
Log.BenchmarkEnd(1);
Log.LogBenchmark('Loading DataBase System', 1);
@@ -284,22 +269,43 @@ begin
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);
- Log.LogStatus('Creating Core', 'Initialization');
-{
- Core := TCore.Create(
- USDXShortVersionStr,
- MakeVersion(USDX_VERSION_MAJOR,
- USDX_VERSION_MINOR,
- USDX_VERSION_RELEASE,
- chr(0))
- );
-}
+ { prepare software cursor }
+ Display.SetCursor;
+
+ {**
+ * Start background music
+ *}
+ SoundLib.StartBgMusic;
- Log.LogStatus('Running Core', 'Initialization');
- //Core.Run;
+ // check microphone settings, goto record options if they are corrupt
+ if (not AudioInputProcessor.ValidateSettings) then
+ Display.CurrentScreen^.FadeTo( @ScreenOptionsRecord );
//------------------------------
// Start Mainloop
@@ -318,62 +324,58 @@ begin
// call an uninitialize routine for every initialize step
// or at least use the corresponding Free methods
+ Log.LogStatus('Finalize Media', 'Finalization');
FinalizeMedia();
- //TTF_Quit();
+ Log.LogStatus('Uninitialize 3D', 'Finalization');
+ Finalize3D();
+
+ Log.LogStatus('Finalize SDL', 'Finalization');
SDL_Quit();
- if assigned(Log) then
- begin
- Log.LogStatus('Main Loop', 'Finished');
- Log.Free;
- end;
+ Log.LogStatus('Finalize Log', 'Finalization');
+ Log.Free;
{$IFNDEF Debug}
end;
{$ENDIF}
end;
procedure MainLoop;
-var
- Delay: integer;
const
MAX_FPS = 100;
+var
+ Delay: integer;
+ TicksCurrent: cardinal;
+ TicksBeforeFrame: cardinal;
+ Continue: boolean;
begin
SDL_EnableKeyRepeat(125, 125);
CountSkipTime(); // JB - for some reason this seems to be needed when we use the SDL Timer functions.
- while not Done do
+ while Continue do
begin
+ TicksBeforeFrame := SDL_GetTicks;
+
// joypad
if (Ini.Joypad = 1) or (Params.Joypad) then
Joy.Update;
// keyboard events
- CheckEvents;
+ Continue := CheckEvents;
// display
- Done := not Display.Draw;
+ Continue := Display.Draw;
SwapBuffers;
- // delay
- CountMidTime;
-
- Delay := Floor(1000 / MAX_FPS - 1000 * TimeMid);
- Log.LogError ('MainLoop', 'Delay: ' + intToStr(Delay));
+ // FPS limiter
+ TicksCurrent := SDL_GetTicks;
+ Delay := 1000 div MAX_FPS - (TicksCurrent - TicksBeforeFrame);
if Delay >= 1 then
SDL_Delay(Delay); // dynamic, maximum is 100 fps
- Log.LogError ('MainLoop', 'Delay: ok ' + intToStr(Delay));
CountSkipTime;
- // reinitialization of graphics
- if Restart then
- begin
- Reinitialize3D;
- Restart := false;
- end;
-
end;
end;
@@ -392,15 +394,13 @@ begin
end;
end;
-procedure CheckEvents;
+function CheckEvents: boolean;
var
Event: TSDL_event;
mouseDown: boolean;
mouseBtn: integer;
begin
- if Assigned(Display.NextScreen) then
- Exit;
-
+ Result := true;
while (SDL_PollEvent(@Event) <> 0) do
begin
case Event.type_ of
@@ -425,29 +425,39 @@ begin
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 / Screen.w,
- Event.button.Y * 600 / Screen.h,
- mouseDown and ((mouseBtn <> SDL_BUTTON_WHEELDOWN) or (mouseBtn <> SDL_BUTTON_WHEELUP)));
-
- if (ScreenPopupError <> nil) and (ScreenPopupError.Visible) then
- done := not ScreenPopupError.ParseMouse(mouseBtn, mouseDown, Event.button.x, Event.button.y)
- else if (ScreenPopupCheck <> nil) and (ScreenPopupCheck.Visible) then
- done := not ScreenPopupCheck.ParseMouse(mouseBtn, mouseDown, Event.button.x, Event.button.y)
- else
- begin
- done := not Display.CurrentScreen^.ParseMouse(mouseBtn, mouseDown, Event.button.x, Event.button.y);
-
- // if screen wants to exit
- if done then
- DoQuit;
+ 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
+ Result := ScreenPopupError.ParseMouse(mouseBtn, mouseDown, Event.button.x, Event.button.y)
+ else if (ScreenPopupInfo <> nil) and (ScreenPopupInfo.Visible) then
+ Result := ScreenPopupInfo.ParseMouse(mouseBtn, mouseDown, Event.button.x, Event.button.y)
+ else if (ScreenPopupCheck <> nil) and (ScreenPopupCheck.Visible) then
+ Result := ScreenPopupCheck.ParseMouse(mouseBtn, mouseDown, Event.button.x, Event.button.y)
+ else
+ begin
+ Result := Display.CurrentScreen^.ParseMouse(mouseBtn, mouseDown, Event.button.x, Event.button.y);
+
+ // if screen wants to exit
+ if not Result then
+ DoQuit;
+ end;
end;
end;
end;
@@ -459,6 +469,12 @@ begin
// 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)
@@ -468,52 +484,72 @@ begin
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 (Event.key.keysym.sym = SDLK_F11) or
- ((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
+ 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
- SDL_SetVideoMode(ScreenW, ScreenH, (Ini.Depth+1) * 16, SDL_OPENGL or SDL_FULLSCREEN);
+ 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
+ Result := ScreenPopupError.ParseInput(Event.key.keysym.sym, Event.key.keysym.unicode, true)
+ else if (ScreenPopupInfo <> nil) and (ScreenPopupInfo.Visible) then
+ Result := ScreenPopupInfo.ParseInput(Event.key.keysym.sym, Event.key.keysym.unicode, true)
+ else if (ScreenPopupCheck <> nil) and (ScreenPopupCheck.Visible) then
+ Result := ScreenPopupCheck.ParseInput(Event.key.keysym.sym, Event.key.keysym.unicode, true)
else
begin
- SDL_SetVideoMode(ScreenW, ScreenH, (Ini.Depth+1) * 16, SDL_OPENGL or SDL_RESIZABLE);
- end;
+ // check if screen wants to exit
+ Result := Display.ParseInput(Event.key.keysym.sym, Event.key.keysym.unicode, true);
- 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
- Done := not ScreenPopupError.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), true)
- else if (ScreenPopupCheck <> nil) and (ScreenPopupCheck.Visible) then
- Done := not ScreenPopupCheck.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), true)
- else
- begin
- // check if screen wants to exit
- Done := not Display.CurrentScreen^.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), true);
-
- // if screen wants to exit
- if Done then
- DoQuit;
+ // if screen wants to exit
+ if not Result then
+ DoQuit;
+ end;
end;
end;
SDL_JOYAXISMOTION:
diff --git a/cmake/src/base/UMusic.pas b/cmake/src/base/UMusic.pas
index 19c54bee..7f2b3e30 100644
--- a/cmake/src/base/UMusic.pas
+++ b/cmake/src/base/UMusic.pas
@@ -34,10 +34,11 @@ interface
{$I switches.inc}
uses
- UTime,
SysUtils,
Classes,
- UBeatTimer;
+ UTime,
+ UBeatTimer,
+ UPath;
type
TNoteType = (ntFreestyle, ntNormal, ntGolden);
@@ -62,7 +63,7 @@ type
Start: integer; // beat the fragment starts at
Length: integer; // length in beats
Tone: integer; // full range tone
- Text: string; // text assigned to this fragment (a syllable, word, etc.)
+ Text: UTF8String; // text assigned to this fragment (a syllable, word, etc.)
NoteType: TNoteType; // note-type: golden-note/freestyle etc.
end;
@@ -73,7 +74,7 @@ type
PLine = ^TLine;
TLine = record
Start: integer; // the start beat of this line (<> start beat of the first note of this line)
- Lyric: string;
+ 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.
@@ -187,10 +188,6 @@ type
end;
type
- TSyncSource = class
- function GetClock(): real; virtual; abstract;
- end;
-
TAudioProcessingStream = class;
TOnCloseHandler = procedure(Stream: TAudioProcessingStream);
@@ -249,8 +246,8 @@ type
TAudioPlaybackStream = class(TAudioProcessingStream)
protected
+ AvgSyncDiff: double; //** average difference between stream and sync clock
SyncSource: TSyncSource;
- AvgSyncDiff: double;
SourceStream: TAudioSourceStream;
function GetLatency(): double; virtual; abstract;
@@ -259,7 +256,7 @@ type
procedure SetVolume(Volume: single); virtual; abstract;
function Synchronize(BufferSize: integer; FormatInfo: TAudioFormatInfo): integer;
procedure FillBufferWithFrame(Buffer: PByteArray; BufferSize: integer; Frame: PByteArray; FrameSize: integer);
- public
+ public
(**
* Opens a SourceStream for playback.
* Note that the caller (not the TAudioPlaybackStream) is responsible to
@@ -315,7 +312,7 @@ type
// soundcard output-devices information
TAudioOutputDevice = class
public
- Name: string; // soundcard name
+ Name: UTF8String; // soundcard name
end;
TAudioOutputDeviceList = array of TAudioOutputDevice;
@@ -323,28 +320,33 @@ type
IGenericPlayback = Interface
['{63A5EBC3-3F4D-4F23-8DFB-B5165FCE33DD}']
function GetName: String;
+ end;
- function Open(const Filename: string): boolean; // true if succeed
- procedure Close;
-
+ 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 GetFrame(Time: Extended);
+ procedure DrawGL(Screen: integer);
+
+ 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;
-
- procedure GetFrame(Time: Extended); // WANT TO RENAME THESE TO BE MORE GENERIC
- procedure DrawGL(Screen: integer); // WANT TO RENAME THESE TO BE MORE GENERIC
+ function Init(): boolean;
+ function Finalize: boolean;
+ function Open(const FileName : IPath): IVideo;
end;
IVideoVisualization = Interface( IVideoPlayback )
@@ -369,6 +371,18 @@ type
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
@@ -376,7 +390,7 @@ type
// nil-pointers is not neccessary anymore.
// PlaySound/StopSound will be removed then, OpenSound will be renamed to
// CreateSound.
- function OpenSound(const Filename: String): TAudioPlaybackStream;
+ function OpenSound(const Filename: IPath): TAudioPlaybackStream;
procedure PlaySound(Stream: TAudioPlaybackStream);
procedure StopSound(Stream: TAudioPlaybackStream);
@@ -391,7 +405,7 @@ type
IGenericDecoder = Interface
['{557B0E9A-604D-47E4-B826-13769F3E10B7}']
- function GetName(): String;
+ function GetName(): string;
function InitializeDecoder(): boolean;
function FinalizeDecoder(): boolean;
//function IsSupported(const Filename: string): boolean;
@@ -400,13 +414,13 @@ type
(*
IVideoDecoder = Interface( IGenericDecoder )
['{2F184B2B-FE69-44D5-9031-0A2462391DCA}']
- function Open(const Filename: string): TVideoDecodeStream;
+ function Open(const Filename: IPath): TVideoDecodeStream;
end;
*)
IAudioDecoder = Interface( IGenericDecoder )
['{AB47B1B6-2AA9-4410-BF8C-EC79561B5478}']
- function Open(const Filename: string): TAudioDecodeStream;
+ function Open(const Filename: IPath): TAudioDecodeStream;
end;
IAudioInput = Interface
@@ -456,7 +470,7 @@ const
SOUNDID_CLICK = 5;
LAST_SOUNDID = SOUNDID_CLICK;
- BaseSoundFilenames: array[0..LAST_SOUNDID] of string = (
+ BaseSoundFilenames: array[0..LAST_SOUNDID] of IPath = (
'%SOUNDPATH%/Common start.mp3', // Start
'%SOUNDPATH%/Common back.mp3', // Back
'%SOUNDPATH%/menu swoosh.mp3', // Swoosh
@@ -497,7 +511,7 @@ type
procedure StartBgMusic();
procedure PauseBgMusic();
// TODO
- //function AddSound(Filename: string): integer;
+ //function AddSound(Filename: IPath): integer;
//procedure RemoveSound(ID: integer);
//function GetSound(ID: integer): TAudioPlaybackStream;
//property Sound[ID: integer]: TAudioPlaybackStream read GetSound; default;
@@ -533,7 +547,7 @@ uses
UCommandLine,
URecord,
ULog,
- UPath;
+ UPathUtils;
var
DefaultVideoPlayback : IVideoPlayback;
@@ -654,7 +668,7 @@ begin
FilterInterfaceList(IAudioDecoder, MediaManager, InterfaceList);
for i := 0 to InterfaceList.Count-1 do
begin
- CurrentAudioDecoder := IAudioDecoder(InterfaceList[i]);
+ CurrentAudioDecoder := InterfaceList[i] as IAudioDecoder;
if (not CurrentAudioDecoder.InitializeDecoder()) then
begin
Log.LogError('Initialize failed, Removing - '+ CurrentAudioDecoder.GetName);
@@ -671,7 +685,7 @@ begin
FilterInterfaceList(IAudioPlayback, MediaManager, InterfaceList);
for i := 0 to InterfaceList.Count-1 do
begin
- CurrentAudioPlayback := IAudioPlayback(InterfaceList[i]);
+ CurrentAudioPlayback := InterfaceList[i] as IAudioPlayback;
if (CurrentAudioPlayback.InitializePlayback()) then
begin
DefaultAudioPlayback := CurrentAudioPlayback;
@@ -686,7 +700,7 @@ begin
FilterInterfaceList(IAudioInput, MediaManager, InterfaceList);
for i := 0 to InterfaceList.Count-1 do
begin
- CurrentAudioInput := IAudioInput(InterfaceList[i]);
+ CurrentAudioInput := InterfaceList[i] as IAudioInput;
if (CurrentAudioInput.InitializeRecord()) then
begin
DefaultAudioInput := CurrentAudioInput;
@@ -719,7 +733,7 @@ begin
FilterInterfaceList(IVideoPlayback, MediaManager, InterfaceList);
for i := 0 to InterfaceList.Count-1 do
begin
- VideoInterface := IVideoPlayback(InterfaceList[i]);
+ VideoInterface := InterfaceList[i] as IVideoPlayback;
if (VideoInterface.Init()) then
begin
DefaultVideoPlayback := VideoInterface;
@@ -734,7 +748,7 @@ begin
FilterInterfaceList(IVideoVisualization, MediaManager, InterfaceList);
for i := 0 to InterfaceList.Count-1 do
begin
- VisualInterface := IVideoVisualization(InterfaceList[i]);
+ VisualInterface := InterfaceList[i] as IVideoVisualization;
if (VisualInterface.Init()) then
begin
DefaultVisualization := VisualInterface;
@@ -748,7 +762,7 @@ begin
// now that we have all interfaces, we can dump them
// TODO: move this to another place
- if FindCmdLineSwitch( cMediaInterfaces ) then
+ if FindCmdLineSwitch(cMediaInterfaces) then
begin
DumpMediaInterfaces();
halt;
@@ -772,27 +786,27 @@ begin
// finalize audio playback interfaces (should be done before the decoders)
FilterInterfaceList(IAudioPlayback, MediaManager, InterfaceList);
for i := 0 to InterfaceList.Count-1 do
- IAudioPlayback(InterfaceList[i]).FinalizePlayback();
+ (InterfaceList[i] as IAudioPlayback).FinalizePlayback();
// finalize audio input interfaces
FilterInterfaceList(IAudioInput, MediaManager, InterfaceList);
for i := 0 to InterfaceList.Count-1 do
- IAudioInput(InterfaceList[i]).FinalizeRecord();
+ (InterfaceList[i] as IAudioInput).FinalizeRecord();
// finalize audio decoder interfaces
FilterInterfaceList(IAudioDecoder, MediaManager, InterfaceList);
for i := 0 to InterfaceList.Count-1 do
- IAudioDecoder(InterfaceList[i]).FinalizeDecoder();
+ (InterfaceList[i] as IAudioDecoder).FinalizeDecoder();
// finalize video interfaces
FilterInterfaceList(IVideoPlayback, MediaManager, InterfaceList);
for i := 0 to InterfaceList.Count-1 do
- IVideoPlayback(InterfaceList[i]).Finalize();
+ (InterfaceList[i] as IVideoPlayback).Finalize();
// finalize audio decoder interfaces
FilterInterfaceList(IVideoVisualization, MediaManager, InterfaceList);
for i := 0 to InterfaceList.Count-1 do
- IVideoVisualization(InterfaceList[i]).Finalize();
+ (InterfaceList[i] as IVideoVisualization).Finalize();
InterfaceList.Free;
@@ -813,12 +827,6 @@ begin
if (AudioInput <> nil) then
AudioInput.CaptureStop;
- if (VideoPlayback <> nil) then
- VideoPlayback.Close;
-
- if (Visualization <> nil) then
- Visualization.Close;
-
UnloadMediaModules();
end;
@@ -855,14 +863,14 @@ procedure TSoundLibrary.LoadSounds();
begin
UnloadSounds();
- Start := AudioPlayback.OpenSound(SoundPath + 'Common start.mp3');
- Back := AudioPlayback.OpenSound(SoundPath + 'Common back.mp3');
- Swoosh := AudioPlayback.OpenSound(SoundPath + 'menu swoosh.mp3');
- Change := AudioPlayback.OpenSound(SoundPath + 'select music change music 50.mp3');
- Option := AudioPlayback.OpenSound(SoundPath + 'option change col.mp3');
- Click := AudioPlayback.OpenSound(SoundPath + 'rimshot022b.mp3');
+ 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 + 'Bebeto_-_Loop010.mp3');
+ BGMusic := AudioPlayback.OpenSound(SoundPath.Append('Bebeto_-_Loop010.mp3'));
if (BGMusic <> nil) then
BGMusic.Loop := True;
@@ -983,6 +991,8 @@ begin
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
@@ -999,11 +1009,15 @@ end;
function TAudioPlaybackStream.Synchronize(BufferSize: integer; FormatInfo: TAudioFormatInfo): integer;
var
TimeDiff: double;
- TimeCorrectionFactor: double;
+ FrameDiff: double;
+ FrameSkip: integer;
+ ReqFrames: integer;
+ MasterClock: real;
+ CurPosition: real;
const
- AVG_HISTORY_FACTOR = 0.9;
- SYNC_THRESHOLD = 0.045;
- MAX_SYNC_DIFF_TIME = 0.002;
+ AVG_HISTORY_FACTOR = 0.7;
+ SYNC_REPOS_THRESHOLD = 5.000;
+ SYNC_SOFT_THRESHOLD = 0.010;
begin
Result := BufferSize;
@@ -1013,9 +1027,12 @@ begin
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 := SyncSource.GetClock() - (Position - GetLatency());
+ TimeDiff := MasterClock - CurPosition;
// calculate average time difference (some sort of weighted mean).
// The bigger AVG_HISTORY_FACTOR is, the smoother is the average diff.
@@ -1030,35 +1047,46 @@ begin
AvgSyncDiff := TimeDiff * (1-AVG_HISTORY_FACTOR) +
AvgSyncDiff * AVG_HISTORY_FACTOR;
- // check if sync needed
- if (Abs(AvgSyncDiff) >= SYNC_THRESHOLD) then
+ {$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
- // TODO: use SetPosition if diff is too large (>5s)
- if (TimeDiff < 1) then
- TimeCorrectionFactor := Sign(TimeDiff)*TimeDiff*TimeDiff
- else
- TimeCorrectionFactor := TimeDiff;
-
- // calculate adapted buffer size
- // reduce size of data to fetch if music is ahead, increase otherwise
- Result := BufferSize + Round(TimeCorrectionFactor * FormatInfo.SampleRate) * FormatInfo.FrameSize;
+ {$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 average
+ // reset sync info
AvgSyncDiff := -1;
end;
-
- (*
- DebugWriteln('Diff: ' + floattostrf(TimeDiff, ffFixed, 15, 3) +
- '| SyS: ' + floattostrf(SyncSource.GetClock(), ffFixed, 15, 3) +
- '| Pos: ' + floattostrf(Position, ffFixed, 15, 3) +
- '| Avg: ' + floattostrf(AvgSyncDiff, ffFixed, 15, 3));
- *)
end;
(*
- * Fills a buffer with copies of the given frame or with 0 if frame.
+ * 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
diff --git a/cmake/src/base/UNote.pas b/cmake/src/base/UNote.pas
index 6da4cf07..6eb99df9 100644
--- a/cmake/src/base/UNote.pas
+++ b/cmake/src/base/UNote.pas
@@ -19,8 +19,8 @@
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
- * $URL: https://ultrastardx.svn.sourceforge.net/svnroot/ultrastardx/trunk/src/base/UNote.pas $
- * $Id: UNote.pas 1626 2009-03-07 19:53:00Z k-m_schindler $
+ * $URL$
+ * $Id$
*}
unit UNote;
@@ -61,7 +61,7 @@ type
PPLayer = ^TPlayer;
TPlayer = record
- Name: string;
+ Name: UTF8String;
// Index in Teaminfo record
TeamID: byte;
@@ -123,13 +123,12 @@ uses
UCatCovers,
UDataBase,
UPlaylist,
- UDLLManager,
UParty,
UConfig,
UCommon,
UGraphic,
UGraphicClasses,
- UPath,
+ UPathUtils,
UPlatform,
UThemes;
diff --git a/cmake/src/base/UParty.pas b/cmake/src/base/UParty.pas
index e29b977c..2f89afd6 100644
--- a/cmake/src/base/UParty.pas
+++ b/cmake/src/base/UParty.pas
@@ -34,350 +34,979 @@ interface
{$I switches.inc}
uses
- ModiSDK;
+ ULua;
type
- TRoundInfo = record
- Plugin: word;
- Winner: byte;
+ { 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
- TeamOrderEntry = record
- TeamNum: byte;
- Score: byte;
+ 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
- TeamOrderArray = array[0..5] of byte;
+ NextPlayer: Integer; //Id of the player that plays the next (the current) song
- TPartyPlugin = record
- ID: byte;
- TimesPlayed: byte;
+ Players: array of TParty_PlayerInfo;
end;
- TPartySession = class
+ TPartyGame = class
private
- function GetRandomPlayer(Team: byte): byte;
- function GetRandomPlugin(Plugins: array of TPartyPlugin): byte;
- function IsWinner(Player, Winner: byte): boolean;
+ 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 TRoundInfo;
- CurRound: byte;
+ //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;
- procedure StartNewParty(NumRounds: byte);
- procedure StartRound;
- procedure EndRound;
- function GetTeamOrder: TeamOrderArray;
- function GetWinnerString(Round: byte): string;
+ { 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 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;
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
- PartySession: TPartySession;
+ Party: TPartyGame;
implementation
uses
- UDLLManager,
UGraphic,
- UNote,
ULanguage,
- ULog;
+ ULog,
+ ULuaCore,
+ UDisplay,
+ USong,
+ UNote,
+ SysUtils;
-constructor TPartySession.Create;
+//-------------
+// Just the constructor
+//-------------
+constructor TPartyGame.Create;
begin
inherited;
+
+ Clear;
end;
-//----------
-// Returns a number of a random plugin
-//----------
-function TPartySession.GetRandomPlugin(Plugins: array of TPartyPlugin): byte;
+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
- LowestTP: byte;
- NumPwithLTP: word;
- I: integer;
- R: word;
+ I, R: integer;
+ lowestTP: Integer;
+ NumPwithLTP: Integer;
begin
- LowestTP := high(byte);
+ LowestTP := high(Integer);
NumPwithLTP := 0;
+ Result := 0;
- //Search for Plugins not often played yet
- for I := 0 to high(Plugins) do
+ // search for players that have less played yet
+ for I := 0 to High(Teams[Team].Players) do
begin
- if (Plugins[I].TimesPlayed < lowestTP) then
+ if (Teams[Team].Players[I].TimesPlayed < lowestTP) then
begin
- lowestTP := Plugins[I].TimesPlayed;
+ lowestTP := Teams[Team].Players[I].TimesPlayed;
NumPwithLTP := 1;
end
- else if (Plugins[I].TimesPlayed = lowestTP) then
+ else if (Teams[Team].Players[I].TimesPlayed = lowestTP) then
begin
Inc(NumPwithLTP);
end;
end;
- //Create random no
+ // create random number
R := Random(NumPwithLTP);
- //Search for random plugin
- for I := 0 to high(Plugins) do
+ // search for selected random player
+ for I := 0 to High(Teams[Team].Players) do
begin
- if Plugins[I].TimesPlayed = LowestTP then
+ if Teams[Team].Players[I].TimesPlayed = lowestTP then
begin
- //Plugin found
if (R = 0) then
- begin
- Result := Plugins[I].ID;
- Inc(Plugins[I].TimesPlayed);
+ begin // found selected player
+ Result := I;
Break;
end;
+
Dec(R);
end;
end;
end;
//----------
-//StartNewParty - Reset and prepares for new party
+//GenScores - inc scores for cur. round
//----------
-procedure TPartySession.StartNewParty(NumRounds: byte);
+procedure TPartyGame.GenScores;
var
- Plugins: array of TPartyPlugin;
- TeamMode: boolean;
- Len: integer;
- I, J: integer;
+ 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
- //Set current round to 1
- CurRound := 255;
+ if (Length(Teams) = 0) then
+ Result := true
+ else
+ begin
+ if (Modes[I].TeamCount and (1 shl (Length(Teams) - 1)) <> 0) then
+ begin
+ Result := true;
- PlayersPlay := Teams.NumTeams;
+ 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;
- //Get team-mode and set joker, also set TimesPlayed
- TeamMode := true;
- for I := 0 to Teams.NumTeams - 1 do
+{ 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
- if Teams.Teaminfo[I].NumPlayers < 2 then
+ Result := false;
+ for I := 0 to High(Modes) do
begin
- TeamMode := false;
+ Result := ModePlayable(I);
+
+ if Result then
+ Exit;
end;
- //Set player attributes
- for J := 0 to Teams.TeamInfo[I].NumPlayers-1 do
+ 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
- Teams.TeamInfo[I].Playerinfo[J].TimesPlayed := 0;
+ Inc(Len);
+ SetLength(Result, Len + 1);
+ Result[Len].Index := I;
+ Result[Len].Name := Language.Translate('MODE_' + Uppercase(Modes[I].Name) + '_NAME');
end;
- Teams.Teaminfo[I].Joker := Round(NumRounds * 0.7);
- Teams.Teaminfo[I].Score := 0;
+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;
- //Fill plugin array
- SetLength(Plugins, 0);
- for I := 0 to high(DLLMan.Plugins) do
+{ 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
- if TeamMode or (not DLLMan.Plugins[I].TeamModeOnly) then
- begin
- //Add only those plugins playable with current PlayerConfiguration
- Len := Length(Plugins);
- SetLength(Plugins, Len + 1);
- Plugins[Len].ID := I;
- Plugins[Len].TimesPlayed := 0;
- end;
+ // 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;
- //Set rounds
- if (Length(Plugins) >= 1) then
+ if (not bPartyStarted) and (Length(Rounds) > 0) and (Length(Teams) >= Party_Teams_Min) then
begin
- SetLength (Rounds, NumRounds);
- for I := 0 to NumRounds - 1 do
+ // 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
- PartySession.Rounds[I].Plugin := GetRandomPlugin(Plugins);
- PartySession.Rounds[I].Winner := 255;
+ // 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
- SetLength (Rounds, 0);
+ Result := false;
end;
-{**
- * Returns a random player to play next round
- *}
-function TPartySession.GetRandomPlayer(Team: byte): byte;
-var
- I, R: integer;
- LowestTP: byte;
- NumPwithLTP: byte;
+{ 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
- LowestTP := high(byte);
- NumPwithLTP := 0;
- Result := 0;
-
- //Search for players that have not often played yet
- for I := 0 to Teams.Teaminfo[Team].NumPlayers - 1 do
+ if (Length(Player) = Length(Teams)) then
begin
- if (Teams.Teaminfo[Team].Playerinfo[I].TimesPlayed < lowestTP) then
+ SetLength(Ranking, Length(Teams));
+ SetLength(Scores, Length(Teams));
+
+ // fill ranking array
+ for I := 0 to High(Ranking) do
begin
- lowestTP := Teams.Teaminfo[Team].Playerinfo[I].TimesPlayed;
- NumPwithLTP := 1;
- end
- else if (Teams.Teaminfo[Team].Playerinfo[I].TimesPlayed = lowestTP) then
+ 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
- Inc(NumPwithLTP);
+ 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 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
+ Rounds[CurRound].AlreadyPlayed := true;
+
+ GenScores;
end;
- //Create random number
- R := Random(NumPwithLTP);
+ // 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;
- //Search for random player
- for I := 0 to Teams.Teaminfo[Team].NumPlayers - 1 do
+ // some lines concerning the next round
+ if (CurRound >= 0) then
begin
- if Teams.Teaminfo[Team].Playerinfo[I].TimesPlayed = lowestTP then
+ // 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
- //Player found
- if (R = 0) then
- begin
- Result := I;
- Break;
- end;
-
- Dec(R);
+ if (P.CallFunctionByName(Func, 0, 1)) then
+ // check result
+ Result := (lua_toboolean(P.LuaState, 1));
end;
end;
end;
-{**
- * Prepares ScreenSingModi for next round and loads plugin
- *}
-procedure TPartySession.StartRound;
-var
- I: integer;
+{ 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 ((CurRound < high(Rounds)) or (CurRound = high(CurRound))) then
+ if not bPartyStarted then
+ ExecuteDefault := true
+ else if (CurRound >= 0) then
begin
- //Increase Current Round
- Inc(CurRound);
-
- Rounds[CurRound].Winner := 255;
- DllMan.LoadPlugin(Rounds[CurRound].Plugin);
+ // 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;
- //Select Players
- for I := 0 to Teams.NumTeams - 1 do
- Teams.Teaminfo[I].CurPlayer := GetRandomPlayer(I);
+ with Modes[Rounds[CurRound].Mode] do
+ ExecuteDefault := (CallLua(Parent, Functions.BeforeSongSelect));
+ end
+ else
+ ExecuteDefault := true;
- //Set ScreenSingModie Variables
- ScreenSingModi.TeamInfo := Teams;
+ // execute default function:
+ if ExecuteDefault then
+ begin
+ // display song select screen
+ Display.FadeTo(@ScreenSong);
end;
end;
-//----------
-//EndRound - Get Winner from ScreenSingModi and Save Data to RoundArray
-//----------
-procedure TPartySession.EndRound;
-var
- I: Integer;
+procedure TPartyGame.CallAfterSongSelect;
+ var
+ ExecuteDefault: boolean;
begin
- //Copy Winner
- Rounds[CurRound].Winner := ScreenSingModi.Winner;
- //Set Scores
- GenScores;
+ 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;
- //Increase TimesPlayed 4 all Players
- For I := 0 to Teams.NumTeams-1 do
- Inc(Teams.Teaminfo[I].Playerinfo[Teams.Teaminfo[I].CurPlayer].TimesPlayed);
+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;
-//----------
-//IsWinner - returns true if the player's bit is set in the winner byte
-//----------
-function TPartySession.IsWinner(Player, Winner: byte): boolean;
-var
- Mask: byte;
+procedure TPartyGame.CallOnSing;
+ var
+ ExecuteDefault: boolean;
begin
- Mask := 1 shl Player;
- Result := (Winner and Mask) <> 0;
+ 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;
-//----------
-//GenScores - increase scores for current round
-//----------
-procedure TPartySession.GenScores;
-var
- I: byte;
+procedure TPartyGame.CallAfterSing;
+ var
+ ExecuteDefault: boolean;
begin
- for I := 0 to Teams.NumTeams - 1 do
+ 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 isWinner(I, Rounds[CurRound].Winner) then
- Inc(Teams.Teaminfo[I].Score);
+ if (bPartyGame) then
+ // display party score screen
+ Display.FadeTo(@ScreenPartyScore)
+ else //display standard score screen
+ Display.FadeTo(@ScreenScore);
end;
end;
-//----------
-//GetTeamOrder - returns the placement of each Team [First Position of Array is Teamnum of first placed Team, ...]
-//----------
-function TPartySession.GetTeamOrder: TeamOrderArray;
-var
- I, J: integer;
- ATeams: array [0..5] of TeamOrderEntry;
- TempTeam: TeamOrderEntry;
+{ 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
- // TODO: PartyMode: Write this in another way, so that teams with the same score get the same place
- //Fill Team array
- for I := 0 to Teams.NumTeams - 1 do
+ SetLength(Result, Length(Teams));
+
+ // fill ranking array
+ for I := 0 to High(Result) do
begin
- ATeams[I].Teamnum := I;
- ATeams[I].Score := Teams.Teaminfo[I].Score;
+ Result[I].Team := I;
+ Result[I].Rank := 0;
end;
- //Sort teams
- for J := 0 to Teams.NumTeams - 1 do
- for I := 1 to Teams.NumTeams - 1 do
- if ATeams[I].Score > ATeams[I-1].Score then
+ // 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
- TempTeam := ATeams[I-1];
- ATeams[I-1] := ATeams[I];
- ATeams[I] := TempTeam;
+ 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;
- //Copy to Result
- for I := 0 to Teams.NumTeams-1 do
- Result[I] := ATeams[I].TeamNum;
+ 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;
-//----------
-//GetWinnerString - Get string with WinnerTeam Name, when there is more than one Winner than Connect with and or ,
-//----------
-function TPartySession.GetWinnerString(Round: byte): string;
+{ 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 string;
- I: integer;
+ Winners: array of UTF8String;
+ I: integer;
+ Ranking: AParty_TeamRanking;
begin
- Result := Language.Translate('PARTY_NOBODY');
+ Result := '';
+ Ranking := nil;
- if (Round > High(Rounds)) then
- exit;
-
- if (Rounds[Round].Winner = 0) then
+ if (Round >= 0) and (Round <= High(Rounds)) then
begin
- exit;
- end;
+ 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 (Rounds[Round].Winner = 255) then
- begin
- Result := Language.Translate('PARTY_NOTPLAYEDYET');
- exit;
- end;
- SetLength(Winners, 0);
- for I := 0 to Teams.NumTeams - 1 do
+ if (Ranking <> nil) then
begin
- if isWinner(I, Rounds[Round].Winner) then
+ SetLength(Winners, 0);
+ for I := 0 to High(Ranking) do
begin
- SetLength(Winners, Length(Winners) + 1);
- Winners[high(Winners)] := Teams.TeamInfo[I].Name;
+ 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;
- Result := Language.Implode(Winners);
+
+ if (Length(Result) = 0) then
+ Result := Language.Translate('PARTY_NOBODY');
end;
end.
diff --git a/cmake/src/base/UPath.pas b/cmake/src/base/UPath.pas
index 2316ac02..7c00e7b1 100644
--- a/cmake/src/base/UPath.pas
+++ b/cmake/src/base/UPath.pas
@@ -1,188 +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: https://ultrastardx.svn.sourceforge.net/svnroot/ultrastardx/trunk/src/base/UPath.pas $
- * $Id: UPath.pas 1624 2009-03-06 23:45:10Z k-m_schindler $
- *}
-
-unit UPath;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-
-uses
- SysUtils,
- Classes;
-
-var
- // Absolute Paths
- GamePath: string;
- SoundPath: string;
- SongPaths: TStringList;
- LogPath: string;
- ThemePath: string;
- SkinsPath: string;
- ScreenshotsPath: string;
- CoverPaths: TStringList;
- LanguagesPath: string;
- PluginPath: string;
- VisualsPath: string;
- FontPath: string;
- ResourcesPath: string;
- PlayListPath: string;
-
-function FindPath(out PathResult: string; const RequestedPath: string; NeedsWritePermission: boolean): boolean;
-procedure InitializePaths;
-procedure AddSongPath(const Path: string);
-
-implementation
-
-uses
- StrUtils,
- UPlatform,
- UCommandLine,
- ULog;
-
-procedure AddSpecialPath(var PathList: TStringList; const Path: string);
-var
- Index: integer;
- PathAbs, OldPathAbs: string;
-begin
- if (PathList = nil) then
- PathList := TStringList.Create;
-
- if (Path = '') or not ForceDirectories(Path) then
- Exit;
-
- PathAbs := IncludeTrailingPathDelimiter(ExpandFileName(Path));
-
- // check if path or a part of the path was already added
- for Index := 0 to PathList.Count-1 do
- begin
- OldPathAbs := IncludeTrailingPathDelimiter(ExpandFileName(PathList[Index]));
- // 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 (AnsiStartsText(OldPathAbs, PathAbs)) then
- begin
- // ignore the new path
- Exit;
- end;
-
- // check if a previously added directory is a sub-directory of the new one.
- if (AnsiStartsText(PathAbs, OldPathAbs)) then
- begin
- // replace the old with the new one.
- PathList[Index] := PathAbs;
- Exit;
- end;
- end;
-
- PathList.Add(PathAbs);
-end;
-
-procedure AddSongPath(const Path: string);
-begin
- AddSpecialPath(SongPaths, Path);
-end;
-
-procedure AddCoverPath(const Path: string);
-begin
- AddSpecialPath(CoverPaths, Path);
-end;
-
-(**
- * Initialize a path variable
- * After setting paths, make sure that paths exist
- *)
-function FindPath(out PathResult: string;
- const RequestedPath: string;
- NeedsWritePermission: boolean)
- : boolean;
-begin
- Result := false;
-
- if (RequestedPath = '') then
- Exit;
-
- // Make sure the directory exists
- if (not ForceDirectories(RequestedPath)) then
- begin
- PathResult := '';
- Exit;
- end;
-
- PathResult := IncludeTrailingPathDelimiter(RequestedPath);
-
- if (NeedsWritePermission) and
- (FileIsReadOnly(RequestedPath)) then
- begin
- Exit;
- end;
-
- Result := true;
-end;
-
-(**
- * Function sets all absolute paths e.g. song path and makes sure the directorys exist
- *)
-procedure InitializePaths;
-begin
- // Log directory (must be writable)
- if (not FindPath(LogPath, Platform.GetLogPath, true)) then
- begin
- Log.FileOutputEnabled := false;
- Log.LogWarn('Log directory "'+ Platform.GetLogPath +'" not available', 'InitializePaths');
- end;
-
- FindPath(SoundPath, Platform.GetGameSharedPath + 'sounds', false);
- FindPath(ThemePath, Platform.GetGameSharedPath + 'themes', false);
- FindPath(SkinsPath, Platform.GetGameSharedPath + 'themes', false);
- FindPath(LanguagesPath, Platform.GetGameSharedPath + 'languages', false);
- FindPath(PluginPath, Platform.GetGameSharedPath + 'plugins', false);
- FindPath(VisualsPath, Platform.GetGameSharedPath + 'visuals', false);
- FindPath(FontPath, Platform.GetGameSharedPath + 'fonts', false);
- FindPath(ResourcesPath, Platform.GetGameSharedPath + 'resources', false);
-
- // Playlists are not shared as we need one directory to write too
- FindPath(PlaylistPath, Platform.GetGameUserPath + 'playlists', true);
-
- // Screenshot directory (must be writable)
- if (not FindPath(ScreenshotsPath, Platform.GetGameUserPath + 'screenshots', true)) then
- begin
- Log.LogWarn('Screenshot directory "'+ Platform.GetGameUserPath +'" not available', 'InitializePaths');
- end;
-
- // Add song paths
- AddSongPath(Params.SongPath);
- AddSongPath(Platform.GetGameSharedPath + 'songs');
- AddSongPath(Platform.GetGameUserPath + 'songs');
-
- // Add category cover paths
- AddCoverPath(Platform.GetGameSharedPath + 'covers');
- AddCoverPath(Platform.GetGameUserPath + 'covers');
-end;
-
-end.
+{* 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.FileIsReadOnly(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/cmake/src/base/UPathUtils.pas b/cmake/src/base/UPathUtils.pas
new file mode 100644
index 00000000..c2bcdd4b
--- /dev/null
+++ b/cmake/src/base/UPathUtils.pas
@@ -0,0 +1,196 @@
+{* 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);
+ AddSongPath(SharedPath.Append('songs'));
+ AddSongPath(UserPath.Append('songs'));
+
+ // Add category cover paths
+ AddCoverPath(SharedPath.Append('covers'));
+ AddCoverPath(UserPath.Append('covers'));
+end;
+
+end.
diff --git a/cmake/src/base/UPlatform.pas b/cmake/src/base/UPlatform.pas
index 6f13481c..11c67fa7 100644
--- a/cmake/src/base/UPlatform.pas
+++ b/cmake/src/base/UPlatform.pas
@@ -39,28 +39,20 @@ interface
{$I switches.inc}
uses
- Classes;
+ Classes,
+ UPath;
type
- TDirectoryEntry = record
- Name: WideString;
- IsDirectory: boolean;
- IsFile: boolean;
- end;
-
- TDirectoryEntryArray = array of TDirectoryEntry;
-
TPlatform = class
- function GetExecutionDir(): string;
+ function GetExecutionDir(): IPath;
procedure Init; virtual;
- function DirectoryFindFiles(Dir, Filter: WideString; ReturnAllSubDirs: boolean): TDirectoryEntryArray; virtual; abstract;
+
function TerminateIfAlreadyRunning(var WndTitle: string): boolean; virtual;
- function FindSongFile(Dir, Mask: WideString): WideString; virtual;
procedure Halt; virtual;
- function GetLogPath: WideString; virtual; abstract;
- function GetGameSharedPath: WideString; virtual; abstract;
- function GetGameUserPath: WideString; virtual; abstract;
- function CopyFile(const Source, Target: WideString; FailIfExists: boolean): boolean; virtual;
+
+ function GetLogPath: IPath; virtual; abstract;
+ function GetGameSharedPath: IPath; virtual; abstract;
+ function GetGameUserPath: IPath; virtual; abstract;
end;
function Platform(): TPlatform;
@@ -76,7 +68,9 @@ uses
{$ELSEIF Defined(UNIX)}
UPlatformLinux,
{$IFEND}
- ULog;
+ ULog,
+ UUnicodeUtils,
+ UFilesystem;
// I modified it to use the Platform_singleton in this location (in the implementation)
@@ -109,9 +103,13 @@ end;
{**
* Returns the directory of the executable
*}
-function TPlatform.GetExecutionDir(): string;
+function TPlatform.GetExecutionDir(): IPath;
+var
+ ExecName, ExecDir: IPath;
begin
- Result := ExpandFileName(ExtractFilePath(ParamStr(0)));
+ ExecName := Path(ParamStr(0));
+ ExecDir := ExecName.GetPath;
+ Result := ExecDir.GetAbsolutePath();
end;
(**
@@ -122,65 +120,6 @@ begin
Result := false;
end;
-(**
- * Default FindSongFile() implementation
- *)
-function TPlatform.FindSongFile(Dir, Mask: WideString): WideString;
-var
- SR: TSearchRec; // for parsing song directory
-begin
- Result := '';
- if SysUtils.FindFirst(Dir + Mask, faDirectory, SR) = 0 then
- begin
- Result := SR.Name;
- end;
- SysUtils.FindClose(SR);
-end;
-
-function TPlatform.CopyFile(const Source, Target: WideString; 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, fmOpenRead);
- TargetFile := TFileStream.Create(Target, 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;
-
-
initialization
{$IF Defined(MSWINDOWS)}
Platform_singleton := TPlatformWindows.Create;
diff --git a/cmake/src/base/UPlatformLinux.pas b/cmake/src/base/UPlatformLinux.pas
index 30499a97..693facaa 100644
--- a/cmake/src/base/UPlatformLinux.pas
+++ b/cmake/src/base/UPlatformLinux.pas
@@ -36,7 +36,8 @@ interface
uses
Classes,
UPlatform,
- UConfig;
+ UConfig,
+ UPath;
type
TPlatformLinux = class(TPlatform)
@@ -44,15 +45,13 @@ type
UseLocalDirs: boolean;
procedure DetectLocalExecution();
- function GetHomeDir(): string;
+ function GetHomeDir(): IPath;
public
procedure Init; override;
-
- function DirectoryFindFiles(Dir, Filter: WideString; ReturnAllSubDirs: Boolean): TDirectoryEntryArray; override;
-
- function GetLogPath : WideString; override;
- function GetGameSharedPath : WideString; override;
- function GetGameUserPath : WideString; override;
+
+ function GetLogPath : IPath; override;
+ function GetGameSharedPath : IPath; override;
+ function GetGameUserPath : IPath; override;
end;
implementation
@@ -60,9 +59,7 @@ implementation
uses
UCommandLine,
BaseUnix,
- {$IF FPC_VERSION_INT >= 2002002}
pwd,
- {$IFEND}
SysUtils,
ULog;
@@ -88,114 +85,65 @@ end;
*}
procedure TPlatformLinux.DetectLocalExecution();
var
- LocalDir: string;
+ LocalDir, LanguageDir: IPath;
begin
- LocalDir := GetExecutionDir();
-
// we just check if the 'languages' folder exists in the
// directory of the executable. If so -> local execution.
- UseLocalDirs := (DirectoryExists(LocalDir + 'languages'));
-end;
-
-function TPlatformLinux.DirectoryFindFiles(Dir, Filter: WideString; ReturnAllSubDirs: Boolean): TDirectoryEntryArray;
-var
- i: Integer;
- TheDir : pDir;
- ADirent : pDirent;
- Entry : Longint;
- lAttrib : integer;
-begin
- i := 0;
- Filter := LowerCase(Filter);
-
- TheDir := FpOpenDir( Dir );
- if Assigned(TheDir) then
- begin
- repeat
- ADirent := FpReadDir(TheDir^);
-
- if Assigned(ADirent) and (ADirent^.d_name <> '.') and (ADirent^.d_name <> '..') then
- begin
- lAttrib := FileGetAttr(Dir + ADirent^.d_name);
- if ReturnAllSubDirs and ((lAttrib and faDirectory) <> 0) then
- begin
- SetLength( Result, i + 1);
- Result[i].Name := ADirent^.d_name;
- Result[i].IsDirectory := true;
- Result[i].IsFile := false;
- i := i + 1;
- end
- else if (Length(Filter) = 0) or (Pos( Filter, LowerCase(ADirent^.d_name)) > 0) then
- begin
- SetLength( Result, i + 1);
- Result[i].Name := ADirent^.d_name;
- Result[i].IsDirectory := false;
- Result[i].IsFile := true;
- i := i + 1;
- end;
- end;
- until (ADirent = nil);
-
- FpCloseDir(TheDir^);
- end;
+ LocalDir := GetExecutionDir();
+ LanguageDir := LocalDir.Append('languages');
+ UseLocalDirs := LanguageDir.IsDirectory;
end;
-function TPlatformLinux.GetLogPath: WideString;
+function TPlatformLinux.GetLogPath: IPath;
begin
if UseLocalDirs then
Result := GetExecutionDir()
else
- Result := GetGameUserPath() + 'logs/';
+ Result := GetGameUserPath().Append('logs', pdAppend);
// create non-existing directories
- ForceDirectories(Result);
+ Result.CreateDirectory(true);
end;
-function TPlatformLinux.GetGameSharedPath: WideString;
+function TPlatformLinux.GetGameSharedPath: IPath;
begin
if UseLocalDirs then
Result := GetExecutionDir()
else
- Result := IncludeTrailingPathDelimiter(INSTALL_DATADIR);
+ Result := Path(INSTALL_DATADIR, pdAppend);
end;
-function TPlatformLinux.GetGameUserPath: WideString;
+function TPlatformLinux.GetGameUserPath: IPath;
begin
if UseLocalDirs then
Result := GetExecutionDir()
else
- Result := GetHomeDir() + '.ultrastardx/';
+ Result := GetHomeDir().Append('.ultrastardx', pdAppend);
end;
{**
* Returns the user's home directory terminated by a path delimiter
*}
-function TPlatformLinux.GetHomeDir(): string;
-{$IF FPC_VERSION_INT >= 2002002}
+function TPlatformLinux.GetHomeDir(): IPath;
var
PasswdEntry: PPasswd;
-{$IFEND}
begin
- Result := '';
+ Result := PATH_NONE;
- {$IF FPC_VERSION_INT >= 2002002}
// try to retrieve the info from passwd
PasswdEntry := FpGetpwuid(FpGetuid());
if (PasswdEntry <> nil) then
- Result := PasswdEntry.pw_dir;
- {$IFEND}
+ Result := Path(PasswdEntry.pw_dir);
// fallback if passwd does not contain the path
- if (Result = '') then
- Result := GetEnvironmentVariable('HOME');
+ if (Result.IsUnset) then
+ Result := Path(GetEnvironmentVariable('HOME'));
// add trailing path delimiter (normally '/')
- if (Result <> '') then
- Result := IncludeTrailingPathDelimiter(Result);
+ if (Result.IsSet) then
+ Result := Result.AppendPathDelim();
- {$IF FPC_VERSION_INT >= 2002002}
// GetUserDir() is another function that returns a user path.
// It uses env-var HOME or a fallback to a temp-dir.
//Result := GetUserDir();
- {$IFEND}
end;
end.
diff --git a/cmake/src/base/UPlatformMacOSX.pas b/cmake/src/base/UPlatformMacOSX.pas
index 96e4bc63..d55e8bea 100644
--- a/cmake/src/base/UPlatformMacOSX.pas
+++ b/cmake/src/base/UPlatformMacOSX.pas
@@ -36,7 +36,9 @@ interface
uses
Classes,
ULog,
- UPlatform;
+ UPlatform,
+ UFilesystem,
+ UPath;
type
{**
@@ -93,19 +95,21 @@ type
* GetBundlePath returns the path to the application bundle
* UltraStarDeluxe.app.
*}
- function GetBundlePath: WideString;
+ function GetBundlePath: IPath;
{**
* GetApplicationSupportPath returns the path to
* $HOME/Library/Application Support/UltraStarDeluxe.
*}
- function GetApplicationSupportPath: WideString;
+ function GetApplicationSupportPath: IPath;
{**
* see the description of @link(Init).
*}
procedure CreateUserFolders();
+ function GetHomeDir(): IPath;
+
public
{**
* Init simply calls @link(CreateUserFolders), which in turn scans the
@@ -116,37 +120,30 @@ type
procedure Init; override;
{**
- * DirectoryFindFiles returns all entries of a folder with names and
- * booleans about their type, i.e. file or directory.
- *}
- function DirectoryFindFiles(Dir, Filter: WideString; ReturnAllSubDirs: boolean): TDirectoryEntryArray; override;
-
- {**
* GetLogPath returns the path for log messages. Currently it is set to
- * $HOME/Library/Application Support/UltraStarDeluxe/Log.
+ * $HOME/Library/Application Support/UltraStarDeluxe/log.
*}
- function GetLogPath : WideString; override;
+ function GetLogPath: IPath; override;
{**
* GetGameSharedPath returns the path for shared resources. Currently it
* is set to /Library/Application Support/UltraStarDeluxe.
* However it is not used.
*}
- function GetGameSharedPath : WideString; override;
+ 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 songs, themes, ....
*}
- function GetGameUserPath : WideString; override;
+ function GetGameUserPath: IPath; override;
end;
implementation
uses
- SysUtils,
- BaseUnix;
+ SysUtils;
procedure TPlatformMacOSX.Init;
begin
@@ -154,178 +151,131 @@ begin
end;
procedure TPlatformMacOSX.CreateUserFolders();
-const
- // used to construct the @link(UserPathName)
- PathName: string = '/Library/Application Support/UltraStarDeluxe';
var
- RelativePath: string;
+ 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: string;
+ 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: string;
- // This record contains the result of a file search with FindFirst or FindNext
- SearchInfo: TSearchRec;
+ 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: TStringList;
+ 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;
- Counter: longint;
+ I: longint;
// These three are for creating directories, due to possible symlinks
CreatedDirectory: boolean;
FileAttrs: integer;
- DirectoryPath: string;
-
- UserPathName: string;
+ DirectoryPath: IPath;
+ UserPath: IPath;
+ SrcFile, TgtFile: IPath;
begin
// Get the current folder and save it in OldBaseDir for returning to it, when
// finished.
- GetDir(0, OldBaseDir);
+ OldBaseDir := FileSystem.GetCurrentDir();
- // UltraStarDeluxe.app/Contents contains all the default files and
- // folders.
- BaseDir := OldBaseDir + '/UltraStarDeluxe.app/Contents';
- ChDir(BaseDir);
+ // 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.
- UserPathName := GetEnvironmentVariable('HOME') + PathName;
+ // Right now, only $HOME/Library/Application Support/UltraStarDeluxe is used.
+ UserPath := GetGameUserPath();
DirectoryIsFinished := 0;
- DirectoryList := TStringList.Create();
- FileList := TStringList.Create();
- DirectoryList.Add('.');
+ // replace with IInterfaceList
+ DirectoryList := TInterfaceList.Create();
+ FileList := TInterfaceList.Create();
+ DirectoryList.Add(Path('.'));
// create the folder and file lists
repeat
-
- RelativePath := DirectoryList[DirectoryIsFinished];
- ChDir(BaseDir + '/' + RelativePath);
- if (FindFirst('*', faAnyFile, SearchInfo) = 0) then
+ RelativePath := (DirectoryList[DirectoryIsFinished] as IPath);
+ FileSystem.SetCurrentDir(BaseDir.Append(RelativePath));
+ Iter := FileSystem.FileFind(Path('*'), faAnyFile);
+ while (Iter.HasNext) do
begin
- repeat
- if DirectoryExists(SearchInfo.Name) then
- begin
- if (SearchInfo.Name <> '.') and (SearchInfo.Name <> '..') then
- DirectoryList.Add(RelativePath + '/' + SearchInfo.Name);
- end
- else
- Filelist.Add(RelativePath + '/' + SearchInfo.Name);
- until (FindNext(SearchInfo) <> 0);
+ 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;
- FindClose(SearchInfo);
Inc(DirectoryIsFinished);
until (DirectoryIsFinished = DirectoryList.Count);
// create missing folders
- ForceDirectories(UserPathName); // should not be necessary since (UserPathName+'/.') is created.
- for Counter := 0 to DirectoryList.Count-1 do
+ UserPath.CreateDirectory(true); // should not be necessary since (UserPathName+'/.') is created.
+ for I := 0 to DirectoryList.Count-1 do
begin
- DirectoryPath := UserPathName + '/' + DirectoryList[Counter];
- CreatedDirectory := ForceDirectories(DirectoryPath);
- FileAttrs := FileGetAttr(DirectoryPath);
- // Don't know how to analyse the target of the link.
+ 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 "'+ UserPathName + '/' + DirectoryList[Counter] +'"',
+ Log.LogError('Failed to create the folder "'+ DirectoryPath.ToNative +'"',
'TPlatformMacOSX.CreateUserFolders');
end;
- DirectoryList.Free();
// copy missing files
- for Counter := 0 to Filelist.Count-1 do
+ for I := 0 to Filelist.Count-1 do
begin
- CopyFile(BaseDir + '/' + Filelist[Counter],
- UserPathName + '/' + Filelist[Counter], true);
+ CurPath := Filelist[I] as IPath;
+ SrcFile := BaseDir.Append(CurPath);
+ TgtFile := UserPath.Append(CurPath);
+ SrcFile.CopyFile(TgtFile, true);
end;
- FileList.Free();
// go back to the initial folder
- ChDir(OldBaseDir);
+ FileSystem.SetCurrentDir(OldBaseDir);
end;
-function TPlatformMacOSX.GetBundlePath: WideString;
-var
- i, pos : integer;
+function TPlatformMacOSX.GetBundlePath: IPath;
begin
// Mac applications are packaged in folders.
// Cutting the last two folders yields the application folder.
-
- Result := GetExecutionDir();
- for i := 1 to 2 do
- begin
- pos := Length(Result);
- repeat
- Delete(Result, pos, 1);
- pos := Length(Result);
- until (pos = 0) or (Result[pos] = '/');
- end;
+ Result := GetExecutionDir().GetParent().GetParent();
end;
-function TPlatformMacOSX.GetApplicationSupportPath: WideString;
+function TPlatformMacOSX.GetApplicationSupportPath: IPath;
const
- PathName : string = '/Library/Application Support/UltraStarDeluxe';
+ PathName: string = 'Library/Application Support/UltraStarDeluxe';
begin
- Result := GetEnvironmentVariable('HOME') + PathName + '/';
+ Result := GetHomeDir().Append(PathName, pdAppend);
end;
-function TPlatformMacOSX.GetLogPath: WideString;
+function TPlatformMacOSX.GetHomeDir(): IPath;
begin
- Result := GetApplicationSupportPath + 'Logs';
+ Result := Path(GetEnvironmentVariable('HOME'));
end;
-function TPlatformMacOSX.GetGameSharedPath: WideString;
+function TPlatformMacOSX.GetLogPath: IPath;
begin
- Result := GetApplicationSupportPath;
+ Result := GetApplicationSupportPath.Append('logs');
end;
-function TPlatformMacOSX.GetGameUserPath: WideString;
+function TPlatformMacOSX.GetGameSharedPath: IPath;
begin
Result := GetApplicationSupportPath;
end;
-function TPlatformMacOSX.DirectoryFindFiles(Dir, Filter: WideString; ReturnAllSubDirs: boolean): TDirectoryEntryArray;
-var
- i : integer;
- TheDir : pdir;
- ADirent : pDirent;
- lAttrib : integer;
+function TPlatformMacOSX.GetGameUserPath: IPath;
begin
- i := 0;
- Filter := LowerCase(Filter);
-
- TheDir := FPOpenDir(Dir);
- if Assigned(TheDir) then
- repeat
- ADirent := FPReadDir(TheDir);
-
- if Assigned(ADirent) and (ADirent^.d_name <> '.') and (ADirent^.d_name <> '..') then
- begin
- lAttrib := FileGetAttr(Dir + ADirent^.d_name);
- if ReturnAllSubDirs and ((lAttrib and faDirectory) <> 0) then
- begin
- SetLength(Result, i + 1);
- Result[i].Name := ADirent^.d_name;
- Result[i].IsDirectory := true;
- Result[i].IsFile := false;
- i := i + 1;
- end
- else if (Length(Filter) = 0) or (Pos( Filter, LowerCase(ADirent^.d_name)) > 0) then
- begin
- SetLength(Result, i + 1);
- Result[i].Name := ADirent^.d_name;
- Result[i].IsDirectory := false;
- Result[i].IsFile := true;
- i := i + 1;
- end;
- end;
- until ADirent = nil;
-
- FPCloseDir(TheDir);
+ Result := GetApplicationSupportPath;
end;
end.
diff --git a/cmake/src/base/UPlatformWindows.pas b/cmake/src/base/UPlatformWindows.pas
index e198958a..91d3cce6 100644
--- a/cmake/src/base/UPlatformWindows.pas
+++ b/cmake/src/base/UPlatformWindows.pas
@@ -38,21 +38,23 @@ interface
uses
Classes,
- UPlatform;
+ UPlatform,
+ UPath;
type
TPlatformWindows = class(TPlatform)
private
- function GetSpecialPath(CSIDL: integer): WideString;
+ UseLocalDirs: boolean;
+
+ function GetSpecialPath(CSIDL: integer): IPath;
+ procedure DetectLocalExecution();
public
- function DirectoryFindFiles(Dir, Filter: WideString; ReturnAllSubDirs: Boolean): TDirectoryEntryArray; override;
+ procedure Init; override;
function TerminateIfAlreadyRunning(var WndTitle: String): Boolean; override;
- function GetLogPath: WideString; override;
- function GetGameSharedPath: WideString; override;
- function GetGameUserPath: WideString; override;
-
- function CopyFile(const Source, Target: WideString; FailIfExists: boolean): boolean; override;
+ function GetLogPath: IPath; override;
+ function GetGameSharedPath: IPath; override;
+ function GetGameUserPath: IPath; override;
end;
implementation
@@ -63,93 +65,10 @@ uses
Windows,
UConfig;
-type
- TSearchRecW = record
- Time: Integer;
- Size: Integer;
- Attr: Integer;
- Name: WideString;
- ExcludeAttr: Integer;
- FindHandle: THandle;
- FindData: TWin32FindDataW;
- end;
-
-function FindFirstW(const Path: WideString; Attr: Integer; var F: TSearchRecW): Integer; forward;
-function FindNextW(var F: TSearchRecW): Integer; forward;
-procedure FindCloseW(var F: TSearchRecW); forward;
-function FindMatchingFileW(var F: TSearchRecW): Integer; forward;
-function DirectoryExistsW(const Directory: widestring): Boolean; forward;
-
-function FindFirstW(const Path: widestring; Attr: Integer; var F: TSearchRecW): Integer;
-const
- faSpecial = faHidden or faSysFile or faVolumeID or faDirectory;
-begin
- F.ExcludeAttr := not Attr and faSpecial;
-{$IFDEF Delphi}
- F.FindHandle := FindFirstFileW(PWideChar(Path), F.FindData);
-{$ELSE}
- F.FindHandle := FindFirstFileW(PWideChar(Path), @F.FindData);
-{$ENDIF}
- if F.FindHandle <> INVALID_HANDLE_VALUE then
- begin
- Result := FindMatchingFileW(F);
- if Result <> 0 then FindCloseW(F);
- end else
- Result := GetLastError;
-end;
-
-function FindNextW(var F: TSearchRecW): Integer;
-begin
-{$IFDEF Delphi}
- if FindNextFileW(F.FindHandle, F.FindData) then
-{$ELSE}
- if FindNextFileW(F.FindHandle, @F.FindData) then
-{$ENDIF}
- Result := FindMatchingFileW(F)
- else
- Result := GetLastError;
-end;
-
-procedure FindCloseW(var F: TSearchRecW);
-begin
- if F.FindHandle <> INVALID_HANDLE_VALUE then
- begin
- Windows.FindClose(F.FindHandle);
- F.FindHandle := INVALID_HANDLE_VALUE;
- end;
-end;
-
-function FindMatchingFileW(var F: TSearchRecW): Integer;
-var
- LocalFileTime: TFileTime;
-begin
- with F do
- begin
- while FindData.dwFileAttributes and ExcludeAttr <> 0 do
-{$IFDEF Delphi}
- if not FindNextFileW(FindHandle, FindData) then
-{$ELSE}
- if not FindNextFileW(FindHandle, @FindData) then
-{$ENDIF}
- begin
- Result := GetLastError;
- Exit;
- end;
- FileTimeToLocalFileTime(FindData.ftLastWriteTime, LocalFileTime);
- FileTimeToDosDateTime(LocalFileTime, LongRec(Time).Hi, LongRec(Time).Lo);
- Size := FindData.nFileSizeLow;
- Attr := FindData.dwFileAttributes;
- Name := FindData.cFileName;
- end;
- Result := 0;
-end;
-
-function DirectoryExistsW(const Directory: widestring): Boolean;
-var
- Code: Integer;
+procedure TPlatformWindows.Init;
begin
- Code := GetFileAttributesW(PWideChar(Directory));
- Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
+ inherited Init();
+ DetectLocalExecution();
end;
//------------------------------
@@ -180,41 +99,6 @@ begin
end;
end;
-function TPlatformWindows.DirectoryFindFiles(Dir, Filter: WideString; ReturnAllSubDirs: Boolean): TDirectoryEntryArray;
-var
- i : Integer;
- SR : TSearchRecW;
- Attrib : Integer;
-begin
- i := 0;
- Filter := LowerCase(Filter);
-
- if FindFirstW(Dir + '*', faAnyFile or faDirectory, SR) = 0 then
- repeat
- if (SR.Name <> '.') and (SR.Name <> '..') then
- begin
- Attrib := FileGetAttr(Dir + SR.name);
- if ReturnAllSubDirs and ((Attrib and faDirectory) <> 0) then
- begin
- SetLength( Result, i + 1);
- Result[i].Name := SR.name;
- Result[i].IsDirectory := true;
- Result[i].IsFile := false;
- i := i + 1;
- end
- else if (Length(Filter) = 0) or (Pos( Filter, LowerCase(SR.Name)) > 0) then
- begin
- SetLength( Result, i + 1);
- Result[i].Name := SR.Name;
- Result[i].IsDirectory := false;
- Result[i].IsFile := true;
- i := i + 1;
- end;
- end;
- until FindNextW(SR) <> 0;
- FindCloseW(SR);
-end;
-
(**
* Returns the path of a special folder.
*
@@ -225,37 +109,101 @@ end;
* 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): WideString;
+function TPlatformWindows.GetSpecialPath(CSIDL: integer): IPath;
var
Buffer: array [0..MAX_PATH-1] of WideChar;
begin
-{$IF Defined(Delphi) or (FPC_VERSION_INT >= 2002002)} // >= 2.2.2
if (SHGetSpecialFolderPathW(0, @Buffer, CSIDL, false)) then
- Result := Buffer
+ Result := Path(Buffer)
else
-{$IFEND}
- Result := '';
+ Result := PATH_NONE;
end;
-function TPlatformWindows.GetLogPath: WideString;
+{**
+ * 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
- Result := GetExecutionDir();
+ 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.GetGameSharedPath: WideString;
+function TPlatformWindows.GetLogPath: IPath;
begin
- Result := GetExecutionDir();
+ Result := GetGameUserPath;
end;
-function TPlatformWindows.GetGameUserPath: WideString;
+function TPlatformWindows.GetGameSharedPath: IPath;
begin
- //Result := GetSpecialPath(CSIDL_APPDATA) + PathDelim + 'UltraStarDX' + PathDelim;
Result := GetExecutionDir();
end;
-function TPlatformWindows.CopyFile(const Source, Target: WideString; FailIfExists: boolean): boolean;
+function TPlatformWindows.GetGameUserPath: IPath;
begin
- Result := Windows.CopyFileW(PWideChar(Source), PWideChar(Target), FailIfExists);
+ if UseLocalDirs then
+ Result := GetExecutionDir()
+ else
+ Result := GetSpecialPath(CSIDL_APPDATA).Append('ultrastardx', pdAppend);
end;
end.
diff --git a/cmake/src/base/UPlaylist.pas b/cmake/src/base/UPlaylist.pas
index 419ce687..f12e06cf 100644
--- a/cmake/src/base/UPlaylist.pas
+++ b/cmake/src/base/UPlaylist.pas
@@ -34,21 +34,23 @@ interface
{$I switches.inc}
uses
+ Classes,
USong,
- UPath;
+ UPath,
+ UPathUtils;
type
TPlaylistItem = record
- Artist: String;
- Title: String;
+ Artist: UTF8String;
+ Title: UTF8String;
SongID: Integer;
end;
APlaylistItem = array of TPlaylistItem;
TPlaylist = record
- Name: String;
- Filename: String;
+ Name: UTF8String;
+ Filename: IPath;
Items: APlaylistItem;
end;
@@ -68,20 +70,20 @@ type
Playlists: APlaylist;
constructor Create;
- Procedure LoadPlayLists;
- Function LoadPlayList(Index: Cardinal; Filename: String): Boolean;
- Procedure SavePlayList(Index: Cardinal);
+ procedure LoadPlayLists;
+ function LoadPlayList(Index: Cardinal; const Filename: IPath): Boolean;
+ procedure SavePlayList(Index: Cardinal);
- Procedure SetPlayList(Index: Cardinal);
+ procedure SetPlayList(Index: Cardinal);
- Function AddPlaylist(Name: String): Cardinal;
- Procedure DelPlaylist(const 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 AddItem(const SongID: Cardinal; const iPlaylist: Integer = -1);
+ procedure DelItem(const iItem: Cardinal; const iPlaylist: Integer = -1);
- Procedure GetNames(var PLNames: array of String);
- Function GetIndexbySongID(const SongID: Cardinal; const iPlaylist: Integer = -1): Integer;
+ procedure GetNames(var PLNames: array of UTF8String);
+ function GetIndexbySongID(const SongID: Cardinal; const iPlaylist: Integer = -1): Integer;
end;
{Modes:
@@ -95,13 +97,15 @@ type
implementation
-uses USongs,
- ULog,
- UMain,
- //UFiles,
- UGraphic,
- UThemes,
- SysUtils;
+uses
+ SysUtils,
+ USongs,
+ ULog,
+ UMain,
+ UFilesystem,
+ UGraphic,
+ UThemes,
+ UUnicodeUtils;
//----------
//Create - Construct Class - Dummy for now
@@ -117,90 +121,90 @@ end;
//----------
Procedure TPlayListManager.LoadPlayLists;
var
- SR: TSearchRec;
Len: Integer;
PlayListBuffer: TPlayList;
+ Iter: IFileIterator;
+ FileInfo: TFileInfo;
begin
SetLength(Playlists, 0);
- if FindFirst(PlayListPath + '*.upl', 0, SR) = 0 then
+ Iter := FileSystem.FileFind(PlayListPath.Append('*.upl'), 0);
+ while (Iter.HasNext) do
begin
- repeat
- Len := Length(Playlists);
- SetLength(Playlists, Len +1);
+ Len := Length(Playlists);
+ SetLength(Playlists, Len + 1);
+
+ FileInfo := Iter.Next;
- if not LoadPlayList (Len, Sr.Name) then
- SetLength(Playlists, Len)
- else
+ 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
- // 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;
+ Playlists[Len+1] := Playlists[Len];
+ Dec(Len);
end;
-
- until FindNext(SR) <> 0;
- FindClose(SR);
- end;
+ Playlists[Len+1] := PlayListBuffer;
+ end;
+ end;
end;
//----------
//LoadPlayList - Load a Playlist in the Array
//----------
-Function TPlayListManager.LoadPlayList(Index: Cardinal; Filename: String): Boolean;
- var
- F: TextFile;
- Line: String;
- PosDelimiter: Integer;
- SongID: Integer;
- Len: Integer;
+function TPlayListManager.LoadPlayList(Index: Cardinal; const Filename: IPath): Boolean;
- Function FindSong(Artist, Title: String): Integer;
+ 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
+ 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
- if not FileExists(PlayListPath + Filename) then
- begin
- Log.LogError('Could not load Playlist: ' + Filename);
- Result := False;
- Exit;
+ //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;
- //Load File
- AssignFile(F, PlayListPath + FileName);
- Reset(F);
-
//Set Filename
- PlayLists[Index].Filename := Filename;
- PlayLists[Index].Name := '';
+ Playlists[Index].Filename := Filename;
+ Playlists[Index].Name := '';
//Read Until End of File
- While not Eof(F) do
+ while TextStream.ReadLine(Line) do
begin
- //Read Curent Line
- Readln(F, Line);
-
if (Length(Line) > 0) then
begin
- PosDelimiter := Pos(':', Line);
- if (PosDelimiter <> 0) then
+ PosDelimiter := UTF8Pos(':', Line);
+ if (PosDelimiter <> 0) then
begin
//Comment or Name String
if (Line[1] = '#') then
@@ -224,7 +228,7 @@ begin
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 + ', ' + Line);
+ else Log.LogError('Could not find Song in Playlist: ' + PlayLists[Index].Filename.ToNative + ', ' + Line);
end;
end;
end;
@@ -233,71 +237,70 @@ begin
//If no special name is given, use Filename
if PlayLists[Index].Name = '' then
begin
- PlayLists[Index].Name := ChangeFileExt(FileName, '');
+ PlayLists[Index].Name := FileName.SetExtension('').ToUTF8;
end;
//Finish (Close File)
- CloseFile(F);
+ TextStream.Free;
end;
-//----------
-//SavePlayList - Saves the specified Playlist
-//----------
-Procedure TPlayListManager.SavePlayList(Index: Cardinal);
+{**
+ * Saves the specified Playlist
+ *}
+procedure TPlayListManager.SavePlayList(Index: Cardinal);
var
- F: TextFile;
+ TextStream: TTextFileStream;
+ PlaylistFile: IPath;
I: Integer;
begin
- if (Not FileExists(PlaylistPath + Playlists[Index].Filename)) OR (Not FileisReadOnly(PlaylistPath + Playlists[Index].Filename)) then
- begin
+ PlaylistFile := PlaylistPath.Append(Playlists[Index].Filename);
- //open File for Rewriting
- AssignFile(F, PlaylistPath + Playlists[Index].Filename);
- try
- try
- Rewrite(F);
+ // cannot update read-only file
+ if PlaylistFile.IsFile() and PlaylistFile.IsReadOnly() then
+ Exit;
- //Write Version (not nessecary but helpful)
- WriteLn(F, '######################################');
- WriteLn(F, '#Ultrastar Deluxe Playlist Format v1.0');
- WriteLn(F, '#Playlist "' + Playlists[Index].Name + '" with ' + InttoStr(Length(Playlists[Index].Items)) + ' Songs.');
- WriteLn(F, '######################################');
+ // 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
- WriteLn(F, '#Name: ' + Playlists[Index].Name);
+ // Write name information
+ TextStream.WriteLine('#Name: ' + Playlists[Index].Name);
- //Write Song Information
- WriteLn(F, '#Songs:');
+ // Write song information
+ TextStream.WriteLine('#Songs:');
- For I := 0 to high(Playlists[Index].Items) do
- begin
- WriteLn(F, Playlists[Index].Items[I].Artist + ' : ' + Playlists[Index].Items[I].Title);
- end;
- except
- log.LogError('Could not write Playlistfile "' + Playlists[Index].Name + '"');
- end;
- finally
- CloseFile(F);
+ 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;
-//----------
-//SetPlayList - Display a Playlist in CatSongs
-//----------
-Procedure TPlayListManager.SetPlayList(Index: Cardinal);
+{**
+ * Display a Playlist in CatSongs
+ *}
+procedure TPlayListManager.SetPlayList(Index: Cardinal);
var
I: Integer;
begin
- If (Int(Index) > High(PlayLists)) then
+ if (Int(Index) > High(PlayLists)) then
exit;
//Hide all Songs
- For I := 0 to high(CatSongs.Song) do
+ 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
+ for I := 0 to high(PlayLists[Index].Items) do
begin
CatSongs.Song[PlayLists[Index].Items[I].SongID].Visible := True;
end;
@@ -324,31 +327,33 @@ end;
//----------
//AddPlaylist - Adds a Playlist and Returns the Index
//----------
-Function TPlayListManager.AddPlaylist(Name: String): Cardinal;
+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
+ 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;
+ Playlists[Result].Name := Name;
+
+ // clear playlist items
+ SetLength(Playlists[Result].Items, 0);
I := 1;
- if (not FileExists(PlaylistPath + Name + '.upl')) then
- Playlists[Result].Filename := Name + '.upl'
- else
+ PlaylistFile := PlaylistPath.Append(Name + '.upl');
+ while (PlaylistFile.Exists) do
begin
- repeat
- Inc(I);
- until not FileExists(PlaylistPath + Name + InttoStr(I) + '.upl');
- Playlists[Result].Filename := Name + InttoStr(I) + '.upl';
+ Inc(I);
+ PlaylistFile := PlaylistPath.Append(Name + InttoStr(I) + '.upl');
end;
+ Playlists[Result].Filename := PlaylistFile.GetName;
//Save new Playlist
SavePlayList(Result);
@@ -357,28 +362,28 @@ end;
//----------
//DelPlaylist - Deletes a Playlist
//----------
-Procedure TPlayListManager.DelPlaylist(const Index: Cardinal);
+procedure TPlayListManager.DelPlaylist(const Index: Cardinal);
var
I: Integer;
- Filename: String;
+ Filename: IPath;
begin
- If Int(Index) > High(Playlists) then
+ if Int(Index) > High(Playlists) then
Exit;
- Filename := PlaylistPath + Playlists[Index].Filename;
+ Filename := PlaylistPath.Append(Playlists[Index].Filename);
//If not FileExists or File is not Writeable then exit
- If (Not FileExists(Filename)) OR (FileisReadOnly(Filename)) then
+ if (not Filename.IsFile()) or (Filename.IsReadOnly()) then
Exit;
//Delete Playlist from FileSystem
- if Not DeleteFile(Filename) then
+ if not Filename.DeleteFile() then
Exit;
//Delete Playlist from Array
//move all PLs to the Hole
- For I := Index to High(Playlists)-1 do
+ for I := Index to High(Playlists)-1 do
PlayLists[I] := PlayLists[I+1];
//Delete last Playlist
@@ -390,7 +395,7 @@ begin
begin
ScreenSong.UnLoadDetailedCover;
ScreenSong.HideCatTL;
- CatSongs.SetFilter('', 0);
+ CatSongs.SetFilter('', fltAll);
ScreenSong.Interaction := 0;
ScreenSong.FixSelected;
ScreenSong.ChangeMusic;
@@ -471,7 +476,7 @@ end;
//----------
//GetNames - Writes Playlist Names in a Array
//----------
-Procedure TPlayListManager.GetNames(var PLNames: array of String);
+procedure TPlayListManager.GetNames(var PLNames: array of UTF8String);
var
I: Integer;
Len: Integer;
diff --git a/cmake/src/base/URecord.pas b/cmake/src/base/URecord.pas
index 2c2093a0..c183875c 100644
--- a/cmake/src/base/URecord.pas
+++ b/cmake/src/base/URecord.pas
@@ -95,14 +95,14 @@ const
type
TAudioInputSource = record
- Name: string;
+ Name: UTF8String;
end;
// soundcard input-devices information
TAudioInputDevice = class
public
CfgIndex: integer; // index of this device in Ini.InputDeviceConfig
- Name: string; // soundcard name
+ 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)
@@ -133,6 +133,7 @@ type
destructor Destroy; override;
procedure UpdateInputDeviceConfig;
+ function ValidateSettings: boolean;
// handle microphone input
procedure HandleMicrophoneData(Buffer: PByteArray; Size: integer;
@@ -143,7 +144,7 @@ type
private
Started: boolean;
protected
- function UnifyDeviceName(const name: string; deviceIndex: integer): string;
+ function UnifyDeviceName(const name: UTF8String; deviceIndex: integer): UTF8String;
public
function GetName: String; virtual; abstract;
function InitializeRecord: boolean; virtual; abstract;
@@ -162,6 +163,8 @@ implementation
uses
ULog,
+ UGraphic,
+ ULanguage,
UNote;
var
@@ -577,6 +580,7 @@ begin
deviceCfg.Name := Trim(device.Name);
deviceCfg.Input := 0;
+ deviceCfg.Latency := LATENCY_AUTODETECT;
channelCount := device.AudioFormat.Channels;
SetLength(deviceCfg.ChannelToPlayerMap, channelCount);
@@ -593,6 +597,50 @@ begin
end;
end;
+function TAudioInputProcessor.ValidateSettings: boolean;
+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] 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 <> 0) then
+ begin
+ // check if player is already assigned to another device/channel
+ if (PlayerMap[PlayerID]) then
+ begin
+ ScreenPopupError.ShowPopup(
+ Format(Language.Translate('ERROR_PLAYER_DEVICE_ASSIGNMENT'),
+ [PlayerID]));
+ Result := false;
+ Exit;
+ end;
+
+ // mark player as assigned to a device
+ PlayerMap[PlayerID] := true;
+ end;
+ end;
+ end;
+ Result := true;
+end;
+
{*
* Handles captured microphone input data.
* Params:
@@ -741,11 +789,11 @@ begin
Started := false;
end;
-function TAudioInputBase.UnifyDeviceName(const name: string; deviceIndex: integer): string;
+function TAudioInputBase.UnifyDeviceName(const name: UTF8String; deviceIndex: integer): UTF8String;
var
count: integer; // count of devices with this name
- function IsDuplicate(const name: string): boolean;
+ function IsDuplicate(const name: UTF8String): boolean;
var
i: integer;
begin
@@ -753,10 +801,13 @@ var
// search devices with same description
for i := 0 to deviceIndex-1 do
begin
- if (AudioInputProcessor.DeviceList[i].Name = name) then
+ if (AudioInputProcessor.DeviceList[i] <> nil) then
begin
- Result := true;
- Break;
+ if (AudioInputProcessor.DeviceList[i].Name = name) then
+ begin
+ Result := true;
+ Break;
+ end;
end;
end;
end;
diff --git a/cmake/src/base/USingScores.pas b/cmake/src/base/USingScores.pas
index 89896d2d..26c5dfe8 100644
--- a/cmake/src/base/USingScores.pas
+++ b/cmake/src/base/USingScores.pas
@@ -117,9 +117,9 @@ type
TScorePopUp = record
Player: byte; // index of the popups player
TimeStamp: cardinal; // timestamp of popups spawn
- Rating: byte; // 0 to 8, type of rating (cool, bad, etc.)
- ScoreGiven: word; // score that has already been given to the player
- ScoreDiff: word; // difference between cur score at spawn and old score
+ 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;
@@ -129,7 +129,7 @@ type
//-----------
TSingScores = class
private
- Positions: aScorePosition;
+ aPositions: aScorePosition;
aPlayers: aScorePlayer;
oPositionCount: byte;
oPlayerCount: byte;
@@ -138,9 +138,18 @@ type
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);
@@ -149,6 +158,10 @@ type
// 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)
@@ -174,6 +187,7 @@ type
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;
@@ -201,8 +215,14 @@ type
// 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: byte; const Score: word);
+ procedure SpawnPopUp(const PlayerIndex: byte; const Rating: integer; const Score: integer);
// removes all popups from mem
procedure KillAllPopUps;
@@ -215,6 +235,7 @@ implementation
uses
SysUtils,
+ Math,
SDL,
TextGL,
ULog,
@@ -266,7 +287,7 @@ procedure TSingScores.AddPosition(const pPosition: PScorePosition);
begin
if (PositionCount < MaxPositions) then
begin
- Positions[PositionCount] := pPosition^;
+ aPositions[PositionCount] := pPosition^;
Inc(oPositionCount);
end;
end;
@@ -318,6 +339,7 @@ procedure TSingScores.ClearPlayers;
begin
KillAllPopUps;
oPlayerCount := 0;
+ TimePassed := 0;
end;
{**
@@ -328,6 +350,7 @@ begin
KillAllPopUps;
oPlayerCount := 0;
oPositionCount := 0;
+ TimePassed := 0;
end;
{**
@@ -360,7 +383,7 @@ var
nPosition.PUW := nPosition.BGW;
nPosition.PUH := nPosition.BGH;
- nPosition.PUFont := 2;
+ nPosition.PUFont := ftOutline1;
nPosition.PUFontSize := 18;
nPosition.PUStartX := nPosition.BGX;
@@ -400,9 +423,33 @@ begin
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: byte; const Score: word);
+procedure TSingScores.SpawnPopUp(const PlayerIndex: byte; const Rating: integer; const Score: integer);
var
Cur: PScorePopUp;
begin
@@ -414,10 +461,12 @@ begin
Cur.Player := PlayerIndex;
Cur.TimeStamp := SDL_GetTicks;
- // limit rating value to 8
+ // 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;
@@ -513,6 +562,27 @@ begin
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
*}
@@ -532,7 +602,7 @@ var
for I := 0 to PositionCount - 1 do
begin
- if ((Positions[I].PlayerCount and bPlayerCount) <> 0) then
+ if ((aPositions[I].PlayerCount and bPlayerCount) <> 0) then
Inc(Result);
end;
end;
@@ -546,7 +616,7 @@ var
for I := 0 to PositionCount - 1 do
begin
- if ((Positions[I].PlayerCount and bPlayerCount) <> 0) then
+ if ((aPositions[I].PlayerCount and bPlayerCount) <> 0) then
begin
if (bPlayer = 0) then
begin
@@ -614,6 +684,8 @@ var
CurPopUp, LastPopUp: PScorePopUp;
begin
CurTime := SDL_GetTicks;
+ if (TimePassed <> 0) then
+ TimePassed := CurTime - TimePassed;
if Visible then
begin
@@ -644,6 +716,7 @@ begin
// draw players w/ rating bar
for I := 0 to PlayerCount-1 do
begin
+ DoRaiseScore(I);
DrawScore(I);
DrawRatingBar(I);
end
@@ -651,10 +724,42 @@ begin
// 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;
{**
@@ -701,13 +806,13 @@ begin
Progress := TimeDiff / Settings.Phase1Time;
- W := Positions[PIndex].PUW * Sin(Progress/2*Pi);
- H := Positions[PIndex].PUH * Sin(Progress/2*Pi);
+ W := aPositions[PIndex].PUW * Sin(Progress/2*Pi);
+ H := aPositions[PIndex].PUH * Sin(Progress/2*Pi);
- X := Positions[PIndex].PUStartX + (Positions[PIndex].PUW - W)/2;
- Y := Positions[PIndex].PUStartY + (Positions[PIndex].PUH - H)/2;
+ X := aPositions[PIndex].PUStartX + (aPositions[PIndex].PUW - W)/2;
+ Y := aPositions[PIndex].PUStartY + (aPositions[PIndex].PUH - H)/2;
- FontSize := Round(Progress * Positions[PIndex].PUFontSize);
+ FontSize := Round(Progress * aPositions[PIndex].PUFontSize);
FontOffset := (H - FontSize) / 2;
Alpha := 1;
end
@@ -717,20 +822,20 @@ begin
// phase 2 - the moving
Progress := (TimeDiff - Settings.Phase1Time) / Settings.Phase2Time;
- W := Positions[PIndex].PUW;
- H := Positions[PIndex].PUH;
+ W := aPositions[PIndex].PUW;
+ H := aPositions[PIndex].PUH;
- PosDiff := Positions[PIndex].PUTargetX - Positions[PIndex].PUStartX;
+ PosDiff := aPositions[PIndex].PUTargetX - aPositions[PIndex].PUStartX;
if PosDiff > 0 then
PosDiff := PosDiff + W;
- X := Positions[PIndex].PUStartX + PosDiff * sqr(Progress);
+ X := aPositions[PIndex].PUStartX + PosDiff * sqr(Progress);
- PosDiff := Positions[PIndex].PUTargetY - Positions[PIndex].PUStartY;
+ PosDiff := aPositions[PIndex].PUTargetY - aPositions[PIndex].PUStartY;
if PosDiff < 0 then
- PosDiff := PosDiff + Positions[PIndex].BGH;
- Y := Positions[PIndex].PUStartY + PosDiff * sqr(Progress);
+ PosDiff := PosDiff + aPositions[PIndex].BGH;
+ Y := aPositions[PIndex].PUStartY + PosDiff * sqr(Progress);
- FontSize := Positions[PIndex].PUFontSize;
+ FontSize := aPositions[PIndex].PUFontSize;
FontOffset := (H - FontSize) / 2;
Alpha := 1 - 0.3 * Progress;
end
@@ -763,24 +868,24 @@ begin
// set positions etc.
Alpha := 0.7 - 0.7 * Progress;
- W := Positions[PIndex].PUW;
- H := Positions[PIndex].PUH;
+ W := aPositions[PIndex].PUW;
+ H := aPositions[PIndex].PUH;
- PosDiff := Positions[PIndex].PUTargetX - Positions[PIndex].PUStartX;
+ PosDiff := aPositions[PIndex].PUTargetX - aPositions[PIndex].PUStartX;
if (PosDiff > 0) then
PosDiff := W
else
PosDiff := 0;
- X := Positions[PIndex].PUTargetX + PosDiff * Progress;
+ X := aPositions[PIndex].PUTargetX + PosDiff * Progress;
- PosDiff := Positions[PIndex].PUTargetY - Positions[PIndex].PUStartY;
+ PosDiff := aPositions[PIndex].PUTargetY - aPositions[PIndex].PUStartY;
if (PosDiff < 0) then
- PosDiff := -Positions[PIndex].BGH
+ PosDiff := -aPositions[PIndex].BGH
else
PosDiff := 0;
- Y := Positions[PIndex].PUTargetY - PosDiff * (1 - Progress);
+ Y := aPositions[PIndex].PUTargetY - PosDiff * (1 - Progress);
- FontSize := Positions[PIndex].PUFontSize;
+ FontSize := aPositions[PIndex].PUFontSize;
FontOffset := (H - FontSize) / 2;
end
else
@@ -817,7 +922,7 @@ begin
glDisable(GL_BLEND);
// set font style and size
- SetFontStyle(Positions[PIndex].PUFont);
+ SetFontStyle(aPositions[PIndex].PUFont);
SetFontItalic(false);
SetFontSize(FontSize);
SetFontReflection(false, 0);
@@ -853,7 +958,7 @@ 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 := @Positions[Players[Index].Position and 127];
+ Position := @aPositions[Players[Index].Position and 127];
// draw scorebg
glEnable(GL_TEXTURE_2D);
@@ -905,7 +1010,7 @@ begin
Players[index].RBVisible and
Players[index].Visible) then
begin
- Position := @Positions[Players[Index].Position and 127];
+ Position := @aPositions[Players[Index].Position and 127];
if (Enabled and Players[Index].Enabled) then
begin
diff --git a/cmake/src/base/USkins.pas b/cmake/src/base/USkins.pas
index a4722d95..a909b081 100644
--- a/cmake/src/base/USkins.pas
+++ b/cmake/src/base/USkins.pas
@@ -33,32 +33,42 @@ interface
{$I switches.inc}
+uses
+ UPath,
+ UCommon;
+
type
TSkinTexture = record
Name: string;
- FileName: string;
+ FileName: IPath;
end;
TSkinEntry = record
Theme: string;
Name: string;
- Path: string;
- FileName: string;
+ Path: IPath;
+ FileName: IPath;
+
+ DefaultColor: integer;
Creator: string; // not used yet
end;
TSkin = class
Skin: array of TSkinEntry;
SkinTexture: array of TSkinTexture;
- SkinPath: string;
+ SkinPath: IPath;
Color: integer;
constructor Create;
procedure LoadList;
- procedure ParseDir(Dir: string);
- procedure LoadHeader(FileName: string);
+ procedure ParseDir(Dir: IPath);
+ procedure LoadHeader(FileName: IPath);
procedure LoadSkin(Name: string);
- function GetTextureFileName(TextureName: string): 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;
@@ -71,10 +81,12 @@ uses
IniFiles,
Classes,
SysUtils,
+ Math,
UIni,
ULog,
UMain,
- UPath;
+ UPathUtils,
+ UFileSystem;
constructor TSkin.Create;
begin
@@ -86,48 +98,47 @@ end;
procedure TSkin.LoadList;
var
- SR: TSearchRec;
+ Iter: IFileIterator;
+ DirInfo: TFileInfo;
begin
- if FindFirst(SkinsPath+'*', faDirectory, SR) = 0 then
+ Iter := FileSystem.FileFind(SkinsPath.Append('*'), faDirectory);
+ while Iter.HasNext do
begin
- repeat
- if (SR.Name <> '.') and (SR.Name <> '..') then
- ParseDir(SkinsPath + SR.Name + PathDelim);
- until FindNext(SR) <> 0;
- end; // if
- FindClose(SR);
+ 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: string);
+procedure TSkin.ParseDir(Dir: IPath);
var
- SR: TSearchRec;
+ Iter: IFileIterator;
+ IniInfo: TFileInfo;
begin
- if FindFirst(Dir + '*.ini', faAnyFile, SR) = 0 then
+ Iter := FileSystem.FileFind(Dir.Append('*.ini'), 0);
+ while Iter.HasNext do
begin
- repeat
-
- if (SR.Name <> '.') and (SR.Name <> '..') then
- LoadHeader(Dir + SR.Name);
-
- until FindNext(SR) <> 0;
+ IniInfo := Iter.Next;
+ LoadHeader(Dir.Append(IniInfo.Name));
end;
end;
-procedure TSkin.LoadHeader(FileName: string);
+procedure TSkin.LoadHeader(FileName: IPath);
var
SkinIni: TMemIniFile;
S: integer;
begin
- SkinIni := TMemIniFile.Create(FileName);
+ SkinIni := TMemIniFile.Create(FileName.ToNative);
S := Length(Skin);
SetLength(Skin, S+1);
- Skin[S].Path := IncludeTrailingPathDelimiter(ExtractFileDir(FileName));
- Skin[S].FileName := ExtractFileName(FileName);
+ 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;
@@ -142,7 +153,7 @@ begin
S := GetSkinNumber(Name);
SkinPath := Skin[S].Path;
- SkinIni := TMemIniFile.Create(SkinPath + Skin[S].FileName);
+ SkinIni := TMemIniFile.Create(SkinPath.Append(Skin[S].FileName).ToNative);
SL := TStringList.Create;
SkinIni.ReadSection('Textures', SL);
@@ -151,42 +162,33 @@ begin
for T := 0 to SL.Count-1 do
begin
SkinTexture[T].Name := SL.Strings[T];
- SkinTexture[T].FileName := SkinIni.ReadString('Textures', SL.Strings[T], '');
+ SkinTexture[T].FileName := Path(SkinIni.ReadString('Textures', SL.Strings[T], ''));
end;
SL.Free;
SkinIni.Free;
end;
-function TSkin.GetTextureFileName(TextureName: string): string;
+function TSkin.GetTextureFileName(TextureName: string): IPath;
var
T: integer;
begin
- Result := '';
+ Result := PATH_NONE;
for T := 0 to High(SkinTexture) do
begin
- if ( SkinTexture[T].Name = TextureName ) and
- ( SkinTexture[T].FileName <> '' ) then
+ if (SkinTexture[T].Name = TextureName) and
+ (SkinTexture[T].FileName.IsSet) then
begin
- Result := SkinPath + SkinTexture[T].FileName;
+ Result := SkinPath.Append(SkinTexture[T].FileName);
end;
end;
- if ( TextureName <> '' ) and
- ( Result <> '' ) then
+ if (TextureName <> '') and (Result.IsSet) then
begin
//Log.LogError('', '-----------------------------------------');
//Log.LogError(TextureName+' - '+ Result, 'TSkin.GetTextureFileName');
end;
-
-{ Result := SkinPath + 'Bar.jpg';
- if TextureName = 'Ball' then
- Result := SkinPath + 'Ball.bmp';
- if Copy(TextureName, 1, 4) = 'Gray' then
- Result := SkinPath + 'Ball.bmp';
- if Copy(TextureName, 1, 6) = 'NoteBG' then
- Result := SkinPath + 'Ball.bmp';}
end;
function TSkin.GetSkinNumber(Name: string): integer;
@@ -195,25 +197,52 @@ var
begin
Result := 0; // set default to the first available skin
for S := 0 to High(Skin) do
- if Skin[S].Name = Name then
+ if CompareText(Skin[S].Name, Name) = 0 then
Result := S;
end;
-procedure TSkin.onThemeChange;
-var
- S: integer;
- Name: String;
+procedure TSkin.GetSkinsByTheme(Theme: string; out Skins: TUTF8StringDynArray);
+ var
+ I: Integer;
+ Len: integer;
begin
- Ini.SkinNo:=0;
- SetLength(ISkin, 0);
- Name := Uppercase(ITheme[Ini.Theme]);
- for S := 0 to High(Skin) do
- if Name = Uppercase(Skin[S].Theme) then
+ SetLength(Skins, 0);
+ Len := 0;
+
+ for I := 0 to High(Skin) do
+ if CompareText(Theme, Skin[I].Theme) = 0 then
begin
- SetLength(ISkin, Length(ISkin)+1);
- ISkin[High(ISkin)] := Skin[S].Name;
+ 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/cmake/src/base/USong.pas b/cmake/src/base/USong.pas
index 57f78a27..a441fe40 100644
--- a/cmake/src/base/USong.pas
+++ b/cmake/src/base/USong.pas
@@ -56,7 +56,11 @@ uses
PseudoThread,
{$ENDIF}
UCatCovers,
- UXMLSong;
+ UXMLSong,
+ UUnicodeUtils,
+ UTextEncoding,
+ UFilesystem,
+ UPath;
type
@@ -68,42 +72,62 @@ type
end;
TScore = record
- Name: WideString;
+ Name: UTF8String;
Score: integer;
- Length: string;
+ 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
- procedure ParseNote(LineNumber: integer; TypeP: char; StartP, DurationP, NoteP: integer; LyricS: string);
+ 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 ReadTXTHeader( const aFileName : WideString ): boolean;
- function ReadXMLHeader( const aFileName : WideString ): boolean;
+ 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: WideString;
- Folder: WideString; // for sorting by folder
- fFileName,
- FileName: WideString;
+ 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
- //Category: array of WideString; // TODO: do we need this?
- Genre: WideString;
- Edition: WideString;
- Language: WideString;
+ Genre: UTF8String;
+ Edition: UTF8String;
+ Language: UTF8String;
+ Year: Integer;
- Title: WideString;
- Artist: WideString;
+ Title: UTF8String;
+ Artist: UTF8String;
- Text: WideString;
- Creator: WideString;
+ Creator: UTF8String;
- Cover: WideString;
CoverTex: TTexture;
- Mp3: WideString;
- Background: WideString;
- Video: WideString;
+
VideoGAP: real;
NotesGAP: integer;
Start: real; // in seconds
@@ -113,6 +137,10 @@ type
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
@@ -122,23 +150,21 @@ type
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
- SongFile: TextFile; // all procedures in this unit operate on this file
-
Base : array[0..1] of integer;
Rel : array[0..1] of integer;
Mult : integer;
MultBPM : integer;
- LastError: String;
+ LastError: AnsiString;
function GetErrorLineNo: integer;
property ErrorLineNo: integer read GetErrorLineNo;
- constructor Create (); overload;
- constructor Create ( const aFileName : WideString ); overload;
+ constructor Create(); overload;
+ constructor Create(const aFileName : IPath); overload;
function LoadSong: boolean;
function LoadXMLSong: boolean;
- function Analyse(): boolean;
+ function Analyse(const ReadCustomTags: Boolean = false): boolean;
function AnalyseXML(): boolean;
procedure Clear();
end;
@@ -149,67 +175,82 @@ uses
StrUtils,
TextGL,
UIni,
- UPath,
+ UPathUtils,
UMusic, //needed for Lines
UNote; //needed for Player
+const
+ DEFAULT_ENCODING = encAuto;
+
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;
-constructor TSong.Create( const aFileName: WideString );
- // 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 GetFolderCategory: WideString;
- var
- I: Integer;
- P: Integer; //position of next path delimiter
- begin
- Result := 'Unknown'; //default folder category, if we can't locate the song dir
+// 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
- if (AnsiStartsText(SongPaths.Strings[I], aFilename)) then
+ 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
- P := PosEx(PathDelim, aFilename, Length(SongPaths.Strings[I]) + 1);
-
- If (P > 0) then
- begin
- // we have found the category name => get it
- Result := copy(self.Path, Length(SongPaths.Strings[I]) + 1, P - Length(SongPaths.Strings[I]) - 1);
- end
- else
- begin
- // songs are in the "root" of the songdir => use songdir for the categorys name
- Result := SongPaths.Strings[I];
- end;
-
- Exit;
+ // 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;
- fFileName := aFileName;
LastError := '';
- if fileexists( aFileName ) then
+ Self.Path := aFileName.GetPath;
+ Self.FileName := aFileName.GetName;
+ Self.Folder := GetFolderCategory(aFileName);
+
+ (*
+ if (aFileName.IsFile) then
begin
- self.Path := ExtractFilePath( aFileName );
- self.Folder := GetFolderCategory;
- self.FileName := ExtractFileName( aFileName );
- (*
- if ReadTXTHeader( aFileName ) then
+ if ReadTXTHeader(aFileName) then
begin
LoadSong();
end
@@ -218,45 +259,189 @@ 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.LoadSong(): boolean;
+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;
-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
- TempC: char;
- Text: string;
- CP: integer; // Current Player (0 or 1)
+ CurLine: RawByteString;
+ LinePos: integer;
Count: integer;
Both: boolean;
- Param1: integer;
- Param2: integer;
- Param3: integer;
- ParamS: string;
- I: integer;
+ Param0: AnsiChar;
+ Param1: integer;
+ Param2: integer;
+ Param3: integer;
+ ParamLyric: UTF8String;
+
+ I: integer;
+ NotesFound: boolean;
+ SongFile: TTextFileStream;
+ FileNamePath: IPath;
begin
Result := false;
LastError := '';
- if not FileExists(Path + PathDelim + FileName) then
+ FileNamePath := Path.Append(FileName);
+ if not FileNamePath.IsFile() then
begin
LastError := 'ERROR_CORRUPT_SONG_FILE_NOT_FOUND';
- Log.LogError('File not found: "' + Path + PathDelim + FileName + '"', 'TSong.LoadSong()');
- exit;
+ 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;
- CP := 0;
Both := false;
if Length(Player) = 2 then
@@ -264,156 +449,157 @@ begin
try
// Open song file for reading.....
- FileMode := fmOpenRead;
- AssignFile(SongFile, fFileName);
- Reset(SongFile);
-
- //Clear old Song Header
- if (self.Path = '') then
- self.Path := ExtractFilePath(FileName);
-
- if (self.FileName = '') then
- self.Filename := ExtractFileName(FileName);
-
- FileLineNo := 0;
- //Search for Note Begining
- repeat
- ReadLn(SongFile, Text);
- Inc(FileLineNo);
+ 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 (EoF(SongFile)) then
+ if (not NotesFound) then
begin //Song File Corrupted - No Notes
- CloseFile(SongFile);
- Log.LogError('Could not load txt File, no Notes found: ' + FileName);
+ Log.LogError('Could not load txt File, no notes found: ' + FileNamePath.ToNative);
LastError := 'ERROR_CORRUPT_SONG_NO_NOTES';
Exit;
end;
- Read(SongFile, TempC);
- until ((TempC = ':') or (TempC = 'F') or (TempC = '*'));
- 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 (TempC <> 'E') and (not EOF(SongFile)) do
- begin
-
- if (TempC = ':') or (TempC = '*') or (TempC = 'F') then
- begin
- // read notes
- Read(SongFile, Param1);
- Read(SongFile, Param2);
- Read(SongFile, Param3);
- Read(SongFile, ParamS);
-
- //Check for ZeroNote
- if Param2 = 0 then
- Log.LogError('Found ZeroNote at "'+TempC+' '+IntToStr(Param1)+' '+IntToStr(Param2)+' '+IntToStr(Param3)+ParamS+'" -> Note ignored!')
- else
- begin
- // add notes
- if not Both then
- // P1
- ParseNote(0, TempC, (Param1+Rel[0]) * Mult, Param2 * Mult, Param3, ParamS)
- else
- begin
- // P1 + P2
- ParseNote(0, TempC, (Param1+Rel[0]) * Mult, Param2 * Mult, Param3, ParamS);
- ParseNote(1, TempC, (Param1+Rel[1]) * Mult, Param2 * Mult, Param3, ParamS);
- end;
- end; //Zeronote check
- end // if
-
- else if TempC = '-' then
+ SetLength(Lines, 2);
+ for Count := 0 to High(Lines) do
begin
- // reads sentence
- Read(SongFile, Param1);
- if self.Relative then
- Read(SongFile, Param2); // 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
+ 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;
- else if TempC = 'B' then
+ while true do
begin
- SetLength(self.BPM, Length(self.BPM) + 1);
- Read(SongFile, self.BPM[High(self.BPM)].StartBeat);
- self.BPM[High(self.BPM)].StartBeat := self.BPM[High(self.BPM)].StartBeat + Rel[0];
+ LinePos := 1;
- Read(SongFile, Text);
- self.BPM[High(self.BPM)].BPM := StrToFloat(Text);
- self.BPM[High(self.BPM)].BPM := self.BPM[High(self.BPM)].BPM * Mult * MultBPM;
- end;
+ 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
+ Log.LogWarn(Format('"%s" in line %d: %s',
+ [FileNamePath.ToNative, FileLineNo, 'found note with length zero -> note ignored']), 'TSong.LoadSong')
+ //Log.LogError('Found zero-length note at "'+Param0+' '+IntToStr(Param1)+' '+IntToStr(Param2)+' '+IntToStr(Param3)+ParamLyric+'" -> Note ignored!')
+ else
+ begin
+ // 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; //Zeronote check
+ 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
- ReadLn(SongFile); //Jump to next line in File, otherwise the next Read would catch the linebreak(e.g. #13 #10 on win32)
+ 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];
- Read(SongFile, TempC);
- Inc(FileLineNo);
- end; // while}
+ self.BPM[High(self.BPM)].BPM := ParseLyricFloatParam(CurLine, LinePos);
+ self.BPM[High(self.BPM)].BPM := self.BPM[High(self.BPM)].BPM * Mult * MultBPM;
+ end;
- CloseFile(SongFile);
+ // Read next line in File
+ if (not SongFile.ReadLine(CurLine)) then
+ Break;
- for I := 0 to High(Lines) do
+ Inc(FileLineNo);
+ end; // while
+ finally
+ SongFile.Free;
+ end;
+ except
+ on E: Exception 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: "' + fFileName + '"');
- 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: ' + Filename);
- end;
- end;
+ Log.LogError(Format('Error loading file: "%s" in line %d,%d: %s',
+ [FileNamePath.ToNative, FileLineNo, LinePos, E.Message]));
+ Exit;
end;
+ end;
- for Count := 0 to High(Lines) do
+ for I := 0 to High(Lines) do
+ begin
+ if ((Both) or (I = 0)) then
begin
- if (High(Lines[Count].Line) >= 0) then
- Lines[Count].Line[High(Lines[Count].Line)].LastLine := true;
- end;
- except
- try
- CloseFile(SongFile);
- except
+ 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;
- LastError := 'ERROR_CORRUPT_SONG_ERROR_IN_LINE';
- Log.LogError('Error Loading File: "' + fFileName + '" in Line ' + inttostr(FileLineNo));
- exit;
+ 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;
@@ -421,11 +607,7 @@ end;
//Load XML Song
function TSong.LoadXMLSong(): boolean;
-
var
- //TempC: char;
- Text: string;
- CP: integer; // Current Player (0 or 1)
Count: integer;
Both: boolean;
Param1: integer;
@@ -438,14 +620,15 @@ var
NoteType: char;
SentenceEnd, Rest, Time: integer;
Parser: TParser;
-
+ FileNamePath: IPath;
begin
Result := false;
LastError := '';
- if not FileExists(Path + PathDelim + FileName) then
+ FileNamePath := Path.Append(FileName);
+ if not FileNamePath.IsFile() then
begin
- Log.LogError('File not found: "' + Path + PathDelim + FileName + '"', 'TSong.LoadSong()');
+ Log.LogError('File not found: "' + FileNamePath.ToNative + '"', 'TSong.LoadSong()');
exit;
end;
@@ -454,7 +637,6 @@ begin
Lines[0].ScoreValue := 0;
self.Relative := false;
Rel[0] := 0;
- CP := 0;
Both := false;
if Length(Player) = 2 then
@@ -484,7 +666,7 @@ begin
//Try to Parse the Song
- if Parser.ParseSong(Path + PathDelim + FileName) then
+ if Parser.ParseSong(FileNamePath) then
begin
//Writeln('XML Inputfile Parsed succesful');
@@ -551,7 +733,7 @@ begin
end
else
begin
- Log.LogError('Could not parse Inputfile: ' + Path + PathDelim + FileName);
+ Log.LogError('Could not parse inputfile: ' + FileNamePath.ToNative);
exit;
end;
@@ -563,14 +745,11 @@ begin
Result := true;
end;
-function TSong.ReadXMLHeader(const aFileName : WideString): boolean;
-
+function TSong.ReadXMLHeader(const aFileName : IPath): boolean;
var
- //Line, Identifier, Value: string;
- //Temp : word;
Done : byte;
Parser : TParser;
-
+ FileNamePath: IPath;
begin
Result := true;
Done := 0;
@@ -579,7 +758,8 @@ begin
Parser := TParser.Create;
Parser.Settings.DashReplacement := '~';
- if Parser.ParseSong(self.Path + self.FileName) then
+ FileNamePath := Self.Path.Append(Self.FileName);
+ if Parser.ParseSong(FileNamePath) then
begin
//-----------
//Required Attributes
@@ -598,9 +778,9 @@ begin
Done := Done or 2;
//MP3 File //Test if Exists
- self.Mp3 := platform.FindSongFile(Path, '*.mp3');
+ Self.Mp3 := FindSongFile(Self.Path, '*.mp3');
//Add Mp3 Flag to Done
- if (FileExists(self.Path + self.Mp3)) then
+ if (Self.Path.Append(Self.Mp3).IsFile()) then
Done := Done or 4;
//Beats per Minute
@@ -621,16 +801,16 @@ begin
self.GAP := Parser.SongInfo.Header.Gap;
//Cover Picture
- self.Cover := platform.FindSongFile(Path, '*[CO].jpg');
+ self.Cover := FindSongFile(Path, '*[CO].jpg');
//Background Picture
- self.Background := platform.FindSongFile(Path, '*[BG].jpg');
+ self.Background := FindSongFile(Path, '*[BG].jpg');
// Video File
// self.Video := Value
// Video Gap
- // self.VideoGAP := song_StrtoFloat( Value )
+ // self.VideoGAP := StrtoFloatI18n( Value )
//Genre Sorting
self.Genre := Parser.SongInfo.Header.Genre;
@@ -645,7 +825,7 @@ begin
self.Language := Parser.SongInfo.Header.Language;
end
else
- Log.LogError('File Incomplete or not SingStar XML (A): ' + aFileName);
+ Log.LogError('File incomplete or not SingStar XML (A): ' + aFileName.ToNative);
Parser.Free;
@@ -654,220 +834,297 @@ begin
begin
Result := false;
if (Done and 8) = 0 then //No BPM Flag
- Log.LogError('BPM Tag Missing: ' + self.FileName)
+ 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)
+ 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)
+ 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)
+ Log.LogError('Title tag missing: ' + self.FileName.ToNative)
else //unknown Error
- Log.LogError('File Incomplete or not SingStar XML (B - '+ inttostr(Done) +'): ' + aFileName);
+ 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(const aFileName : WideString): boolean;
-
- function song_StrtoFloat( aValue : string ) : extended;
-
- var
- lValue : string;
-
+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
- lValue := aValue;
-
- if (Pos(',', lValue) <> 0) then
- lValue[Pos(',', lValue)] := '.';
-
- Result := StrToFloatDef(lValue, 0);
+ 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;
-
-var
- Line, Identifier, Value: string;
- Temp : word;
- Done : byte;
-
begin
Result := true;
Done := 0;
- //Read first Line
- ReadLn (SongFile, Line);
+ FullFileName := Path.Append(Filename).ToNative;
+ //Read first Line
+ SongFile.ReadLine(Line);
if (Length(Line) <= 0) then
begin
- Log.LogError('File Starts with Empty Line: ' + aFileName);
+ 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);
- Temp := Pos(':', Line);
+ SepPos := Pos(':', Line);
- //Line has a Seperator-> Headerline
- if (Temp <> 0) then
+ //Line has no Seperator, ignore non header field
+ if (SepPos = 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
+ AddCustomTag('', Copy(Line, 2, Length(Line) - 1));
+ // read next line
+ if (not SongFile.ReadLine(Line)) then
begin
- //-----------
- //Required Attributes
- //-----------
+ Result := false;
+ Log.LogError('File incomplete or not Ultrastar txt (A): ' + FullFileName);
+ Break;
+ end;
+ Continue;
+ end;
- {$IFDEF UTF8_FILENAMES}
- if ((Identifier = 'MP3') or (Identifier = 'BACKGROUND') or (Identifier = 'COVER') or (Identifier = 'VIDEO')) then
- Value := Utf8Encode(Value);
- {$ENDIF}
+ //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));
- //Title
- if (Identifier = 'TITLE') then
- begin
- self.Title := Value;
+ //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
- //Add Title Flag to Done
- Done := Done or 1;
- end
+ //-----------
+ //Required Attributes
+ //-----------
- //Artist
- else if (Identifier = 'ARTIST') then
- begin
- self.Artist := Value;
+ if (Identifier = 'TITLE') then
+ begin
+ DecodeStringUTF8(Value, Title, Encoding);
+ //Add Title Flag to Done
+ Done := Done or 1;
+ end
- //Add Artist Flag to Done
- Done := Done or 2;
- end
+ else if (Identifier = 'ARTIST') then
+ begin
+ DecodeStringUTF8(Value, Artist, Encoding);
+ //Add Artist Flag to Done
+ Done := Done or 2;
+ end
- //MP3 File //Test if Exists
- else if (Identifier = 'MP3') and (FileExists(self.Path + Value)) then
+ //MP3 File
+ else if (Identifier = 'MP3') then
+ begin
+ EncFile := DecodeFilename(Value);
+ if (Self.Path.Append(EncFile).IsFile) then
begin
- self.Mp3 := Value;
+ self.Mp3 := EncFile;
//Add Mp3 Flag to Done
Done := Done or 4;
- end
+ end;
+ end
+
+ //Beats per Minute
+ else if (Identifier = 'BPM') then
+ begin
+ SetLength(self.BPM, 1);
+ self.BPM[0].StartBeat := 0;
- //Beats per Minute
- else if (Identifier = 'BPM') then
+ self.BPM[0].BPM := StrToFloatI18n( Value ) * Mult * MultBPM;
+
+ if self.BPM[0].BPM <> 0 then
begin
- SetLength(self.BPM, 1);
- self.BPM[0].StartBeat := 0;
+ //Add BPM Flag to Done
+ Done := Done or 8;
+ end;
+ end
- self.BPM[0].BPM := song_StrtoFloat( Value ) * Mult * MultBPM;
+ //---------
+ //Additional Header Information
+ //---------
- if self.BPM[0].BPM <> 0 then
- begin
- //Add BPM Flag to Done
- Done := Done or 8;
- end;
- end
+ // Gap
+ else if (Identifier = 'GAP') then
+ begin
+ self.GAP := StrToFloatI18n(Value);
+ end
- //---------
- //Additional Header Information
- //---------
+ //Cover Picture
+ else if (Identifier = 'COVER') then
+ begin
+ self.Cover := DecodeFilename(Value);
+ end
- // Gap
- else if (Identifier = 'GAP') then
- self.GAP := song_StrtoFloat( Value )
+ //Background Picture
+ else if (Identifier = 'BACKGROUND') then
+ begin
+ self.Background := DecodeFilename(Value);
+ end
- //Cover Picture
- else if (Identifier = 'COVER') then
- self.Cover := Value
+ // 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
- //Background Picture
- else if (Identifier = 'BACKGROUND') then
- self.Background := Value
+ // Video Gap
+ else if (Identifier = 'VIDEOGAP') then
+ begin
+ self.VideoGAP := StrToFloatI18n( Value )
+ end
- // Video File
- else if (Identifier = 'VIDEO') then
- begin
- if (FileExists(self.Path + Value)) then
- self.Video := Value
- else
- Log.LogError('Can''t find Video File in Song: ' + aFileName);
- end
+ //Genre Sorting
+ else if (Identifier = 'GENRE') then
+ begin
+ DecodeStringUTF8(Value, Genre, Encoding)
+ end
- // Video Gap
- else if (Identifier = 'VIDEOGAP') then
- self.VideoGAP := song_StrtoFloat( Value )
+ //Edition Sorting
+ else if (Identifier = 'EDITION') then
+ begin
+ DecodeStringUTF8(Value, Edition, Encoding)
+ end
- //Genre Sorting
- else if (Identifier = 'GENRE') then
- self.Genre := Value
+ //Creator Tag
+ else if (Identifier = 'CREATOR') then
+ begin
+ DecodeStringUTF8(Value, Creator, Encoding)
+ end
- //Edition Sorting
- else if (Identifier = 'EDITION') then
- self.Edition := Value
+ //Language Sorting
+ else if (Identifier = 'LANGUAGE') then
+ begin
+ DecodeStringUTF8(Value, Language, Encoding)
+ end
- //Creator Tag
- else if (Identifier = 'CREATOR') then
- self.Creator := Value
+ //Language Sorting
+ else if (Identifier = 'YEAR') then
+ begin
+ TryStrtoInt(Value, self.Year)
+ end
- //Language Sorting
- else if (Identifier = 'LANGUAGE') then
- self.Language := Value
+ // Song Start
+ else if (Identifier = 'START') then
+ begin
+ self.Start := StrToFloatI18n( Value )
+ end
- // Song Start
- else if (Identifier = 'START') then
- self.Start := song_StrtoFloat( Value )
+ // Song Ending
+ else if (Identifier = 'END') then
+ begin
+ TryStrtoInt(Value, self.Finish)
+ end
- // Song Ending
- else if (Identifier = 'END') then
- TryStrtoInt(Value, self.Finish)
+ // Resolution
+ else if (Identifier = 'RESOLUTION') then
+ begin
+ TryStrtoInt(Value, self.Resolution)
+ end
- // Resolution
- else if (Identifier = 'RESOLUTION') then
- TryStrtoInt(Value, self.Resolution)
+ // Notes Gap
+ else if (Identifier = 'NOTESGAP') then
+ begin
+ TryStrtoInt(Value, self.NotesGAP)
+ end
- // Notes Gap
- else if (Identifier = 'NOTESGAP') then
- TryStrtoInt(Value, self.NotesGAP)
- // Relative Notes
- else if (Identifier = 'RELATIVE') and (uppercase(Value) = 'YES') then
+ // 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, DEFAULT_ENCODING);
+ end
+
+ // unsupported tag
+ else
+ begin
+ AddCustomTag(Identifier, Value);
end;
- end;
- if not EOF(SongFile) then
- ReadLn (SongFile, Line)
- else
+ 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): ' + aFileName);
- break;
+ Log.LogError('File incomplete or not Ultrastar txt (A): ' + FullFileName);
+ Break;
end;
+ end; // while
- end;
-
- if self.Cover = '' then
- self.Cover := platform.FindSongFile(Path, '*[CO].jpg');
+ 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: ' + self.FileName)
+ Log.LogError('BPM tag missing: ' + FullFileName)
else if (Done and 4) = 0 then //No MP3 Flag
- Log.LogError('MP3 Tag/File Missing: ' + self.FileName)
+ Log.LogError('MP3 tag/file missing: ' + FullFileName)
else if (Done and 2) = 0 then //No Artist Flag
- Log.LogError('Artist Tag Missing: ' + self.FileName)
+ Log.LogError('Artist tag missing: ' + FullFileName)
else if (Done and 1) = 0 then //No Title Flag
- Log.LogError('Title Tag Missing: ' + self.FileName)
+ Log.LogError('Title tag missing: ' + FullFileName)
else //unknown Error
- Log.LogError('File Incomplete or not Ultrastar TxT (B - '+ inttostr(Done) +'): ' + aFileName);
+ Log.LogError('File incomplete or not Ultrastar txt (B - '+ inttostr(Done) +'): ' + FullFileName);
end;
-
end;
function TSong.GetErrorLineNo: integer;
@@ -878,48 +1135,8 @@ begin
Result := -1;
end;
-procedure TSong.ParseNote(LineNumber: integer; TypeP: char; StartP, DurationP, NoteP: integer; LyricS: string);
-
+procedure TSong.ParseNote(LineNumber: integer; TypeP: char; StartP, DurationP, NoteP: integer; LyricS: UTF8String);
begin
- case Ini.Solmization of
- 1: // european
- begin
- case (NoteP mod 12) of
- 0..1: LyricS := ' do ';
- 2..3: LyricS := ' re ';
- 4: LyricS := ' mi ';
- 5..6: LyricS := ' fa ';
- 7..8: LyricS := ' sol ';
- 9..10: LyricS := ' la ';
- 11: LyricS := ' si ';
- end;
- end;
- 2: // japanese
- begin
- case (NoteP mod 12) of
- 0..1: LyricS := ' do ';
- 2..3: LyricS := ' re ';
- 4: LyricS := ' mi ';
- 5..6: LyricS := ' fa ';
- 7..8: LyricS := ' so ';
- 9..10: LyricS := ' la ';
- 11: LyricS := ' shi ';
- end;
- end;
- 3: // american
- begin
- case (NoteP mod 12) of
- 0..1: LyricS := ' do ';
- 2..3: LyricS := ' re ';
- 4: LyricS := ' mi ';
- 5..6: LyricS := ' fa ';
- 7..8: LyricS := ' sol ';
- 9..10: LyricS := ' la ';
- 11: LyricS := ' ti ';
- end;
- end;
- end; // case
-
with Lines[LineNumber].Line[Lines[LineNumber].High] do
begin
SetLength(Note, Length(Note) + 1);
@@ -956,14 +1173,9 @@ begin
if Note[HighNote].Tone < BaseNote then
BaseNote := Note[HighNote].Tone;
- //delete the space that seperates the notes pitch from its lyrics
- //it is left in the LyricS string because Read("some ordinal type") will
- //set the files pointer to the first whitespace character after the
- //ordinal string. Trim is no solution because it would cut the spaces
- //that seperate the words of the lyrics, too.
- Delete(LyricS, 1, 1);
+ Note[HighNote].Color := 1; // default color to 1 for editor
- Note[HighNote].Text := LyricS;
+ DecodeStringUTF8(LyricS, Note[HighNote].Text, Encoding);
Lyric := Lyric + Note[HighNote].Text;
End_ := Note[HighNote].Start + Note[HighNote].Length;
@@ -971,10 +1183,8 @@ begin
end;
procedure TSong.NewSentence(LineNumberP: integer; Param1, Param2: integer);
-
var
I: integer;
-
begin
if (Lines[LineNumberP].Line[Lines[LineNumberP].High].HighNote <> -1) then
@@ -985,7 +1195,8 @@ begin
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);
+ 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;
@@ -1012,8 +1223,7 @@ begin
Lines[LineNumberP].Line[Lines[LineNumberP].High].LastLine := false;
end;
-procedure TSong.clear();
-
+procedure TSong.Clear();
begin
//Main Information
Title := '';
@@ -1022,24 +1232,27 @@ begin
//Sortings:
Genre := 'Unknown';
Edition := 'Unknown';
- Language := 'Unknown'; //Language Patch
+ Language := 'Unknown';
+ Year := 0;
+
+ // set to default encoding
+ Encoding := DEFAULT_ENCODING;
+
+ // clear custom header tags
+ SetLength(CustomTags, 0);
//Required Information
- Mp3 := '';
- {$IFDEF FPC}
- setlength( BPM, 0 );
- {$ELSE}
- BPM := nil;
- {$ENDIF}
+ Mp3 := PATH_NONE;
+ SetLength(BPM, 0);
GAP := 0;
Start := 0;
Finish := 0;
//Additional Information
- Background := '';
- Cover := '';
- Video := '';
+ Background := PATH_NONE;
+ Cover := PATH_NONE;
+ Video := PATH_NONE;
VideoGAP := 0;
NotesGAP := 0;
Resolution := 4;
@@ -1048,8 +1261,9 @@ begin
Relative := false;
end;
-function TSong.Analyse(): boolean;
-
+function TSong.Analyse(const ReadCustomTags: Boolean): boolean;
+var
+ SongFile: TTextFileStream;
begin
Result := false;
@@ -1057,20 +1271,15 @@ begin
FileLineNo := 0;
//Open File and set File Pointer to the beginning
- AssignFile(SongFile, self.Path + self.FileName);
-
+ SongFile := TMemTextFileStream.Create(Self.Path.Append(Self.FileName), fmOpenRead);
try
- Reset(SongFile);
-
//Clear old Song Header
- self.clear;
+ Self.clear;
//Read Header
- Result := self.ReadTxTHeader( FileName )
-
- //And Close File
+ Result := Self.ReadTxTHeader(SongFile, ReadCustomTags)
finally
- CloseFile(SongFile);
+ SongFile.Free;
end;
end;
diff --git a/cmake/src/base/USongs.pas b/cmake/src/base/USongs.pas
index a7231cb3..cfc32a99 100644
--- a/cmake/src/base/USongs.pas
+++ b/cmake/src/base/USongs.pas
@@ -40,32 +40,36 @@ interface
{$ENDIF}
uses
+ SysUtils,
+ Classes,
{$IFDEF MSWINDOWS}
Windows,
DirWatch,
{$ELSE}
{$IFNDEF DARWIN}
- syscall,
+ syscall,
{$ENDIF}
baseunix,
UnixType,
{$ENDIF}
- SysUtils,
- Classes,
UPlatform,
ULog,
UTexture,
UCommon,
- {$IFDEF DARWIN}
- cthreads,
- {$ENDIF}
{$IFDEF USE_PSEUDO_THREAD}
- PseudoThread,
+ PseudoThread,
{$ENDIF}
+ UPath,
USong,
+ UIni,
UCatCovers;
type
+ TSongFilter = (
+ fltAll,
+ fltTitle,
+ fltArtist
+ );
TBPM = record
BPM: real;
@@ -73,11 +77,13 @@ type
end;
TScore = record
- Name: widestring;
+ Name: UTF8String;
Score: integer;
Length: string;
end;
+ TPathDynArray = array of IPath;
+
{$IFDEF USE_PSEUDO_THREAD}
TSongs = class(TPseudoThread)
{$ELSE}
@@ -102,11 +108,11 @@ type
procedure LoadSongList; // load all songs
- procedure BrowseDir(Dir: widestring); // should return number of songs in the future
- procedure BrowseTXTFiles(Dir: widestring);
- procedure BrowseXMLFiles(Dir: widestring);
- procedure Sort(Order: integer);
- function FindSongFile(Dir, Mask: widestring): widestring;
+ 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;
@@ -128,7 +134,7 @@ type
function VisibleSongs: integer; // returns number of visible songs (for tabs)
function VisibleIndex(Index: integer): integer; // returns visible song index (skips invisible)
- function SetFilter(FilterStr: string; const fType: byte): cardinal;
+ function SetFilter(FilterStr: UTF8String; Filter: TSongFilter): cardinal;
end;
var
@@ -156,9 +162,11 @@ uses
UCovers,
UFiles,
UGraphic,
- UIni,
- UPath,
- UNote;
+ UMain,
+ UPathUtils,
+ UNote,
+ UFilesystem,
+ UUnicodeUtils;
constructor TSongs.Create();
begin
@@ -232,7 +240,7 @@ begin
// browse directories
for I := 0 to SongPaths.Count-1 do
- BrowseDir(SongPaths[I]);
+ BrowseDir(SongPaths[I] as IPath);
if assigned(CatSongs) then
CatSongs.Refresh;
@@ -264,84 +272,92 @@ begin
Resume();
end;
-procedure TSongs.BrowseDir(Dir: widestring);
+procedure TSongs.BrowseDir(Dir: IPath);
begin
BrowseTXTFiles(Dir);
BrowseXMLFiles(Dir);
end;
-procedure TSongs.BrowseTXTFiles(Dir: widestring);
+procedure TSongs.FindFilesByExtension(const Dir: IPath; const Ext: IPath; Recursive: Boolean; var Files: TPathDynArray);
var
- i: integer;
- Files: TDirectoryEntryArray;
- lSong: TSong;
+ Iter: IFileIterator;
+ FileInfo: TFileInfo;
+ FileName: IPath;
begin
-
- try
- Files := Platform.DirectoryFindFiles(Dir, '.txt', true)
- except
- Log.LogError('Couldn''t deal with directory/file: ' + Dir + ' in TSongs.BrowseTXTFiles')
- end;
-
- for i := 0 to Length(Files) - 1 do
+ // search for all files and directories
+ Iter := FileSystem.FileFind(Dir.Append('*'), faAnyFile);
+ while (Iter.HasNext) do
begin
- if Files[i].IsDirectory then
+ FileInfo := Iter.Next;
+ FileName := FileInfo.Name;
+ if ((FileInfo.Attr and faDirectory) <> 0) then
begin
- BrowseTXTFiles(Dir + Files[i].Name + PathDelim); //Recursive Call
+ if Recursive and (not FileName.Equals('.')) and (not FileName.Equals('..')) then
+ FindFilesByExtension(Dir.Append(FileName), Ext, true, Files);
end
else
begin
- lSong := TSong.create(Dir + Files[i].Name);
-
- if lSong.Analyse then
- SongList.add(lSong)
- else
+ if (Ext.Equals(FileName.GetExtension(), true)) then
begin
- Log.LogError('AnalyseFile failed for "' + Files[i].Name + '".');
- freeandnil(lSong);
+ SetLength(Files, Length(Files)+1);
+ Files[High(Files)] := Dir.Append(FileName);
end;
-
end;
end;
- SetLength(Files, 0);
-
end;
-procedure TSongs.BrowseXMLFiles(Dir: widestring);
+procedure TSongs.BrowseTXTFiles(Dir: IPath);
var
- i: integer;
- Files: TDirectoryEntryArray;
- lSong: TSong;
+ I: integer;
+ Files: TPathDynArray;
+ Song: TSong;
+ Extension: IPath;
begin
+ SetLength(Files, 0);
+ Extension := Path('.txt');
+ FindFilesByExtension(Dir, Extension, true, Files);
- try
- Files := Platform.DirectoryFindFiles(Dir, '.xml', true)
- except
- Log.LogError('Couldn''t deal with directory/file: ' + Dir + ' in TSongs.BrowseXMLFiles')
- end;
-
- for i := 0 to Length(Files) - 1 do
+ for I := 0 to High(Files) do
begin
- if Files[i].IsDirectory then
- begin
- BrowseXMLFiles(Dir + Files[i].Name + PathDelim); // Recursive Call
- end
+ Song := TSong.Create(Files[I]);
+
+ if Song.Analyse then
+ SongList.Add(Song)
else
begin
- lSong := TSong.create(Dir + Files[i].Name);
+ Log.LogError('AnalyseFile failed for "' + Files[I].ToNative + '".');
+ FreeAndNil(Song);
+ end;
+ end;
- if lSong.AnalyseXML then
- SongList.add(lSong)
- else
- begin
- Log.LogError('AnalyseFile failed for "' + Files[i].Name + '".');
- freeandnil(lSong);
- 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);
+ SetLength(Files, 0);
end;
(*
@@ -350,35 +366,35 @@ end;
function CompareByEdition(Song1, Song2: Pointer): integer;
begin
- Result := CompareText(TSong(Song1).Edition, TSong(Song2).Edition);
+ Result := UTF8CompareText(TSong(Song1).Edition, TSong(Song2).Edition);
end;
function CompareByGenre(Song1, Song2: Pointer): integer;
begin
- Result := CompareText(TSong(Song1).Genre, TSong(Song2).Genre);
+ Result := UTF8CompareText(TSong(Song1).Genre, TSong(Song2).Genre);
end;
function CompareByTitle(Song1, Song2: Pointer): integer;
begin
- Result := CompareText(TSong(Song1).Title, TSong(Song2).Title);
+ Result := UTF8CompareText(TSong(Song1).Title, TSong(Song2).Title);
end;
function CompareByArtist(Song1, Song2: Pointer): integer;
begin
- Result := CompareText(TSong(Song1).Artist, TSong(Song2).Artist);
+ Result := UTF8CompareText(TSong(Song1).Artist, TSong(Song2).Artist);
end;
function CompareByFolder(Song1, Song2: Pointer): integer;
begin
- Result := CompareText(TSong(Song1).Folder, TSong(Song2).Folder);
+ Result := UTF8CompareText(TSong(Song1).Folder, TSong(Song2).Folder);
end;
function CompareByLanguage(Song1, Song2: Pointer): integer;
begin
- Result := CompareText(TSong(Song1).Language, TSong(Song2).Language);
+ Result := UTF8CompareText(TSong(Song1).Language, TSong(Song2).Language);
end;
-procedure TSongs.Sort(Order: integer);
+procedure TSongs.Sort(Order: TSortingType);
var
CompareFunc: TListSortCompare;
begin
@@ -394,8 +410,6 @@ begin
CompareFunc := CompareByArtist;
sFolder: // by folder
CompareFunc := CompareByFolder;
- sTitle2: // by title2
- CompareFunc := CompareByTitle;
sArtist2: // by artist2
CompareFunc := CompareByArtist;
sLanguage: // by Language
@@ -412,21 +426,9 @@ begin
MergeSort(SongList, CompareFunc);
end;
-function TSongs.FindSongFile(Dir, Mask: widestring): widestring;
-var
- SR: TSearchRec; // for parsing song directory
-begin
- Result := '';
- if FindFirst(Dir + Mask, faDirectory, SR) = 0 then
- begin
- Result := SR.Name;
- end; // if
- FindClose(SR);
-end;
-
procedure TCatSongs.SortSongs();
begin
- case Ini.Sorting of
+ case TSortingType(Ini.Sorting) of
sEdition: begin
Songs.Sort(sTitle);
Songs.Sort(sArtist);
@@ -454,12 +456,8 @@ begin
Songs.Sort(sTitle);
Songs.Sort(sArtist);
end;
- sTitle2: begin
- Songs.Sort(sArtist2);
- Songs.Sort(sTitle2);
- end;
sArtist2: begin
- Songs.Sort(sTitle2);
+ Songs.Sort(sTitle);
Songs.Sort(sArtist2);
end;
end; // case
@@ -469,14 +467,14 @@ procedure TCatSongs.Refresh;
var
SongIndex: integer;
CurSong: TSong;
- CatIndex: integer; // index of current song in Song
- Letter: char; // current letter for sorting using letter
- CurCategory: string; // current edition for sorting using edition, genre etc.
- Order: integer; // number used for ordernum
- LetterTmp: char;
- CatNumber: integer; // Number of Song in Category
-
- procedure AddCategoryButton(const CategoryName: string);
+ 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
@@ -488,7 +486,7 @@ var
Song[CatIndex].Main := true;
Song[CatIndex].OrderTyp := 0;
Song[CatIndex].OrderNum := Order;
- Song[CatIndex].Cover := CatCovers.GetCover(Ini.Sorting, CategoryName);
+ Song[CatIndex].Cover := CatCovers.GetCover(TSortingType(Ini.Sorting), CategoryName);
Song[CatIndex].Visible := true;
// set number of songs in previous category
@@ -511,7 +509,7 @@ begin
// 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;
+ Letter := 0;
// clear song-list
for SongIndex := 0 to Songs.SongList.Count - 1 do
@@ -530,101 +528,102 @@ begin
// if tabs are on, add section buttons for each new section
if (Ini.Tabs = 1) then
begin
- if (Ini.Sorting = sEdition) and
- (CompareText(CurCategory, CurSong.Edition) <> 0) then
- begin
- CurCategory := CurSong.Edition;
-
- // TODO: remove this block if it is not needed anymore
- {
- if CurSection = 'Singstar Part 2' then CoverName := 'Singstar';
- if CurSection = 'Singstar German' then CoverName := 'Singstar';
- if CurSection = 'Singstar Spanish' then CoverName := 'Singstar';
- if CurSection = 'Singstar Italian' then CoverName := 'Singstar';
- if CurSection = 'Singstar French' then CoverName := 'Singstar';
- if CurSection = 'Singstar 80s Polish' then CoverName := 'Singstar 80s';
- }
-
- // add Category Button
- AddCategoryButton(CurCategory);
- end
-
- else if (Ini.Sorting = sGenre) and
- (CompareText(CurCategory, CurSong.Genre) <> 0) then
- begin
- CurCategory := CurSong.Genre;
- // add Genre Button
- AddCategoryButton(CurCategory);
- end
-
- else if (Ini.Sorting = sLanguage) and
- (CompareText(CurCategory, CurSong.Language) <> 0) then
- begin
- CurCategory := CurSong.Language;
- // add Language Button
- AddCategoryButton(CurCategory);
- end
-
- else if (Ini.Sorting = sTitle) and
- (Length(CurSong.Title) >= 1) and
- (Letter <> UpperCase(CurSong.Title)[1]) then
- begin
- Letter := Uppercase(CurSong.Title)[1];
- // add a letter Category Button
- AddCategoryButton(Letter);
- end
+ 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;
- else if (Ini.Sorting = sArtist) and
- (Length(CurSong.Artist) >= 1) and
- (Letter <> UpperCase(CurSong.Artist)[1]) then
- begin
- Letter := UpperCase(CurSong.Artist)[1];
- // add a letter Category Button
- AddCategoryButton(Letter);
- end
+ sGenre: begin
+ if (CompareText(CurCategory, CurSong.Genre) <> 0) then
+ begin
+ CurCategory := CurSong.Genre;
+ // add Genre Button
+ AddCategoryButton(CurCategory);
+ end;
+ end;
- else if (Ini.Sorting = sFolder) and
- (CompareText(CurCategory, CurSong.Folder) <> 0) then
- begin
- CurCategory := CurSong.Folder;
- // add folder tab
- AddCategoryButton(CurCategory);
- end
+ sLanguage: begin
+ if (CompareText(CurCategory, CurSong.Language) <> 0) then
+ begin
+ CurCategory := CurSong.Language;
+ // add Language Button
+ AddCategoryButton(CurCategory);
+ end
+ end;
- else if (Ini.Sorting = sTitle2) and
- (Length(CurSong.Title) >= 1) then
- begin
- // pack all numbers into a category named '#'
- if (CurSong.Title[1] >= '0') and (CurSong.Title[1] <= '9') then
- LetterTmp := '#'
- else
- LetterTmp := UpperCase(CurSong.Title)[1];
+ 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;
- if (Letter <> LetterTmp) then
- begin
- Letter := LetterTmp;
- // add a letter Category Button
- AddCategoryButton(Letter);
+ 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;
- end
- else if (Ini.Sorting = sArtist2) and
- (Length(CurSong.Artist)>=1) then
- begin
- // pack all numbers into a category named '#'
- if (CurSong.Artist[1] >= '0') and (CurSong.Artist[1] <= '9') then
- LetterTmp := '#'
- else
- LetterTmp := UpperCase(CurSong.Artist)[1];
+ sFolder: begin
+ if (UTF8CompareText(CurCategory, CurSong.Folder) <> 0) then
+ begin
+ CurCategory := CurSong.Folder;
+ // add folder tab
+ AddCategoryButton(CurCategory);
+ end;
+ end;
- if (Letter <> LetterTmp) then
- begin
- Letter := LetterTmp;
- // add a letter Category Button
- AddCategoryButton(Letter);
+ 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;
- end;
+
+ end; // case (Ini.Sorting)
+ end; // if (Ini.Tabs = 1)
CatIndex := Length(Song);
SetLength(Song, CatIndex+1);
@@ -728,14 +727,18 @@ var
I: integer;
begin
Result := -1;
- I := SearchFrom + 1;
- while not CatSongs.Song[I].Visible do
+ I := SearchFrom;
+ while (Result = -1) do
begin
Inc (I);
- if (I>high(CatSongs.Song)) then
- I := low(CatSongs.Song);
+
+ if (I > High(CatSongs.Song)) then
+ I := Low(CatSongs.Song);
if (I = SearchFrom) then // Make One Round and no song found->quit
- break;
+ Break;
+
+ if (CatSongs.Song[I].Visible) then
+ Result := I;
end;
end;
// Wrong song selected when tabs on bug End
@@ -771,58 +774,58 @@ begin
end;
end;
-function TCatSongs.SetFilter(FilterStr: string; const fType: byte): cardinal;
+function TCatSongs.SetFilter(FilterStr: UTF8String; Filter: TSongFilter): cardinal;
var
I, J: integer;
- cString: string;
- SearchStr: array of string;
+ TmpString: UTF8String;
+ WordArray: array of UTF8String;
begin
-{
- fType: 0: All
- 1: Title
- 2: Artist
-}
FilterStr := Trim(FilterStr);
- if FilterStr<>'' then
+ if (FilterStr <> '') then
begin
Result := 0;
- // Create Search Array
- SetLength(SearchStr, 1);
+
+ // initialize word array
+ SetLength(WordArray, 1);
+
+ // Copy words to SearchStr
I := Pos(' ', FilterStr);
while (I <> 0) do
begin
- SetLength(SearchStr, Length(SearchStr) + 1);
- cString := Copy(FilterStr, 1, I - 1);
- if (cString <> ' ') and (cString <> '') then
- SearchStr[High(SearchStr) - 1] := cString;
- Delete (FilterStr, 1, I);
+ WordArray[High(WordArray)] := Copy(FilterStr, 1, I-1);
+ SetLength(WordArray, Length(WordArray) + 1);
- I := Pos (' ', FilterStr);
+ FilterStr := TrimLeft(Copy(FilterStr, I+1, Length(FilterStr)-I));
+ I := Pos(' ', FilterStr);
end;
- // Copy last Word
- if (FilterStr <> ' ') and (FilterStr <> '') then
- SearchStr[High(SearchStr)] := FilterStr;
+
+ // Copy last word
+ WordArray[High(WordArray)] := FilterStr;
for I := 0 to High(Song) do
begin
if not Song[i].Main then
begin
- case fType of
- 0: cString := Song[I].Artist + ' ' + Song[i].Title + ' ' + Song[i].Folder;
- 1: cString := Song[I].Title;
- 2: cString := Song[I].Artist;
+ 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(SearchStr) do
+ Song[i].Visible := true;
+ // Look for every searched word
+ for J := 0 to High(WordArray) do
begin
- Song[i].Visible := Song[i].Visible and AnsiContainsText(cString, SearchStr[J])
+ 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;
+ Song[i].Visible := false;
end;
CatNumShow := -2;
end
@@ -830,7 +833,7 @@ begin
begin
for i := 0 to High(Song) do
begin
- Song[i].Visible := (Ini.Tabs=1) = Song[i].Main;
+ Song[i].Visible := (Ini.Tabs = 1) = Song[i].Main;
CatNumShow := -1;
end;
Result := 0;
diff --git a/cmake/src/base/UTextEncoding.pas b/cmake/src/base/UTextEncoding.pas
index 6eec8eec..0c9ba4cc 100644
--- a/cmake/src/base/UTextEncoding.pas
+++ b/cmake/src/base/UTextEncoding.pas
@@ -19,8 +19,8 @@
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
- * $URL: https://ultrastardx.svn.sourceforge.net/svnroot/ultrastardx/trunk/src/menu/UMenuText.pas $
- * $Id: UMenuText.pas 1485 2008-10-28 20:16:05Z tobigun $
+ * $URL$
+ * $Id$
*}
unit UTextEncoding;
@@ -34,114 +34,215 @@ interface
{$I switches.inc}
uses
- SysUtils;
+ SysUtils,
+ UUnicodeUtils;
type
- TEncoding = (encCP1250, encCP1252, encUTF8, encNative);
+ 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;
-function RecodeString(const Src: string; SrcEncoding: TEncoding): WideString;
+{**
+ * 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
- TConversionTable = array[0..127] of WideChar;
+ 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
- // Windows-1250 Central/Eastern Europe (used by Ultrastar)
- CP1250Table: TConversionTable = (
- { $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
- );
+ ERROR_CHAR = '?';
- // Windows-1252 Western Europe (used by UltraStar Deluxe < 1.1)
- CP1252Table: TConversionTable = (
- { $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,
- { $A0 }
- #$00A0, #$00A1, #$00A2, #$00A3, #$00A4, #$00A5, #$00A6, #$00A7,
- #$00A8, #$00A9, #$00AA, #$00AB, #$00AC, #$00AD, #$00AE, #$00AF,
- { $B0 }
- #$00B0, #$00B1, #$00B2, #$00B3, #$00B4, #$00B5, #$00B6, #$00B7,
- #$00B8, #$00B9, #$00BA, #$00BB, #$00BC, #$00BD, #$00BE, #$00BF,
- { $C0 }
- #$00C0, #$00C1, #$00C2, #$00C3, #$00C4, #$00C5, #$00C6, #$00C7,
- #$00C8, #$00C9, #$00CA, #$00CB, #$00CC, #$00CD, #$00CE, #$00CF,
- { $D0 }
- #$00D0, #$00D1, #$00D2, #$00D3, #$00D4, #$00D5, #$00D6, #$00D7,
- #$00D8, #$00D9, #$00DA, #$00DB, #$00DC, #$00DD, #$00DE, #$00DF,
- { $E0 }
- #$00E0, #$00E1, #$00E2, #$00E3, #$00E4, #$00E5, #$00E6, #$00E7,
- #$00E8, #$00E9, #$00EA, #$00EB, #$00EC, #$00ED, #$00EE, #$00EF,
- { $F0 }
- #$00F0, #$00F1, #$00F2, #$00F3, #$00F4, #$00F5, #$00F6, #$00F7,
- #$00F8, #$00F9, #$00FA, #$00FB, #$00FC, #$00FD, #$00FE, #$00FF
- );
+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 Convert(const Src: string; const Table: TConversionTable): WideString;
+function TSingleByteEncoder.Decode(const InStr: RawByteString; out OutStr: UCS4String): boolean;
var
- SrcPos, DstPos: integer;
+ I: integer;
begin
- SetLength(Result, Length(Src));
- DstPos := 1;
- for SrcPos := 1 to Length(Src) do
+ SetLength(OutStr, Length(InStr)+1);
+ Result := true;
+ for I := 1 to Length(InStr) do
begin
- if (Src[SrcPos] < #128) then
- begin
- // copy ASCII char
- Result[DstPos] := Src[SrcPos];
- Inc(DstPos);
- end
- else
+ 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
- // look-up char
- Result[DstPos] := Table[Ord(Src[SrcPos]) - 128];
- // ignore invalid characters
- if (Result[DstPos] <> #0) then
- Inc(DstPos);
+ Result := Encoding;
+ Exit;
end;
end;
- SetLength(Result, DstPos-1);
+ Result := Default;
end;
-function RecodeString(const Src: string; SrcEncoding: TEncoding): WideString;
+function EncodingName(Encoding: TEncoding): AnsiString;
begin
- case SrcEncoding of
- encCP1250:
- Result := Convert(Src, CP1250Table);
- encCP1252:
- Result := Convert(Src, CP1252Table);
- encUTF8:
- Result := UTF8Decode(Src);
- encNative:
- Result := UTF8Decode(AnsiToUtf8(Src));
- end;
+ 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/cmake/src/base/UTexture.pas b/cmake/src/base/UTexture.pas
index 97f244fe..c1334dd7 100644
--- a/cmake/src/base/UTexture.pas
+++ b/cmake/src/base/UTexture.pas
@@ -40,6 +40,7 @@ uses
Classes,
SysUtils,
UCommon,
+ UPath,
SDL,
SDL_Image;
@@ -66,7 +67,7 @@ type
TexX2: real;
TexY2: real;
Alpha: real;
- Name: string; // experimental for handling cache images. maybe it's useful for dynamic skins
+ Name: IPath; // experimental for handling cache images. maybe it's useful for dynamic skins
end;
type
@@ -91,7 +92,7 @@ procedure AdjustPixelFormat(var TexSurface: PSDL_Surface; Typ: TTextureType);
type
PTextureEntry = ^TTextureEntry;
TTextureEntry = record
- Name: string;
+ Name: IPath;
Typ: TTextureType;
Color: cardinal;
@@ -105,7 +106,7 @@ type
Texture: array of TTextureEntry;
public
procedure AddTexture(var Tex: TTexture; Typ: TTextureType; Color: cardinal; Cache: boolean);
- function FindTexture(const Name: string; Typ: TTextureType; Color: cardinal): integer;
+ function FindTexture(const Name: IPath; Typ: TTextureType; Color: cardinal): integer;
end;
TTextureUnit = class
@@ -116,14 +117,14 @@ type
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: string; Typ: TTextureType; FromCache: boolean = false): TTexture; overload;
- function GetTexture(const Name: string; Typ: TTextureType; Col: LongWord; FromCache: boolean = false): TTexture; overload;
- function LoadTexture(FromRegistry: boolean; const Identifier: string; Typ: TTextureType; Col: LongWord): TTexture; overload;
- function LoadTexture(const Identifier: string; Typ: TTextureType; Col: LongWord): TTexture; overload;
- function LoadTexture(const Identifier: string): TTexture; overload;
- function CreateTexture(Data: PChar; const Name: string; Width, Height: word; BitsPerPixel: byte): TTexture;
- procedure UnloadTexture(const Name: string; Typ: TTextureType; FromCache: boolean); overload;
- procedure UnloadTexture(const Name: string; Typ: TTextureType; Col: cardinal; FromCache: boolean); 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;
@@ -188,7 +189,7 @@ begin
Texture[TextureIndex].Texture := Tex;
end;
-function TTextureDatabase.FindTexture(const Name: string; Typ: TTextureType; Color: cardinal): integer;
+function TTextureDatabase.FindTexture(const Name: IPath; Typ: TTextureType; Color: cardinal): integer;
var
TextureIndex: integer;
CurrentTexture: PTextureEntry;
@@ -197,7 +198,7 @@ begin
for TextureIndex := 0 to High(Texture) do
begin
CurrentTexture := @Texture[TextureIndex];
- if (CurrentTexture.Name = Name) and
+ if (CurrentTexture.Name.Equals(Name)) and
(CurrentTexture.Typ = Typ) then
begin
// colorized textures must match in their color too
@@ -235,18 +236,18 @@ begin
TextureDatabase.AddTexture(Tex, Typ, Color, Cache);
end;
-function TTextureUnit.LoadTexture(FromRegistry: boolean; const Identifier: string; Typ: TTextureType; Col: LongWord): TTexture;
+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: string): TTexture;
+function TTextureUnit.LoadTexture(const Identifier: IPath): TTexture;
begin
Result := LoadTexture(Identifier, TEXTURE_TYPE_PLAIN, 0);
end;
-function TTextureUnit.LoadTexture(const Identifier: string; Typ: TTextureType; Col: LongWord): TTexture;
+function TTextureUnit.LoadTexture(const Identifier: IPath; Typ: TTextureType; Col: LongWord): TTexture;
var
TexSurface: PSDL_Surface;
newWidth, newHeight: integer;
@@ -260,7 +261,7 @@ begin
TexSurface := LoadImage(Identifier);
if not assigned(TexSurface) then
begin
- Log.LogError('Could not load texture: "' + Identifier +'" with type "'+ TextureTypeToStr(Typ) +'"',
+ Log.LogError('Could not load texture: "' + Identifier.ToNative +'" with type "'+ TextureTypeToStr(Typ) +'"',
'TTextureUnit.LoadTexture');
Exit;
end;
@@ -363,16 +364,16 @@ begin
SDL_FreeSurface(TexSurface);
end;
-function TTextureUnit.GetTexture(const Name: string; Typ: TTextureType; FromCache: boolean): TTexture;
+function TTextureUnit.GetTexture(const Name: IPath; Typ: TTextureType; FromCache: boolean): TTexture;
begin
Result := GetTexture(Name, Typ, 0, FromCache);
end;
-function TTextureUnit.GetTexture(const Name: string; Typ: TTextureType; Col: LongWord; FromCache: boolean): TTexture;
+function TTextureUnit.GetTexture(const Name: IPath; Typ: TTextureType; Col: LongWord; FromCache: boolean): TTexture;
var
TextureIndex: integer;
begin
- if (Name = '') then
+ if (Name.IsUnset) then
begin
// zero texture data
FillChar(Result, SizeOf(Result), 0);
@@ -413,7 +414,7 @@ begin
Result := TextureDatabase.Texture[TextureIndex].Texture;
end;
-function TTextureUnit.CreateTexture(Data: PChar; const Name: string; Width, Height: word; BitsPerPixel: byte): TTexture;
+function TTextureUnit.CreateTexture(Data: PChar; const Name: IPath; Width, Height: word; BitsPerPixel: byte): TTexture;
var
//Error: integer;
ActTex: GLuint;
@@ -467,12 +468,12 @@ begin
Result.Name := Name;
end;
-procedure TTextureUnit.UnloadTexture(const Name: string; Typ: TTextureType; FromCache: boolean);
+procedure TTextureUnit.UnloadTexture(const Name: IPath; Typ: TTextureType; FromCache: boolean);
begin
UnloadTexture(Name, Typ, 0, FromCache);
end;
-procedure TTextureUnit.UnloadTexture(const Name: string; Typ: TTextureType; Col: cardinal; FromCache: boolean);
+procedure TTextureUnit.UnloadTexture(const Name: IPath; Typ: TTextureType; Col: cardinal; FromCache: boolean);
var
T: integer;
TexNum: GLuint;
@@ -539,7 +540,8 @@ begin
Exit;
end;
end;
- Log.LogWarn('Unknown texture type: "' + TypeStr + '". Using default texture type "' + TextureTypeToStr(Default) + '"', 'ParseTextureType');
+ Log.LogInfo('Unknown texture type: "' + TypeStr + '". Using default texture type "'
+ + TextureTypeToStr(Default) + '"', 'UTexture.ParseTextureType');
Result := Default;
end;
diff --git a/cmake/src/base/UThemes.pas b/cmake/src/base/UThemes.pas
index 3fd77853..b385406f 100644
--- a/cmake/src/base/UThemes.pas
+++ b/cmake/src/base/UThemes.pas
@@ -34,11 +34,12 @@ interface
{$I switches.inc}
uses
- ULog,
IniFiles,
SysUtils,
Classes,
- UTexture;
+ ULog,
+ UTexture,
+ UPath;
type
TRGB = record
@@ -112,7 +113,7 @@ type
Font: integer;
Size: integer;
Align: integer;
- Text: string;
+ Text: UTF8String;
//Reflection
Reflection: boolean;
ReflectionSpacing: real;
@@ -169,7 +170,9 @@ type
TThemeSelectSlide = record
Tex: string;
+ Typ: TTextureType;
TexSBG: string;
+ TypSBG: TTextureType;
X: integer;
Y: integer;
W: integer;
@@ -182,7 +185,7 @@ type
showArrows:boolean;
oneItemOnly:boolean;
- Text: string;
+ Text: UTF8String;
ColR, ColG, ColB, Int: real;
DColR, DColG, DColB, DInt: real;
TColR, TColG, TColB, TInt: real;
@@ -215,7 +218,7 @@ type
TThemeBasic = class
Background: TThemeBackground;
Text: AThemeText;
- Static: AThemeStatic;
+ Statics: AThemeStatic;
//Button Collection Mod
ButtonCollection: AThemeButtonCollection;
@@ -236,8 +239,8 @@ type
TextDescription: TThemeText;
TextDescriptionLong: TThemeText;
- Description: array[0..5] of string;
- DescriptionLong: array[0..5] of string;
+ Description: array[0..5] of UTF8String;
+ DescriptionLong: array[0..5] of UTF8String;
end;
TThemeName = class(TThemeBasic)
@@ -354,7 +357,7 @@ type
TextP3RScore: TThemeText;
//Linebonus Translations
- LineBonusText: array [0..8] of string;
+ LineBonusText: array [0..8] of UTF8String;
//Pause Popup
PausePopUp: TThemeStatic;
@@ -396,6 +399,7 @@ type
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;
@@ -408,6 +412,7 @@ type
TextNumber: AThemeText;
TextName: AThemeText;
TextScore: AThemeText;
+ TextDate: AThemeText;
end;
TThemeOptions = class(TThemeBasic)
@@ -421,7 +426,7 @@ type
ButtonExit: TThemeButton;
TextDescription: TThemeText;
- Description: array[0..7] of string;
+ Description: array[0..7] of UTF8String;
end;
TThemeOptionsGame = class(TThemeBasic)
@@ -496,8 +501,8 @@ type
TextDescription: TThemeText;
TextDescriptionLong: TThemeText;
- Description: array[0..5] of string;
- DescriptionLong: array[0..5] of string;
+ Description: array[0..5] of UTF8string;
+ DescriptionLong: array[0..5] of UTF8string;
end;
//Error- and Check-Popup
@@ -531,10 +536,10 @@ type
TextFound: TThemeText;
//Translated Texts
- Songsfound: string;
- NoSongsfound: string;
- CatText: string;
- IType: array [0..2] of string;
+ Songsfound: UTF8String;
+ NoSongsfound: UTF8String;
+ CatText: UTF8String;
+ IType: array [0..2] of UTF8String;
end;
//Party Screens
@@ -646,17 +651,17 @@ type
SelectLevel: TThemeSelectSlide;
SelectPlayList: TThemeSelectSlide;
SelectPlayList2: TThemeSelectSlide;
- SelectRounds: TThemeSelectSlide;
- SelectTeams: TThemeSelectSlide;
- SelectPlayers1: TThemeSelectSlide;
- SelectPlayers2: TThemeSelectSlide;
- SelectPlayers3: TThemeSelectSlide;
{ButtonNext: TThemeButton;
ButtonPrev: TThemeButton;}
end;
TThemePartyPlayer = class(TThemeBasic)
+ SelectTeams: TThemeSelectSlide;
+ SelectPlayers1: TThemeSelectSlide;
+ SelectPlayers2: TThemeSelectSlide;
+ SelectPlayers3: TThemeSelectSlide;
+
Team1Name: TThemeButton;
Player1Name: TThemeButton;
Player2Name: TThemeButton;
@@ -679,6 +684,11 @@ type
ButtonPrev: TThemeButton;}
end;
+ TThemePartyRounds = class(TThemeBasic)
+ SelectRoundCount: TThemeSelectSlide;
+ SelectRound: array [0..6] of TThemeSelectSlide;
+ end;
+
//Stats Screens
TThemeStatMain = class(TThemeBasic)
ButtonScores: TThemeButton;
@@ -700,15 +710,22 @@ type
TextPage: TThemeText;
TextList: AThemeText;
- Description: array[0..3] of string;
- DescriptionR: array[0..3] of string;
- FormatStr: array[0..3] of string;
- PageStr: string;
+ 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: string;
+ CatText: UTF8String;
+ end;
+
+ TThemeEntry = record
+ Name: string;
+ Filename: IPath;
+ DefaultSkin: integer;
+ Creator: string;
end;
TTheme = class
@@ -721,8 +738,9 @@ type
LastThemeBasic: TThemeBasic;
procedure CreateThemeObjects();
-
+ procedure LoadHeader(FileName: IPath);
public
+ Themes: array of TThemeEntry;
Loading: TThemeLoading;
Main: TThemeMain;
Name: TThemeName;
@@ -754,6 +772,7 @@ type
PartyWin: TThemePartyWin;
PartyOptions: TThemePartyOptions;
PartyPlayer: TThemePartyPlayer;
+ PartyRounds: TThemePartyRounds;
//Stats Screens:
StatMain: TThemeStatMain;
@@ -761,11 +780,13 @@ type
Playlist: TThemePlaylist;
- ILevel: array[0..2] of string;
+ ILevel: array[0..2] of UTF8String;
+
+ constructor Create;
- constructor Create(const FileName: string); overload; // Initialize theme system
- constructor Create(const FileName: string; Color: integer); overload; // Initialize theme system with color
- function LoadTheme(FileName: string; sColor: integer): boolean; // Load some theme settings from file
+ procedure LoadList;
+
+ function LoadTheme(ThemeNum: integer; sColor: integer): boolean; // Load some theme settings from file
procedure LoadColors;
@@ -818,9 +839,13 @@ uses
ULanguage,
USkins,
UIni,
+ UPathUtils,
+ UFileSystem,
+ TextGL,
gl,
glext,
- math;
+ math,
+ StrUtils;
//-----------
//Helper procs to use TRGB in Opengl ...maybe this should be somewhere else
@@ -845,12 +870,7 @@ begin
glColor4f(Color.R, Color.G, Color.B, Min(Color.A, Alpha));
end;
-constructor TTheme.Create(const FileName: string);
-begin
- Create(FileName, 0);
-end;
-
-constructor TTheme.Create(const FileName: string; Color: integer);
+constructor TTheme.Create;
begin
inherited Create();
@@ -884,16 +904,89 @@ begin
PartyScore := TThemePartyScore.Create;
PartyOptions := TThemePartyOptions.Create;
PartyPlayer := TThemePartyPlayer.Create;
+ PartyRounds := TThemePartyRounds.Create;
//Stats Screens:
StatMain := TThemeStatMain.Create;
StatDetail := TThemeStatDetail.Create;
- LoadTheme(FileName, Color);
+ //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(FileName: string; sColor: integer): boolean;
+function TTheme.LoadTheme(ThemeNum: integer; sColor: integer): boolean;
var
I: integer;
begin
@@ -901,23 +994,21 @@ begin
CreateThemeObjects();
- Log.LogStatus('Loading: '+ FileName, 'TTheme.LoadTheme');
+ Log.LogStatus('Loading: '+ Themes[ThemeNum].FileName.ToNative, 'TTheme.LoadTheme');
- FileName := AdaptFilePaths(FileName);
-
- if not FileExists(FileName) then
+ if not Themes[ThemeNum].FileName.IsFile() then
begin
- Log.LogError('Theme does not exist ('+ FileName +')', 'TTheme.LoadTheme');
+ Log.LogError('Theme does not exist ('+ Themes[ThemeNum].FileName.ToNative +')', 'TTheme.LoadTheme');
end;
- if FileExists(FileName) then
+ if Themes[ThemeNum].FileName.IsFile() then
begin
Result := true;
{$IFDEF THEMESAVE}
- ThemeIni := TIniFile.Create(FileName);
+ ThemeIni := TIniFile.Create(Themes[ThemeNum].FileName.ToNative);
{$ELSE}
- ThemeIni := TMemIniFile.Create(FileName);
+ ThemeIni := TMemIniFile.Create(Themes[ThemeNum].FileName.ToNative);
{$ENDIF}
if ThemeIni.ReadString('Theme', 'Name', '') <> '' then
@@ -1164,6 +1255,7 @@ begin
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;
@@ -1177,6 +1269,7 @@ begin
ThemeLoadTexts(Top5.TextNumber, 'Top5TextNumber');
ThemeLoadTexts(Top5.TextName, 'Top5TextName');
ThemeLoadTexts(Top5.TextScore, 'Top5TextScore');
+ ThemeLoadTexts(Top5.TextDate, 'Top5TextDate');
// Options
ThemeLoadBasic(Options, 'Options');
@@ -1434,17 +1527,17 @@ begin
ThemeLoadSelectSlide(PartyOptions.SelectLevel, 'PartyOptionsSelectLevel');
ThemeLoadSelectSlide(PartyOptions.SelectPlayList, 'PartyOptionsSelectPlayList');
ThemeLoadSelectSlide(PartyOptions.SelectPlayList2, 'PartyOptionsSelectPlayList2');
- ThemeLoadSelectSlide(PartyOptions.SelectRounds, 'PartyOptionsSelectRounds');
- ThemeLoadSelectSlide(PartyOptions.SelectTeams, 'PartyOptionsSelectTeams');
- ThemeLoadSelectSlide(PartyOptions.SelectPlayers1, 'PartyOptionsSelectPlayers1');
- ThemeLoadSelectSlide(PartyOptions.SelectPlayers2, 'PartyOptionsSelectPlayers2');
- ThemeLoadSelectSlide(PartyOptions.SelectPlayers3, 'PartyOptionsSelectPlayers3');
-
{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');
@@ -1463,6 +1556,13 @@ begin
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');}
@@ -1524,7 +1624,7 @@ procedure TTheme.ThemeLoadBasic(Theme: TThemeBasic; const Name: string);
begin
ThemeLoadBackground(Theme.Background, Name);
ThemeLoadTexts(Theme.Text, Name + 'Text');
- ThemeLoadStatics(Theme.Static, Name + 'Static');
+ ThemeLoadStatics(Theme.Statics, Name + 'Static');
ThemeLoadButtonCollections(Theme.ButtonCollection, Name + 'ButtonCollection');
LastThemeBasic := Theme;
@@ -1568,7 +1668,7 @@ begin
ThemeText.ColG := ThemeIni.ReadFloat(Name, 'ColG', 0);
ThemeText.ColB := ThemeIni.ReadFloat(Name, 'ColB', 0);
- ThemeText.Font := ThemeIni.ReadInteger(Name, 'Font', 0);
+ ThemeText.Font := ThemeIni.ReadInteger(Name, 'Font', ftNormal);
ThemeText.Size := ThemeIni.ReadInteger(Name, 'Size', 0);
ThemeText.Align := ThemeIni.ReadInteger(Name, 'Align', 0);
@@ -1773,7 +1873,9 @@ 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);
@@ -1807,6 +1909,9 @@ begin
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);
@@ -2023,15 +2128,15 @@ begin
//New Theme-Color Patch
4: begin
// violet
- Result.R := 230/255;
- Result.G := 63/255;
- Result.B := 230/255;
+ Result.R := 212/255;
+ Result.G := 71/255;
+ Result.B := 247/255;
end;
5: begin
// orange
- Result.R := 255/255;
+ Result.R := 247/255;
Result.G := 144/255;
- Result.B := 0;
+ Result.B := 71/255;
end;
6: begin
// yellow
@@ -2193,7 +2298,7 @@ begin
ThemeIni.WriteInteger(Name, 'Texts', Length(Theme.Text));
ThemeSaveBackground(Theme.Background, Name + 'Background');
- ThemeSaveStatics(Theme.Static, Name + 'Static');
+ ThemeSaveStatics(Theme.Statics, Name + 'Static');
ThemeSaveTexts(Theme.Text, Name + 'Text');
end;
diff --git a/cmake/src/base/UTime.pas b/cmake/src/base/UTime.pas
index 83844cb5..0610ef59 100644
--- a/cmake/src/base/UTime.pas
+++ b/cmake/src/base/UTime.pas
@@ -40,20 +40,26 @@ type
function GetTime(): real;
end;
+ TRelativeTimerState = (rtsStopped, rtsWait, rtsPaused, rtsRunning);
+
TRelativeTimer = class
private
AbsoluteTime: int64; // system-clock reference time for calculation of CurrentTime
- RelativeTimeOffset: real;
- Paused: boolean;
+ RelativeTime: real;
TriggerMode: boolean;
+ State: TRelativeTimerState;
public
- constructor Create(TriggerMode: boolean = false);
+ constructor Create();
+ procedure Start(WaitForTrigger: boolean = false);
procedure Pause();
- procedure Resume();
+ procedure Stop();
function GetTime(): real;
- function GetAndResetTime(): real;
- procedure SetTime(Time: real; Trigger: boolean = true);
- procedure Reset();
+ procedure SetTime(Time: real);
+ function GetState(): TRelativeTimerState;
+ end;
+
+ TSyncSource = class
+ function GetClock(): real; virtual; abstract;
end;
procedure CountSkipTimeSet;
@@ -126,85 +132,115 @@ end;
* TRelativeTimer
**}
-(*
- * creates a new timer.
- * if triggermode is false (default), the timer
- * will immediately begin with counting.
- * if triggermode is true, it will wait until get/settime() or pause() is called
- * for the first time.
+(**
+ * 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(TriggerMode: boolean);
+constructor TRelativeTimer.Create();
begin
- inherited Create();
- Self.TriggerMode := TriggerMode;
- Reset();
- Paused := false;
+ State := rtsStopped;
+ AbsoluteTime := 0;
+ RelativeTime := 0;
end;
-procedure TRelativeTimer.Pause();
+(**
+ * 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
- RelativeTimeOffset := GetTime();
- Paused := true;
+ 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;
-procedure TRelativeTimer.Resume();
+(**
+ * Pauses the timer and leaves the counter untouched.
+ *)
+procedure TRelativeTimer.Pause();
begin
- AbsoluteTime := SDL_GetTicks();
- Paused := false;
+ if (State = rtsRunning) then
+ begin
+ // Important: GetTime() must be called in running state
+ RelativeTime := GetTime();
+ State := rtsPaused;
+ end;
end;
-(*
- * Returns the counter of the timer.
- * If in TriggerMode it will return 0 and start the counter on the first call.
+(**
+ * Stops the timer and sets its counter to 0.
*)
-function TRelativeTimer.GetTime: real;
+procedure TRelativeTimer.Stop();
begin
- // initialize absolute time on first call in triggered mode
- if (TriggerMode and (AbsoluteTime = 0)) then
+ if (State <> rtsStopped) then
begin
- AbsoluteTime := SDL_GetTicks();
- Result := RelativeTimeOffset;
- Exit;
+ State := rtsStopped;
+ RelativeTime := 0;
end;
-
- if Paused then
- Result := RelativeTimeOffset
- else
- Result := RelativeTimeOffset + (SDL_GetTicks() - AbsoluteTime) / cSDLCorrectionRatio;
end;
-(*
- * Returns the counter of the timer and resets the counter to 0 afterwards.
- * Note: In TriggerMode the counter will not be stopped as with Reset().
+(**
+ * 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.GetAndResetTime(): real;
+function TRelativeTimer.GetTime(): real;
begin
- Result := GetTime();
- SetTime(0);
+ 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 timer to the given time. This will trigger in TriggerMode if
- * Trigger is set to true. Otherwise the counter's state will not change.
+(**
+ * 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; Trigger: boolean);
+procedure TRelativeTimer.SetTime(Time: real);
begin
- RelativeTimeOffset := Time;
- if ((not TriggerMode) or Trigger) then
- AbsoluteTime := SDL_GetTicks();
+ RelativeTime := Time;
+ AbsoluteTime := SDL_GetTicks();
+ // start triggered
+ if (State = rtsWait) then
+ State := rtsRunning;
end;
-(*
- * Resets the counter of the timer to 0.
- * If in TriggerMode the timer will not start counting until it is triggered again.
- *)
-procedure TRelativeTimer.Reset();
+function TRelativeTimer.GetState(): TRelativeTimerState;
begin
- RelativeTimeOffset := 0;
- if (TriggerMode) then
- AbsoluteTime := 0
- else
- AbsoluteTime := SDL_GetTicks();
+ Result := State;
end;
end.
diff --git a/cmake/src/base/UUnicodeUtils.pas b/cmake/src/base/UUnicodeUtils.pas
new file mode 100644
index 00000000..37b53a67
--- /dev/null
+++ b/cmake/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/cmake/src/base/UXMLSong.pas b/cmake/src/base/UXMLSong.pas
index 58b48789..e9751eba 100644
--- a/cmake/src/base/UXMLSong.pas
+++ b/cmake/src/base/UXMLSong.pas
@@ -34,7 +34,9 @@ interface
{$I switches.inc}
uses
- Classes;
+ Classes,
+ UPath,
+ UUnicodeUtils;
type
TNote = record
@@ -42,30 +44,30 @@ type
Duration: Cardinal;
Tone: Integer;
NoteTyp: Byte;
- Lyric: String;
+ Lyric: UTF8String;
end;
- ANote = Array of TNote;
+ ANote = array of TNote;
TSentence = record
Singer: Byte;
Duration: Cardinal;
Notes: ANote;
end;
- ASentence = Array of TSentence;
+ ASentence = array of TSentence;
- TSongInfo = Record
+ TSongInfo = record
ID: Cardinal;
DualChannel: Boolean;
- Header: Record
- Artist: String;
- Title: String;
+ Header: record
+ Artist: UTF8String;
+ Title: UTF8String;
Gap: Cardinal;
BPM: Real;
Resolution: Byte;
- Edition: String;
- Genre: String;
- Year: String;
- Language: String;
+ Edition: UTF8String;
+ Genre: UTF8String;
+ Year: UTF8String;
+ Language: UTF8String;
end;
CountSentences: Cardinal;
Sentences: ASentence;
@@ -81,23 +83,23 @@ type
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: String): Boolean;
+ function ParseLine(Line: RawByteString): Boolean;
public
SongInfo: TSongInfo;
- ErrorMessage: String;
- Edition: String;
- SingstarVersion: String;
+ ErrorMessage: string;
+ Edition: UTF8String;
+ SingstarVersion: string;
- Settings: Record
+ Settings: record
DashReplacement: Char;
end;
- Constructor Create;
+ constructor Create;
- Function ParseConfigforEdition(const Filename: String): String;
+ function ParseConfigForEdition(const Filename: IPath): String;
- Function ParseSongHeader(const Filename: String): Boolean; //Parse Song Header only
- Function ParseSong (const Filename: String): Boolean; //Parse whole Song
+ function ParseSongHeader(const Filename: IPath): Boolean; //Parse Song Header only
+ function ParseSong (const Filename: IPath): Boolean; //Parse whole Song
end;
const
@@ -114,9 +116,12 @@ const
DS_Both = 3;
implementation
-uses SysUtils, StrUtils;
-Constructor TParser.Create;
+uses
+ SysUtils,
+ StrUtils;
+
+constructor TParser.Create;
begin
inherited Create;
ErrorMessage := '';
@@ -124,19 +129,24 @@ begin
DecimalSeparator := '.';
end;
-Function TParser.ParseSong (const Filename: String): Boolean;
-var I: Integer;
+function TParser.ParseSong(const Filename: IPath): Boolean;
+var
+ I: Integer;
+ FileStream: TBinaryFileStream;
begin
Result := False;
- if FileExists(Filename) then
+ if Filename.IsFile() then
begin
- SSFile := TStringList.Create;
+ ErrorMessage := 'Can''t open melody.xml file';
+ SSFile := TStringList.Create;
+ FileStream := TBinaryFileStream.Create(Filename, fmOpenRead);
try
- ErrorMessage := 'Can''t open melody.xml file';
- SSFile.LoadFromFile(Filename);
+ SSFile.LoadFromStream(FileStream);
+
ErrorMessage := '';
Result := True;
+
I := 0;
SongInfo.CountSentences := 0;
@@ -153,7 +163,7 @@ begin
SetLength(SongInfo.Sentences, 0);
- While Result And (I < SSFile.Count) do
+ while Result and (I < SSFile.Count) do
begin
Result := ParseLine(SSFile.Strings[I]);
@@ -162,21 +172,24 @@ begin
finally
SSFile.Free;
+ FileStream.Free;
end;
end;
end;
-Function TParser.ParseSongHeader (const Filename: String): Boolean;
-var I: Integer;
+function TParser.ParseSongHeader (const Filename: IPath): Boolean;
+var
+ I: Integer;
+ Stream: TBinaryFileStream;
begin
Result := False;
- if FileExists(Filename) then
+
+ if Filename.IsFile() then
begin
SSFile := TStringList.Create;
- SSFile.Clear;
-
+ Stream := TBinaryFileStream.Create(Filename, fmOpenRead);
try
- SSFile.LoadFromFile(Filename);
+ SSFile.LoadFromStream(Stream);
If (SSFile.Count > 0) then
begin
@@ -207,6 +220,7 @@ begin
finally
SSFile.Free;
+ Stream.Free;
end;
end
else
@@ -569,18 +583,20 @@ begin
Result := true;
end;
-Function TParser.ParseConfigforEdition(const Filename: String): String;
+Function TParser.ParseConfigForEdition(const Filename: IPath): String;
var
txt: TStringlist;
+ Stream: TBinaryFileStream;
I: Integer;
J, K: Integer;
S: String;
begin
Result := '';
- txt := TStringlist.Create;
- try
- txt.LoadFromFile(Filename);
+ 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]);
@@ -600,6 +616,7 @@ begin
Edition := Result;
finally
txt.Free;
+ Stream.Free;
end;
end;
diff --git a/cmake/src/config-win.inc b/cmake/src/config-win.inc
index e3ca8840..72e00aef 100644
--- a/cmake/src/config-win.inc
+++ b/cmake/src/config-win.inc
@@ -1,4 +1,4 @@
-{*****************************************************************
+{*****************************************************************
* Configuration file for UltraStar Deluxe 1.1
*****************************************************************}
@@ -6,28 +6,28 @@
{$DEFINE HaveFFmpeg}
{$IF Defined(HaveFFmpeg) and Defined(IncludeConstants)}
- av__codec = 'avcodec-51';
- LIBAVCODEC_VERSION_MAJOR = 51;
- LIBAVCODEC_VERSION_MINOR = 16;
+ av__codec = 'avcodec-52';
+ LIBAVCODEC_VERSION_MAJOR = 52;
+ LIBAVCODEC_VERSION_MINOR = 45;
LIBAVCODEC_VERSION_RELEASE = 0;
- av__format = 'avformat-50';
- LIBAVFORMAT_VERSION_MAJOR = 50;
- LIBAVFORMAT_VERSION_MINOR = 5;
+ av__format = 'avformat-52';
+ LIBAVFORMAT_VERSION_MAJOR = 52;
+ LIBAVFORMAT_VERSION_MINOR = 46;
LIBAVFORMAT_VERSION_RELEASE = 0;
- av__util = 'avutil-49';
- LIBAVUTIL_VERSION_MAJOR = 49;
- LIBAVUTIL_VERSION_MINOR = 0;
- LIBAVUTIL_VERSION_RELEASE = 1;
+ av__util = 'avutil-50';
+ LIBAVUTIL_VERSION_MAJOR = 50;
+ LIBAVUTIL_VERSION_MINOR = 7;
+ LIBAVUTIL_VERSION_RELEASE = 0;
{$IFEND}
-{$UNDEF HaveSWScale}
+{$DEFINE HaveSWScale}
{$IF Defined(HaveSWScale) and Defined(IncludeConstants)}
sw__scale = 'swscale-0';
LIBSWSCALE_VERSION_MAJOR = 0;
- LIBSWSCALE_VERSION_MINOR = 5;
- LIBSWSCALE_VERSION_RELEASE = 0;
+ LIBSWSCALE_VERSION_MINOR = 7;
+ LIBSWSCALE_VERSION_RELEASE = 2;
{$IFEND}
{$DEFINE HaveProjectM}
@@ -53,4 +53,3 @@
LIBSAMPLERATE_VERSION_MINOR = 1;
LIBSAMPLERATE_VERSION_RELEASE = 3;
{$IFEND}
-
diff --git a/cmake/src/config.inc.in b/cmake/src/config.inc.in
index b955aa2c..7750a7aa 100644
--- a/cmake/src/config.inc.in
+++ b/cmake/src/config.inc.in
@@ -5,6 +5,10 @@
{* Libraries *}
+{$IF Defined(IncludeConstants)}
+ lua_lib_name = '@lua_LIB_NAME@';
+{$IFEND}
+
{$CMAKEDEFINE(ffmpeg_FOUND) HaveFFmpeg}
{$IF Defined(HaveFFmpeg) and Defined(IncludeConstants)}
av__codec = 'libavcodec';
@@ -47,4 +51,3 @@
{$IFEND}
{$CMAKEDEFINE(portmixer_FOUND) HavePortmixer}
-
diff --git a/cmake/src/encoding/Auto.inc b/cmake/src/encoding/Auto.inc
new file mode 100644
index 00000000..f404c2f6
--- /dev/null
+++ b/cmake/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/cmake/src/encoding/CP1250.inc b/cmake/src/encoding/CP1250.inc
new file mode 100644
index 00000000..5628156e
--- /dev/null
+++ b/cmake/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/cmake/src/encoding/CP1252.inc b/cmake/src/encoding/CP1252.inc
new file mode 100644
index 00000000..f7d3f8ea
--- /dev/null
+++ b/cmake/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/cmake/src/encoding/Locale.inc b/cmake/src/encoding/Locale.inc
new file mode 100644
index 00000000..a3cdcebc
--- /dev/null
+++ b/cmake/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/cmake/src/encoding/UTF8.inc b/cmake/src/encoding/UTF8.inc
new file mode 100644
index 00000000..43eacfbd
--- /dev/null
+++ b/cmake/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/cmake/src/lib/FreeImage/FreeBitmap.pas b/cmake/src/lib/FreeImage/FreeBitmap.pas
index 4e5f50a4..d32fb5cb 100644
--- a/cmake/src/lib/FreeImage/FreeBitmap.pas
+++ b/cmake/src/lib/FreeImage/FreeBitmap.pas
@@ -33,7 +33,7 @@ unit FreeBitmap;
{$IFDEF FPC}
{$MODE Delphi}
- {$H+} // use AnsiString
+ {$H+} // use long strings
{$ENDIF}
interface
diff --git a/cmake/src/lib/JEDI-SDL/OpenGL/Pas/glext.pas b/cmake/src/lib/JEDI-SDL/OpenGL/Pas/glext.pas
index 1fc70f8a..871247a9 100644
--- a/cmake/src/lib/JEDI-SDL/OpenGL/Pas/glext.pas
+++ b/cmake/src/lib/JEDI-SDL/OpenGL/Pas/glext.pas
@@ -4282,32 +4282,33 @@ begin
if (Pos(' ', extension) <> 0) or (extension = '') then
begin
- Result := FALSE;
+ Result := false;
Exit;
end;
if searchIn = '' then
extensions := glGetString(GL_EXTENSIONS)
else
- //StrLCopy( extensions, searchIn, StrLen(searchIn)+1 );
+ //StrLCopy(extensions, searchIn, StrLen(searchIn) + 1);
extensions := searchIn;
start := extensions;
- while TRUE do
+ while true do
begin
- where := StrPos(start, extension );
- if where = nil then Break;
- terminator := Pointer(Integer(where) + Integer( strlen( extension ) ) );
- if (where = start) or (PChar(Integer(where) - 1)^ = ' ') then
+ 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;
+ Result := true;
Exit;
end;
end;
start := terminator;
end;
- Result := FALSE;
+ Result := false;
end;
diff --git a/cmake/src/lib/JEDI-SDL/SDL/Pas/jedi-sdl.inc b/cmake/src/lib/JEDI-SDL/SDL/Pas/jedi-sdl.inc
index fed972b5..31817d24 100644
--- a/cmake/src/lib/JEDI-SDL/SDL/Pas/jedi-sdl.inc
+++ b/cmake/src/lib/JEDI-SDL/SDL/Pas/jedi-sdl.inc
@@ -332,7 +332,7 @@
{$ELSE}
{$DEFINE __OS_DOS__}
{$ENDIF}
- {$IFDEF WIN32}
+ {$IFDEF MSWINDOWS}
{$DEFINE UseWin}
{$ENDIF}
{$DEFINE HAS_TYPES}
@@ -380,13 +380,13 @@
{$OA+} // Objects and structures align
{$ENDIF}
-{$IFDEF Win32}
+{$IFDEF MSWINDOWS}
{$DEFINE OS_BigMem}
-{$ELSE Win32}
+{$ELSE MSWINDOWS}
{$IFDEF ver70}
{$DEFINE assembler}
{$ENDIF} { use 16-bit assembler! }
-{$ENDIF Win32}
+{$ENDIF MSWINDOWS}
{ ************************** dos/dos-like platforms **************}
{$IFDEF Windows}
diff --git a/cmake/src/lib/JEDI-SDL/SDL/Pas/moduleloader.pas b/cmake/src/lib/JEDI-SDL/SDL/Pas/moduleloader.pas
index ea4f220c..796aa0ab 100644
--- a/cmake/src/lib/JEDI-SDL/SDL/Pas/moduleloader.pas
+++ b/cmake/src/lib/JEDI-SDL/SDL/Pas/moduleloader.pas
@@ -59,7 +59,7 @@ interface
// each OS gets its own IFDEFed complete code block to make reading easier
-{$IFDEF WIN32}
+{$IFDEF MSWINDOWS}
uses
Windows;
diff --git a/cmake/src/lib/JEDI-SDL/SDL/Pas/sdl.pas b/cmake/src/lib/JEDI-SDL/SDL/Pas/sdl.pas
index 0d7e46af..736009c2 100644
--- a/cmake/src/lib/JEDI-SDL/SDL/Pas/sdl.pas
+++ b/cmake/src/lib/JEDI-SDL/SDL/Pas/sdl.pas
@@ -370,7 +370,7 @@ const
{$IFDEF DARWIN}
SDLLibName = 'libSDL-1.2.0.dylib';
{$linklib libSDL-1.2.0}
- {$linklib gcc}
+// {$linklib gcc}
{$linklib SDLmain}
{$linkframework Cocoa}
{$PASCALMAINNAME SDL_main}
diff --git a/cmake/src/lib/Lua/ULua.pas b/cmake/src/lib/Lua/ULua.pas
new file mode 100644
index 00000000..1de48a3c
--- /dev/null
+++ b/cmake/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/cmake/src/lib/SQLite/SQLite3.pas b/cmake/src/lib/SQLite/SQLite3.pas
index 9537606c..7b7207c4 100644
--- a/cmake/src/lib/SQLite/SQLite3.pas
+++ b/cmake/src/lib/SQLite/SQLite3.pas
@@ -10,7 +10,7 @@ unit SQLite3;
{$IFDEF FPC}
{$MODE DELPHI}
- {$H+} (* use AnsiString *)
+ {$H+} (* use long strings *)
{$PACKENUM 4} (* use 4-byte enums *)
{$PACKRECORDS C} (* C/C++-compatible record packing *)
{$ELSE}
diff --git a/cmake/src/lib/SQLite/SQLiteTable3.pas b/cmake/src/lib/SQLite/SQLiteTable3.pas
index 7df76363..3aed54a4 100644
--- a/cmake/src/lib/SQLite/SQLiteTable3.pas
+++ b/cmake/src/lib/SQLite/SQLiteTable3.pas
@@ -139,6 +139,7 @@ type
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);
@@ -759,6 +760,26 @@ begin
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);
diff --git a/cmake/src/lib/TntUnicodeControls/License.txt b/cmake/src/lib/TntUnicodeControls/License.txt
new file mode 100644
index 00000000..8ac7f75b
--- /dev/null
+++ b/cmake/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/cmake/src/lib/TntUnicodeControls/Readme.txt b/cmake/src/lib/TntUnicodeControls/Readme.txt
new file mode 100644
index 00000000..a2d8f799
--- /dev/null
+++ b/cmake/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/cmake/src/lib/TntUnicodeControls/TntClasses.pas b/cmake/src/lib/TntUnicodeControls/TntClasses.pas
new file mode 100644
index 00000000..f0ebd14c
--- /dev/null
+++ b/cmake/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/cmake/src/lib/TntUnicodeControls/TntCompilers.inc b/cmake/src/lib/TntUnicodeControls/TntCompilers.inc
new file mode 100644
index 00000000..90b51ef2
--- /dev/null
+++ b/cmake/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/cmake/src/lib/TntUnicodeControls/TntFormatStrUtils.pas b/cmake/src/lib/TntUnicodeControls/TntFormatStrUtils.pas
new file mode 100644
index 00000000..80aefd4a
--- /dev/null
+++ b/cmake/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/cmake/src/lib/TntUnicodeControls/TntSysUtils.pas b/cmake/src/lib/TntUnicodeControls/TntSysUtils.pas
new file mode 100644
index 00000000..b7cf2467
--- /dev/null
+++ b/cmake/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/cmake/src/lib/TntUnicodeControls/TntSystem.pas b/cmake/src/lib/TntUnicodeControls/TntSystem.pas
new file mode 100644
index 00000000..e613ce0c
--- /dev/null
+++ b/cmake/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/cmake/src/lib/TntUnicodeControls/TntWideStrUtils.pas b/cmake/src/lib/TntUnicodeControls/TntWideStrUtils.pas
new file mode 100644
index 00000000..99f63aea
--- /dev/null
+++ b/cmake/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/cmake/src/lib/TntUnicodeControls/TntWideStrings.pas b/cmake/src/lib/TntUnicodeControls/TntWideStrings.pas
new file mode 100644
index 00000000..75132d22
--- /dev/null
+++ b/cmake/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/cmake/src/lib/TntUnicodeControls/TntWindows.pas b/cmake/src/lib/TntUnicodeControls/TntWindows.pas
new file mode 100644
index 00000000..8fd7ec88
--- /dev/null
+++ b/cmake/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/cmake/src/lib/bass/bass.chm b/cmake/src/lib/bass/bass.chm
index 79ab64a2..8071fb0b 100644
--- a/cmake/src/lib/bass/bass.chm
+++ b/cmake/src/lib/bass/bass.chm
Binary files differ
diff --git a/cmake/src/lib/bass/bass.txt b/cmake/src/lib/bass/bass.txt
index cdaa7bf0..381519e1 100644
--- a/cmake/src/lib/bass/bass.txt
+++ b/cmake/src/lib/bass/bass.txt
@@ -1,5 +1,5 @@
BASS 2.4
-Copyright (c) 1999-2008 Un4seen Developments Ltd. All rights reserved.
+Copyright (c) 1999-2009 Un4seen Developments Ltd. All rights reserved.
Files that you should have found in the BASS package
====================================================
@@ -136,8 +136,8 @@ VB\ Visual Basic API and examples...
MODLIVESPEC.BAS
MULTI\ Multiple device example
PRJMULTI.VBP
- PRJMULTI.FRM
- PRJDEVICE.FRM
+ FRMMULTI.FRM
+ FRMDEVICE.FRM
NETRADIO\ Internet streaming example
PRJNETRADIO.VBP
FRMNETRADIO.FRM
@@ -199,6 +199,8 @@ DELPHI\ Delphi API and examples...
LIVEFX.DPR
UNIT1.PAS
UNIT1.DFM
+ LIVESPEC\ "Live" version of spectrum analyser example
+ LIVESPEC.DPR
MULTI\ Multiple device example
MULTI.DPR
UNIT1.PAS
@@ -229,6 +231,10 @@ DELPHI\ Delphi API and examples...
SPEAKERS.DPR
UNIT1.PAS
UNIT1.DFM
+ SPECTRUM\ Spectrum analyser example
+ SPECTRUM.DPR
+ UNIT1.PAS
+ COMMON.INC
STREAMTEST\ User stream example
STREAMTEST.DPR
STMAIN.PAS
@@ -281,9 +287,12 @@ CUSTLOOP\ Custom looping example
MAKEFILE
DSPTEST\ DSP example
DSPTEST.C
- DSPTEST.RC
MAKEFILE
DSPTEST.NIB
+FXTEST\ DX8 effect example
+ FXTEST.C
+ MAKEFILE
+ FXTEST.NIB
LIVESPEC\ "Live" version of spectrum analyser example
LIVESPEC.C
MAKEFILE
@@ -567,6 +576,73 @@ 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
@@ -588,7 +664,7 @@ change to the BASS interface are listed.
BASS_FILEPOS_BUFFER (BASS_StreamGetFilePosition mode)
* Sinc interpolated MOD music mixing
BASS_MUSIC_SINCINTER (BASS_MusicLoad flag)
-* MO3 v2.4 support
+* MO3 2.4 support
BASS_MusicLoad
* MOD orders positioning incorporated into channel functions
BASS_ChannelGetLength
@@ -637,7 +713,7 @@ change to the BASS interface are listed.
BASS_ChannelSetFlags *removed*
SPEAKERS example updated
* 256 sample FFT
- BASS_DATA_FFT256 (BASS_ChannelGetDat flag)
+ BASS_DATA_FFT256 (BASS_ChannelGetData flag)
* Channel locking to prevent access by other threads
BASS_ChannelLock
* Manual channel buffer updating
@@ -730,7 +806,7 @@ change to the BASS interface are listed.
BASS_ChannelStop
* Sample channels created paused to prevent overriding before playback
BASS_SampleGetChannel
-* Separate "MP3-FREE" version using Windows/OSX MP3 decoder
+* Separate "MP3-FREE" version using the OS's MP3 decoder
BASS_CONFIG_MP3_CODEC *removed*
2.3.0.1 - 12/6/2006
@@ -1458,7 +1534,7 @@ change to the BASS interface are listed.
0.8 - 24/1/2000
---------------
-* Improved MP3 performance on P2/K6 and above CPUs - fast!
+* Improved MP3 performance on P2/K6 and above CPUs
* User DSP functions on streams and MOD musics
BASS_ChannelSetDSP
BASS_ChannelRemoveDSP
@@ -1645,7 +1721,7 @@ API/Sample contributors
Visual Basic: Adam Hoult, Hendrik Knaepen, Arthur Aminov,
Peter Hebels
Delphi: Titus Miloi, Rogier Timmermans, Alessandro Cappellozza,
- Jesse Naranjo, Chris Troesken
+ Jesse Naranjo, Chris Troesken, Evgeny Melnikov
MASM: Octavian Chis
diff --git a/cmake/src/lib/bass/delphi/bass.pas b/cmake/src/lib/bass/delphi/bass.pas
index 85d10355..e87b05f5 100644
--- a/cmake/src/lib/bass/delphi/bass.pas
+++ b/cmake/src/lib/bass/delphi/bass.pas
@@ -1,12 +1,14 @@
{
BASS 2.4 Delphi unit
- Copyright (c) 1999-2008 Un4seen Developments Ltd.
+ 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;
@@ -24,12 +26,6 @@ interface
{$DEFINE DLL_CDECL}
{$ENDIF}
-// IMPORTANT: define BASS_242 when switching to 2.4.2(.1) as
-// BASS_RECORDINFO.driver was removed.
-// Otherwise BASS_RECORDINFO.freq will point to a wrong location.
-{$UNDEF BASS_242}
-
-
{$IFDEF MSWINDOWS}
uses
Windows;
@@ -40,7 +36,7 @@ const
BASSVERSIONTEXT = '2.4';
// Use these to test for error from functions that return a DWORD or QWORD
- DW_ERROR = Cardinal(-1); // -1 (DWORD)
+ DW_ERROR = LongWord(-1); // -1 (DWORD)
QW_ERROR = Int64(-1); // -1 (QWORD)
// Error codes returned by BASS_ErrorGetCode()
@@ -100,6 +96,9 @@ const
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;
@@ -113,6 +112,9 @@ const
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
@@ -229,6 +231,7 @@ const
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;
@@ -250,7 +253,6 @@ const
BASS_3DALG_FULL = 2;
BASS_3DALG_LIGHT = 3;
-{$IFDEF MSWINDOWS}
// EAX environments, use with BASS_SetEAXParameters
EAX_ENVIRONMENT_GENERIC = 0;
EAX_ENVIRONMENT_PADDEDCELL = 1;
@@ -280,7 +282,6 @@ const
EAX_ENVIRONMENT_PSYCHOTIC = 25;
// total number of environments
EAX_ENVIRONMENT_COUNT = 26;
-{$ENDIF}
BASS_STREAMPROC_END = $80000000; // end of user stream flag
@@ -359,17 +360,21 @@ const
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 Broadcast Audio Extension tags : TAG_BEXT structure
+ 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;
@@ -404,10 +409,10 @@ const
BASS_DX8_PHASE_180 = 4;
type
- DWORD = cardinal;
+ DWORD = LongWord;
BOOL = LongBool;
FLOAT = Single;
- QWORD = int64; // 64-bit (replace "int64" with "comp" if using Delphi 3)
+ QWORD = Int64;
HMUSIC = DWORD; // MOD music handle
HSAMPLE = DWORD; // sample handle
@@ -449,9 +454,6 @@ type
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
- {$IFNDEF BASS_242}
- driver: PChar; // driver
- {$ENDIF}
freq: DWORD; // current input rate (OSX only)
end;
@@ -485,7 +487,7 @@ type
origres: DWORD; // original resolution
plugin: HPLUGIN; // plugin
sample: HSAMPLE; // sample
- filename: PAnsiChar; // filename
+ filename: PChar; // filename
end;
BASS_PLUGINFORM = record
@@ -534,7 +536,7 @@ type
genre: Byte;
end;
- // BWF Broadcast Audio Extension tag structure
+ // BWF "bext" tag structure
TAG_BEXT = record
Description: Array[0..255] of AnsiChar; // description
Originator: Array[0..31] of AnsiChar; // name of the originator
@@ -548,6 +550,42 @@ type
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;
@@ -599,14 +637,14 @@ type
end;
BASS_DX8_I3DL2REVERB = record
- lRoom: Longint; // [-10000, 0] default: -1000 mB
- lRoomHF: Longint; // [-10000, 0] default: 0 mB
+ 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
+ lReflections: LongInt; // [-10000, 1000] default: -2602 mB
flReflectionsDelay: FLOAT; // [0.0, 0.3] default: 0.007 s
- lReverb: Longint; // [-10000, 2000] default: 200 mB
+ 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 %
@@ -695,6 +733,9 @@ const
{$IFDEF MSWINDOWS}
bassdll = 'bass.dll';
{$ENDIF}
+{$IFDEF LINUX}
+ bassdll = 'bass';
+{$ENDIF}
{$IFDEF DARWIN}
bassdll = 'libbass.dylib';
{$linklib libbass}
@@ -705,12 +746,12 @@ function BASS_GetConfig(option: DWORD): DWORD; {$IFDEF DLL_STDCALL}stdcall;{$END
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_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: Integer; freq, flags: DWORD; win: HWND; clsid: PGUID): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+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: Integer; freq, flags: DWORD; win: Pointer; clsid: Pointer): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL}cdecl;{$ENDIF} external bassdll;
+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;
@@ -727,7 +768,7 @@ function BASS_Pause: BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$IFDEF DLL_CDECL
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: PAnsiChar; flags: DWORD): HPLUGIN; {$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;
@@ -737,7 +778,7 @@ function BASS_Set3DPosition(var pos, vel, front, top: BASS_3DVECTOR): BOOL; {$IF
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_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}
@@ -765,14 +806,14 @@ function BASS_StreamPutData(handle: HSTREAM; buffer: Pointer; length: DWORD): DW
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_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: Integer): PAnsiChar; {$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_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;
@@ -792,7 +833,7 @@ function BASS_ChannelSetAttribute(handle, attrib: DWORD; value: FLOAT): BOOL; {$
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_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;
@@ -803,11 +844,11 @@ function BASS_ChannelGetLevel(handle: DWORD): DWORD; {$IFDEF DLL_STDCALL}stdcall
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_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: Integer): HFX; {$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;
@@ -817,7 +858,7 @@ function BASS_FXReset(handle: HFX): BOOL; {$IFDEF DLL_STDCALL}stdcall;{$ENDIF}{$
function BASS_SPEAKER_N(n: DWORD): DWORD;
{$IFDEF MSWINDOWS}
-function BASS_SetEAXPreset(env: Integer): BOOL;
+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
@@ -834,7 +875,7 @@ begin
end;
{$IFDEF MSWINDOWS}
-function BASS_SetEAXPreset(env: Integer): BOOL;
+function BASS_SetEAXPreset(env: LongInt): BOOL;
begin
case (env) of
EAX_ENVIRONMENT_GENERIC:
diff --git a/cmake/src/lib/ctypes/ctypes.pas b/cmake/src/lib/ctypes/ctypes.pas
index 6cdf77fc..694552dc 100644
--- a/cmake/src/lib/ctypes/ctypes.pas
+++ b/cmake/src/lib/ctypes/ctypes.pas
@@ -1,72 +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.
+{
+ 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/cmake/src/lib/ffmpeg/avcodec.pas b/cmake/src/lib/ffmpeg/avcodec.pas
index ceb1b7f0..7e55e13a 100644
--- a/cmake/src/lib/ffmpeg/avcodec.pas
+++ b/cmake/src/lib/ffmpeg/avcodec.pas
@@ -27,13 +27,9 @@
(*
* Conversion of libavcodec/avcodec.h
* Min. version: 51.16.0, revision 6577, Sat Oct 7 15:30:46 2006 UTC
- * Max. version: 52.11.0, revision 16912, Sun Feb 1 02:00:19 2009 UTC
+ * Max. version: 52.67.2, revision 23191, Wed May 19 19:30 2010 CET
+ *
*)
-{
- * update to
- * Max. version: 52.31.2, Sar Jun 13 22:05:00 2009 UTC
- * MiSchi
-}
unit avcodec;
@@ -63,9 +59,34 @@ uses
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 = 31;
+ LIBAVCODEC_MAX_VERSION_MINOR = 67;
LIBAVCODEC_MAX_VERSION_RELEASE = 2;
LIBAVCODEC_MAX_VERSION = (LIBAVCODEC_MAX_VERSION_MAJOR * VERSION_MAJOR) +
(LIBAVCODEC_MAX_VERSION_MINOR * VERSION_MINOR) +
@@ -173,7 +194,9 @@ type
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,
@@ -260,6 +283,33 @@ type
{$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}
//* various PCM "codecs" */
CODEC_ID_PCM_S16LE= $10000,
@@ -286,6 +336,9 @@ type
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,
@@ -390,6 +443,13 @@ type
{$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,
@@ -398,6 +458,12 @@ type
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}
(* other specific kind of codecs (generally used for attachments) *)
CODEC_ID_TTF= $18000,
@@ -416,6 +482,7 @@ const
CODEC_ID_MPEG4AAC = CODEC_ID_AAC;
{$IFEND}
+{$IF LIBAVCODEC_VERSION_MAJOR < 53} // < 53.0.0
type
TCodecType = (
CODEC_TYPE_UNKNOWN = -1,
@@ -426,6 +493,25 @@ type
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
@@ -465,6 +551,13 @@ const
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);
@@ -483,6 +576,9 @@ const
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
@@ -494,11 +590,30 @@ const
CH_FRONT_RIGHT_OF_CENTER);
CH_LAYOUT_STEREO_DOWNMIX = (CH_STEREO_LEFT or CH_STEREO_RIGHT);
-
-const
- {* in bytes *}
+{* 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
@@ -507,6 +622,7 @@ const
* MPEG bitstreams could cause overread and segfault.
*}
FF_INPUT_BUFFER_PADDING_SIZE = 8;
+{$IFEND}
{**
* minimum encoding buffer size.
@@ -676,6 +792,16 @@ const
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)
@@ -684,11 +810,11 @@ const
(* /Fx *)
(* codec capabilities *)
-const
CODEC_CAP_DRAW_HORIZ_BAND = $0001; ///< decoder can use draw_horiz_band callback
(**
- * Codec uses get_buffer() for allocating buffers.
- * direct rendering method 1
+ * 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 *)
@@ -712,6 +838,21 @@ const
*)
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}
+
//the following defines may change, don't expect compatibility if you use them
MB_TYPE_INTRA4x4 = $001;
MB_TYPE_INTRA16x16 = $002; //FIXME h264 specific
@@ -765,6 +906,9 @@ 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)
@@ -809,6 +953,9 @@ const
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 a older more strict version of the spec or reference software
@@ -854,6 +1001,9 @@ const
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;
@@ -974,11 +1124,11 @@ const
FF_COMPRESSION_DEFAULT = -1;
+{$IF LIBAVCODEC_MAX_VERSION_MAJOR < 53}
const
AVPALETTE_SIZE = 1024;
AVPALETTE_COUNT = 256;
-{$IF LIBAVCODEC_MAX_VERSION_MAJOR < 53}
type
(**
* AVPaletteControl
@@ -1054,7 +1204,7 @@ type
end;
const
- {$IF LIBAVCODEC_VERSION >= 52030002} // >= 52.30.2
+ {$IF LIBAVCODEC_VERSION < 52030002} // < 52.30.2
PKT_FLAG_KEY = $0001;
{$ELSE}
AV_PKT_FLAG_KEY = $0001;
@@ -1079,7 +1229,11 @@ type
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
@@ -1088,6 +1242,23 @@ type
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}
end;
{**
@@ -1283,7 +1454,8 @@ type
*)
dct_coeff: PsmallInt;
(**
- * motion referece frame index
+ * motion reference frame index
+ * the order in which these are stored can depend on the codec.
* - encoding: Set by user.
* - decoding: Set by libavcodec.
*)
@@ -1307,118 +1479,11 @@ type
*)
hwaccel_data_private: pointer;
{$IFEND}
+
{$IF LIBAVCODEC_VERSION >= 52022000} // >= 52.22.0
hwaccel_picture_private: pointer;
{$IFEND}
- {$IF LIBAVCODEC_VERSION >= 51070000} // >= 51.70.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}
end;
(**
@@ -1563,7 +1628,7 @@ type
* - encoding: Set by user.
* - decoding: Set by libavcodec.
*)
- sample_fmt: TSampleFormat; ///< sample format, currenly unused
+ sample_fmt: TSampleFormat; ///< sample format
(* The following data should not be initialized. *)
(**
@@ -1689,7 +1754,11 @@ type
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 *)
(**
@@ -1760,7 +1829,7 @@ type
(**
* 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_dimensions() should be used to find the required width and
+ * 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
@@ -2745,7 +2814,111 @@ type
reordered_opaque: cint64;
{$IFEND}
- {$IF LIBAVCODEC_VERSION >= 52028000} // 52.28.0
+ {$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
@@ -2753,6 +2926,95 @@ type
*)
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}
end;
(**
@@ -2760,7 +3022,11 @@ type
*)
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 *)
@@ -2815,13 +3081,23 @@ type
*)
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.
*
@@ -2983,6 +3259,9 @@ type
{$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
@@ -3005,7 +3284,7 @@ procedure av_destruct_packet(pkt: PAVPacket);
*
* @param pkt packet
*)
-procedure av_init_packet(pkt: PAVPacket);
+procedure av_init_packet(var pkt: TAVPacket);
cdecl; external av__codec;
(*
@@ -3223,6 +3502,7 @@ function avcodec_get_pix_fmt_name(pix_fmt: TAVPixelFormat): PAnsiChar;
procedure avcodec_set_dimensions(s: PAVCodecContext; width: cint; height: cint);
cdecl; external av__codec;
+{$IF LIBAVCODEC_MAX_VERSION_MAJOR < 53}
(**
* Returns the pixel format corresponding to the name name.
*
@@ -3232,12 +3512,22 @@ procedure avcodec_set_dimensions(s: PAVCodecContext; width: cint; height: cint);
* 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.
+ * 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}
-function avcodec_pix_fmt_to_codec_tag(p: TAVPixelFormat): cuint;
+(**
+ * Returns 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;
const
@@ -3390,6 +3680,20 @@ function avcodec_build(): cuint;
cdecl; external av__codec; deprecated;
{$IFEND}
+{$IF LIBAVCODEC_VERSION >= 52041000} // 52.41.0
+(**
+ * Returns the libavcodec build-time configuration.
+ *)
+function avcodec_configuration(): PAnsiChar;
+ cdecl; external av__codec;
+
+(**
+ * Returns the libavcodec license.
+ *)
+function avcodec_license(): PAnsiChar;
+ cdecl; external av__codec;
+{$IFEND}
+
(**
* Initializes libavcodec.
*
@@ -3463,8 +3767,13 @@ procedure avcodec_get_context_defaults(s: PAVCodecContext);
{$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}
(**
@@ -3480,8 +3789,29 @@ function avcodec_alloc_context(): PAVCodecContext;
{$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}
(**
@@ -3508,9 +3838,38 @@ 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
+(**
+ * Returns 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}
+
+(**
+ * Modifies 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.
+ *)
procedure avcodec_align_dimensions(s: PAVCodecContext; width: PCint; height: PCint);
cdecl; external av__codec;
+{$IF LIBAVCODEC_VERSION >= 52055000} // >= 52.55.0
+(**
+ * Modifies 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].
+ *)
+procedure avcodec_align_dimensions2(s: PAVCodecContext; width: PCint; height: PCint;
+ linesize_align: PQuadIntArray);
+ cdecl; external av__codec;
+{$IFEND}
+
(**
* Checks if the given dimension of a picture is valid, meaning that all
* bytes of the picture can be addressed with a signed int.
@@ -3529,11 +3888,10 @@ function avcodec_thread_init(s: PAVCodecContext; thread_count: cint): cint;
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;
-{$ELSE}
+{$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}
@@ -3545,6 +3903,11 @@ function avcodec_default_execute(s: PAVCodecContext; func: TExecuteFunc; arg: PP
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
(**
@@ -3595,7 +3958,7 @@ function avcodec_decode_audio(avctx: PAVCodecContext; samples: PSmallint;
*
* @deprecated Use avcodec_decode_audio3 instead.
* @param avctx the codec context
- * @param[out] samples the output buffer
+ * @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
@@ -3613,9 +3976,11 @@ function avcodec_decode_audio2(avctx: PAVCodecContext; samples: PSmallint;
(**
* Decodes 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.
+ * 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 decompressed, frame_size_ptr is zero. Otherwise, it is the
+ * 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
@@ -3638,7 +4003,7 @@ function avcodec_decode_audio2(avctx: PAVCodecContext; samples: PSmallint;
* (AltiVec and SSE do).
*
* @note Some codecs have a delay between input and output, these need to be
- * feeded with avpkt->data=NULL, avpkt->size=0 at the end to return the remaining frames.
+ * 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
@@ -3648,7 +4013,7 @@ function avcodec_decode_audio2(avctx: PAVCodecContext; samples: PSmallint;
* 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 could be decompressed.
+ * 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;
@@ -3664,6 +4029,8 @@ function avcodec_decode_audio3(avctx: PAVCodecContext; samples: PSmallint;
* @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.
* @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.
@@ -3701,7 +4068,7 @@ function avcodec_decode_video(avctx: PAVCodecContext; picture: PAVFrame;
* @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&PKT_FLAG_KEY. All decoders are designed to use the least
+ * 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
@@ -3987,9 +4354,10 @@ type
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_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;
@@ -4112,6 +4480,7 @@ function av_bitstream_filter_filter(bsfc: PAVBitStreamFilterContext;
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;
@@ -4255,6 +4624,13 @@ function img_pad(dst: PAVPicture; src: {const} PAVPicture; height, width: cint;
cdecl; external av__codec; deprecated;
{$IFEND}
+(**
+ * Encodes 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;
@@ -4286,6 +4662,13 @@ function av_parse_video_frame_rate(frame_rate: PAVRational; str: {const} PAnsiCh
cdecl; external av__codec;
{$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
@@ -4313,13 +4696,20 @@ const
{$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
-{$IF EINVAL > 0}
- AVERROR_SIGN = -1;
-{$ELSE}
- {* Some platforms have E* and errno already negated. *}
- AVERROR_SIGN = 1;
-{$IFEND}
+ AVERROR_SIGN = (EINVAL shr 30) and $00000002 - 1;
(*
#if EINVAL > 0
@@ -4347,6 +4737,35 @@ const
// 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
+(**
+ * Logs 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;
+
+(**
+ * Logs 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
(**
@@ -4396,18 +4815,15 @@ type
implementation
-{$IF (LIBAVCODEC_VERSION >= 52025000) and (LIBAVCODEC_VERSION <= 5202700)} // 52.25.0
+{$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 (pkt <> nil) then
+ if assigned(pkt) then
begin
- if (pkt.destruct <> nil) then
- pkt.destruct(pkt)
- else
- begin
- pkt.data = NULL;
- pkt.size = 0;
- end;
+ if assigned(pkt^.destruct) then
+ pkt^.destruct(pkt);
+ pkt^.data := NIL;
+ pkt^.size := 0;
end;
end;
{$IFEND}
diff --git a/cmake/src/lib/ffmpeg/avformat.pas b/cmake/src/lib/ffmpeg/avformat.pas
index 0ec2c118..b745f962 100644
--- a/cmake/src/lib/ffmpeg/avformat.pas
+++ b/cmake/src/lib/ffmpeg/avformat.pas
@@ -26,14 +26,9 @@
(*
* Conversion of libavformat/avformat.h
- * Min. version: 50.5.0 , revision 6577, Sat Oct 7 15:30:46 2006 UTC
- * Max. version: 52.25.0, revision 16986, Wed Feb 4 05:56:39 2009 UTC
+ * Min. version: 50.5.0 , revision 6577, Sat Oct 7 15:30:46 2006 UTC
+ * Max. version: 52.63.0, revision 23179, Wed May 19 19:17:00 2010 CET
*)
-{
- * update to
- * Max. version: 52.34.0, Sat Jun 13 00:37:00 2009 UTC
- * MiSchi
-}
unit avformat;
@@ -63,9 +58,34 @@ uses
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 = 34;
+ LIBAVFORMAT_MAX_VERSION_MINOR = 63;
LIBAVFORMAT_MAX_VERSION_RELEASE = 0;
LIBAVFORMAT_MAX_VERSION = (LIBAVFORMAT_MAX_VERSION_MAJOR * VERSION_MAJOR) +
(LIBAVFORMAT_MAX_VERSION_MINOR * VERSION_MINOR) +
@@ -91,19 +111,36 @@ const
{$IF LIBAVFORMAT_VERSION >= 52020000} // 52.20.0
(**
- * Returns the LIBAVFORMAT_VERSION_INT constant.
+ * 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
+(**
+ * Returns the libavformat build-time configuration.
+ *)
+function avformat_configuration(): {const} PansiChar;
+ cdecl; external av__format;
+
+(**
+ * Returns 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.
+ * 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
@@ -122,6 +159,13 @@ type
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;
@@ -133,9 +177,11 @@ type
PAVMetadata = Pointer;
{$IF LIBAVFORMAT_VERSION > 52024001} // > 52.24.1
+{$IF LIBAVFORMAT_VERSION_MAJOR = 52}
(**
* Gets 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.
*)
@@ -148,9 +194,25 @@ function av_metadata_get(m: PAVMetadata; key: {const} PAnsiChar;
* @param key tag key to add to m (will be av_strduped)
* @param value tag value to add to m (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}
+{$IFEND}
+
+{$IF LIBAVFORMAT_VERSION >= 52043000} // >= 52.43.0
+(**
+ * Sets the given tag in m, overwriting an existing tag.
+ * @param key tag key to add to m (will be av_strduped depending on flags)
+ * @param value tag value to add to m (will be av_strduped depending on flags)
+ * @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}
(**
* Frees all the memory allocated for an AVMetadata struct.
@@ -161,7 +223,7 @@ procedure av_metadata_free(var m: PAVMetadata);
(* packet functions *)
-{$IF LIBAVCODEC_VERSION < 52032000} // < 52.32.0
+{$IF LIBAVFORMAT_VERSION < 52032000} // < 52.32.0
type
PAVPacket = ^TAVPacket;
TAVPacket = record
@@ -259,7 +321,7 @@ function av_new_packet(var pkt: TAVPacket; size: cint): cint;
function av_get_packet(s: PByteIOContext; var pkt: TAVPacket; size: cint): cint;
cdecl; external av__format;
-{$IF LIBAVCODEC_VERSION < 52032000} // < 52.32.0
+{$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.
@@ -295,8 +357,8 @@ type
(** This structure contains the data a format has to probe a file. *)
TAVProbeData = record
filename: PAnsiChar;
- buf: PByteArray;
- buf_size: cint;
+ 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
@@ -316,19 +378,36 @@ const
{$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_MAJOR < 53}
MAX_STREAMS = 20;
+{$ELSE}
+ MAX_STREAMS = 100;
+{$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;
@@ -347,8 +426,20 @@ const
// used by TAVFormatContext.debug
FF_FDEBUG_TS = 0001;
- {$IF LIBAVFORMAT_VERSION >= 52034000} // > 52.34.0
+ {$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
@@ -543,11 +634,11 @@ type
(** General purpose read-only value that the format can use. *)
value: cint;
- (** Start/resume playing - only meaningful if using a network-based format
+ (** Starts/resumes 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
+ (** Pauses playing - only meaningful if using a network-based format
(RTSP). *)
read_pause: function (c: PAVFormatContext): cint; cdecl;
@@ -557,7 +648,7 @@ type
{$IF LIBAVFORMAT_VERSION >= 52030000} // 52.30.0
(**
- * Seek to timestamp ts.
+ * Seeks 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.
@@ -724,13 +815,32 @@ type
*)
reference_dts: cint64;
{$IFEND}
- {$IF LIBAVFORMAT_VERSION >= 52034000} // > 52.34.0
+ {$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;
(**
@@ -781,8 +891,9 @@ type
It is deduced from the AVStream values. *)
start_time: cint64;
(** Decoding: duration of the stream, in AV_TIME_BASE fractional
- seconds. NEVER set this value directly: it is deduced from the
- AVStream values. *)
+ 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;
@@ -804,7 +915,11 @@ type
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;
@@ -903,6 +1018,26 @@ type
{$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;
(**
@@ -1019,15 +1154,39 @@ procedure av_register_input_format(format: PAVInputFormat);
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;
+ cdecl; external av__format; deprecated;
+{$IFEND}
+(**
+ * Returns the output format in the list of registered output formats
+ * which best matches the provided parameters, or returns 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}
(**
* Guesses the codec ID based upon muxer and filename.
@@ -1038,7 +1197,7 @@ function av_guess_codec(fmt: PAVOutputFormat; short_name: PAnsiChar;
cdecl; external av__format;
(**
- * Send a nice hexadecimal dump of a buffer to the specified file stream.
+ * Sends 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
@@ -1051,7 +1210,7 @@ procedure av_hex_dump(f: PAVFile; buf: PByteArray; size: cint);
{$IF LIBAVFORMAT_VERSION >= 51011000} // 51.11.0
(**
- * Send a nice hexadecimal dump of a buffer to the log.
+ * Sends 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.
@@ -1067,7 +1226,7 @@ procedure av_hex_dump_log(avcl: Pointer; level: cint; buf: PByteArray; size: cin
{$IFEND}
(**
- * Send a nice dump of a packet to the specified file stream.
+ * Sends 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
@@ -1078,7 +1237,7 @@ procedure av_pkt_dump(f: PAVFile; pkt: PAVPacket; dump_payload: cint);
{$IF LIBAVFORMAT_VERSION >= 51011000} // 51.11.0
(**
- * Send a nice dump of a packet to the log.
+ * Sends 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.
@@ -1092,7 +1251,7 @@ procedure av_pkt_dump_log(avcl: Pointer; level: cint; pkt: PAVPacket; dump_paylo
{$IFEND}
(**
- * Initialize libavformat and register all the muxers, demuxers and
+ * Initializes libavformat and registers all the muxers, demuxers and
* protocols. If you do not call this function, then you can select
* exactly which formats you want to support.
*
@@ -1104,9 +1263,23 @@ procedure av_register_all();
cdecl; external av__format;
{$IF LIBAVFORMAT_VERSION >= 51008000} // 51.8.0
-(** codec tag <-> codec id *)
+(**
+ * Gets 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;
+
+(**
+ * Gets the 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}
@@ -1120,7 +1293,7 @@ function av_find_input_format(short_name: PAnsiChar): PAVInputFormat;
cdecl; external av__format;
(**
- * Guess file format.
+ * Guesses file format.
*
* @param is_opened Whether the file is already opened; determines whether
* demuxers with or without AVFMT_NOFILE are probed.
@@ -1128,17 +1301,33 @@ function av_find_input_format(short_name: PAnsiChar): PAVInputFormat;
function av_probe_input_format(pd: PAVProbeData; is_opened: cint): PAVInputFormat;
cdecl; external av__format;
+{$IF LIBAVFORMAT_VERSION >= 52062000} // 52.62.0
+(**
+ * Guesses 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}
+
(**
* Allocates 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(ic_ptr: PAVFormatContext;
+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
+ * Opens 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.
@@ -1156,7 +1345,7 @@ function av_open_input_file(var ic_ptr: PAVFormatContext; filename: PAnsiChar;
{$IF LIBAVFORMAT_VERSION >= 52026000} // 52.26.0
(**
- * Allocate an AVFormatContext.
+ * Allocates an AVFormatContext.
* Can be freed with av_free() but do not forget to free everything you
* explicitly allocated as well!
*)
@@ -1173,7 +1362,7 @@ function av_alloc_format_context(): PAVFormatContext;
{$IFEND}
(**
- * Read packets of a media file to get stream information. This
+ * Reads 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.
@@ -1189,7 +1378,7 @@ function av_find_stream_info(ic: PAVFormatContext): cint;
cdecl; external av__format;
(**
- * Read a transport packet from a media file.
+ * Reads a transport packet from a media file.
*
* This function is obsolete and should never be used.
* Use av_read_frame() instead.
@@ -1202,7 +1391,7 @@ function av_read_packet(s: PAVFormatContext; var pkt: TAVPacket): cint;
cdecl; external av__format;
(**
- * Return the next frame of a stream.
+ * Returns the next frame of a stream.
*
* The returned packet is valid
* until the next av_read_frame() or until av_close_input_file() and
@@ -1224,7 +1413,7 @@ function av_read_frame(s: PAVFormatContext; var pkt: TAVPacket): cint;
cdecl; external av__format;
(**
- * Seek to the keyframe at timestamp.
+ * Seeks 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
@@ -1240,7 +1429,7 @@ function av_seek_frame(s: PAVFormatContext; stream_index: cint; timestamp: cint6
{$IF LIBAVFORMAT_VERSION >= 52026000} // 52.26.0
(**
- * Seek to timestamp ts.
+ * Seeks 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.
@@ -1259,7 +1448,7 @@ function av_seek_frame(s: PAVFormatContext; stream_index: cint; timestamp: cint6
* @param ts target timestamp
* @param max_ts largest acceptable timestamp
* @param flags flags
- * @returns >=0 on success, error code otherwise
+ * @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
@@ -1275,14 +1464,14 @@ function avformat_seek_file(s: PAVFormatContext;
{$IFEND}
(**
- * Start playing a network-based stream (e.g. RTSP stream) at the
+ * Starts 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).
+ * Pauses a network-based stream (e.g. RTSP stream).
*
* Use av_read_play() to resume it.
*)
@@ -1291,7 +1480,7 @@ function av_read_pause(s: PAVFormatContext): cint;
{$IF LIBAVFORMAT_VERSION >= 52003000} // 52.3.0
(**
- * Free a AVFormatContext allocated by av_open_input_stream.
+ * Frees a AVFormatContext allocated by av_open_input_stream.
* @param s context to free
*)
procedure av_close_input_stream(s: PAVFormatContext);
@@ -1299,7 +1488,7 @@ procedure av_close_input_stream(s: PAVFormatContext);
{$IFEND}
(**
- * Close a media file (but not its codecs).
+ * Closes a media file (but not its codecs).
*
* @param s media file handle
*)
@@ -1307,7 +1496,7 @@ procedure av_close_input_file(s: PAVFormatContext);
cdecl; external av__format;
(**
- * Add a new stream to a media file.
+ * Adds 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
@@ -1325,7 +1514,7 @@ function av_new_program(s: PAVFormatContext; id: cint): PAVProgram;
{$IF LIBAVFORMAT_VERSION >= 52014000} // 52.14.0
(**
- * Add a new chapter.
+ * Adds a new chapter.
* This function is NOT part of the public API
* and should ONLY be used by demuxers.
*
@@ -1343,7 +1532,7 @@ function ff_new_chapter(s: PAVFormatContext; id: cint; time_base: TAVRational;
{$IFEND}
(**
- * Set the pts for a given stream.
+ * Sets the pts for a given stream.
*
* @param s stream
* @param pts_wrap_bits number of bits effectively used by the pts
@@ -1352,13 +1541,20 @@ function ff_new_chapter(s: PAVFormatContext; id: cint; time_base: TAVRational;
* @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;
@@ -1387,7 +1583,7 @@ procedure ff_reduce_index(s: PAVFormatContext; stream_index: cint);
{$IFEND}
(**
- * Add an index entry into a sorted list. Update the entry if the list
+ * Adds an index entry into a sorted list. Updates the entry if the list
* already contains it.
*
* @param timestamp timestamp in the timebase of the given stream
@@ -1447,7 +1643,7 @@ function av_set_parameters(s: PAVFormatContext; ap: PAVFormatParameters): cint;
cdecl; external av__format;
(**
- * Allocate the stream private data and write the stream header to an
+ * Allocates the stream private data and writes the stream header to an
* output media file.
*
* @param s media file handle
@@ -1457,7 +1653,7 @@ function av_write_header(s: PAVFormatContext): cint;
cdecl; external av__format;
(**
- * Write a packet to an output media file.
+ * Writes 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
@@ -1490,7 +1686,7 @@ function av_interleaved_write_frame(s: PAVFormatContext; var pkt: TAVPacket): ci
cdecl; external av__format;
(**
- * Interleave a packet per dts in an output media file.
+ * Interleaves 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()
@@ -1527,8 +1723,8 @@ procedure ff_interleave_add_packet(s: PAVFormatContext;
{$IFEND}
(**
- * @brief Write the stream trailer to an output media file and
- * free the file private data.
+ * Writes the stream trailer to an output media file and frees the
+ * file private data.
*
* May only be called after a successful call to av_write_header.
*
@@ -1639,7 +1835,7 @@ function av_get_frame_filename(buf: PAnsiChar; buf_size: cint;
{$IFEND};
(**
- * Check whether filename actually is a numbered sequence generator.
+ * Checks whether filename actually is a numbered sequence generator.
*
* @param filename possible numbered sequence string
* @return 1 if a valid numbered sequence string, 0 otherwise
@@ -1652,7 +1848,7 @@ function av_filename_number_test(filename: PAnsiChar): cint;
{$IF LIBAVFORMAT_VERSION >= 51012002} // 51.12.2
(**
- * Generate an SDP for an RTP session.
+ * Generates 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
@@ -1669,6 +1865,17 @@ function avf_sdp_create(ac: PPAVFormatContext; n_files: cint; buff: PByteArray;
cdecl; external av__format;
{$IFEND}
+{$IF LIBAVFORMAT_VERSION >= 52060000} // 52.60.0
+(**
+ * Returns 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
@@ -1686,7 +1893,7 @@ begin
end;
{$IFEND}
-{$IF LIBAVCODEC_VERSION < 52032000} // < 52.32.0
+{$IF LIBAVFORMAT_VERSION < 52032000} // < 52.32.0
procedure av_free_packet(pkt: PAVPacket);
begin
if ((pkt <> nil) and (@pkt^.destruct <> nil)) then
diff --git a/cmake/src/lib/ffmpeg/avio.pas b/cmake/src/lib/ffmpeg/avio.pas
index dc0a330b..4863ee39 100644
--- a/cmake/src/lib/ffmpeg/avio.pas
+++ b/cmake/src/lib/ffmpeg/avio.pas
@@ -28,11 +28,11 @@
(*
* Conversion of libavformat/avio.h
* unbuffered I/O operations
- * revision 16100, Sat Dec 13 13:39:13 2008 UTC
- * update Tue, Jun 10 01:00:00 2009 UTC
- *
* @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.62.0, revision 23004, Tue May 11 19:29:00 2010 CET
*)
unit avio;
@@ -70,6 +70,16 @@ const
*)
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;
@@ -93,7 +103,7 @@ type
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 filename *)
+ filename: PAnsiChar; (**< specified URL *)
end;
PPURLContext = ^PURLContext;
@@ -106,16 +116,54 @@ type
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}
+
+(**
+ * Reads up to size bytes from the resource accessed by h, and stores
+ * 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;
- url_read_complete: 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; buf: PByteArray; size: cint): cint; cdecl;
+
+(**
+ * Changes 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;
- url_read_pause: function (h: PURLContext): cint;
+ 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;
@@ -124,6 +172,9 @@ type
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}
end;
(**
@@ -168,31 +219,85 @@ type
{$IF LIBAVFORMAT_VERSION >= 52021000} // 52.21.0
+(**
+ * Creates an URLContext for accessing to the resource indicated by
+ * URL, and opens 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}
+
+(**
+ * Creates an URLContext for accessing to the resource indicated by
+ * url, and opens 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; buf: PByteArray; size: cint): cint;
cdecl; external av__format;
function url_seek (h: PURLContext; pos: cint64; whence: cint): cint64;
cdecl; external av__format;
+
+(**
+ * Closes the resource accessed by the URLContext h, and frees 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;
+
+(**
+ * Returns 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;
@@ -264,30 +369,36 @@ var
url_interrupt_cb: PURLInterruptCB; external av__format;
**)
-{
-* 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.
-}
{$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
(**
+ * Registers the URLProtocol protocol.
+ *)
+(**
* @deprecated Use av_register_protocol() instead.
*)
-function register_protocol (protocol: PURLProtocol): cint;
+function register_protocol(protocol: PURLProtocol): cint;
cdecl; external av__format;
+(** Alias for register_protocol() *)
+function av_register_protocol(protocol: PURLProtocol): cint;
+ cdecl; external av__format name 'register_protocol';
{$ELSE}
-function av_register_protocol (protocol: PURLProtocol): cint;
+function av_register_protocol(protocol: PURLProtocol): 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;
+ 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;
@@ -400,11 +511,10 @@ function url_fgets(s: PByteIOContext; buf: PAnsiChar; buf_size: cint): PAnsiChar
procedure put_flush_packet (s: PByteIOContext);
cdecl; external av__format;
-
(**
* Reads size bytes from ByteIOContext into buf.
- * @returns number of bytes read or AVERROR
+ * @return number of bytes read or AVERROR
*)
function get_buffer(s: PByteIOContext; buf: PByteArray; size: cint): cint;
cdecl; external av__format;
@@ -413,7 +523,7 @@ function get_buffer(s: PByteIOContext; buf: PByteArray; size: cint): cint;
* Reads size bytes from ByteIOContext into buf.
* This reads at most 1 packet. If that is not enough fewer bytes will be
* returned.
- * @returns number of bytes read or AVERROR
+ * @return number of bytes read or AVERROR
*)
function get_partial_buffer(s: PByteIOContext; buf: PByteArray; size: cint): cint;
cdecl; external av__format;
@@ -449,8 +559,17 @@ function ff_get_v(bc: PByteIOContext): cuint64;
function url_is_streamed(s: PByteIOContext): cint; {$IFDEF HasInline}inline;{$ENDIF}
-(** @note when opened as read/write, the buffers are only used for
- writing *)
+(**
+ * Creates and initializes 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}
@@ -462,6 +581,7 @@ function url_fdopen (s: PByteIOContext; h: PURLContext): cint;
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.
@@ -470,14 +590,48 @@ function url_setbufsize (s: PByteIOContext; buf_size: cint): cint;
function url_resetbuf(s: PByteIOContext; flags: cint): cint;
cdecl; external av__format;
{$IFEND}
+{$IFEND}
-(** @note when opened as read/write, the buffers are only used for
- writing *)
+{$IF LIBAVFORMAT_VERSION >= 52061000} // 52.61.0
+(**
+ * Rewinds 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}
+
+(**
+ * Creates and initializes 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;
diff --git a/cmake/src/lib/ffmpeg/avutil.pas b/cmake/src/lib/ffmpeg/avutil.pas
index 6a93ea12..c26700c6 100644
--- a/cmake/src/lib/ffmpeg/avutil.pas
+++ b/cmake/src/lib/ffmpeg/avutil.pas
@@ -28,22 +28,20 @@
* Conversions of
*
* libavutil/avutil.h:
- * Min. version: 49.0.1, revision 6577, Sat Oct 7 15:30:46 2006 UTC
- * Max. version: 49.14.0, revision 16912, Sun Feb 1 02:00:19 2009 UTC
+ * Min. version: 49.0.1, revision 6577, Sat Oct 7 15:30:46 2006 UTC
+ * Max. version: 50.15.2, revision 23059, Tue May 11 22:05:00 2010 CET
*
* libavutil/mem.h:
* revision 16590, Tue Jan 13 23:44:16 2009 UTC
*
* libavutil/log.h:
* revision 16571, Tue Jan 13 00:14:43 2009 UTC
+ *
+ * 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.
+ *
*)
-{
- Update changes auf avutil.h, mem.h and log.h
- Max. version 50.03.0, Tue, Jun 09 24:00:00 2009 UTC
- 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;
@@ -65,13 +63,41 @@ 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 = 3;
- LIBAVUTIL_MAX_VERSION_RELEASE = 0;
+ LIBAVUTIL_MAX_VERSION_MINOR = 15;
+ LIBAVUTIL_MAX_VERSION_RELEASE = 2;
LIBAVUTIL_MAX_VERSION = (LIBAVUTIL_MAX_VERSION_MAJOR * VERSION_MAJOR) +
(LIBAVUTIL_MAX_VERSION_MINOR * VERSION_MINOR) +
(LIBAVUTIL_MAX_VERSION_RELEASE * VERSION_RELEASE);
@@ -101,6 +127,41 @@ function avutil_version(): cuint;
cdecl; external av__format;
{$IFEND}
+{$IF LIBAVUTIL_VERSION >= 50004000} // >= 50.4.0
+(**
+ * Returns the libavutil build-time configuration.
+ *)
+function avutil_configuration(): PAnsiChar;
+ cdecl; external av__format;
+
+(**
+ * Returns the libavutil license.
+ *)
+function avutil_license(): PAnsiChar;
+ cdecl; external av__format;
+{$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:
@@ -148,8 +209,8 @@ type
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
- PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black, 1 is white
+ 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)
@@ -166,12 +227,12 @@ type
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, 4bpp, (msb)1B 2G 1R(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, 4bpp, (msb)1R 2G 1B(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 for UV
+ 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
@@ -193,8 +254,8 @@ type
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, big-endian
- PIX_FMT_RGB48LE, ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, little-endian
+ 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
@@ -267,11 +328,13 @@ const
PIX_FMT_YUV422 = PIX_FMT_YUYV422;
{$IFEND}
-(* libavutil/common.h *) // until now MKTAG is all from common.h KMS 9/6/2009
+(* 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 *)
(**
@@ -287,7 +350,7 @@ function av_malloc(size: cuint): pointer;
(**
* Allocates or reallocates a block of memory.
- * If ptr is NULL and size > 0, allocates a new block. If \p
+ * If ptr is NULL and size > 0, allocates a new block. If
* size is zero, frees the memory block pointed to by ptr.
* @param size Size in bytes for the memory block to be allocated or
* reallocated.
@@ -326,7 +389,7 @@ function av_mallocz(size: cuint): pointer;
* Duplicates the string s.
* @param s string to be duplicated.
* @return Pointer to a newly allocated string containing a
- * copy of \p s or NULL if the string cannot be allocated.
+ * 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}
@@ -388,11 +451,40 @@ const
AV_LOG_DEBUG = 48;
{$IFEND}
+(**
+ * Sends 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);
+**}
implementation
@@ -403,4 +495,10 @@ 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/cmake/src/lib/ffmpeg/error.pas b/cmake/src/lib/ffmpeg/error.pas
new file mode 100644
index 00000000..95cecd0f
--- /dev/null
+++ b/cmake/src/lib/ffmpeg/error.pas
@@ -0,0 +1,113 @@
+(*
+ * 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.15.2, revision 23059, Tue May 11 18:30 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
+(*
+ * Puts 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 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/cmake/src/lib/ffmpeg/mathematics.pas b/cmake/src/lib/ffmpeg/mathematics.pas
index 92ee0a5e..3a1f6a2c 100644
--- a/cmake/src/lib/ffmpeg/mathematics.pas
+++ b/cmake/src/lib/ffmpeg/mathematics.pas
@@ -26,10 +26,8 @@
(*
* Conversion of libavutil/mathematics.h
- * revision 16844, Wed Jan 28 08:50:10 2009 UTC
+ * avutil max. version 50.15.2, revision 23059, Tue May 11 22:10:00 2010 CET
*
- * update, MiSchi, no code change
- * Fri Jun 12 2009 21:50:00 UTC
*)
unit mathematics;
@@ -53,8 +51,18 @@ 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}
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 = (
@@ -66,6 +74,11 @@ type
);
{$IF LIBAVUTIL_VERSION >= 49013000} // 49.13.0
+(**
+ * Returns 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}
@@ -90,6 +103,17 @@ function av_rescale_rnd (a, b, c: cint64; enum: TAVRounding): cint64;
function av_rescale_q (a: cint64; bq, cq: TAVRational): cint64;
cdecl; external av__util; {av_const}
+{$IF LIBAVUTIL_VERSION >= 50008000} // 50.8.0
+(**
+ * Compares 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}
+
implementation
end.
diff --git a/cmake/src/lib/ffmpeg/opt.pas b/cmake/src/lib/ffmpeg/opt.pas
index a2e2cce9..c755ed35 100644
--- a/cmake/src/lib/ffmpeg/opt.pas
+++ b/cmake/src/lib/ffmpeg/opt.pas
@@ -23,14 +23,10 @@
* - 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
- * revision 16912, Sun Feb 1 02:00:19 2009 UTC
+ * Max. avcodec version: 52.67.0, revision 23057, Tue May 11 18:17 2010 CET
*
- * update, MiSchi, no code change
- * Fri Jun 12 2009 21:50:00 UTC
*)
unit opt;
@@ -110,6 +106,53 @@ type
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
(**
* Looks for an option in obj. Looks only for the options which
@@ -189,10 +232,10 @@ function av_set_q(obj: pointer; name: {const} PAnsiChar; n: TAVRational): PAVOpt
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: PAVOption): cdouble;
+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: PAVOption): TAVRational;
+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;
diff --git a/cmake/src/lib/ffmpeg/rational.pas b/cmake/src/lib/ffmpeg/rational.pas
index b940009d..6ca9c0d1 100644
--- a/cmake/src/lib/ffmpeg/rational.pas
+++ b/cmake/src/lib/ffmpeg/rational.pas
@@ -27,10 +27,8 @@
(*
* Conversion of libavutil/rational.h
- * revision 16912, Sun Feb 1 02:00:19 2009 UTC
+ * avutil max. version 50.15.2, revision 23059, Tue May 11 22:10:00 2010 CET
*
- * update, MiSchi, no code change
- * Fri Jun 12 2009 22:20:00 UTC
*)
unit rational;
diff --git a/cmake/src/lib/ffmpeg/src/MacOSX/MacOSXReadMe.txt b/cmake/src/lib/ffmpeg/src/MacOSX/MacOSXReadMe.txt
deleted file mode 100644
index c2f5826a..00000000
--- a/cmake/src/lib/ffmpeg/src/MacOSX/MacOSXReadMe.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-If you are using fink to install ffmpeg and friends,
-you can skip the rest of this notes.
-
-How to download an build ffmpeg for UltraStar Deluxe on Mac OS X:
-
-1. Open a terminal.
-
-2. cd into the Game/Code/lib/ffmpeg/src/MacOSX directory
-
-3. Run the following command:
-
-svn checkout svn://svn.mplayerhq.hu/ffmpeg/trunk ffmpeg
-
-4. The compile ffmpeg. I made a script for this:
-
-./build_ffmpeg.sh
-
-5. On OS X you have to patch the the dylibs. Run the following
- script. It patches the dylibs and copies them to the
- lib/ffmpeg dir:
-
-./copy_and_patch_dylibs.sh
-
-You're done.
diff --git a/cmake/src/lib/ffmpeg/src/MacOSX/build_ffmpeg.sh b/cmake/src/lib/ffmpeg/src/MacOSX/build_ffmpeg.sh
deleted file mode 100755
index bcb3ca1e..00000000
--- a/cmake/src/lib/ffmpeg/src/MacOSX/build_ffmpeg.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/bash
-
-cd ffmpeg
-./configure --enable-shared --disable-static --disable-mmx
-make
-
diff --git a/cmake/src/lib/ffmpeg/src/MacOSX/copy_and_patch_dylibs.sh b/cmake/src/lib/ffmpeg/src/MacOSX/copy_and_patch_dylibs.sh
deleted file mode 100755
index 064d2ecc..00000000
--- a/cmake/src/lib/ffmpeg/src/MacOSX/copy_and_patch_dylibs.sh
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/bash
-
-# Copy dylibs:
-cp ffmpeg/libavcodec/libavcodec.51.dylib ../../libavcodec.dylib
-cp ffmpeg/libavformat/libavformat.52.dylib ../../libavformat.dylib
-cp ffmpeg/libavutil/libavutil.49.dylib ../../libavutil.dylib
-
-# Patching libavcodec:
-install_name_tool -id @executable_path/libavcodec.dylib ../../libavcodec.dylib
-install_name_tool -change /usr/local/lib/libavutil.dylib @executable_path/libavutil.dylib ../../libavcodec.dylib
-
-# Patching libavformat:
-install_name_tool -id @executable_path/libavformat.dylib ../../libavformat.dylib
-install_name_tool -change /usr/local/lib/libavutil.dylib @executable_path/libavutil.dylib ../../libavformat.dylib
-install_name_tool -change /usr/local/lib/libavcodec.dylib @executable_path/libavcodec.dylib ../../libavformat.dylib
-
-# Patching libavcodec:
-install_name_tool -id @executable_path/libavutil.dylib ../../libavutil.dylib
-
-# Printing result:
-otool -L ../../libavutil.dylib
-otool -L ../../libavcodec.dylib
-otool -L ../../libavformat.dylib \ No newline at end of file
diff --git a/cmake/src/lib/ffmpeg/swscale.pas b/cmake/src/lib/ffmpeg/swscale.pas
index c0aabf45..4f923f04 100644
--- a/cmake/src/lib/ffmpeg/swscale.pas
+++ b/cmake/src/lib/ffmpeg/swscale.pas
@@ -23,7 +23,7 @@
(*
* Conversion of libswscale/swscale.h
- * revision 27592, Fri Sep 12 21:46:53 2008 UTC
+ * Max. version: 0.10.0, revision 31050, Tue May 11 19:40:00 2010 CET
*)
unit swscale;
@@ -49,10 +49,35 @@ uses
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 = 7;
- LIBSWSCALE_MAX_VERSION_RELEASE = 1;
+ LIBSWSCALE_MAX_VERSION_MAJOR = 0;
+ LIBSWSCALE_MAX_VERSION_MINOR = 10;
+ 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);
@@ -78,6 +103,20 @@ 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;
@@ -124,6 +163,18 @@ const
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
@@ -148,6 +199,26 @@ type
{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;
@@ -175,6 +246,10 @@ function sws_getContext(srcW: cint; srcH: cint; srcFormat: TAVPixelFormat;
* 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
@@ -192,14 +267,15 @@ function sws_getContext(srcW: cint; srcH: cint; srcFormat: TAVPixelFormat;
* the destination image
* @return the height of the output slice
*)
-function sws_scale(context: PSwsContext; srcSlice: PPCuint8Array; srcStride: PCintArray;
- srcSliceY: cint; srcSliceH: cint; dst: PPCuint8Array; dstStride: PCintArray): cint;
+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; src: PPCuint8Array; srcStride: PCintArray;
- srcSliceY: cint; srcSliceH: cint; dst: PPCuint8Array; dstStride: PCintArray): cint;
+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}
diff --git a/cmake/src/lib/fft/UFFT.pas b/cmake/src/lib/fft/UFFT.pas
index 6b094c98..5a056a8c 100644
--- a/cmake/src/lib/fft/UFFT.pas
+++ b/cmake/src/lib/fft/UFFT.pas
@@ -47,7 +47,7 @@ unit UFFT;
{$IFDEF FPC}
{$MODE Delphi}
- {$H+} // Use AnsiString
+ {$H+} // Use long strings
{$ENDIF}
interface
diff --git a/cmake/src/lib/freetype/demo/engine-test.bdsproj b/cmake/src/lib/freetype/demo/engine-test.bdsproj
index 9547f18f..e5b3e97d 100644
--- a/cmake/src/lib/freetype/demo/engine-test.bdsproj
+++ b/cmake/src/lib/freetype/demo/engine-test.bdsproj
@@ -27,13 +27,13 @@
<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">0</Compiler>
- <Compiler Name="P">1</Compiler>
- <Compiler Name="Q">0</Compiler>
- <Compiler Name="R">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>
diff --git a/cmake/src/lib/freetype/demo/engine-test.dpr b/cmake/src/lib/freetype/demo/engine-test.dpr
index 80177735..bbd7d890 100644
--- a/cmake/src/lib/freetype/demo/engine-test.dpr
+++ b/cmake/src/lib/freetype/demo/engine-test.dpr
@@ -27,7 +27,9 @@ uses
ctypes in '../../ctypes/ctypes.pas',
{$ENDIF}
FreeType in '../freetype.pas',
- UFont in '../../../base/UFont.pas',
+ UFont in 'UFont.pas',
+ //UFont in '../../../base/UFont.pas',
+ UUnicodeUtils in '../../../base/UUnicodeUtils.pas',
math,
sysutils;
@@ -41,7 +43,7 @@ const
//FONT_FILE = 'C:/Windows/Fonts/Arial.ttf';
//FONT_FILE = 'C:/Windows/Fonts/SimSun.ttf';
//FONT_FILE = 'eurostarregularextended.ttf';
- FONT_FILE = 'FreeSans.ttf';
+ FONT_FILE = '../../../../game/fonts/FreeSans/FreeSans.ttf';
var
OurFont: TScalableFont;
@@ -129,11 +131,11 @@ begin
// Really Nice Perspective Calculations
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
- //OurFont := TFTScalableFont.Create(FONT_FILE, 64);
+ OurFont := TFTScalableFont.Create(FONT_FILE, 64, 0.03);
//OurFont := TFTFont.Create(FONT_FILE, 128);
- OurFont := TFTScalableOutlineFont.Create(FONT_FILE, 64, 0.05);
+ //OurFont := TFTScalableOutlineFont.Create(FONT_FILE, 64, 0.03);
//OurFont.UseKerning := false;
- TFTScalableOutlineFont(OurFont).SetOutlineColor(1, 0, 0);
+ //TFTScalableOutlineFont(OurFont).SetOutlineColor(1, 0, 0, 1);
//OurFont := TOutlineFont.Create(FONT_FILE, 32, 2);
//OurFont.LineSpacing := OurFont.LineSpacing * 0.5;
@@ -183,7 +185,7 @@ begin
//OurFont.SetOutlineColor(0.5, 0.5, 0.5);
//OurFont.ReflectionSpacing := -4;
//OurFont.UseKerning := false;
- OurFont.Height := 64;//cnt2;
+ OurFont.Height := 150;//cnt2;
//OurFont.Reset;
//OurFont.Aspect := 2;
@@ -191,7 +193,7 @@ begin
bounds := OurFont.BBox(msg);
//glRectf(bounds.Left, OurFont.Ascender, bounds.Right, OurFont.Ascender-OurFont.Height);
- glColor3f(1, 1, 1);
+ glColor4f(1, 1, 1, 1);
//OurFont.ReflectionSpacing := 0;
OurFont.Print(msg);
diff --git a/cmake/src/lib/freetype/demo/engine-test.lpi b/cmake/src/lib/freetype/demo/engine-test.lpi
index 6cbfe1eb..45483a56 100644
--- a/cmake/src/lib/freetype/demo/engine-test.lpi
+++ b/cmake/src/lib/freetype/demo/engine-test.lpi
@@ -28,14 +28,14 @@
</local>
</RunParams>
<Units Count="16">
- <Unit0>
- <Filename Value="engine-test.dpr"/>
- <IsPartOfProject Value="True"/>
- <CursorPos X="25" Y="135"/>
- <TopLine Value="118"/>
- <EditorIndex Value="0"/>
- <UsageCount Value="72"/>
- <Loaded Value="True"/>
+ <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"/>
@@ -139,13 +139,22 @@
<UnitName Value="UFont"/>
<CursorPos X="15" Y="1752"/>
<TopLine Value="1734"/>
- <UsageCount Value="10"/>
- </Unit15>
- </Units>
- <JumpHistory Count="0" HistoryIndex="-1"/>
- </ProjectOptions>
- <CompilerOptions>
- <Version Value="8"/>
+ <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\"/>
diff --git a/cmake/src/lib/freetype/freetype.pas b/cmake/src/lib/freetype/freetype.pas
index 6a9d2062..01f507bc 100644
--- a/cmake/src/lib/freetype/freetype.pas
+++ b/cmake/src/lib/freetype/freetype.pas
@@ -1,23 +1,42 @@
-//----------------------------------------------------------------------------
-// FreeType2 pascal header
-//----------------------------------------------------------------------------
-// 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.
-//
-//----------------------------------------------------------------------------
-// Adapted by the UltraStar Deluxe Team
-//----------------------------------------------------------------------------
+(***************************************************************************)
+(* *)
+(* 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;
@@ -36,7 +55,7 @@ uses
const
{$IF Defined(MSWINDOWS)}
- ft_lib = 'libfreetype-6.dll';
+ ft_lib = 'freetype6.dll';
{$ELSEIF Defined(DARWIN)}
ft_lib = 'libfreetype.dylib';
{$LINKLIB libfreetype}
@@ -45,32 +64,24 @@ const
{$IFEND}
type
- FT_Byte = cuchar;
- FT_Short = csshort;
- FT_UShort = cushort;
- FT_Int = csint;
- FT_UInt = cuint;
- FT_Int16 = cint16;
- FT_UInt16 = cuint16;
- FT_Int32 = cint32;
- FT_UInt32 = cuint32;
- FT_Long = cslong;
- FT_ULong = culong;
-
- FT_Fixed = cslong;
- FT_Pos = cslong;
- FT_Error = cint;
- FT_F26Dot6 = cslong;
- FT_String = cchar;
- FT_Bool = cuchar;
-
- PFT_Byte = ^FT_Byte;
- PFT_Short = ^FT_Short;
- PFT_String = ^FT_String;
-
-
- TByteArray = array [0 .. (MaxInt div SizeOf(byte))-1] of byte;
- PByteArray = ^TByteArray;
+ (*************************************************************************)
+ (* *)
+ (* <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;
(*************************************************************************)
@@ -141,6 +152,34 @@ const
(*************************************************************************)
(* *)
+ (* <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 *)
(* *)
@@ -278,65 +317,47 @@ const
(* *)
type
PFT_Encoding = ^FT_Encoding;
- FT_Encoding = array[0..3] of char;
-const
- FT_ENCODING_NONE: FT_Encoding = (#0 ,#0 ,#0 ,#0 );
- FT_ENCODING_MS_SYMBOL: FT_Encoding = ('s', 'y', 'm', 'b' );
- FT_ENCODING_UNICODE: FT_Encoding = ('u', 'n', 'i', 'c' );
-
- FT_ENCODING_SJIS: FT_Encoding = ('s', 'j', 'i', 's');
- FT_ENCODING_GB2312: FT_Encoding = ('g', 'b', ' ', ' ');
- FT_ENCODING_BIG5: FT_Encoding = ('b', 'i', 'g', '5');
- FT_ENCODING_WANSUNG: FT_Encoding = ('w', 'a', 'n', 's');
- FT_ENCODING_JOHAB: FT_Encoding = ('j', 'o', 'h', 'a');
-
- (*************************************************************************)
- (* *)
- (* <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. *)
- (* *)
-type
- FT_Glyph_Format = array[0..3] of char;
+ FT_Encoding = cint32; // 32 bit enum of FT_ENC_TAG
const
- FT_GLYPH_FORMAT_NONE: FT_Glyph_Format = (#0, #0, #0, #0 );
-
- FT_GLYPH_FORMAT_COMPOSITE: FT_Glyph_Format = ('c', 'o', 'm', 'p' );
- FT_GLYPH_FORMAT_BITMAP: FT_Glyph_Format = ('b', 'i', 't', 's' );
- FT_GLYPH_FORMAT_OUTLINE: FT_Glyph_Format = ('o', 'u', 't', 'l' );
- FT_GLYPH_FORMAT_PLOTTER: FT_Glyph_Format = ('p', 'l', 'o', 't' );
+ 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);
(*************************************************************************)
@@ -358,7 +379,7 @@ const
const
FT_STYLE_FLAG_ITALIC = 1 shl 0;
FT_STYLE_FLAG_BOLD = 1 shl 1;
-
+
(***************************************************************************
*
@@ -567,7 +588,7 @@ const
(* perform this pass. *)
(* *)
type
- FT_Render_Mode = FT_Int;
+ FT_Render_Mode = cint;
const
FT_RENDER_MODE_NORMAL = 0;
FT_RENDER_MODE_LIGHT = FT_RENDER_MODE_NORMAL + 1;
@@ -579,63 +600,34 @@ const
(*************************************************************************)
(* *)
- (* <Enum> *)
- (* FT_Pixel_Mode *)
+ (* <Type> *)
+ (* FT_GlyphSlot *)
(* *)
(* <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. *)
+ (* 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. *)
(* *)
- (* <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. *)
+ (* 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_Pixel_Mode = byte;
-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_GlyphSlot = ^FT_GlyphSlotRec;
- FT_PIXEL_MODE_MAX = FT_PIXEL_MODE_LCD_V + 1; (* do not remove *)
+
+{$DEFINE TYPE_DECL}
+{$I ftconfig.inc}
+{$I fttypes.inc}
+{$I ftimage.inc}
+{$I ftglyph.inc}
+{$I ftstroke.inc}
+{$I ftoutln.inc}
+{$UNDEF TYPE_DECL}
(*************************************************************************)
@@ -674,7 +666,6 @@ const
(* vertAdvance :: *)
(* Advance height for vertical layout. *)
(* *)
-type
FT_Glyph_Metrics = record
width ,
height : FT_Pos;
@@ -759,140 +750,6 @@ type
(*************************************************************************)
(* *)
- (* <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;
-
-
- (*************************************************************************)
- (* *)
- (* <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;
- n_points : FT_Short;
-
- points : PFT_Vector;
- tags : PChar;
- contours : PFT_Short;
-
- flags : FT_Int;
- end;
-
-
- (*************************************************************************)
- (* *)
- (* <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 ,
- width : FT_Int;
- pitch : FT_Int;
- buffer : PByteArray;
- num_grays : FT_Short;
- pixel_mode ,
- palette_mode : byte;
- palette : pointer;
- end;
-
-
- (*************************************************************************)
- (* *)
(* <Type> *)
(* FT_Face *)
(* *)
@@ -950,183 +807,10 @@ type
PAFT_CharMap = ^FT_CharMap;
AFT_CharMap = array[0..High(Word)] of FT_CharMap;
- (*************************************************************************)
- (* *)
- (* <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 = ^FT_LibraryRec;
- FT_LibraryRec = record // internal
- end;
-
- (*************************************************************************)
- (* *)
- (* <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. *)
- (* *)
- (*************************************************************************)
-
- (* forward declaration to a private type *)
- PFT_Glyph_Class = ^FT_Glyph_Class;
- FT_Glyph_Class = record // internal
- end;
-
- (*************************************************************************)
- (* *)
- (* <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;
(*************************************************************************)
@@ -1149,101 +833,6 @@ type
(*************************************************************************)
(* *)
- (* <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;
-
- (*************************************************************************)
- (* *)
- (* <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;
-
-
- (*************************************************************************)
- (* *)
- (* <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. *)
- (* *)
- FT_GlyphSlot = ^FT_GlyphSlotRec;
-
- (*************************************************************************)
- (* *)
(* <Struct> *)
(* FT_GlyphSlotRec *)
(* *)
@@ -1432,7 +1021,7 @@ type
subglyphs : FT_SubGlyph;
control_data : pointer;
- control_len : longint;
+ control_len : clong;
lsb_delta: FT_Pos;
rsb_delta: FT_Pos;
@@ -1497,15 +1086,15 @@ type
(* computations. *)
(* *)
FT_Size_Metrics = record
- x_ppem ,
- y_ppem : FT_UShort;
- x_scale ,
- y_scale : FT_Fixed;
-
- ascender ,
- descender : FT_Pos;
- height : FT_Pos;
- max_advance : FT_Pos;
+ 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;
(*************************************************************************)
@@ -1786,21 +1375,29 @@ type
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_CURVE_TAG ( flag ) *)
+ (* FT_HAS_KERNING( face ) *)
(* *)
- function FT_CURVE_TAG(flag: byte): byte;
-
-const
- FT_CURVE_TAG_ON = 1;
- FT_CURVE_TAG_CONIC = 0;
- FT_CURVE_TAG_CUBIC = 2;
-
+ (* @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: *)
@@ -1813,16 +1410,6 @@ const
(* *)
function FT_IS_SCALABLE(face : FT_Face ) : cbool;
- (*************************************************************************)
- (* *)
- (* @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;
(*************************************************************************)
(* *)
@@ -2284,216 +1871,12 @@ const
pixel_height : FT_UInt ) : FT_Error;
cdecl; external ft_lib name 'FT_Set_Pixel_Sizes';
- (*************************************************************************)
- (* *)
- (* <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';
-
- (*************************************************************************)
- (* *)
- (* <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. *)
- (* *)
-type
- FT_Glyph_BBox_Mode = FT_UInt;
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';
+ 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;
- (*************************************************************************)
- (* *)
- (* <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';
implementation
@@ -2504,17 +1887,17 @@ begin
result := flag and 3;
end;
-{ FT_IS_SCALABLE }
-function FT_IS_SCALABLE(face : FT_Face ) : cbool;
-begin
- result := cbool(face.face_flags and FT_FACE_FLAG_SCALABLE );
-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/cmake/src/lib/freetype/ftconfig.inc b/cmake/src/lib/freetype/ftconfig.inc
new file mode 100644
index 00000000..100fb2e0
--- /dev/null
+++ b/cmake/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/cmake/src/lib/freetype/ftglyph.inc b/cmake/src/lib/freetype/ftglyph.inc
new file mode 100644
index 00000000..0d4acc99
--- /dev/null
+++ b/cmake/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/cmake/src/lib/freetype/ftimage.inc b/cmake/src/lib/freetype/ftimage.inc
new file mode 100644
index 00000000..d16d52a2
--- /dev/null
+++ b/cmake/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/cmake/src/lib/freetype/ftoutln.inc b/cmake/src/lib/freetype/ftoutln.inc
new file mode 100644
index 00000000..997c6cb3
--- /dev/null
+++ b/cmake/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/cmake/src/lib/freetype/ftstroke.inc b/cmake/src/lib/freetype/ftstroke.inc
new file mode 100644
index 00000000..bf8a00ae
--- /dev/null
+++ b/cmake/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/cmake/src/lib/freetype/fttypes.inc b/cmake/src/lib/freetype/fttypes.inc
new file mode 100644
index 00000000..a64432e6
--- /dev/null
+++ b/cmake/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/cmake/src/lib/lib-info.txt b/cmake/src/lib/lib-info.txt
index 59502c7a..0a184568 100644
--- a/cmake/src/lib/lib-info.txt
+++ b/cmake/src/lib/lib-info.txt
@@ -1,60 +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)
+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/cmake/src/lib/midi/CIRCBUF.PAS b/cmake/src/lib/midi/CIRCBUF.PAS
index 77cb3643..3ceb4c6e 100644
--- a/cmake/src/lib/midi/CIRCBUF.PAS
+++ b/cmake/src/lib/midi/CIRCBUF.PAS
@@ -23,7 +23,7 @@ interface
{$IFDEF FPC}
{$MODE Delphi}
- {$H+} // use AnsiString
+ {$H+} // use long strings
{$ENDIF}
Uses
diff --git a/cmake/src/lib/midi/DELPHMCB.PAS b/cmake/src/lib/midi/DELPHMCB.PAS
index e607627d..ef0d5451 100644
--- a/cmake/src/lib/midi/DELPHMCB.PAS
+++ b/cmake/src/lib/midi/DELPHMCB.PAS
@@ -13,7 +13,7 @@ interface
{$IFDEF FPC}
{$MODE Delphi}
- {$H+} // use AnsiString
+ {$H+} // use long strings
{$ENDIF}
uses
diff --git a/cmake/src/lib/midi/MIDIDEFS.PAS b/cmake/src/lib/midi/MIDIDEFS.PAS
index fc8eed26..4afe56ef 100644
--- a/cmake/src/lib/midi/MIDIDEFS.PAS
+++ b/cmake/src/lib/midi/MIDIDEFS.PAS
@@ -13,7 +13,7 @@ interface
{$IFDEF FPC}
{$MODE Delphi}
- {$H+} // use AnsiString
+ {$H+} // use long strings
{$ENDIF}
uses
diff --git a/cmake/src/lib/midi/MIDITYPE.PAS b/cmake/src/lib/midi/MIDITYPE.PAS
index b1ec1bdd..45b50820 100644
--- a/cmake/src/lib/midi/MIDITYPE.PAS
+++ b/cmake/src/lib/midi/MIDITYPE.PAS
@@ -10,7 +10,7 @@ interface
{$IFDEF FPC}
{$MODE Delphi}
- {$H+} // use AnsiString
+ {$H+} // use long strings
{$ENDIF}
uses
diff --git a/cmake/src/lib/midi/MidiFile.pas b/cmake/src/lib/midi/MidiFile.pas
index 11b1ca0b..acf44c04 100644
--- a/cmake/src/lib/midi/MidiFile.pas
+++ b/cmake/src/lib/midi/MidiFile.pas
@@ -92,18 +92,18 @@ interface
{$IFDEF FPC}
{$MODE Delphi}
- {$H+} // use AnsiString
+ {$H+} // use long strings
{$ENDIF}
uses
Windows,
- //Forms,
Messages,
Classes,
{$IFDEF FPC}
WinAllocation,
{$ENDIF}
- SysUtils;
+ SysUtils,
+ UPath;
type
TChunkType = (illegal, header, track);
@@ -162,7 +162,7 @@ type
procedure WndProc(var Msg : TMessage);
protected
{ Protected declarations }
- midiFile: file of byte;
+ midiFile: TBinaryFileStream;
chunkType: TChunkType;
chunkLength: integer;
chunkData: PByte;
@@ -177,7 +177,7 @@ type
FBpm: integer;
FBeatsPerMeasure: integer;
FusPerTick: double;
- FFilename: string;
+ FFilename: IPath;
Tracks: TList;
currentTrack: TMidiTrack;
@@ -191,7 +191,7 @@ type
currentPos: Double; // Current Position in ticks
procedure OnTrackReady;
- procedure setFilename(val: string);
+ procedure SetFilename(val: IPath);
procedure ReadChunkHeader;
procedure ReadChunkContent;
procedure ReadChunk;
@@ -221,7 +221,7 @@ type
function Ready: boolean;
published
{ Published declarations }
- property Filename: string read FFilename write setFilename;
+ property Filename: IPath read FFilename write SetFilename;
property NumberOfTracks: integer read numberTracks;
property TicksPerQuarter: integer read deltaTicks;
property FileFormat: TFileFormat read FFileFormat;
@@ -463,7 +463,7 @@ begin
result := Tracks.Items[index];
end;
-procedure TMidifile.setFilename(val: string);
+procedure TMidifile.SetFilename(val: IPath);
begin
FFilename := val;
// ReadFile;
@@ -586,7 +586,7 @@ procedure TMidifile.ReadChunkHeader;
var
theByte: array[0..7] of byte;
begin
- BlockRead(midiFile, theByte, 8);
+ midiFile.Read(theByte[0], 8);
if (theByte[0] = $4D) and (theByte[1] = $54) then
begin
if (theByte[2] = $68) and (theByte[3] = $64) then
@@ -608,7 +608,7 @@ begin
if not (chunkData = nil) then
FreeMem(chunkData);
GetMem(chunkData, chunkLength + 10);
- BlockRead(midiFile, chunkData^, chunkLength);
+ midiFile.Read(chunkData^, chunkLength);
chunkIndex := chunkData;
chunkEnd := PByte(integer(chunkIndex) + integer(chunkLength) - 1);
end;
@@ -848,12 +848,10 @@ begin
Tracks.Clear;
chunkType := illegal;
- AssignFile(midiFile, FFilename);
- FileMode := 0;
- Reset(midiFile);
- while not eof(midiFile) do
+ midiFile := TBinaryFileStream.Create(FFilename, fmOpenRead);
+ while (midiFile.Position < midiFile.Size) do
ReadChunk;
- CloseFile(midiFile);
+ FreeAndNil(midiFile);
numberTracks := Tracks.Count;
end;
diff --git a/cmake/src/lib/midi/MidiScope.pas b/cmake/src/lib/midi/MidiScope.pas
index 42fc65fc..afc20b0f 100644
--- a/cmake/src/lib/midi/MidiScope.pas
+++ b/cmake/src/lib/midi/MidiScope.pas
@@ -20,7 +20,7 @@ interface
{$IFDEF FPC}
{$MODE Delphi}
- {$H+} // use AnsiString
+ {$H+} // use long strings
{$ENDIF}
uses
diff --git a/cmake/src/lib/midi/Midicons.pas b/cmake/src/lib/midi/Midicons.pas
index 35dbb5f3..72259beb 100644
--- a/cmake/src/lib/midi/Midicons.pas
+++ b/cmake/src/lib/midi/Midicons.pas
@@ -11,7 +11,7 @@ interface
{$IFDEF FPC}
{$MODE Delphi}
- {$H+} // use AnsiString
+ {$H+} // use long strings
{$ENDIF}
uses Messages;
diff --git a/cmake/src/lib/midi/Midiin.pas b/cmake/src/lib/midi/Midiin.pas
index 21db0298..a055669a 100644
--- a/cmake/src/lib/midi/Midiin.pas
+++ b/cmake/src/lib/midi/Midiin.pas
@@ -103,7 +103,7 @@ interface
{$IFDEF FPC}
{$MODE Delphi}
- {$H+} // use AnsiString
+ {$H+} // use long strings
{$ENDIF}
uses
@@ -237,20 +237,13 @@ uses Controls,
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 WIN32}
+{$IFDEF MSWINDOWS}
function midiHandler(
hMidiIn: HMidiIn;
wMsg: UINT;
dwInstance: DWORD;
dwParam1: DWORD;
dwParam2: DWORD): Boolean; stdcall; external 'DELMID32.DLL';
-{$ELSE}
-procedure midiHandler(
- hMidiIn: HMidiIn;
- wMsg: Word;
- dwInstance: DWORD;
- dwParam1: DWORD;
- dwParam2: DWORD); far; external 'DELPHMID';
{$ENDIF}
*)
{-------------------------------------------------------------------}
diff --git a/cmake/src/lib/midi/Midiout.pas b/cmake/src/lib/midi/Midiout.pas
index 606d0dae..7ce385eb 100644
--- a/cmake/src/lib/midi/Midiout.pas
+++ b/cmake/src/lib/midi/Midiout.pas
@@ -98,7 +98,7 @@ interface
{$IFDEF FPC}
{$MODE Delphi}
- {$H+} // use AnsiString
+ {$H+} // use long strings
{$ENDIF}
uses
@@ -234,20 +234,13 @@ implementation
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 WIN32}
+{$IFDEF MSWINDOWS}
function midiHandler(
hMidiIn: HMidiIn;
wMsg: UINT;
dwInstance: DWORD;
dwParam1: DWORD;
dwParam2: DWORD): Boolean; stdcall; external 'DELMID32.DLL';
-{$ELSE}
-function midiHandler(
- hMidiIn: HMidiIn;
- wMsg: Word;
- dwInstance: DWORD;
- dwParam1: DWORD;
- dwParam2: DWORD): Boolean; far; external 'DELPHMID.DLL';
{$ENDIF}
*)
diff --git a/cmake/src/lib/other/DirWatch.pas b/cmake/src/lib/other/DirWatch.pas
index 9d395840..1e00ec5d 100644
--- a/cmake/src/lib/other/DirWatch.pas
+++ b/cmake/src/lib/other/DirWatch.pas
@@ -25,7 +25,7 @@ interface
{$IFDEF FPC}
{$MODE Delphi}
- {$H+} // use AnsiString
+ {$H+} // use long strings
{$ENDIF}
uses
diff --git a/cmake/src/lib/pcre/pcre.pas b/cmake/src/lib/pcre/pcre.pas
new file mode 100644
index 00000000..50e3371a
--- /dev/null
+++ b/cmake/src/lib/pcre/pcre.pas
@@ -0,0 +1,852 @@
+{**************************************************************************************************}
+{ }
+{ 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 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';
+ {$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}
+ 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/cmake/src/lib/portaudio/portaudio.pas b/cmake/src/lib/portaudio/portaudio.pas
index a0286b48..ea7d06b7 100644
--- a/cmake/src/lib/portaudio/portaudio.pas
+++ b/cmake/src/lib/portaudio/portaudio.pas
@@ -109,8 +109,8 @@ type TPaErrorCode = {enum}cint; const
paStreamIsNotStopped = (paNotInitialized+18);
paInputOverflowed = (paNotInitialized+19);
paOutputUnderflowed = (paNotInitialized+20);
- paHostApiNotFound = (paNotInitialized+21);
- paInvalidHostApi = (paNotInitialized+22);
+ 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 *}
diff --git a/cmake/src/lib/projectM/cwrapper/projectM-cwrapper.h b/cmake/src/lib/projectM/cwrapper/projectM-cwrapper.h
index 43f36ef4..125b1253 100644
--- a/cmake/src/lib/projectM/cwrapper/projectM-cwrapper.h
+++ b/cmake/src/lib/projectM/cwrapper/projectM-cwrapper.h
@@ -7,10 +7,11 @@
#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_1_02_00
+#define PROJECTM_VERSION_INT PROJECTM_VERSION_2_00_00
#endif
extern "C" {
diff --git a/cmake/src/lib/projectM/projectM.pas b/cmake/src/lib/projectM/projectM.pas
index 4adba17d..533cb19b 100644
--- a/cmake/src/lib/projectM/projectM.pas
+++ b/cmake/src/lib/projectM/projectM.pas
@@ -2,7 +2,7 @@ unit projectM;
{$IFDEF FPC}
{$MODE DELPHI}
- {$H+} (* use AnsiString *)
+ {$H+} (* use long strings *)
{$PACKENUM 4} (* use 4-byte enums *)
{$PACKRECORDS C} (* C/C++-compatible record packing *)
{$ELSE}
diff --git a/cmake/src/lib/zlib/zlib.pas b/cmake/src/lib/zlib/zlib.pas
index 31d6a68b..8d09313f 100644
--- a/cmake/src/lib/zlib/zlib.pas
+++ b/cmake/src/lib/zlib/zlib.pas
@@ -14,7 +14,7 @@ interface
{$ifdef FPC}
{$mode objfpc} // Needed for array of const
- {$H+} // use AnsiString
+ {$H+} // use long strings
{$PACKRECORDS C}
{$endif}
diff --git a/cmake/src/lua/UHookableEvent.pas b/cmake/src/lua/UHookableEvent.pas
new file mode 100644
index 00000000..8ad7ea9c
--- /dev/null
+++ b/cmake/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/cmake/src/lua/ULuaCore.pas b/cmake/src/lua/ULuaCore.pas
new file mode 100644
index 00000000..ea9fd991
--- /dev/null
+++ b/cmake/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/cmake/src/lua/ULuaGl.pas b/cmake/src/lua/ULuaGl.pas
new file mode 100644
index 00000000..178853b6
--- /dev/null
+++ b/cmake/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/cmake/src/lua/ULuaLog.pas b/cmake/src/lua/ULuaLog.pas
new file mode 100644
index 00000000..95efaa19
--- /dev/null
+++ b/cmake/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/cmake/src/lua/ULuaParty.pas b/cmake/src/lua/ULuaParty.pas
new file mode 100644
index 00000000..69096e97
--- /dev/null
+++ b/cmake/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/cmake/src/lua/ULuaScreenSing.pas b/cmake/src/lua/ULuaScreenSing.pas
new file mode 100644
index 00000000..7e17224c
--- /dev/null
+++ b/cmake/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/cmake/src/lua/ULuaTextGL.pas b/cmake/src/lua/ULuaTextGL.pas
new file mode 100644
index 00000000..2e70a2c1
--- /dev/null
+++ b/cmake/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/cmake/src/lua/ULuaTexture.pas b/cmake/src/lua/ULuaTexture.pas
new file mode 100644
index 00000000..931c0405
--- /dev/null
+++ b/cmake/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/cmake/src/lua/ULuaUsdx.pas b/cmake/src/lua/ULuaUsdx.pas
new file mode 100644
index 00000000..d92289b1
--- /dev/null
+++ b/cmake/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/cmake/src/lua/ULuaUtils.pas b/cmake/src/lua/ULuaUtils.pas
new file mode 100644
index 00000000..143b34d4
--- /dev/null
+++ b/cmake/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/cmake/src/media/UAudioCore_Bass.pas b/cmake/src/media/UAudioCore_Bass.pas
index 12623dc1..3a84dcd7 100644
--- a/cmake/src/media/UAudioCore_Bass.pas
+++ b/cmake/src/media/UAudioCore_Bass.pas
@@ -44,10 +44,13 @@ type
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
@@ -56,6 +59,11 @@ 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;
@@ -71,6 +79,27 @@ begin
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());
diff --git a/cmake/src/media/UAudioCore_Portaudio.pas b/cmake/src/media/UAudioCore_Portaudio.pas
index 25ceae3c..c97b5d10 100644
--- a/cmake/src/media/UAudioCore_Portaudio.pas
+++ b/cmake/src/media/UAudioCore_Portaudio.pas
@@ -40,11 +40,15 @@ uses
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;
+ function TestDevice(inParams, outParams: PPaStreamParameters; var sampleRate: double): boolean;
end;
implementation
@@ -92,6 +96,7 @@ var
constructor TAudioCore_Portaudio.Create();
begin
inherited;
+ InitCount := 0;
end;
class function TAudioCore_Portaudio.GetInstance(): TAudioCore_Portaudio;
@@ -101,9 +106,60 @@ begin
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;
+ i: integer;
apiIndex: TPaHostApiIndex;
apiInfo: PPaHostApiInfo;
begin
@@ -112,11 +168,11 @@ begin
// select preferred sound-API
for i:= 0 to High(ApiPreferenceOrder) do
begin
- if(ApiPreferenceOrder[i] <> paDefaultApi) then
+ if (ApiPreferenceOrder[i] <> paDefaultApi) then
begin
// check if API is available
apiIndex := Pa_HostApiTypeIdToHostApiIndex(ApiPreferenceOrder[i]);
- if(apiIndex >= 0) then
+ 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
@@ -132,7 +188,7 @@ begin
end;
// None of the preferred APIs is available -> use default
- if(result < 0) then
+ if (result < 0) then
begin
result := Pa_GetDefaultHostApi();
end;
@@ -141,9 +197,9 @@ end;
{*
* Portaudio test callback used by TestDevice().
*}
-function TestCallback(input: Pointer; output: Pointer; frameCount: Longword;
+function TestCallback(input: pointer; output: pointer; frameCount: longword;
timeInfo: PPaStreamCallbackTimeInfo; statusFlags: TPaStreamCallbackFlags;
- inputDevice: Pointer): Integer; cdecl;
+ inputDevice: pointer): integer; cdecl;
begin
// this callback is called only once
result := paAbort;
@@ -189,15 +245,15 @@ end;
* 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;
+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;
+ stream: PPaStream;
+ err: TPaError;
cbWorks: boolean;
cbPolls: integer;
- i: integer;
-const
- altSampleRates: array[0..1] of Double = (44100, 48000); // alternative sample-rates
+ i: integer;
begin
Result := false;
@@ -206,7 +262,7 @@ begin
// check if device supports our input-format
err := Pa_IsFormatSupported(inParams, outParams, sampleRate);
- if(err <> paNoError) then
+ if (err <> paNoError) then
begin
// we cannot fix the error -> exit
if (err <> paInvalidSampleRate) then
@@ -244,14 +300,14 @@ begin
err := Pa_OpenStream(stream, inParams, outParams, sampleRate,
paFramesPerBufferUnspecified,
paNoFlag, @TestCallback, nil);
- if(err <> paNoError) then
+ if (err <> paNoError) then
begin
exit;
end;
// start the callback
err := Pa_StartStream(stream);
- if(err <> paNoError) then
+ if (err <> paNoError) then
begin
Pa_CloseStream(stream);
exit;
diff --git a/cmake/src/media/UAudioDecoder_Bass.pas b/cmake/src/media/UAudioDecoder_Bass.pas
index 6bbdaeaa..d6d2425a 100644
--- a/cmake/src/media/UAudioDecoder_Bass.pas
+++ b/cmake/src/media/UAudioDecoder_Bass.pas
@@ -38,11 +38,12 @@ implementation
uses
Classes,
SysUtils,
+ bass,
UMain,
UMusic,
UAudioCore_Bass,
ULog,
- bass;
+ UPath;
type
TBassDecodeStream = class(TAudioDecodeStream)
@@ -75,7 +76,7 @@ type
function InitializeDecoder(): boolean;
function FinalizeDecoder(): boolean;
- function Open(const Filename: string): TAudioDecodeStream;
+ function Open(const Filename: IPath): TAudioDecodeStream;
end;
var
@@ -213,7 +214,10 @@ end;
function TAudioDecoder_Bass.InitializeDecoder(): boolean;
begin
+ Result := false;
BassCore := TAudioCore_Bass.GetInstance();
+ if not BassCore.CheckVersion then
+ Exit;
Result := true;
end;
@@ -222,7 +226,7 @@ begin
Result := true;
end;
-function TAudioDecoder_Bass.Open(const Filename: string): TAudioDecodeStream;
+function TAudioDecoder_Bass.Open(const Filename: IPath): TAudioDecodeStream;
var
Stream: HSTREAM;
ChannelInfo: BASS_CHANNELINFO;
@@ -237,7 +241,14 @@ begin
// TODO: use BASS_STREAM_PRESCAN for accurate seeking in VBR-files?
// disadvantage: seeking will slow down.
- Stream := BASS_StreamCreateFile(False, PAnsiChar(Filename), 0, 0, BASS_STREAM_DECODE);
+
+ {$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');
@@ -247,7 +258,7 @@ begin
// check if BASS opened some erroneously recognized file-formats
if BASS_ChannelGetInfo(Stream, channelInfo) then
begin
- fileExt := ExtractFileExt(Filename);
+ 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
diff --git a/cmake/src/media/UAudioDecoder_FFmpeg.pas b/cmake/src/media/UAudioDecoder_FFmpeg.pas
index 97d8a8df..7ca98885 100644
--- a/cmake/src/media/UAudioDecoder_FFmpeg.pas
+++ b/cmake/src/media/UAudioDecoder_FFmpeg.pas
@@ -56,23 +56,24 @@ interface
implementation
uses
+ SDL, // SDL redefines some base types -> include before SysUtils to ignore them
Classes,
Math,
- UMusic,
- UIni,
- UMain,
+ SysUtils,
avcodec,
avformat,
avutil,
avio,
mathematics, // used for av_rescale_q
rational,
- SDL,
- SysUtils,
+ UMusic,
+ UIni,
+ UMain,
UMediaCore_FFmpeg,
ULog,
UCommon,
- UConfig;
+ UConfig,
+ UPath;
const
MAX_AUDIOQ_SIZE = (5 * 16 * 1024);
@@ -138,7 +139,7 @@ type
AudioBufferSize: integer;
AudioBuffer: PByteArray;
- Filename: string;
+ Filename: IPath;
procedure SetPositionIntern(Time: real; Flush: boolean; Blocking: boolean);
procedure SetEOF(State: boolean); {$IFDEF HasInline}inline;{$ENDIF}
@@ -161,7 +162,7 @@ type
constructor Create();
destructor Destroy(); override;
- function Open(const Filename: string): boolean;
+ function Open(const Filename: IPath): boolean;
procedure Close(); override;
function GetLength(): real; override;
@@ -183,7 +184,7 @@ type
function InitializeDecoder(): boolean;
function FinalizeDecoder(): boolean;
- function Open(const Filename: string): TAudioDecodeStream;
+ function Open(const Filename: IPath): TAudioDecodeStream;
end;
var
@@ -270,7 +271,7 @@ begin
inherited;
end;
-function TFFmpegDecodeStream.Open(const Filename: string): boolean;
+function TFFmpegDecodeStream.Open(const Filename: IPath): boolean;
var
SampleFormat: TAudioSampleFormat;
AVResult: integer;
@@ -280,18 +281,18 @@ begin
Close();
Reset();
- if (not FileExists(Filename)) then
+ if (not Filename.IsFile) then
begin
- Log.LogError('Audio-file does not exist: "' + Filename + '"', 'UAudio_FFmpeg');
+ Log.LogError('Audio-file does not exist: "' + Filename.ToNative + '"', 'UAudio_FFmpeg');
Exit;
end;
Self.Filename := Filename;
- // open audio file
- if (av_open_input_file(FormatCtx, PAnsiChar(Filename), nil, 0, nil) <> 0) then
+ // use custom 'ufile' protocol for UTF-8 support
+ if (av_open_input_file(FormatCtx, PAnsiChar('ufile:'+FileName.ToUTF8), nil, 0, nil) <> 0) then
begin
- Log.LogError('av_open_input_file failed: "' + Filename + '"', 'UAudio_FFmpeg');
+ Log.LogError('av_open_input_file failed: "' + Filename.ToNative + '"', 'UAudio_FFmpeg');
Exit;
end;
@@ -301,7 +302,7 @@ begin
// retrieve stream information
if (av_find_stream_info(FormatCtx) < 0) then
begin
- Log.LogError('av_find_stream_info failed: "' + Filename + '"', 'UAudio_FFmpeg');
+ Log.LogError('av_find_stream_info failed: "' + Filename.ToNative + '"', 'UAudio_FFmpeg');
Close();
Exit;
end;
@@ -310,13 +311,13 @@ begin
FormatCtx^.pb.eof_reached := 0;
{$IFDEF DebugFFmpegDecode}
- dump_format(FormatCtx, 0, PAnsiChar(Filename), 0);
+ dump_format(FormatCtx, 0, PAnsiChar(Filename.ToNative), 0);
{$ENDIF}
AudioStreamIndex := FFmpegCore.FindAudioStreamIndex(FormatCtx);
if (AudioStreamIndex < 0) then
begin
- Log.LogError('FindAudioStreamIndex: No Audio-stream found "' + Filename + '"', 'UAudio_FFmpeg');
+ Log.LogError('FindAudioStreamIndex: No Audio-stream found "' + Filename.ToNative + '"', 'UAudio_FFmpeg');
Close();
Exit;
end;
@@ -324,6 +325,7 @@ begin
//Log.LogStatus('AudioStreamIndex is: '+ inttostr(ffmpegStreamID), 'UAudio_FFmpeg');
AudioStream := FormatCtx.streams[AudioStreamIndex];
+ AudioStreamPos := 0;
CodecCtx := AudioStream^.codec;
// TODO: should we use this or not? Should we allow 5.1 channel audio?
@@ -574,30 +576,38 @@ begin
PauseParser();
PauseDecoder();
SDL_mutexP(StateLock);
-
- // configure seek parameters
- SeekPos := Time;
- SeekFlush := Flush;
- SeekFlags := AVSEEK_FLAG_ANY;
- SeekRequest := 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 < AudioStreamPos) then
- SeekFlags := SeekFlags or AVSEEK_FLAG_BACKWARD;
-
- EOFState := false;
- ErrorState := false;
-
- // send a reuse signal in case the parser was stopped (e.g. because of an EOF)
- SDL_CondSignal(ParserIdleCond);
-
- SDL_mutexV(StateLock);
- ResumeDecoder();
- ResumeParser();
+ try
+ EOFState := false;
+ ErrorState := 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 = AudioStreamPos) then
+ Exit;
+
+ // configure seek parameters
+ SeekPos := Time;
+ SeekFlush := Flush;
+ SeekFlags := AVSEEK_FLAG_ANY;
+ SeekRequest := 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 <= AudioStreamPos) then
+ SeekFlags := SeekFlags or AVSEEK_FLAG_BACKWARD;
+
+ // send a reuse signal in case the parser was stopped (e.g. because of an EOF)
+ SDL_CondSignal(ParserIdleCond);
+ finally
+ SDL_mutexV(StateLock);
+ ResumeDecoder();
+ ResumeParser();
+ end;
// in blocking mode, wait until seeking is done
if (Blocking) then
@@ -1117,7 +1127,7 @@ begin
Result := true;
end;
-function TAudioDecoder_FFmpeg.Open(const Filename: string): TAudioDecodeStream;
+function TAudioDecoder_FFmpeg.Open(const Filename: IPath): TAudioDecodeStream;
var
Stream: TFFmpegDecodeStream;
begin
diff --git a/cmake/src/media/UAudioInput_Bass.pas b/cmake/src/media/UAudioInput_Bass.pas
index ad6c3818..b8f914c5 100644
--- a/cmake/src/media/UAudioInput_Bass.pas
+++ b/cmake/src/media/UAudioInput_Bass.pas
@@ -46,6 +46,7 @@ uses
UIni,
ULog,
UAudioCore_Bass,
+ UTextEncoding,
UCommon, // (Note: for MakeLong on non-windows platforms)
{$IFDEF MSWINDOWS}
Windows, // (Note: for MakeLong)
@@ -352,7 +353,7 @@ end;
function TAudioInput_Bass.EnumDevices(): boolean;
var
- Descr: PChar;
+ Descr: UTF8String;
SourceName: PChar;
Flags: integer;
BassDeviceID: integer;
@@ -389,9 +390,12 @@ begin
BassDevice := TBassInputDevice.Create();
AudioInputProcessor.DeviceList[DeviceIndex] := BassDevice;
- Descr := DeviceInfo.name;
-
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)
@@ -459,7 +463,9 @@ begin
break;
SetLength(BassDevice.Source, Length(BassDevice.Source)+1);
- BassDevice.Source[SourceIndex].Name := SourceName;
+ // 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)^);
@@ -489,6 +495,11 @@ end;
function TAudioInput_Bass.InitializeRecord(): boolean;
begin
BassCore := TAudioCore_Bass.GetInstance();
+ if not BassCore.CheckVersion then
+ begin
+ Result := false;
+ Exit;
+ end;
Result := EnumDevices();
end;
diff --git a/cmake/src/media/UAudioInput_Portaudio.pas b/cmake/src/media/UAudioInput_Portaudio.pas
index 31d2882b..c7364eb4 100644
--- a/cmake/src/media/UAudioInput_Portaudio.pas
+++ b/cmake/src/media/UAudioInput_Portaudio.pas
@@ -45,11 +45,14 @@ uses
portmixer,
{$ENDIF}
portaudio,
+ ctypes,
UAudioCore_Portaudio,
- URecord,
+ UUnicodeUtils,
+ UTextEncoding,
UIni,
ULog,
- UMain;
+ UMain,
+ URecord;
type
TAudioInput_Portaudio = class(TAudioInputBase)
@@ -57,7 +60,7 @@ type
AudioCore: TAudioCore_Portaudio;
function EnumDevices(): boolean;
public
- function GetName: String; override;
+ function GetName: string; override;
function InitializeRecord: boolean; override;
function FinalizeRecord: boolean; override;
end;
@@ -70,31 +73,76 @@ type
{$ENDIF}
PaDeviceIndex: TPaDeviceIndex;
public
- function Open(): boolean;
+ function Open(): boolean;
function Close(): boolean;
function Start(): boolean; override;
- function Stop(): 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: Longword;
+function MicrophoneCallback(input: pointer; output: pointer; frameCount: culong;
timeInfo: PPaStreamCallbackTimeInfo; statusFlags: TPaStreamCallbackFlags;
- inputDevice: Pointer): Integer; cdecl; forward;
+ inputDevice: pointer): cint; cdecl; forward;
-function MicrophoneTestCallback(input: Pointer; output: Pointer; frameCount: Longword;
+function MicrophoneTestCallback(input: pointer; output: pointer; frameCount: culong;
timeInfo: PPaStreamCallbackTimeInfo; statusFlags: TPaStreamCallbackFlags;
- inputDevice: Pointer): Integer; cdecl; forward;
+ 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;
@@ -107,19 +155,19 @@ begin
device := PaDeviceIndex;
channelCount := AudioFormat.Channels;
sampleFormat := paInt16;
- suggestedLatency := deviceInfo^.defaultLowInputLatency;
+ suggestedLatency := DetermineInputLatency(deviceInfo);
hostApiSpecificStreamInfo := nil;
end;
- //Log.LogStatus(deviceInfo^.name, 'Portaudio');
- //Log.LogStatus(floattostr(deviceInfo^.defaultLowInputLatency), 'Portaudio');
+ 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
+ @MicrophoneCallback, pointer(Self));
+ if (Error <> paNoError) then
begin
Log.LogError('Error opening stream: ' + Pa_GetErrorText(Error), 'TPortaudioInputDevice.Open');
Exit;
@@ -155,7 +203,7 @@ end;
function TPortaudioInputDevice.Start(): boolean;
var
- Error: TPaError;
+ Error: TPaError;
begin
Result := false;
@@ -169,7 +217,7 @@ begin
// start capture
Error := Pa_StartStream(RecordStream);
- if(Error <> paNoError) then
+ if (Error <> paNoError) then
begin
Log.LogError('Error starting stream: ' + Pa_GetErrorText(Error), 'TPortaudioInputDevice.Start');
Close();
@@ -268,34 +316,36 @@ end;
function TAudioInput_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: TPortaudioInputDevice;
- inputParams: TPaStreamParameters;
- stream: PPaStream;
- streamInfo: PPaStreamInfo;
- sampleRate: double;
- latency: TPaTime;
+ 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: string;
+ 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
+ if (paApiIndex = -1) then
begin
Log.LogError('No working Audio-API found', 'TAudioInput_Portaudio.EnumDevices');
Exit;
@@ -303,17 +353,17 @@ begin
paApiInfo := Pa_GetHostApiInfo(paApiIndex);
- SC := 0;
+ 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
- deviceIndex := Pa_HostApiDeviceIndexToDeviceIndex(paApiIndex, i);
- deviceInfo := Pa_GetDeviceInfo(deviceIndex);
+ paDeviceIndex := Pa_HostApiDeviceIndexToDeviceIndex(paApiIndex, i);
+ paDeviceInfo := Pa_GetDeviceInfo(paDeviceIndex);
- channelCnt := deviceInfo^.maxInputChannels;
+ channelCnt := paDeviceInfo^.maxInputChannels;
// current device is no input device -> skip
if (channelCnt <= 0) then
@@ -326,25 +376,25 @@ begin
channelCnt := 2;
paDevice := TPortaudioInputDevice.Create();
- AudioInputProcessor.DeviceList[SC] := paDevice;
+ AudioInputProcessor.DeviceList[deviceIndex] := paDevice;
// retrieve device-name
- deviceName := deviceInfo^.name;
- paDevice.Name := deviceName;
- paDevice.PaDeviceIndex := deviceIndex;
+ deviceName := ConvertPaStringToUTF8(paDeviceInfo^.name);
+ paDevice.Name := UnifyDeviceName(deviceName, deviceIndex);
+ paDevice.PaDeviceIndex := paDeviceIndex;
- sampleRate := deviceInfo^.defaultSampleRate;
+ sampleRate := paDeviceInfo^.defaultSampleRate;
- // 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;
+ // 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
- // TODO: retry with input-latency set to 20ms (defaultLowInputLatency might
- // not be set correctly in OSS)
with inputParams do
begin
- device := deviceIndex;
+ device := paDeviceIndex;
channelCount := channelCnt;
sampleFormat := paInt16;
suggestedLatency := latency;
@@ -364,7 +414,7 @@ begin
// open device for further info
err := Pa_OpenStream(stream, @inputParams, nil, sampleRate,
paFramesPerBufferUnspecified, paNoFlag, @MicrophoneTestCallback, nil);
- if(err <> paNoError) then
+ if (err <> paNoError) then
begin
// unable to open device -> skip
errMsg := Pa_GetErrorText(err);
@@ -421,7 +471,7 @@ begin
for sourceIndex := 1 to sourceCnt do
begin
sourceName := Px_GetInputSourceName(mixer, sourceIndex-1);
- paDevice.Source[sourceIndex].Name := sourceName;
+ paDevice.Source[sourceIndex].Name := ConvertPaStringToUTF8(sourceName);
end;
Px_CloseMixer(mixer);
@@ -430,48 +480,41 @@ begin
// close test-stream
Pa_CloseStream(stream);
- Inc(SC);
+ Inc(deviceIndex);
end;
// adjust size to actual input-device count
- SetLength(AudioInputProcessor.DeviceList, SC);
+ SetLength(AudioInputProcessor.DeviceList, deviceIndex);
- Log.LogStatus('#Input-Devices: ' + inttostr(SC), 'Portaudio');
+ Log.LogStatus('#Input-Devices: ' + inttostr(deviceIndex), 'Portaudio');
Result := true;
end;
function TAudioInput_Portaudio.InitializeRecord(): boolean;
-var
- err: TPaError;
begin
+ Result := false;
AudioCore := TAudioCore_Portaudio.GetInstance();
// initialize portaudio
- err := Pa_Initialize();
- if(err <> paNoError) then
- begin
- Log.LogError(Pa_GetErrorText(err), 'TAudioInput_Portaudio.InitializeRecord');
- Result := false;
- Exit;
- end;
-
+ if (not AudioCore.Initialize()) then
+ Exit;
Result := EnumDevices();
end;
function TAudioInput_Portaudio.FinalizeRecord: boolean;
begin
CaptureStop;
- Pa_Terminate();
+ AudioCore.Terminate();
Result := inherited FinalizeRecord();
end;
{*
* Portaudio input capture callback.
*}
-function MicrophoneCallback(input: Pointer; output: Pointer; frameCount: Longword;
+function MicrophoneCallback(input: pointer; output: pointer; frameCount: culong;
timeInfo: PPaStreamCallbackTimeInfo; statusFlags: TPaStreamCallbackFlags;
- inputDevice: Pointer): Integer; cdecl;
+ inputDevice: pointer): cint; cdecl;
begin
AudioInputProcessor.HandleMicrophoneData(input, frameCount*4, inputDevice);
result := paContinue;
@@ -480,15 +523,14 @@ end;
{*
* Portaudio test capture callback.
*}
-function MicrophoneTestCallback(input: Pointer; output: Pointer; frameCount: Longword;
+function MicrophoneTestCallback(input: pointer; output: pointer; frameCount: culong;
timeInfo: PPaStreamCallbackTimeInfo; statusFlags: TPaStreamCallbackFlags;
- inputDevice: Pointer): Integer; cdecl;
+ inputDevice: pointer): cint; cdecl;
begin
// this callback is called only once
result := paAbort;
end;
-
initialization
MediaManager.add(TAudioInput_Portaudio.Create);
diff --git a/cmake/src/media/UAudioPlaybackBase.pas b/cmake/src/media/UAudioPlaybackBase.pas
index 7d143fdc..5f317257 100644
--- a/cmake/src/media/UAudioPlaybackBase.pas
+++ b/cmake/src/media/UAudioPlaybackBase.pas
@@ -34,7 +34,9 @@ interface
{$I switches.inc}
uses
- UMusic;
+ UMusic,
+ UTime,
+ UPath;
type
TAudioPlaybackBase = class(TInterfacedObject, IAudioPlayback)
@@ -46,12 +48,12 @@ type
function GetLatency(): double; virtual; abstract;
// open sound or music stream (used by Open() and OpenSound())
- function OpenStream(const Filename: string): TAudioPlaybackStream;
- function OpenDecodeStream(const Filename: string): TAudioDecodeStream;
+ function OpenStream(const Filename: IPath): TAudioPlaybackStream;
+ function OpenDecodeStream(const Filename: IPath): TAudioDecodeStream;
public
function GetName: string; virtual; abstract;
- function Open(const Filename: string): boolean; // true if succeed
+ function Open(const Filename: IPath): boolean; // true if succeed
procedure Close;
procedure Play;
@@ -79,7 +81,7 @@ type
function Length: real;
// Sounds
- function OpenSound(const Filename: string): TAudioPlaybackStream;
+ function OpenSound(const Filename: IPath): TAudioPlaybackStream;
procedure PlaySound(Stream: TAudioPlaybackStream);
procedure StopSound(Stream: TAudioPlaybackStream);
@@ -108,7 +110,7 @@ begin
Result := true;
end;
-function TAudioPlaybackBase.Open(const Filename: string): boolean;
+function TAudioPlaybackBase.Open(const Filename: IPath): boolean;
begin
// free old MusicStream
MusicStream.Free;
@@ -130,7 +132,7 @@ begin
FreeAndNil(MusicStream);
end;
-function TAudioPlaybackBase.OpenDecodeStream(const Filename: String): TAudioDecodeStream;
+function TAudioPlaybackBase.OpenDecodeStream(const Filename: IPath): TAudioDecodeStream;
var
i: integer;
begin
@@ -140,7 +142,7 @@ begin
if (assigned(Result)) then
begin
Log.LogInfo('Using decoder ' + IAudioDecoder(AudioDecoders[i]).GetName() +
- ' for "' + Filename + '"', 'TAudioPlaybackBase.OpenDecodeStream');
+ ' for "' + Filename.ToNative + '"', 'TAudioPlaybackBase.OpenDecodeStream');
Exit;
end;
end;
@@ -157,7 +159,7 @@ begin
SourceStream.Free;
end;
-function TAudioPlaybackBase.OpenStream(const Filename: string): TAudioPlaybackStream;
+function TAudioPlaybackBase.OpenStream(const Filename: IPath): TAudioPlaybackStream;
var
PlaybackStream: TAudioPlaybackStream;
DecodeStream: TAudioDecodeStream;
@@ -169,7 +171,7 @@ begin
DecodeStream := OpenDecodeStream(Filename);
if (not assigned(DecodeStream)) then
begin
- Log.LogStatus('Could not open "' + Filename + '"', 'TAudioPlayback_Bass.OpenStream');
+ Log.LogStatus('Could not open "' + Filename.ToNative + '"', 'TAudioPlayback_Bass.OpenStream');
Exit;
end;
@@ -283,7 +285,7 @@ begin
Result := 0;
end;
-function TAudioPlaybackBase.OpenSound(const Filename: string): TAudioPlaybackStream;
+function TAudioPlaybackBase.OpenSound(const Filename: IPath): TAudioPlaybackStream;
begin
Result := OpenStream(Filename);
end;
diff --git a/cmake/src/media/UAudioPlayback_Bass.pas b/cmake/src/media/UAudioPlayback_Bass.pas
index 923c1d7b..1d7a44dc 100644
--- a/cmake/src/media/UAudioPlayback_Bass.pas
+++ b/cmake/src/media/UAudioPlayback_Bass.pas
@@ -684,9 +684,11 @@ end;
function TAudioPlayback_Bass.InitializePlayback(): boolean;
begin
- result := false;
+ Result := false;
BassCore := TAudioCore_Bass.GetInstance();
+ if not BassCore.CheckVersion then
+ Exit;
EnumDevices();
@@ -706,7 +708,7 @@ begin
//BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 10);
//BASS_SetConfig(BASS_CONFIG_BUFFER, 100);
- result := true;
+ Result := true;
end;
function TAudioPlayback_Bass.FinalizePlayback(): boolean;
diff --git a/cmake/src/media/UAudioPlayback_Portaudio.pas b/cmake/src/media/UAudioPlayback_Portaudio.pas
index ddbd03d6..6fbae6e3 100644
--- a/cmake/src/media/UAudioPlayback_Portaudio.pas
+++ b/cmake/src/media/UAudioPlayback_Portaudio.pas
@@ -307,22 +307,16 @@ var
paApiIndex : TPaHostApiIndex;
paApiInfo : PPaHostApiInfo;
paOutDevice : TPaDeviceIndex;
- err: TPaError;
begin
Result := false;
-
AudioCore := TAudioCore_Portaudio.GetInstance();
// initialize portaudio
- err := Pa_Initialize();
- if(err <> paNoError) then
- begin
- Log.LogError(Pa_GetErrorText(err), 'TAudioInput_Portaudio.InitializeRecord');
+ if (not AudioCore.Initialize()) then
Exit;
- end;
paApiIndex := AudioCore.GetPreferredApiIndex();
- if(paApiIndex = -1) then
+ if (paApiIndex = -1) then
begin
Log.LogError('No working Audio-API found', 'TAudioPlayback_Portaudio.InitializeAudioPlaybackEngine');
Exit;
@@ -364,13 +358,19 @@ end;
procedure TAudioPlayback_Portaudio.StopAudioPlaybackEngine();
begin
if (paStream <> nil) then
- Pa_StopStream(paStream);
+ 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
- Pa_Terminate();
- Result := true;
+ StopAudioPlaybackEngine();
+ Result := AudioCore.Terminate();
end;
function TAudioPlayback_Portaudio.GetLatency(): double;
diff --git a/cmake/src/media/UAudioPlayback_SoftMixer.pas b/cmake/src/media/UAudioPlayback_SoftMixer.pas
index c87e461d..11df4df5 100644
--- a/cmake/src/media/UAudioPlayback_SoftMixer.pas
+++ b/cmake/src/media/UAudioPlayback_SoftMixer.pas
@@ -47,6 +47,8 @@ type
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;
@@ -58,7 +60,7 @@ type
SourceBufferCount: integer; // number of available bytes in SourceBuffer
Converter: TAudioConverter;
- Status: TStreamStatus;
+ Status: TStreamStatus;
InternalLock: PSDL_Mutex;
SoundEffects: TList;
fVolume: single;
@@ -86,6 +88,8 @@ type
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;
@@ -102,7 +106,7 @@ type
function ReadData(Buffer: PByteArray; BufferSize: integer): integer;
- function GetPCMData(var Data: TPCMData): Cardinal; override;
+ function GetPCMData(var Data: TPCMData): cardinal; override;
procedure GetFFTData(var Data: TFFTData); override;
procedure AddSoundEffect(Effect: TSoundEffect); override;
@@ -148,7 +152,7 @@ type
function CreatePlaybackStream(): TAudioPlaybackStream; override;
public
- function GetName: String; override; abstract;
+ function GetName: string; override; abstract;
function InitializePlayback(): boolean; override;
function FinalizePlayback: boolean; override;
@@ -159,7 +163,7 @@ type
function GetMixer(): TAudioMixerStream; {$IFDEF HasInline}inline;{$ENDIF}
function GetAudioFormatInfo(): TAudioFormatInfo;
- procedure MixBuffers(DstBuffer, SrcBuffer: PByteArray; Size: Cardinal; Volume: Single); virtual;
+ procedure MixBuffers(DstBuffer, SrcBuffer: PByteArray; Size: cardinal; Volume: single); virtual;
end;
type
@@ -369,6 +373,8 @@ begin
fVolume := 0;
SoundEffects.Clear;
FadeInTime := 0;
+
+ LastReadSize := 0;
end;
function TGenericPlaybackStream.Open(SourceStream: TAudioSourceStream): boolean;
@@ -377,11 +383,11 @@ begin
Close();
- if (not assigned(SourceStream)) then
+ if not assigned(SourceStream) then
Exit;
Self.SourceStream := SourceStream;
- if (not InitFormatConversion()) then
+ if not InitFormatConversion() then
begin
// reset decode-stream so it will not be freed on destruction
Self.SourceStream := nil;
@@ -495,7 +501,11 @@ begin
Exit;
Status := ssStopped;
+ // stop fading
+ FadeInTime := 0;
+ LastReadSize := 0;
+
Mixer := Engine.GetMixer();
if (Mixer <> nil) then
Mixer.RemoveStream(Self);
@@ -543,6 +553,7 @@ begin
SampleBufferCount := 0;
SampleBufferPos := 0;
SourceBufferCount := 0;
+ LastReadSize := 0;
end;
procedure TGenericPlaybackStream.ApplySoundEffects(Buffer: PByteArray; BufferSize: integer);
@@ -576,6 +587,8 @@ var
begin
Result := -1;
+ LastReadSize := 0;
+
// sanity check for the source-stream
if (not assigned(SourceStream)) then
Exit;
@@ -747,10 +760,12 @@ begin
end;
// BytesNeeded now contains the number of remaining bytes we were not able to fetch
- Result := BufferSize - BytesNeeded;
+ LastReadTime := SDL_GetTicks;
+ LastReadSize := BufferSize - BytesNeeded;
+ Result := LastReadSize;
end;
-function TGenericPlaybackStream.GetPCMData(var Data: TPCMData): Cardinal;
+function TGenericPlaybackStream.GetPCMData(var Data: TPCMData): cardinal;
var
ByteCount: integer;
begin
@@ -790,7 +805,7 @@ begin
// only works with SInt16 and Float values at the moment
AudioFormat := GetAudioFormatInfo();
- DataIn := AllocMem(FFTSize * SizeOf(Single));
+ DataIn := AllocMem(FFTSize * SizeOf(single));
if (DataIn = nil) then
Exit;
@@ -842,6 +857,28 @@ begin
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;
@@ -850,11 +887,24 @@ begin
begin
LockSampleBuffer();
- // calc the time of source data that is buffered (in the SampleBuffer and SourceBuffer)
- // but not yet outputed
- BufferedTime := (SampleBufferCount - SampleBufferPos) / Engine.FormatInfo.BytesPerSec +
- SourceBufferCount / SourceStream.GetAudioFormatInfo().BytesPerSec;
- // and subtract it from the source position
+ // 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();
@@ -885,7 +935,7 @@ end;
function TGenericPlaybackStream.GetVolume(): single;
var
- FadeAmount: Single;
+ FadeAmount: single;
begin
LockSampleBuffer();
// adjust volume if fading is enabled
@@ -1033,12 +1083,12 @@ begin
//Log.LogStatus('InitializePlayback', 'UAudioPlayback_SoftMixer');
- if(not InitializeAudioPlaybackEngine()) then
+ if (not InitializeAudioPlaybackEngine()) then
Exit;
MixerStream := TAudioMixerStream.Create(Self);
- if(not StartAudioPlaybackEngine()) then
+ if (not StartAudioPlaybackEngine()) then
Exit;
Result := true;
@@ -1100,11 +1150,11 @@ begin
MixerStream.Volume := Volume;
end;
-procedure TAudioPlayback_SoftMixer.MixBuffers(DstBuffer, SrcBuffer: PByteArray; Size: Cardinal; Volume: Single);
+procedure TAudioPlayback_SoftMixer.MixBuffers(DstBuffer, SrcBuffer: PByteArray; Size: cardinal; Volume: single);
var
- SampleIndex: Cardinal;
- SampleInt: Integer;
- SampleFlt: Single;
+ SampleIndex: cardinal;
+ SampleInt: integer;
+ SampleFlt: single;
begin
SampleIndex := 0;
case FormatInfo.Format of
@@ -1141,7 +1191,7 @@ begin
// assign result
PSingle(@DstBuffer[SampleIndex])^ := SampleFlt;
// increase index by one sample
- Inc(SampleIndex, SizeOf(Single));
+ Inc(SampleIndex, SizeOf(single));
end;
end;
else
diff --git a/cmake/src/media/UMediaCore_FFmpeg.pas b/cmake/src/media/UMediaCore_FFmpeg.pas
index 9ad19a5b..2d572ff2 100644
--- a/cmake/src/media/UMediaCore_FFmpeg.pas
+++ b/cmake/src/media/UMediaCore_FFmpeg.pas
@@ -34,12 +34,16 @@ interface
{$I switches.inc}
uses
- UMusic,
+ Classes,
+ ctypes,
+ sdl,
avcodec,
avformat,
avutil,
+ avio,
+ UMusic,
ULog,
- sdl;
+ UPath;
type
PPacketQueue = ^TPacketQueue;
@@ -95,7 +99,24 @@ type
implementation
uses
- SysUtils;
+ 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;
@@ -103,6 +124,7 @@ var
constructor TMediaCore_FFmpeg.Create();
begin
inherited;
+ av_register_protocol(@UTF8FileProtocol);
AVCodecLock := SDL_CreateMutex();
end;
@@ -163,6 +185,7 @@ begin
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
@@ -175,6 +198,20 @@ 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
@@ -194,7 +231,11 @@ begin
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;
@@ -220,6 +261,105 @@ begin
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();
diff --git a/cmake/src/media/UMedia_dummy.pas b/cmake/src/media/UMedia_dummy.pas
index 7558dd0b..8ebfd3a9 100644
--- a/cmake/src/media/UMedia_dummy.pas
+++ b/cmake/src/media/UMedia_dummy.pas
@@ -36,22 +36,24 @@ interface
implementation
uses
- SysUtils,
- math,
- UMusic;
+ SysUtils,
+ math,
+ UTime,
+ UMusic,
+ UPath;
type
- TMedia_dummy = class( TInterfacedObject, IVideoPlayback, IVideoVisualization, IAudioPlayback, IAudioInput )
+ TAudio_Dummy = class( TInterfacedObject, IAudioPlayback, IAudioInput )
private
DummyOutputDeviceList: TAudioOutputDeviceList;
public
constructor Create();
- function GetName: string;
+ function GetName: string;
function Init(): boolean;
function Finalize(): boolean;
- function Open(const aFileName : string): boolean; // true if succeed
+ function Open(const aFileName: IPath): boolean; // true if succeed
procedure Close;
procedure Play;
@@ -63,9 +65,6 @@ type
procedure SetSyncSource(SyncSource: TSyncSource);
- procedure GetFrame(Time: Extended);
- procedure DrawGL(Screen: integer);
-
// IAudioInput
function InitializeRecord: boolean;
function FinalizeRecord: boolean;
@@ -82,13 +81,15 @@ type
procedure FadeIn(Time: real; TargetVolume: single);
procedure SetAppVolume(Volume: single);
procedure SetVolume(Volume: single);
- procedure SetLoop(Enabled: boolean);
procedure Rewind;
+ procedure SetLoop(Enabled: boolean);
+ function GetLoop(): boolean;
+
function Finished: boolean;
function Length: real;
- function OpenSound(const Filename: string): TAudioPlaybackStream;
+ function OpenSound(const Filename: IPath): TAudioPlaybackStream;
procedure CloseSound(var PlaybackStream: TAudioPlaybackStream);
procedure PlaySound(stream: TAudioPlaybackStream);
procedure StopSound(stream: TAudioPlaybackStream);
@@ -97,98 +98,122 @@ type
procedure CloseVoiceStream(var VoiceStream: TAudioVoiceStream);
end;
-function TMedia_dummy.GetName: string;
-begin
- Result := 'dummy';
-end;
+ TVideo_Dummy = class( TInterfacedObject, IVideo )
+ public
+ procedure Close;
-procedure TMedia_dummy.GetFrame(Time: Extended);
-begin
-end;
+ procedure Play;
+ procedure Pause;
+ procedure Stop;
+
+ procedure SetLoop(Enable: boolean);
+ function GetLoop(): boolean;
+
+ procedure SetPosition(Time: real);
+ function GetPosition: real;
+
+ procedure GetFrame(Time: Extended);
+ procedure DrawGL(Screen: integer);
+
+ property Loop: boolean read GetLoop write SetLoop;
+ property Position: real read GetPosition write SetPosition;
+ end;
-procedure TMedia_dummy.DrawGL(Screen: integer);
+ 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 TMedia_dummy.Create();
+constructor TAudio_Dummy.Create();
begin
inherited;
end;
-function TMedia_dummy.Init(): boolean;
+function TAudio_Dummy.Init(): boolean;
begin
Result := true;
end;
-function TMedia_dummy.Finalize(): boolean;
+function TAudio_Dummy.Finalize(): boolean;
begin
Result := true;
end;
-function TMedia_dummy.Open(const aFileName : string): boolean; // true if succeed
+function TAudio_Dummy.Open(const aFileName : IPath): boolean; // true if succeed
begin
Result := false;
end;
-procedure TMedia_dummy.Close;
+procedure TAudio_Dummy.Close;
begin
end;
-procedure TMedia_dummy.Play;
+procedure TAudio_Dummy.Play;
begin
end;
-procedure TMedia_dummy.Pause;
+procedure TAudio_Dummy.Pause;
begin
end;
-procedure TMedia_dummy.Stop;
+procedure TAudio_Dummy.Stop;
begin
end;
-procedure TMedia_dummy.SetPosition(Time: real);
+procedure TAudio_Dummy.SetPosition(Time: real);
begin
end;
-function TMedia_dummy.GetPosition: real;
+function TAudio_Dummy.GetPosition: real;
begin
Result := 0;
end;
-procedure TMedia_dummy.SetSyncSource(SyncSource: TSyncSource);
+procedure TAudio_Dummy.SetSyncSource(SyncSource: TSyncSource);
begin
end;
// IAudioInput
-function TMedia_dummy.InitializeRecord: boolean;
+function TAudio_Dummy.InitializeRecord: boolean;
begin
Result := true;
end;
-function TMedia_dummy.FinalizeRecord: boolean;
+function TAudio_Dummy.FinalizeRecord: boolean;
begin
Result := true;
end;
-procedure TMedia_dummy.CaptureStart;
+procedure TAudio_Dummy.CaptureStart;
begin
end;
-procedure TMedia_dummy.CaptureStop;
+procedure TAudio_Dummy.CaptureStop;
begin
end;
-procedure TMedia_dummy.GetFFTData(var data: TFFTData);
+procedure TAudio_Dummy.GetFFTData(var data: TFFTData);
begin
end;
-function TMedia_dummy.GetPCMData(var data: TPCMData): Cardinal;
+function TAudio_Dummy.GetPCMData(var data: TPCMData): Cardinal;
begin
Result := 0;
end;
// IAudioPlayback
-function TMedia_dummy.InitializePlayback: boolean;
+function TAudio_Dummy.InitializePlayback: boolean;
begin
SetLength(DummyOutputDeviceList, 1);
DummyOutputDeviceList[0] := TAudioOutputDevice.Create();
@@ -196,73 +221,152 @@ begin
Result := true;
end;
-function TMedia_dummy.FinalizePlayback: boolean;
+function TAudio_Dummy.FinalizePlayback: boolean;
begin
Result := true;
end;
-function TMedia_dummy.GetOutputDeviceList(): TAudioOutputDeviceList;
+function TAudio_Dummy.GetOutputDeviceList(): TAudioOutputDeviceList;
begin
Result := DummyOutputDeviceList;
end;
-procedure TMedia_dummy.SetAppVolume(Volume: single);
+procedure TAudio_Dummy.SetAppVolume(Volume: single);
+begin
+end;
+
+procedure TAudio_Dummy.SetVolume(Volume: single);
begin
end;
-procedure TMedia_dummy.SetVolume(Volume: single);
+procedure TAudio_Dummy.SetLoop(Enabled: boolean);
begin
end;
-procedure TMedia_dummy.SetLoop(Enabled: boolean);
+function TAudio_Dummy.GetLoop(): boolean;
begin
+ Result := false;
end;
-procedure TMedia_dummy.FadeIn(Time: real; TargetVolume: single);
+procedure TAudio_Dummy.FadeIn(Time: real; TargetVolume: single);
begin
end;
-procedure TMedia_dummy.Rewind;
+procedure TAudio_Dummy.Rewind;
begin
end;
-function TMedia_dummy.Finished: boolean;
+function TAudio_Dummy.Finished: boolean;
begin
Result := false;
end;
-function TMedia_dummy.Length: real;
+function TAudio_Dummy.Length: real;
begin
Result := 60;
end;
-function TMedia_dummy.OpenSound(const Filename: string): TAudioPlaybackStream;
+function TAudio_Dummy.OpenSound(const Filename: IPath): TAudioPlaybackStream;
begin
Result := nil;
end;
-procedure TMedia_dummy.CloseSound(var PlaybackStream: TAudioPlaybackStream);
+procedure TAudio_Dummy.CloseSound(var PlaybackStream: TAudioPlaybackStream);
begin
end;
-procedure TMedia_dummy.PlaySound(stream: TAudioPlaybackStream);
+procedure TAudio_Dummy.PlaySound(stream: TAudioPlaybackStream);
begin
end;
-procedure TMedia_dummy.StopSound(stream: TAudioPlaybackStream);
+procedure TAudio_Dummy.StopSound(stream: TAudioPlaybackStream);
begin
end;
-function TMedia_dummy.CreateVoiceStream(Channel: integer; FormatInfo: TAudioFormatInfo): TAudioVoiceStream;
+function TAudio_Dummy.CreateVoiceStream(Channel: integer; FormatInfo: TAudioFormatInfo): TAudioVoiceStream;
begin
Result := nil;
end;
-procedure TMedia_dummy.CloseVoiceStream(var VoiceStream: TAudioVoiceStream);
+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.GetFrame(Time: Extended);
+begin
+end;
+
+procedure TVideo_Dummy.DrawGL(Screen: integer);
+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(TMedia_dummy.Create);
+ MediaManager.Add(TAudio_Dummy.Create);
+ MediaManager.Add(TVideoPlayback_Dummy.Create);
end.
diff --git a/cmake/src/media/UVideo.pas b/cmake/src/media/UVideo.pas
index f55690b2..c7d59fc8 100644
--- a/cmake/src/media/UVideo.pas
+++ b/cmake/src/media/UVideo.pas
@@ -22,7 +22,7 @@
* $URL$
* $Id$
*}
-
+
unit UVideo;
{*
@@ -69,8 +69,9 @@ type
implementation
uses
+ SysUtils,
+ Math,
SDL,
- textgl,
avcodec,
avformat,
avutil,
@@ -79,25 +80,36 @@ uses
{$IFDEF UseSWScale}
swscale,
{$ENDIF}
- UMediaCore_FFmpeg,
- math,
gl,
+ glu,
glext,
- SysUtils,
+ textgl,
+ UMediaCore_FFmpeg,
UCommon,
UConfig,
ULog,
UMusic,
UGraphicClasses,
- UGraphic;
+ 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}
type
@@ -106,11 +118,15 @@ type
Upper, Lower: double;
end;
- TVideoPlayback_FFmpeg = class( TInterfacedObject, IVideoPlayback )
+ 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
- fInitialized: boolean;
fEOF: boolean; //**< end-of-file state
fLoop: boolean; //**< looping enabled
@@ -135,43 +151,59 @@ type
fAspect: real; //**< width/height ratio
fAspectCorrection: TAspectCorrection;
-
+
fTimeBase: extended; //**< FFmpeg time base per time unit
- fTime: extended; //**< video time position (absolute)
+ 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 ShowDebugInfo();
public
- function GetName: String;
+ 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;
- function Init(): boolean;
- function Finalize: boolean;
+ procedure SetPosition(Time: real);
+ function GetPosition: real;
- function Open(const aFileName : string): boolean; // true if succeed
- procedure Close;
+ procedure GetFrame(Time: Extended);
+ procedure DrawGL(Screen: integer);
+ end;
+
+ TVideoPlayback_FFmpeg = class( TInterfacedObject, IVideoPlayback )
+ private
+ fInitialized: boolean;
- procedure Play;
- procedure Pause;
- procedure Stop;
+ public
+ function GetName: String;
- procedure SetPosition(Time: real);
- function GetPosition: real;
+ function Init(): boolean;
+ function Finalize: boolean;
- procedure GetFrame(Time: Extended);
- procedure DrawGL(Screen: integer);
+ 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;
@@ -218,53 +250,56 @@ begin
FFmpegCore := TMediaCore_FFmpeg.GetInstance();
- Reset();
av_register_all();
- glGenTextures(1, PGLuint(@fFrameTex));
end;
function TVideoPlayback_FFmpeg.Finalize(): boolean;
begin
- Close();
- glDeleteTextures(1, PGLuint(@fFrameTex));
Result := true;
end;
-procedure TVideoPlayback_FFmpeg.Reset();
+function TVideoPlayback_FFmpeg.Open(const FileName : IPath): IVideo;
+var
+ Video: IVideo_FFmpeg;
begin
- // close previously opened video
- Close();
+ Video := TVideo_FFmpeg.Create;
+ if Video.Open(FileName) then
+ Result := Video
+ else
+ Result := nil;
+end;
- fOpened := False;
- fPaused := False;
- fTimeBase := 0;
- fTime := 0;
- fStream := nil;
- fStreamIndex := -1;
- fFrameTexValid := false;
- fEOF := false;
+{* TVideo_FFmpeg *}
- // TODO: do we really want this by default?
- fLoop := true;
- fLoopTime := 0;
-
- fAspectCorrection := acoCrop;
+constructor TVideo_FFmpeg.Create;
+begin
+ glGenTextures(1, PGLuint(@fFrameTex));
+ Reset();
end;
-function TVideoPlayback_FFmpeg.Open(const aFileName : string): boolean; // true if succeed
+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();
- errnum := av_open_input_file(fFormatContext, PChar(aFileName), nil, 0, nil);
+ 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 "'+aFileName+'" ('+FFmpegCore.GetErrorString(errnum)+')');
+ Log.LogError('Failed to open file "'+ FileName.ToNative +'" ('+FFmpegCore.GetErrorString(errnum)+')');
Exit;
end;
@@ -409,20 +444,63 @@ begin
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);
- glTexEnvi(GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_REPLACE);
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;
+ fOpened := true;
Result := true;
end;
-procedure TVideoPlayback_FFmpeg.Close;
+procedure TVideo_FFmpeg.Reset();
+begin
+ // close previously opened video
+ Close();
+
+ fOpened := False;
+ fPaused := False;
+ fTimeBase := 0;
+ fFrameTime := 0;
+ fStream := nil;
+ fStreamIndex := -1;
+ fFrameTexValid := false;
+
+ fEOF := false;
+
+ fLoop := false;
+ fLoopTime := 0;
+
+ fPboId := 0;
+
+ fAspectCorrection := acoCrop;
+end;
+
+procedure TVideo_FFmpeg.Close;
begin
if (fFrameBuffer <> nil) then
av_free(fFrameBuffer);
@@ -434,7 +512,7 @@ begin
fAVFrame := nil;
fAVFrameRGB := nil;
fFrameBuffer := nil;
-
+
if (fCodecContext <> nil) then
begin
// avcodec_close() is not thread-safe
@@ -452,37 +530,40 @@ begin
fCodecContext := nil;
fFormatContext := nil;
+ if (fPboId <> 0) then
+ glDeleteBuffersARB(1, @fPboId);
+
fOpened := False;
end;
-procedure TVideoPlayback_FFmpeg.SynchronizeTime(Frame: PAVFrame; var pts: double);
+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
- fTime := pts;
+ fFrameTime := pts;
end else
begin
// if we aren't given a pts, set it to the clock
- pts := fTime;
+ 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);
- fTime := fTime + FrameDelay;
+ fFrameTime := fFrameTime + FrameDelay;
end;
{**
* Decode a new frame from the video stream.
- * The decoded frame is stored in fAVFrame. fTime is updated to the new frame's
+ * 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.
+ * @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 TVideoPlayback_FFmpeg.DecodeFrame(): boolean;
+function TVideo_FFmpeg.DecodeFrame(): boolean;
var
FrameFinished: Integer;
VideoPktPts: int64;
@@ -520,7 +601,10 @@ begin
// 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.
@@ -531,18 +615,9 @@ begin
Exit;
end;
- // no error -> wait for user input
-{
- SDL_Delay(100); // initial version, left for documentation
- continue;
-}
-
- // Patch by Hawkear:
- // Why should this function loop in an endless loop if there is an error?
- // This runs in the main thread, so it halts the whole program
- // Therefore, it is better to exit when an error occurs
+ // 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
@@ -573,6 +648,10 @@ begin
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
@@ -587,16 +666,18 @@ begin
Result := true;
end;
-procedure TVideoPlayback_FFmpeg.GetFrame(Time: Extended);
+procedure TVideo_FFmpeg.GetFrame(Time: Extended);
var
errnum: Integer;
- NewTime: Extended;
- TimeDifference: Extended;
+ glErr: GLenum;
+ CurrentTime: Extended;
+ TimeDiff: Extended;
DropFrameCount: Integer;
i: Integer;
Success: boolean;
+ BufferPtr: PGLvoid;
const
- FRAME_DROPCOUNT = 3;
+ SKIP_FRAME_DIFF = 0.010; // start skipping if we are >= 10ms too late
begin
if not fOpened then
Exit;
@@ -604,24 +685,37 @@ begin
if fPaused then
Exit;
+ {*
+ * TODO:
+ * Check if it is correct to assume that fTimeBase is the time of one frame?
+ * The tutorial and FFPlay do not make this assumption.
+ *}
+
+ {*
+ * Synchronization - begin
+ *}
+
// requested stream position (relative to the last loop's start)
- NewTime := Time - fLoopTime;
+ 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
- TimeDifference := NewTime - fTime;
+ TimeDiff := CurrentTime - fFrameTime;
{$IFDEF DebugDisplay}
DebugWriteln('Time: '+inttostr(floor(Time*1000)) + sLineBreak +
- 'VideoTime: '+inttostr(floor(fTime*1000)) + sLineBreak +
+ 'VideoTime: '+inttostr(floor(fFrameTime*1000)) + sLineBreak +
'TimeBase: '+inttostr(floor(fTimeBase*1000)) + sLineBreak +
'TimeDiff: '+inttostr(floor(TimeDifference*1000)));
{$endif}
- // check if last time is more than one frame in the past
- if (TimeDifference < fTimeBase) then
+ // check if time has reached the next frame
+ if (TimeDiff < fTimeBase) then
begin
{$ifdef DebugFrames}
// frame delay debug display
@@ -631,7 +725,7 @@ begin
{$IFDEF DebugDisplay}
DebugWriteln('not getting new frame' + sLineBreak +
'Time: '+inttostr(floor(Time*1000)) + sLineBreak +
- 'VideoTime: '+inttostr(floor(fTime*1000)) + sLineBreak +
+ 'VideoTime: '+inttostr(floor(fFrameTime*1000)) + sLineBreak +
'TimeBase: '+inttostr(floor(fTimeBase*1000)) + sLineBreak +
'TimeDiff: '+inttostr(floor(TimeDifference*1000)));
{$endif}
@@ -644,13 +738,16 @@ begin
{$IFDEF VideoBenchmark}
Log.BenchmarkStart(15);
{$ENDIF}
-
- // fetch new frame (updates fTime)
+
+ // fetch new frame (updates fFrameTime)
Success := DecodeFrame();
- TimeDifference := NewTime - fTime;
+ TimeDiff := CurrentTime - fFrameTime;
// check if we have to skip frames
- if (TimeDifference >= FRAME_DROPCOUNT*fTimeBase) then
+ // Either if we are one frame behind or if the skip threshold has been reached.
+ // Do not skip if the difference is less than fTimeBase as there is no next frame.
+ // Note: We assume that fTimeBase is the length of one frame.
+ if (TimeDiff >= Max(fTimeBase, SKIP_FRAME_DIFF)) then
begin
{$IFDEF DebugFrames}
//frame drop debug display
@@ -663,15 +760,15 @@ begin
{$endif}
// update video-time
- DropFrameCount := Trunc(TimeDifference / fTimeBase);
- fTime := fTime + DropFrameCount*fTimeBase;
+ DropFrameCount := Trunc(TimeDiff / fTimeBase);
+ fFrameTime := fFrameTime + DropFrameCount*fTimeBase;
- // skip half of the frames, this is much smoother than to skip all at once
- for i := 1 to DropFrameCount (*div 2*) do
+ // skip frames
+ for i := 1 to DropFrameCount do
Success := DecodeFrame();
end;
- // check if we got an EOF or error
+ // check if we got an EOF or error
if (not Success) then
begin
if fLoop then
@@ -679,12 +776,16 @@ 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 (fTime-fLoopTime) later.
+ // 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
@@ -693,11 +794,11 @@ begin
// otherwise we convert the pixeldata from YUV to RGB
{$IFDEF UseSWScale}
- errnum := sws_scale(fSwScaleContext, @(fAVFrame.data), @(fAVFrame.linesize),
+ errnum := sws_scale(fSwScaleContext, @fAVFrame.data, @fAVFrame.linesize,
0, fCodecContext^.Height,
- @(fAVFrameRGB.data), @(fAVFrameRGB.linesize));
+ @fAVFrameRGB.data, @fAVFrameRGB.linesize);
{$ELSE}
- // img_convert from lib/ffmpeg/avcodec.pas is actually deprecated.
+ // 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
@@ -707,7 +808,7 @@ begin
PAVPicture(fAVFrame), fCodecContext^.pix_fmt,
fCodecContext^.width, fCodecContext^.height);
{$ENDIF}
-
+
if (errnum < 0) then
begin
Log.LogError('Image conversion failed', 'TVideoPlayback_ffmpeg.GetFrame');
@@ -723,10 +824,51 @@ begin
// Or should we add padding with avpicture_fill? (check which one is faster)
//glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- 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]);
+ // 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;
@@ -743,7 +885,7 @@ begin
{$ENDIF}
end;
-procedure TVideoPlayback_FFmpeg.GetVideoRect(var ScreenRect, TexRect: TRectCoords);
+procedure TVideo_FFmpeg.GetVideoRect(var ScreenRect, TexRect: TRectCoords);
var
ScreenAspect: double; // aspect of screen resolution
ScaledVideoWidth, ScaledVideoHeight: double;
@@ -793,7 +935,7 @@ begin
TexRect.Lower := fCodecContext^.height / fTexHeight;
end;
-procedure TVideoPlayback_FFmpeg.DrawGL(Screen: integer);
+procedure TVideo_FFmpeg.DrawGL(Screen: integer);
var
ScreenRect: TRectCoords;
TexRect: TRectCoords;
@@ -856,10 +998,10 @@ begin
{$IFEND}
end;
-procedure TVideoPlayback_FFmpeg.ShowDebugInfo();
+procedure TVideo_FFmpeg.ShowDebugInfo();
begin
{$IFDEF Info}
- if (fTime+fTimeBase < 0) then
+ if (fFrameTime+fTimeBase < 0) then
begin
glColor4f(0.7, 1, 0.3, 1);
SetFontStyle (1);
@@ -893,28 +1035,39 @@ begin
{$ENDIF}
end;
-procedure TVideoPlayback_FFmpeg.Play;
+procedure TVideo_FFmpeg.Play;
begin
end;
-procedure TVideoPlayback_FFmpeg.Pause;
+procedure TVideo_FFmpeg.Pause;
begin
fPaused := not fPaused;
end;
-procedure TVideoPlayback_FFmpeg.Stop;
+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 fTime is set to Time no matter if the actual position seeked to is
- * at Time or the time of a preceding keyframe. fTime will be updated to the
+ * 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 TVideoPlayback_FFmpeg.SetPosition(Time: real);
+procedure TVideo_FFmpeg.SetPosition(Time: real);
var
SeekFlags: integer;
begin
@@ -936,9 +1089,9 @@ begin
// requested time, let the sync in GetFrame() do its job.
SeekFlags := AVSEEK_FLAG_BACKWARD;
- fTime := Time;
+ fFrameTime := Time;
fEOF := false;
- fFrameTexValid := false;
+ fFrameTexValid := false;
if (av_seek_frame(fFormatContext, fStreamIndex, Floor(Time/fTimeBase), SeekFlags) < 0) then
begin
@@ -949,9 +1102,9 @@ begin
avcodec_flush_buffers(fCodecContext);
end;
-function TVideoPlayback_FFmpeg.GetPosition: real;
+function TVideo_FFmpeg.GetPosition: real;
begin
- Result := fTime;
+ Result := fFrameTime;
end;
initialization
diff --git a/cmake/src/media/UVisualizer.pas b/cmake/src/media/UVisualizer.pas
index 37e0268a..4f553521 100644
--- a/cmake/src/media/UVisualizer.pas
+++ b/cmake/src/media/UVisualizer.pas
@@ -60,12 +60,17 @@ interface
{$I switches.inc}
+{.$DEFINE UseTexture}
+
uses
SDL,
UGraphicClasses,
textgl,
math,
gl,
+ {$IFDEF UseTexture}
+ glu,
+ {$ENDIF}
SysUtils,
UIni,
projectM,
@@ -77,6 +82,7 @@ uses
UGraphic,
UMain,
UConfig,
+ UPath,
ULog;
{$IF PROJECTM_VERSION < 1000000} // < 1.0
@@ -90,31 +96,29 @@ const
{$IFEND}
type
+ TProjectMState = ( pmPlay, pmStop, pmPause );
+
+type
TGLMatrix = array[0..3, 0..3] of GLdouble;
TGLMatrixStack = array of TGLMatrix;
type
- TVideoPlayback_ProjectM = class( TInterfacedObject, IVideoPlayback, IVideoVisualization )
+ TVideo_ProjectM = class( TInterfacedObject, IVideo )
private
- pm: TProjectM;
- ProjectMPath : string;
- Initialized: boolean;
-
- VisualizerStarted: boolean;
- VisualizerPaused: boolean;
+ fPm: TProjectM;
+ fProjectMPath : string;
- VisualTex: GLuint;
- PCMData: TPCMData;
- RndPCMcount: integer;
+ fState: TProjectMState;
- ModelviewMatrixStack: TGLMatrixStack;
- ProjectionMatrixStack: TGLMatrixStack;
- TextureMatrixStack: TGLMatrixStack;
+ fVisualTex: GLuint;
+ fPCMData: TPCMData;
+ fRndPCMcount: integer;
- procedure VisualizerStart;
- procedure VisualizerStop;
+ fModelviewMatrixStack: TGLMatrixStack;
+ fProjectionMatrixStack: TGLMatrixStack;
+ fTextureMatrixStack: TGLMatrixStack;
- procedure VisualizerTogglePause;
+ procedure InitProjectM;
function GetRandomPCMData(var Data: TPCMData): Cardinal;
@@ -125,12 +129,9 @@ type
procedure RestoreOpenGLState();
public
- function GetName: String;
+ constructor Create;
+ destructor Destroy; override;
- function Init(): boolean;
- function Finalize(): boolean;
-
- function Open(const aFileName : string): boolean; // true if succeed
procedure Close;
procedure Play;
@@ -140,10 +141,28 @@ type
procedure SetPosition(Time: real);
function GetPosition: real;
+ procedure SetLoop(Enable: boolean);
+ function GetLoop(): boolean;
+
procedure GetFrame(Time: Extended);
procedure DrawGL(Screen: integer);
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
@@ -153,76 +172,100 @@ end;
function TVideoPlayback_ProjectM.Init(): boolean;
begin
Result := true;
-
- if (Initialized) then
+ if (fInitialized) then
Exit;
- Initialized := true;
+ fInitialized := true;
+end;
- RndPCMcount := 0;
+function TVideoPlayback_ProjectM.Finalize(): boolean;
+begin
+ Result := true;
+end;
+
+function TVideoPlayback_ProjectM.Open(const aFileName: IPath): IVideo;
+begin
+ Result := TVideo_ProjectM.Create;
+end;
- ProjectMPath := ProjectM_DataDir + PathDelim;
- VisualizerStarted := False;
- VisualizerPaused := False;
+{ TVideo_ProjectM }
+
+constructor TVideo_ProjectM.Create;
+begin
+ fRndPCMcount := 0;
+
+ fProjectMPath := ProjectM_DataDir + PathDelim;
+
+ fState := pmStop;
{$IFDEF UseTexture}
- glGenTextures(1, PglUint(@VisualTex));
- glBindTexture(GL_TEXTURE_2D, VisualTex);
+ 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;
-function TVideoPlayback_ProjectM.Finalize(): boolean;
+destructor TVideo_ProjectM.Destroy;
begin
- VisualizerStop();
+ Close();
{$IFDEF UseTexture}
- glDeleteTextures(1, PglUint(@VisualTex));
+ glDeleteTextures(1, PglUint(@fVisualTex));
{$ENDIF}
- Result := true;
end;
-function TVideoPlayback_ProjectM.Open(const aFileName : string): boolean; // true if succeed
+procedure TVideo_ProjectM.Close;
begin
- Result := false;
+ FreeAndNil(fPm);
end;
-procedure TVideoPlayback_ProjectM.Close;
+procedure TVideo_ProjectM.Play;
begin
- VisualizerStop();
+ if (fState = pmStop) and (assigned(fPm)) then
+ fPm.RandomPreset();
+ fState := pmPlay;
end;
-procedure TVideoPlayback_ProjectM.Play;
+procedure TVideo_ProjectM.Pause;
begin
- VisualizerStart();
+ if (fState = pmPlay) then
+ fState := pmPause
+ else if (fState = pmPause) then
+ fState := pmPlay;
end;
-procedure TVideoPlayback_ProjectM.Pause;
+procedure TVideo_ProjectM.Stop;
begin
- VisualizerTogglePause();
+ fState := pmStop;
end;
-procedure TVideoPlayback_ProjectM.Stop;
+procedure TVideo_ProjectM.SetPosition(Time: real);
begin
- VisualizerStop();
+ if assigned(fPm) then
+ fPm.RandomPreset();
end;
-procedure TVideoPlayback_ProjectM.SetPosition(Time: real);
+function TVideo_ProjectM.GetPosition: real;
begin
- if assigned(pm) then
- pm.RandomPreset();
+ Result := 0;
end;
-function TVideoPlayback_ProjectM.GetPosition: real;
+procedure TVideo_ProjectM.SetLoop(Enable: boolean);
begin
- Result := 0;
+end;
+
+function TVideo_ProjectM.GetLoop(): boolean;
+begin
+ Result := true;
end;
{**
* Returns the stack depth of the given OpenGL matrix mode stack.
*}
-function TVideoPlayback_ProjectM.GetMatrixStackDepth(MatrixMode: GLenum): GLint;
+function TVideo_ProjectM.GetMatrixStackDepth(MatrixMode: GLenum): GLint;
begin
// get number of matrices on stack
case (MatrixMode) of
@@ -252,7 +295,7 @@ end;
* By saving the whole stack we are on the safe side, so a nasty bug in the
* visualizer does not corrupt USDX.
*}
-procedure TVideoPlayback_ProjectM.SaveMatrixStack(MatrixMode: GLenum;
+procedure TVideo_ProjectM.SaveMatrixStack(MatrixMode: GLenum;
var MatrixStack: TGLMatrixStack);
var
I: integer;
@@ -288,7 +331,7 @@ end;
{**
* Restores the OpenGL matrix stack stored with SaveMatrixStack.
*}
-procedure TVideoPlayback_ProjectM.RestoreMatrixStack(MatrixMode: GLenum;
+procedure TVideo_ProjectM.RestoreMatrixStack(MatrixMode: GLenum;
var MatrixStack: TGLMatrixStack);
var
I: integer;
@@ -324,15 +367,15 @@ end;
* - Modelview-matrix is pushed to the Modelview-stack
* - the OpenGL error-state (glGetError) is cleared
*}
-procedure TVideoPlayback_ProjectM.SaveOpenGLState();
+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, ProjectionMatrixStack);
- SaveMatrixStack(GL_MODELVIEW, ModelviewMatrixStack);
- SaveMatrixStack(GL_TEXTURE, TextureMatrixStack);
+ SaveMatrixStack(GL_PROJECTION, fProjectionMatrixStack);
+ SaveMatrixStack(GL_MODELVIEW, fModelviewMatrixStack);
+ SaveMatrixStack(GL_TEXTURE, fTextureMatrixStack);
glMatrixMode(GL_MODELVIEW);
@@ -344,15 +387,15 @@ end;
* Restores the OpenGL state saved by SaveOpenGLState()
* and resets the error-state.
*}
-procedure TVideoPlayback_ProjectM.RestoreOpenGLState();
+procedure TVideo_ProjectM.RestoreOpenGLState();
begin
// reset OpenGL error-state
glGetError();
// restore matrix stacks
- RestoreMatrixStack(GL_PROJECTION, ProjectionMatrixStack);
- RestoreMatrixStack(GL_MODELVIEW, ModelviewMatrixStack);
- RestoreMatrixStack(GL_TEXTURE, TextureMatrixStack);
+ RestoreMatrixStack(GL_PROJECTION, fProjectionMatrixStack);
+ RestoreMatrixStack(GL_MODELVIEW, fModelviewMatrixStack);
+ RestoreMatrixStack(GL_TEXTURE, fTextureMatrixStack);
// restore all OpenGL state-machine attributes
// (also restores the matrix mode)
@@ -360,22 +403,19 @@ begin
glPopAttrib();
end;
-procedure TVideoPlayback_ProjectM.VisualizerStart;
+procedure TVideo_ProjectM.InitProjectM;
begin
- if VisualizerStarted then
- Exit;
-
// the OpenGL state must be saved before TProjectM.Create is called
SaveOpenGLState();
try
try
{$IF PROJECTM_VERSION >= 1000000} // >= 1.0
- pm := TProjectM.Create(ProjectMPath + 'config.inp');
+ fPm := TProjectM.Create(fProjectMPath + 'config.inp');
{$ELSE}
- pm := TProjectM.Create(
+ fPm := TProjectM.Create(
meshX, meshY, fps, textureSize, ScreenW, ScreenH,
- ProjectMPath + 'presets', ProjectMPath + 'fonts');
+ fProjectMPath + 'presets', fProjectMPath + 'fonts');
{$IFEND}
except on E: Exception do
begin
@@ -386,72 +426,51 @@ begin
end;
// initialize OpenGL
- pm.ResetGL(ScreenW, ScreenH);
+ fPm.ResetGL(ScreenW, ScreenH);
// skip projectM default-preset
- pm.RandomPreset();
+ 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.
- pm.RenderFrame();
-
- VisualizerPaused := false;
- VisualizerStarted := true;
+ fPm.RenderFrame();
finally
RestoreOpenGLState();
end;
end;
-procedure TVideoPlayback_ProjectM.VisualizerStop;
-begin
- if VisualizerStarted then
- begin
- VisualizerPaused := false;
- VisualizerStarted := false;
- FreeAndNil(pm);
- end;
-end;
-
-procedure TVideoPlayback_ProjectM.VisualizerTogglePause;
-begin
- VisualizerPaused := not VisualizerPaused;
-end;
-
-procedure TVideoPlayback_ProjectM.GetFrame(Time: Extended);
+procedure TVideo_ProjectM.GetFrame(Time: Extended);
var
nSamples: cardinal;
begin
- if not VisualizerStarted then
- Exit;
-
- if VisualizerPaused then
+ if (fState <> pmPlay) then
Exit;
// get audio data
- nSamples := AudioPlayback.GetPCMData(PcmData);
+ nSamples := AudioPlayback.GetPCMData(fPCMData);
// generate some data if non is available
if (nSamples = 0) then
- nSamples := GetRandomPCMData(PcmData);
+ nSamples := GetRandomPCMData(fPCMData);
// send audio-data to projectM
if (nSamples > 0) then
- pm.AddPCM16Data(PSmallInt(@PcmData), nSamples);
+ fPm.AddPCM16Data(PSmallInt(@fPCMData), nSamples);
// store OpenGL state (might be messed up otherwise)
SaveOpenGLState();
try
// setup projectM's OpenGL state
- pm.ResetGL(ScreenW, ScreenH);
+ fPm.ResetGL(ScreenW, ScreenH);
// let projectM render a frame
- pm.RenderFrame();
+ fPm.RenderFrame();
{$IFDEF UseTexture}
- glBindTexture(GL_TEXTURE_2D, VisualTex);
+ glBindTexture(GL_TEXTURE_2D, fVisualTex);
glFlush();
- glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, VisualWidth, VisualHeight, 0);
+ glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, fVisualWidth, fVisualHeight, 0);
{$ENDIF}
finally
// restore USDX OpenGL state
@@ -466,7 +485,7 @@ end;
* Draws the current frame to screen.
* TODO: this is not used yet. Data is directly drawn on GetFrame().
*}
-procedure TVideoPlayback_ProjectM.DrawGL(Screen: integer);
+procedure TVideo_ProjectM.DrawGL(Screen: integer);
begin
{$IFDEF UseTexture}
// have a nice black background to draw on
@@ -477,7 +496,7 @@ begin
end;
// exit if there's nothing to draw
- if not VisualizerStarted then
+ if (fState <> pmPlay) then
Exit;
// setup display
@@ -496,7 +515,7 @@ begin
glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- glBindTexture(GL_TEXTURE_2D, VisualTex);
+ glBindTexture(GL_TEXTURE_2D, fVisualTex);
glColor4f(1, 1, 1, 1);
// draw projectM frame
@@ -523,12 +542,12 @@ end;
* Produces random "sound"-data in case no audio-data is available.
* Otherwise the visualization will look rather boring.
*}
-function TVideoPlayback_ProjectM.GetRandomPCMData(var Data: TPCMData): Cardinal;
+function TVideo_ProjectM.GetRandomPCMData(var Data: TPCMData): Cardinal;
var
i: integer;
begin
// Produce some fake PCM data
- if (RndPCMcount mod 500 = 0) then
+ if (fRndPCMcount mod 500 = 0) then
begin
FillChar(Data, SizeOf(TPCMData), 0);
end
@@ -540,7 +559,7 @@ begin
Data[i][1] := Random(High(Word)+1);
end;
end;
- Inc(RndPCMcount);
+ Inc(fRndPCMcount);
Result := 512;
end;
diff --git a/cmake/src/menu/UDisplay.pas b/cmake/src/menu/UDisplay.pas
index f2eb2ced..e3ec272a 100644
--- a/cmake/src/menu/UDisplay.pas
+++ b/cmake/src/menu/UDisplay.pas
@@ -35,24 +35,32 @@ interface
uses
UCommon,
+ Math,
SDL,
- UMenu,
gl,
glu,
- SysUtils;
+ SysUtils,
+ UMenu,
+ UPath,
+ UMusic,
+ UHookableEvent;
type
TDisplay = class
private
+ ePreDraw: THookableEvent;
+ eDraw: THookableEvent;
+
//fade-to-black-hack
BlackScreen: boolean;
FadeEnabled: boolean; // true if fading is enabled
FadeFailed: boolean; // true if fading is possible (enough memory, etc.)
- FadeState: integer; // fading state, 0 means that the fade texture must be initialized
- LastFadeTime: cardinal; // last fade update time
+ FadeTime: cardinal; // time when fading starts, 0 means that the fade texture must be initialized
+ DoneOnShow: boolean; // true if passed onShow after fading
- FadeTex: array[1..2] of GLuint;
+ FadeTex: array[0..1] of GLuint;
+ TexW, TexH: Cardinal;
FPSCounter: cardinal;
LastFPS: cardinal;
@@ -72,6 +80,9 @@ type
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;
@@ -86,17 +97,29 @@ type
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; Pressed: boolean);
+ 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;
@@ -105,6 +128,9 @@ var
Display: TDisplay;
const
+ { constants for screen transition
+ time in milliseconds }
+ Transition_Fade_Time = 400;
{ constants for software cursor effects
time in milliseconds }
Cursor_FadeIn_Time = 500; // seconds the fade in effect lasts
@@ -123,14 +149,17 @@ uses
UMain,
UTexture,
UTime,
- UPath;
+ ULanguage,
+ UPathUtils;
constructor TDisplay.Create;
-var
- i: integer;
begin
inherited Create;
+ // create events for plugins
+ ePreDraw := THookableEvent.Create('Display.PreDraw');
+ eDraw := THookableEvent.Create('Display.Draw');
+
//popup hack
CheckOK := false;
NextScreen := nil;
@@ -138,18 +167,13 @@ begin
BlackScreen := false;
// fade mod
- FadeState := 0;
+ FadeTime := 0;
FadeEnabled := (Ini.ScreenFade = 1);
FadeFailed := false;
+ DoneOnShow := false;
- glGenTextures(2, @FadeTex);
-
- for i := 1 to 2 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);
- end;
+ glGenTextures(2, PGLuint(@FadeTex));
+ InitFadeTextures();
//Set LastError for OSD to No Error
OSD_LastError := 'No Errors';
@@ -166,16 +190,35 @@ end;
destructor TDisplay.Destroy;
begin
- glDeleteTextures(2, @FadeTex);
+ 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;
@@ -214,20 +257,25 @@ begin
if (not assigned(NextScreen)) and (not BlackScreen) then
begin
+ ePreDraw.CallHookChain(false);
CurrentScreen.Draw;
//popup mod
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 mod
- FadeState := 0;
+ FadeTime := 0;
if ((Ini.ScreenFade = 1) and (not FadeFailed)) then
FadeEnabled := true
else if (Ini.ScreenFade = 0) then
FadeEnabled := false;
+
+ eDraw.CallHookChain(false);
end
else
begin
@@ -240,95 +288,129 @@ begin
if (FadeEnabled and not FadeFailed) then
begin
//Create Fading texture if we're just starting
- if FadeState = 0 then
+ if FadeTime = 0 then
begin
- // save old viewport and resize to fit texture
- glPushAttrib(GL_VIEWPORT_BIT);
- glViewPort(0, 0, 512, 512);
-
// 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]);
- glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 512, 512, 0);
+ 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.LogWarn('Fading disabled: ' + gluErrorString(glError), 'TDisplay.Draw');
+ Log.LogError('Fading disabled: ' + gluErrorString(glError), 'TDisplay.Draw');
end;
- // restore viewport
- glPopAttrib();
-
// blackscreen-hack
- if not BlackScreen then
- NextScreen.onShow;
+ if not BlackScreen and (S = 1) and not DoneOnShow then
+ begin
+ NextScreen.OnShow;
+ DoneOnShow := true;
+ end;
- // update fade state
- LastFadeTime := SDL_GetTicks();
- if (S = 2) or (Screens = 1) then
- FadeState := FadeState + 1;
+
+ // set fade time once on second screen (or first if screens = 1)
+ if (Screens = 1) or (S = 2) then
+ FadeTime := SDL_GetTicks;
end; // end texture creation in first fading step
- //do some time-based fading
+ {//do some time-based fading
currentTime := SDL_GetTicks();
if (currentTime > LastFadeTime+30) and (S = 1) then
begin
- FadeState := FadeState + 4;
+ FadeState := FadeState + 5;
LastFadeTime := currentTime;
- end;
+ end; }
// blackscreen-hack
if not BlackScreen then
- NextScreen.Draw // draw next screen
+ begin
+ ePreDraw.CallHookChain(false);
+ NextScreen.Draw; // draw next screen
+ eDraw.CallHookChain(false);
+ end
else if ScreenAct = 1 then
begin
- glClearColor(0, 0, 0 , 0);
+ 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 (FadeTime = 0) then
+ FadeStateSquare := 0 // for first screen if screens = 2
+ else
+ FadeStateSquare := sqr((SDL_GetTicks - FadeTime) / Transition_Fade_Time);
- FadeStateSquare := (FadeState*FadeState)/10000;
-
- glBindTexture(GL_TEXTURE_2D, FadeTex[S]);
- 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, 0+FadeStateSquare); glVertex2f(0, 600);
- glTexCoord2f(0+FadeStateSquare, 1-FadeStateSquare); glVertex2f(0, 0);
- glTexCoord2f(1-FadeStateSquare, 1-FadeStateSquare); glVertex2f(800, 0);
- glTexCoord2f(1-FadeStateSquare, 0+FadeStateSquare); glVertex2f(800, 600);
- glEnd;
- glDisable(GL_BLEND);
- glDisable(GL_TEXTURE_2D);
+ 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
-// blackscreen hack
+
+ // blackscreen hack
else if not BlackScreen then
begin
NextScreen.OnShow;
end;
- if ((FadeState > 40) or (not FadeEnabled) or FadeFailed) and (S = 1) then
+ if ((FadeTime + Transition_Fade_Time < SDL_GetTicks) or (not FadeEnabled) or FadeFailed) and ((Screens = 1) or (S = 2)) then
begin
// fade out complete...
- FadeState := 0;
+ FadeTime := 0;
+ DoneOnShow := false;
CurrentScreen.onHide;
CurrentScreen.ShowFinish := false;
CurrentScreen := NextScreen;
NextScreen := nil;
if not BlackScreen then
begin
- CurrentScreen.onShowFinish;
+ CurrentScreen.OnShowFinish;
CurrentScreen.ShowFinish := true;
end
else
@@ -341,11 +423,11 @@ begin
// Draw OSD only on first Screen if Debug Mode is enabled
if ((Ini.Debug = 1) or (Params.Debug)) and (S = 1) then
- DrawDebugInformation;
- end; // for
+ DrawDebugInformation;
- if not BlackScreen then
- DrawCursor;
+ if not BlackScreen then
+ DrawCursor;
+ end; // for
end;
{ sets SDL_ShowCursor depending on options set in Ini }
@@ -392,35 +474,51 @@ begin
end;
end;
-{ called when cursor moves, positioning of software cursor }
-procedure TDisplay.MoveCursor(X, Y: double; Pressed: boolean);
+{ called by MoveCursor and OnMouseButton to update last move and start fade in }
+procedure TDisplay.UpdateCursorFade;
var
Ticks: cardinal;
begin
- if (Ini.Mouse = 2) and
- ((X <> Cursor_X) or (Y <> Cursor_Y) or (Pressed <> Cursor_Pressed)) then
+ 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_FadeIn_Time * (1 - (Ticks - Cursor_LastMove)/Cursor_FadeOut_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;
- Cursor_Pressed := Pressed;
- Ticks := SDL_GetTicks;
+ UpdateCursorFade;
+ end;
+end;
- { 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_FadeIn_Time * (1 - (Ticks - Cursor_LastMove)/Cursor_FadeOut_Time))
- else
- Cursor_LastMove := Ticks;
+{ 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;
- Cursor_Visible := true;
- Cursor_Fade := true;
- end
- else if not Cursor_Fade then
- begin
- Cursor_LastMove := Ticks;
- end;
+ UpdateCursorFade;
end;
end;
@@ -429,8 +527,9 @@ procedure TDisplay.DrawCursor;
var
Alpha: single;
Ticks: cardinal;
+ DrawX: double;
begin
- if (Ini.Mouse = 2) then
+ if (Ini.Mouse = 2) and ((Screens = 1) or ((ScreenAct - 1) = (Round(Cursor_X+16) div RenderW))) then
begin // draw software cursor
Ticks := SDL_GetTicks;
@@ -471,6 +570,9 @@ begin
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);
@@ -483,16 +585,16 @@ begin
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
- glVertex2f(Cursor_X, Cursor_Y);
+ glVertex2f(DrawX, Cursor_Y);
glTexCoord2f(0, 1);
- glVertex2f(Cursor_X, Cursor_Y + 32);
+ glVertex2f(DrawX, Cursor_Y + 32);
glTexCoord2f(1, 1);
- glVertex2f(Cursor_X + 32, Cursor_Y + 32);
+ glVertex2f(DrawX + 32, Cursor_Y + 32);
glTexCoord2f(1, 0);
- glVertex2f(Cursor_X + 32, Cursor_Y);
+ glVertex2f(DrawX + 32, Cursor_Y);
glEnd;
glDisable(GL_BLEND);
@@ -501,52 +603,101 @@ begin
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: string;
+ 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 = '') then
+ // Exit if Screenshot-path does not exist or read-only
+ if (ScreenshotsPath.IsUnset) then
Exit;
for Num := 1 to 9999 do
begin
- FileName := IntToStr(Num);
- while Length(FileName) < 4 do
- FileName := '0' + FileName;
- FileName := ScreenshotsPath + 'screenshot' + FileName + '.png';
- if not FileExists(FileName) then
- break
+ // 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
+ // we must take the row-alignment (4byte by default) into account
glGetIntegerv(GL_PACK_ALIGNMENT, @Align);
-// calc aligned row-size
+ // 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);
+ // 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 := WriteJPGImage(FileName, Surface, 95);
+ // Success := WriteBMPImage(FileName, Surface);
Success := WritePNGImage(FileName, Surface);
if Success then
- ScreenPopupError.ShowPopup('Screenshot saved: ' + ExtractFileName(FileName))
+ ScreenPopupInfo.ShowPopup(Format(Language.Translate('SCREENSHOT_SAVED'), [FileName.GetName.ToUTF8()]))
else
- ScreenPopupError.ShowPopup('Screenshot failed');
+ ScreenPopupError.ShowPopup(Language.Translate('SCREENSHOT_FAILED'));
SDL_FreeSurface(Surface);
FreeMem(ScreenData);
@@ -559,7 +710,7 @@ procedure TDisplay.DrawDebugInformation;
var
Ticks: cardinal;
begin
-// Some White Background for information
+ // Some White Background for information
glEnable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glColor4f(1, 1, 1, 0.5);
@@ -571,13 +722,13 @@ begin
glEnd;
glDisable(GL_BLEND);
-// set font specs
- SetFontStyle(0);
+ // set font specs
+ SetFontStyle(ftNormal);
SetFontSize(21);
SetFontItalic(false);
glColor4f(0, 0, 0, 1);
-// calculate fps
+ // calculate fps
Ticks := SDL_GetTicks();
if (Ticks >= NextFPSSwap) then
begin
@@ -588,17 +739,17 @@ begin
Inc(FPSCounter);
-// draw text
+ // draw text
-// fps
+ // fps
SetFontPos(695, 0);
glPrint ('FPS: ' + InttoStr(LastFPS));
-// rspeed
+ // rspeed
SetFontPos(695, 13);
glPrint ('RSpeed: ' + InttoStr(Round(1000 * TimeMid)));
-// lasterror
+ // lasterror
SetFontPos(695, 26);
glColor4f(1, 0, 0, 1);
glPrint (OSD_LastError);
diff --git a/cmake/src/menu/UMenu.pas b/cmake/src/menu/UMenu.pas
index a3f47b3d..b011eddf 100644
--- a/cmake/src/menu/UMenu.pas
+++ b/cmake/src/menu/UMenu.pas
@@ -38,6 +38,7 @@ uses
Math,
gl,
SDL,
+ UPath,
UMenuBackground,
UMenuButton,
UMenuButtonCollection,
@@ -67,7 +68,7 @@ type
ButtonCollection: array of TButtonCollection;
public
Text: array of TText;
- Static: array of TStatic;
+ Statics: array of TStatic;
mX: integer; // mouse X
mY: integer; // mouse Y
@@ -81,8 +82,6 @@ type
//constructor Create(Back: string; W, H: integer); overload; virtual; // W and H are the number of overlaps
// interaction
- function WideCharUpperCase(wchar: WideChar) : WideString;
- function WideStringUpperCase(wstring: WideString) : WideString;
procedure AddInteraction(Typ, Num: integer);
procedure SetInteraction(Num: integer); virtual;
property Interaction: integer read SelInteraction write SetInteraction;
@@ -98,62 +97,62 @@ type
// static
function AddStatic(ThemeStatic: TThemeStatic): integer; overload;
- function AddStatic(X, Y, W, H: real; const Name: string): integer; overload;
- function AddStatic(X, Y, W, H: real; const Name: string; Typ: TTextureType): integer; overload;
- function AddStatic(X, Y, W, H: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType): integer; overload;
- function AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType): integer; overload;
- function AddStatic(X, Y, W, H: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType; Color: integer): integer; overload;
- function AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType; Color: integer): integer; overload;
- function AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; TexX1, TexY1, TexX2, TexY2: real; const Name: string; Typ: TTextureType; Color: integer; Reflection: boolean; ReflectionSpacing: real): 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_: string): integer; overload;
- function AddText(X, Y: real; Style: integer; Size, ColR, ColG, ColB: real; const Text: string): integer; overload;
- function AddText(X, Y, W: real; Style: integer; Size, ColR, ColG, ColB: real; Align: integer; const Text_: string; Reflection_: boolean; ReflectionSpacing_: real; Z : real): 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 Name: string): integer; overload;
- function AddButton(X, Y, W, H: real; const Name: string; Typ: TTextureType; Reflection: boolean): integer; overload;
- function AddButton(X, Y, W, H, ColR, ColG, ColB, Int, DColR, DColG, DColB, DInt: real; const Name: string; Typ: TTextureType; Reflection: boolean; ReflectionSpacing, DeSelectReflectionSpacing: real): 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: string); overload;
- procedure AddButtonText(AddX, AddY: real; ColR, ColG, ColB: real; const AddText: string); overload;
- procedure AddButtonText(AddX, AddY: real; ColR, ColG, ColB: real; Font: integer; Size: integer; Align: integer; const AddText: string); overload;
- procedure AddButtonText(CustomButton: TButton; AddX, AddY: real; ColR, ColG, ColB: real; Font: integer; Size: integer; Align: integer; const AddText: string); overload;
+ 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; Values: array of string): integer; overload;
+ 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 Name: string; Typ: TTextureType; const SBGName: string; SBGTyp: TTextureType;
- const Caption: string; var Data: integer): integer; overload;
- procedure AddSelectSlideOption(const AddText: string); overload;
- procedure AddSelectSlideOption(SelectNo: cardinal; const AddText: string); overload;
- procedure UpdateSelectSlideOptions(ThemeSelectSlide: TThemeSelectSlide; SelectNum: integer; Values: array of string; var Data: integer);
+ 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: string);
+ procedure CheckFadeTo(Screen: PMenu; Msg: UTF8String);
function DrawBG: boolean; virtual;
function DrawFG: boolean; virtual;
function Draw: boolean; virtual;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown : boolean): 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(X1, Y1, W, H, X, Y: real): boolean;
+ 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 OnShow; virtual;
+ procedure OnShowFinish; virtual;
+ procedure OnHide; virtual;
procedure SetAnimationProgress(Progress: real); virtual;
@@ -169,6 +168,8 @@ type
procedure AddBox(X, Y, W, H: real);
end;
+function RGBFloatToInt(R, G, B: double): cardinal;
+
const
MENU_MDOWN = 8;
MENU_MUP = 0;
@@ -205,11 +206,22 @@ uses
UMenuBackgroundFade;
destructor TMenu.Destroy;
+var
+ I: integer;
begin
- if (Background <> nil) then
- begin
- Background.Destroy;
- end;
+ 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;
@@ -220,7 +232,7 @@ begin
Fade := 0;//fWhite;
- SetLength(Static, 0);
+ SetLength(Statics, 0);
SetLength(Button, 0);
//Set ButtonPos to Autoset Length
@@ -337,8 +349,8 @@ begin
AddBackground(ThemeBasic.Background);
//Add Statics and Texts
- for I := 0 to High(ThemeBasic.Static) do
- AddStatic(ThemeBasic.Static[I]);
+ for I := 0 to High(ThemeBasic.Statics) do
+ AddStatic(ThemeBasic.Statics[I]);
for I := 0 to High(ThemeBasic.Text) do
AddText(ThemeBasic.Text[I]);
@@ -378,11 +390,7 @@ procedure TMenu.AddBackground(ThemedSettings: TThemeBackground);
end;
begin
- if (Background <> nil) then
- begin
- Background.Destroy;
- Background := nil;
- end;
+ FreeAndNil(Background);
case ThemedSettings.BGType of
bgtAuto: begin //Automaticly choose one out of BGT_Texture, BGT_Video or BGT_Color
@@ -391,7 +399,7 @@ begin
begin
//At first some intelligent try to decide which BG to load
- FileExt := lowercase(ExtractFileExt(Skin.GetTextureFileName(ThemedSettings.Tex)));
+ FileExt := LowerCase(Skin.GetTextureFileName(ThemedSettings.Tex).GetExtension.ToUTF8);
if IsInArray(FileExt, SUPPORTED_EXTS_BACKGROUNDTEXTURE) then
TryBGCreate(TMenuBackgroundTexture)
@@ -599,69 +607,69 @@ begin
ThemeStatic.Typ, $FFFFFF, ThemeStatic.Reflection, ThemeStatic.Reflectionspacing);
end;
-function TMenu.AddStatic(X, Y, W, H: real; const Name: string): integer;
+function TMenu.AddStatic(X, Y, W, H: real; const TexName: IPath): integer;
begin
- Result := AddStatic(X, Y, W, H, Name, TEXTURE_TYPE_PLAIN);
+ Result := AddStatic(X, Y, W, H, TexName, TEXTURE_TYPE_PLAIN);
end;
function TMenu.AddStatic(X, Y, W, H: real;
- ColR, ColG, ColB: real;
- const Name: string;
+ ColR, ColG, ColB: real;
+ const TexName: IPath;
Typ: TTextureType): integer;
begin
- Result := AddStatic(X, Y, W, H, ColR, ColG, ColB, Name, Typ, $FFFFFF);
+ 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 Name: string;
+ ColR, ColG, ColB: real;
+ const TexName: IPath;
Typ: TTextureType): integer;
begin
- Result := AddStatic(X, Y, W, H, Z, ColR, ColG, ColB, Name, Typ, $FFFFFF);
+ Result := AddStatic(X, Y, W, H, Z, ColR, ColG, ColB, TexName, Typ, $FFFFFF);
end;
function TMenu.AddStatic(X, Y, W, H: real;
- const Name: string;
+ const TexName: IPath;
Typ: TTextureType): integer;
var
StatNum: integer;
begin
// adds static
- StatNum := Length(Static);
- SetLength(Static, StatNum + 1);
- Static[StatNum] := TStatic.Create(Texture.GetTexture(Name, Typ, $FF00FF)); // new skin
+ StatNum := Length(Statics);
+ SetLength(Statics, StatNum + 1);
+ Statics[StatNum] := TStatic.Create(Texture.GetTexture(TexName, Typ, $FF00FF)); // new skin
// configures static
- Static[StatNum].Texture.X := X;
- Static[StatNum].Texture.Y := Y;
- Static[StatNum].Texture.W := W;
- Static[StatNum].Texture.H := H;
- Static[StatNum].Visible := true;
+ 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 Name: string;
+ const TexName: IPath;
Typ: TTextureType;
Color: integer): integer;
begin
- Result := AddStatic(X, Y, W, H, 0, ColR, ColG, ColB, Name, Typ, Color);
+ 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 Name: string;
+ const TexName: IPath;
Typ: TTextureType;
Color: integer): integer;
begin
- Result := AddStatic(X, Y, W, H, Z, ColR, ColG, ColB, 0, 0, 1, 1, Name, Typ, Color, false, 0);
+ 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 Name: string;
+ const TexName: IPath;
Typ: TTextureType;
Color: integer;
Reflection: boolean;
@@ -670,52 +678,52 @@ var
StatNum: integer;
begin
// adds static
- StatNum := Length(Static);
- SetLength(Static, StatNum + 1);
+ StatNum := Length(Statics);
+ SetLength(Statics, StatNum + 1);
// colorize hack
if (Typ = TEXTURE_TYPE_COLORIZED) then
begin
// give encoded color to GetTexture()
- Static[StatNum] := TStatic.Create(Texture.GetTexture(Name, Typ, RGBFloatToInt(ColR, ColG, ColB)));
+ Statics[StatNum] := TStatic.Create(Texture.GetTexture(TexName, Typ, RGBFloatToInt(ColR, ColG, ColB)));
end
else
begin
- Static[StatNum] := TStatic.Create(Texture.GetTexture(Name, Typ, Color)); // new skin
+ Statics[StatNum] := TStatic.Create(Texture.GetTexture(TexName, Typ, Color)); // new skin
end;
// configures static
- Static[StatNum].Texture.X := X;
- Static[StatNum].Texture.Y := Y;
+ Statics[StatNum].Texture.X := X;
+ Statics[StatNum].Texture.Y := Y;
//Set height and width via sprite size if omitted
if(H = 0) then
- Static[StatNum].Texture.H := Static[StatNum].Texture.H
+ Statics[StatNum].Texture.H := Statics[StatNum].Texture.H
else
- Static[StatNum].Texture.H := H;
+ Statics[StatNum].Texture.H := H;
if(W = 0) then
- Static[StatNum].Texture.W := Static[StatNum].Texture.W
+ Statics[StatNum].Texture.W := Statics[StatNum].Texture.W
else
- Static[StatNum].Texture.W := W;
+ Statics[StatNum].Texture.W := W;
- Static[StatNum].Texture.Z := Z;
+ Statics[StatNum].Texture.Z := Z;
if (Typ <> TEXTURE_TYPE_COLORIZED) then
begin
- Static[StatNum].Texture.ColR := ColR;
- Static[StatNum].Texture.ColG := ColG;
- Static[StatNum].Texture.ColB := ColB;
+ Statics[StatNum].Texture.ColR := ColR;
+ Statics[StatNum].Texture.ColG := ColG;
+ Statics[StatNum].Texture.ColB := ColB;
end;
- Static[StatNum].Texture.TexX1 := TexX1;
- Static[StatNum].Texture.TexY1 := TexY1;
- Static[StatNum].Texture.TexX2 := TexX2;
- Static[StatNum].Texture.TexY2 := TexY2;
- Static[StatNum].Texture.Alpha := 1;
- Static[StatNum].Visible := true;
+ 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
- Static[StatNum].Reflection := Reflection;
- Static[StatNum].ReflectionSpacing := ReflectionSpacing;
+ Statics[StatNum].Reflection := Reflection;
+ Statics[StatNum].ReflectionSpacing := ReflectionSpacing;
Result := StatNum;
end;
@@ -726,7 +734,7 @@ begin
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_: string): integer;
+function TMenu.AddText(X, Y: real; const Text_: UTF8String): integer;
var
TextNum: integer;
begin
@@ -739,20 +747,20 @@ end;
function TMenu.AddText(X, Y: real;
Style: integer;
- Size, ColR, ColG, ColB: real
- ; const Text: string): 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_: string;
- Reflection_: boolean;
- ReflectionSpacing_: real;
- Z : real): integer;
+ Size, ColR, ColG, ColB: real;
+ Align: integer;
+ const Text_: UTF8String;
+ Reflection_: boolean;
+ ReflectionSpacing_: real;
+ Z : real): integer;
var
TextNum: integer;
begin
@@ -839,22 +847,20 @@ begin
Button[Result].Texture.Alpha := 0;
end;
end;
- Log.BenchmarkEnd(6);
- Log.LogBenchmark('====> Screen Options32', 6);
end;
-function TMenu.AddButton(X, Y, W, H: real; const Name: string): integer;
+function TMenu.AddButton(X, Y, W, H: real; const TexName: IPath): integer;
begin
- Result := AddButton(X, Y, W, H, Name, TEXTURE_TYPE_PLAIN, false);
+ Result := AddButton(X, Y, W, H, TexName, TEXTURE_TYPE_PLAIN, false);
end;
-function TMenu.AddButton(X, Y, W, H: real; const Name: string; Typ: TTextureType; Reflection: boolean): integer;
+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, Name, TEXTURE_TYPE_PLAIN, Reflection, 15, 15);
+ 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 Name: string;
+ const TexName: IPath;
Typ: TTextureType;
Reflection: boolean;
ReflectionSpacing, DeSelectReflectionSpacing: real): integer;
@@ -876,12 +882,12 @@ begin
if (Typ = TEXTURE_TYPE_COLORIZED) then
begin
// give encoded color to GetTexture()
- Button[Result] := TButton.Create(Texture.GetTexture(Name, Typ, RGBFloatToInt(ColR, ColG, ColB)),
- Texture.GetTexture(Name, Typ, RGBFloatToInt(DColR, DColG, DColB)));
+ 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(Name, Typ));
+ Button[Result] := TButton.Create(Texture.GetTexture(TexName, Typ));
end;
// configures button
@@ -935,11 +941,11 @@ var
J: integer;
begin
// We don't forget about newly implemented static for nice skin ...
- for J := 0 to Length(Static) - 1 do
- Static[J].Draw;
+ for J := 0 to High(Statics) do
+ Statics[J].Draw;
// ... and slightly implemented menutext unit
- for J := 0 to Length(Text) - 1 do
+ for J := 0 to High(Text) do
Text[J].Draw;
// Draw all ButtonCollections
@@ -947,10 +953,10 @@ begin
ButtonCollection[J].Draw;
// Second, we draw all of our buttons
- for J := 0 to Length(Button) - 1 do
+ for J := 0 to High(Button) do
Button[J].Draw;
- for J := 0 to Length(SelectsS) - 1 do
+ for J := 0 to High(SelectsS) do
SelectsS[J].Draw;
// Third, we draw all our widgets
@@ -1178,21 +1184,41 @@ begin
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: string);
+procedure TMenu.CheckFadeTo(Screen: PMenu; Msg: UTF8String);
begin
Display.Fade := 0;
Display.NextScreenWithCheck := Screen;
Display.CheckOK := false;
- ScreenPopupCheck.ShowPopup(msg);
+ ScreenPopupCheck.ShowPopup(msg, OnSaveEncodingError, nil, false);
end;
-procedure TMenu.AddButtonText(AddX, AddY: real; const AddText: string);
+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: string);
+procedure TMenu.AddButtonText(AddX, AddY: real; ColR, ColG, ColB: real; const AddText: UTF8String);
var
Il: integer;
begin
@@ -1208,7 +1234,7 @@ begin
end;
end;
-procedure TMenu.AddButtonText(AddX, AddY: real; ColR, ColG, ColB: real; Font: integer; Size: integer; Align: integer; const AddText: string);
+procedure TMenu.AddButtonText(AddX, AddY: real; ColR, ColG, ColB: real; Font: integer; Size: integer; Align: integer; const AddText: UTF8String);
var
Il: integer;
begin
@@ -1227,7 +1253,7 @@ begin
end;
end;
-procedure TMenu.AddButtonText(CustomButton: TButton; AddX, AddY: real; ColR, ColG, ColB: real; Font: integer; Size: integer; Align: integer; const AddText: string);
+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
@@ -1246,7 +1272,7 @@ begin
end;
end;
-function TMenu.AddSelectSlide(ThemeSelectS: TThemeSelectSlide; var Data: integer; Values: array of string): integer;
+function TMenu.AddSelectSlide(ThemeSelectS: TThemeSelectSlide; var Data: integer; const Values: array of UTF8String): integer;
var
SO: integer;
begin
@@ -1259,8 +1285,8 @@ begin
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), TEXTURE_TYPE_COLORIZED,
- Skin.GetTextureFileName(ThemeSelectS.TexSBG), TEXTURE_TYPE_COLORIZED,
+ 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]);
@@ -1269,6 +1295,8 @@ begin
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;
@@ -1283,8 +1311,8 @@ function TMenu.AddSelectSlide(X, Y, W, H, SkipX, SBGW, ColR, ColG, ColB, Int, DC
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 Name: string; Typ: TTextureType; const SBGName: string; SBGTyp: TTextureType;
- const Caption: string; var Data: integer): integer;
+ const TexName: IPath; Typ: TTextureType; const SBGName: IPath; SBGTyp: TTextureType;
+ const Caption: UTF8String; var Data: integer): integer;
var
S: integer;
I: integer;
@@ -1294,37 +1322,67 @@ begin
SelectsS[S] := TSelectSlide.Create;
if (Typ = TEXTURE_TYPE_COLORIZED) then
- SelectsS[S].Texture := Texture.GetTexture(Name, Typ, RGBFloatToInt(ColR, ColG, ColB))
+ 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
- SelectsS[S].Texture := Texture.GetTexture(Name, Typ);
+ 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;
-
- SelectsS[S].ColR := ColR;
- SelectsS[S].ColG := ColG;
- SelectsS[S].ColB := ColB;
- SelectsS[S].Int := Int;
- SelectsS[S].DColR := DColR;
- SelectsS[S].DColG := DColG;
- SelectsS[S].DColB := DColB;
- SelectsS[S].DInt := DInt;
+ SelectsS[S].H := H;
if (SBGTyp = TEXTURE_TYPE_COLORIZED) then
- SelectsS[S].TextureSBG := Texture.GetTexture(SBGName, SBGTyp, RGBFloatToInt(SBGColR, SBGColG, SBGColB))
+ 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;
+ 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;
+ 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;
@@ -1332,14 +1390,6 @@ begin
SelectsS[S].TextureSBG.Y := Y;
SelectsS[S].SBGW := SBGW;
SelectsS[S].TextureSBG.H := H;
- SelectsS[S].SBGColR := SBGColR;
- SelectsS[S].SBGColG := SBGColG;
- SelectsS[S].SBGColB := SBGColB;
- SelectsS[S].SBGInt := SBGInt;
- SelectsS[S].SBGDColR := SBGDColR;
- SelectsS[S].SBGDColG := SBGDColG;
- SelectsS[S].SBGDColB := SBGDColB;
- SelectsS[S].SBGDInt := SBGDInt;
SelectsS[S].Text.X := X + 20;
SelectsS[S].Text.Y := Y + (SelectsS[S].TextureSBG.H / 2) - 15;
@@ -1414,12 +1464,12 @@ begin
Result := S;
end;
-procedure TMenu.AddSelectSlideOption(const AddText: string);
+procedure TMenu.AddSelectSlideOption(const AddText: UTF8String);
begin
AddSelectSlideOption(High(SelectsS), AddText);
end;
-procedure TMenu.AddSelectSlideOption(SelectNo: cardinal; const AddText: string);
+procedure TMenu.AddSelectSlideOption(SelectNo: cardinal; const AddText: UTF8String);
var
SO: integer;
begin
@@ -1435,7 +1485,8 @@ begin
}
end;
-procedure TMenu.UpdateSelectSlideOptions(ThemeSelectSlide: TThemeSelectSlide; SelectNum: integer; Values: array of string; var Data: integer);
+procedure TMenu.UpdateSelectSlideOptions(ThemeSelectSlide: TThemeSelectSlide;
+ SelectNum: integer; const Values: array of UTF8String; var Data: integer);
var
SO: integer;
begin
@@ -1560,7 +1611,7 @@ begin
AddStatic(X+2, Y+2, W-4, H-4, 1, 1, 1, Skin.GetTextureFileName('MainBar'), TEXTURE_TYPE_COLORIZED);
end;
-procedure TMenu.onShow;
+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.
@@ -1589,57 +1640,18 @@ begin
Background.OnShow;
end;
-procedure TMenu.onShowFinish;
+procedure TMenu.OnShowFinish;
begin
// nothing
end;
-(*
- * Wrapper for WideUpperCase. Needed because some plattforms have problems with
- * unicode support.
- *)
-function TMenu.WideCharUpperCase(wchar: WideChar) : 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. So we have to use Ansi... for the moment.
-
- // cwstring crashes in FPC 2.2.2 so do not use the cwstring stuff
- {.$IFNDEF DARWIN}
- {$IFDEF NOIGNORE}
- // The FPC implementation of WideUpperCase returns nil if wchar is #0 (e.g. if an arrow key is pressed)
- if (wchar <> #0) then
- Result := WideUpperCase(wchar)
- else
- Result := #0;
- {$ELSE}
- Result := AnsiUpperCase(wchar)
- {$ENDIF}
-end;
-
-(*
- * Wrapper for WideUpperCase. Needed because some plattforms have problems with
- * unicode support.
- *)
-function TMenu.WideStringUpperCase(wstring: WideString) : WideString;
-begin
- // cwstring crashes in FPC 2.2.2 so do not use the cwstring stuff
- {.$IFNDEF DARWIN}
- {$IFDEF NOIGNORE}
- Result := WideUpperCase(wstring)
- {$ELSE}
- Result := AnsiUpperCase(wstring);
- {$ENDIF}
-end;
-
-procedure TMenu.onHide;
+procedure TMenu.OnHide;
begin
// nothing
Background.OnFinish;
end;
-function TMenu.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+function TMenu.ParseInput(PressedKey: Cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
begin
// nothing
Result := true;
@@ -1648,6 +1660,7 @@ 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
@@ -1657,55 +1670,80 @@ begin
if RightMbESC and (MouseButton = SDL_BUTTON_RIGHT) and BtnDown then
begin
//if RightMbESC is set, send ESC keypress
- Result:=ParseInput(SDLK_ESCAPE, #0, true);
+ Result:=ParseInput(SDLK_ESCAPE, 0, true);
end;
- nBut := InteractAt(X, Y);
- if nBut >= 0 then
+ // 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
- //select on mouse-over
- if nBut <> Interaction then
- SetInteraction(nBut);
- if (MouseButton = SDL_BUTTON_LEFT) and BtnDown then
- begin
- //click button
- Result:=ParseInput(SDLK_RETURN, #0, true);
- end;
- if (Interactions[nBut].Typ = iSelectS) then
- begin
- //forward/backward in select slide with mousewheel
- if (MouseButton = SDL_BUTTON_WHEELDOWN) and BtnDown then
- begin
- ParseInput(SDLK_RIGHT, #0, true);
- end;
- if (MouseButton = SDL_BUTTON_WHEELUP) and BtnDown then
- begin
- ParseInput(SDLK_LEFT, #0, true);
- end;
- end;
+ if (BtnDown) and (MouseButton = SDL_BUTTON_LEFT) then
+ Result := ParseInput(SDLK_RETURN, 0, true);
end
else
begin
- nBut := CollectionAt(X, Y);
+ nBut := InteractAt(X, Y);
if nBut >= 0 then
begin
- // if over button collection, select first child but don't allow click
- nBut := ButtonCollection[nBut].FirstChild - 1;
+ //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(X1, Y1, W, H, X, Y: real): boolean;
+function TMenu.InRegion(X, Y: real; A: TMouseOverRect): boolean;
begin
- Result := false;
- X1 := X1 * Screen.w / 800;
- W := W * Screen.w / 800;
- Y1 := Y1 * Screen.h / 600;
- H := H * Screen.h / 600;
- if (X >= X1) and (X <= X1 + W) and (Y >= Y1) and (Y <= Y1 + H) then
- Result := true;
+ // 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
@@ -1718,20 +1756,22 @@ begin
for i := Low(Interactions) to High(Interactions) do
begin
case Interactions[i].Typ of
- iButton: if InRegion(Button[Interactions[i].Num].X, Button[Interactions[i].Num].Y, Button[Interactions[i].Num].W, Button[Interactions[i].Num].H, X, Y) and
+ iButton:
+ if InRegion(X, Y, Button[Interactions[i].Num].GetMouseOverArea) and
Button[Interactions[i].Num].Visible then
- begin
+ begin
Result:=i;
exit;
end;
- iBCollectionChild: if InRegion(Button[Interactions[i].Num].X, Button[Interactions[i].Num].Y, Button[Interactions[i].Num].W, Button[Interactions[i].Num].H, X, Y) then
+ iBCollectionChild:
+ if InRegion(X, Y, Button[Interactions[i].Num].GetMouseOverArea) then
begin
Result:=i;
exit;
end;
- iSelectS: if InRegion(SelectSs[Interactions[i].Num].X, SelectSs[Interactions[i].Num].Y, SelectSs[Interactions[i].Num].W, SelectSs[Interactions[i].Num].H, X, Y) or
- InRegion(SelectSs[Interactions[i].Num].TextureSBG.X, SelectSs[Interactions[i].Num].TextureSBG.Y, SelectSs[Interactions[i].Num].TextureSBG.W, SelectSs[Interactions[i].Num].TextureSBG.H, X, Y) then
- begin
+ iSelectS:
+ if InRegion(X, Y, SelectSs[Interactions[i].Num].GetMouseOverArea) then
+ begin
Result:=i;
exit;
end;
@@ -1747,7 +1787,7 @@ begin
Result := -1;
for i:= Low(ButtonCollection) to High(ButtonCollection) do
begin
- if InRegion(ButtonCollection[i].X, ButtonCollection[i].Y, ButtonCollection[i].W, ButtonCollection[i].H, X, Y) and
+ if InRegion(X, Y, ButtonCollection[i].GetMouseOverArea) and
ButtonCollection[i].Visible then
begin
Result:=i;
diff --git a/cmake/src/menu/UMenuBackground.pas b/cmake/src/menu/UMenuBackground.pas
index c85f0806..0e2e63a6 100644
--- a/cmake/src/menu/UMenuBackground.pas
+++ b/cmake/src/menu/UMenuBackground.pas
@@ -1,83 +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.
+{* 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/cmake/src/menu/UMenuBackgroundColor.pas b/cmake/src/menu/UMenuBackgroundColor.pas
index a5c2a70a..45b58c1e 100644
--- a/cmake/src/menu/UMenuBackgroundColor.pas
+++ b/cmake/src/menu/UMenuBackgroundColor.pas
@@ -1,73 +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;
-
+{* 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/cmake/src/menu/UMenuBackgroundFade.pas b/cmake/src/menu/UMenuBackgroundFade.pas
index b61a4542..6d877baa 100644
--- a/cmake/src/menu/UMenuBackgroundFade.pas
+++ b/cmake/src/menu/UMenuBackgroundFade.pas
@@ -1,176 +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;
-
-//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: string;
-begin
- inherited;
- FadeTime := 0;
-
- Color := ThemedSettings.Color;
- Alpha := ThemedSettings.Alpha;
- if (Length(ThemedSettings.Tex) > 0) then
- begin
- texFilename := Skin.GetTextureFileName(ThemedSettings.Tex);
- texFilename := AdaptFilePaths(texFilename);
- 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.
+{* 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/cmake/src/menu/UMenuBackgroundNone.pas b/cmake/src/menu/UMenuBackgroundNone.pas
index 1fccc007..c64f3023 100644
--- a/cmake/src/menu/UMenuBackgroundNone.pas
+++ b/cmake/src/menu/UMenuBackgroundNone.pas
@@ -1,70 +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;
-
+{* 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/cmake/src/menu/UMenuBackgroundTexture.pas b/cmake/src/menu/UMenuBackgroundTexture.pas
index a1b9e88a..f71637ff 100644
--- a/cmake/src/menu/UMenuBackgroundTexture.pas
+++ b/cmake/src/menu/UMenuBackgroundTexture.pas
@@ -1,125 +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;
-
-//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: string;
-begin
- inherited;
-
- if (Length(ThemedSettings.Tex) = 0) then
- raise EMenuBackgroundError.Create('TMenuBackgroundTexture: No texture filename present');
-
- Color := ThemedSettings.Color;
-
- texFilename := Skin.GetTextureFileName(ThemedSettings.Tex);
- texFilename := AdaptFilePaths(texFilename);
- 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.
+{* 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/cmake/src/menu/UMenuBackgroundVideo.pas b/cmake/src/menu/UMenuBackgroundVideo.pas
index d1ce0f09..bfaee702 100644
--- a/cmake/src/menu/UMenuBackgroundVideo.pas
+++ b/cmake/src/menu/UMenuBackgroundVideo.pas
@@ -1,204 +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,
- UVideo;
-
-//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: string): TBGVideo;
- procedure RemoveItem(
- procedure FreeAllItems;
-
- destructor Destroy;
- end;
-
-type }
- TMenuBackgroundVideo = class (TMenuBackground)
- private
- fFilename: string;
- 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,
- UMusic,
- 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);
- fFileName := AdaptFilePaths( fFileName );
-
- if fileexists(fFilename) AND VideoPlayback.Open( fFileName ) then
- begin
- VideoBGTimer.SetTime(0);
- VideoPlayback.Play;
- end
- else
- raise EMenuBackgroundError.Create('TMenuBackgroundVideo: Can''t load background video: ' + fFilename);
-end;
-
-destructor TMenuBackgroundVideo.Destroy;
-begin
-
-end;
-
-procedure TMenuBackgroundVideo.OnShow;
-begin
- if VideoPlayback.Open( fFileName ) then
- begin
- VideoBGTimer.SetTime(0);
- VideoPlayback.Play;
- end;
-end;
-
-procedure TMenuBackgroundVideo.OnFinish;
-begin
-
-end;
-
-procedure TMenuBackgroundVideo.Draw;
-begin
- If (ScreenAct = 1) then //Clear just once when in dual screen mode
- glClear(GL_DEPTH_BUFFER_BIT);
-
- VideoPlayback.GetFrame(VideoBGTimer.GetTime());
- // FIXME: why do we draw on screen 2? Seems to be wrong.
- VideoPlayback.DrawGL(2);
-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: string): TBGVideo;
-begin
-
-end;
-
-procedure TBGVideoPool.FreeAllItems;
-begin
-
-end; }
-
-end.
+{* 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());
+ // FIXME: why do we draw on screen 2? Seems to be wrong.
+ fBgVideo.DrawGL(2);
+ 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/cmake/src/menu/UMenuButton.pas b/cmake/src/menu/UMenuButton.pas
index 923f0b14..868a86f3 100644
--- a/cmake/src/menu/UMenuButton.pas
+++ b/cmake/src/menu/UMenuButton.pas
@@ -38,7 +38,8 @@ uses
UTexture,
gl,
UMenuText,
- SDL;
+ SDL,
+ UMenuInteract;
type
CButton = class of TButton;
@@ -116,6 +117,8 @@ type
constructor Create(Textura: TTexture); overload;
constructor Create(Textura, DSTexture: TTexture); overload;
destructor Destroy; override;
+
+ function GetMouseOverArea: TMouseOverRect;
end;
implementation
@@ -529,6 +532,49 @@ begin
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
diff --git a/cmake/src/menu/UMenuInteract.pas b/cmake/src/menu/UMenuInteract.pas
index beb6bcef..7cb92025 100644
--- a/cmake/src/menu/UMenuInteract.pas
+++ b/cmake/src/menu/UMenuInteract.pas
@@ -39,6 +39,15 @@ type
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.
diff --git a/cmake/src/menu/UMenuSelectSlide.pas b/cmake/src/menu/UMenuSelectSlide.pas
index f9f6bbae..09ce3b9f 100644
--- a/cmake/src/menu/UMenuSelectSlide.pas
+++ b/cmake/src/menu/UMenuSelectSlide.pas
@@ -37,22 +37,29 @@ uses
gl,
TextGL,
UMenuText,
- UTexture;
+ 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 string; // array of names for possible options
+ TextOptT: array of UTF8String; // array of names for possible options
Texture: TTexture; // Select Texture
TextureSBG: TTexture; // Background Selections Texture
-// TextureS: array of TTexture; // Selections Texture (not used)
+
+ 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
@@ -135,8 +142,17 @@ type
//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
@@ -153,6 +169,26 @@ begin
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);
@@ -180,20 +216,30 @@ begin
end
else
begin
- Texture.ColR := DColR;
- Texture.ColG := DColG;
- Texture.ColB := DColB;
- Texture.Int := DInt;
+ 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;
- TextureSBG.ColR := SBGDColR;
- TextureSBG.ColG := SBGDColG;
- TextureSBG.ColB := SBGDColB;
- TextureSBG.Int := SBGDInt;
+ if (ColorizedSBG) then
+ DeselectTextureSBG.Int := SBGDInt
+ else
+ begin
+ TextureSBG.ColR := SBGDColR;
+ TextureSBG.ColG := SBGDColG;
+ TextureSBG.ColB := SBGDColB;
+ TextureSBG.Int := SBGDInt;
+ end;
end;
end;
@@ -236,12 +282,15 @@ begin
begin
Value := 0;
- Tex_SelectS_ArrowL.alpha := 0;
- Tex_SelectS_ArrowR.alpha := 1;
+ 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 := TextOptT[SO];
+ TextOpt[SO].Text := AdjustOptionTextToFit(TextOptT[SO]);
end;
DoSelection(0);
@@ -252,12 +301,12 @@ begin
begin
Value := High(TextOptT);
- Tex_SelectS_ArrowL.alpha := 1;
- Tex_SelectS_ArrowR.alpha := 0;
+ Tex_SelectS_ArrowL.alpha := ArrowAlphaOptionsLeft;
+ Tex_SelectS_ArrowR.alpha := ArrowAlphaNoOptionsLeft;
for SO := High(TextOpt) downto Low(TextOpt) do
begin
- TextOpt[SO].Text := TextOptT[High(TextOptT) - (Lines - SO - 1)];
+ TextOpt[SO].Text := AdjustOptionTextToFit(TextOptT[High(TextOptT) - (Lines - SO - 1)]);
end;
DoSelection(Lines - 1);
end
@@ -265,8 +314,8 @@ begin
//in between first and last
else
begin
- Tex_SelectS_ArrowL.alpha := 1;
- Tex_SelectS_ArrowR.alpha := 1;
+ Tex_SelectS_ArrowL.alpha := ArrowAlphaOptionsLeft;
+ Tex_SelectS_ArrowR.alpha := ArrowAlphaOptionsLeft;
HalfL := Ceil((Lines - 1) / 2);
HalfR := Lines - 1 - HalfL;
@@ -277,7 +326,7 @@ begin
//Change texts
for SO := Low(TextOpt) to High(TextOpt) do
begin
- TextOpt[SO].Text := TextOptT[SO];
+ TextOpt[SO].Text := AdjustOptionTextToFit(TextOptT[SO]);
end;
DoSelection(Value);
@@ -291,10 +340,10 @@ begin
//Change texts
for SO := High(TextOpt) downto Low(TextOpt) do
begin
- TextOpt[SO].Text := TextOptT[High(TextOptT) - (Lines - SO - 1)];
+ TextOpt[SO].Text := AdjustOptionTextToFit(TextOptT[High(TextOptT) - (Lines - SO - 1)]);
end;
- DoSelection (HalfL);
+ DoSelection (HalfL);
end
else
@@ -302,7 +351,7 @@ begin
//Change Texts
for SO := Low(TextOpt) to High(TextOpt) do
begin
- TextOpt[SO].Text := TextOptT[Value - HalfL + SO];
+ TextOpt[SO].Text := AdjustOptionTextToFit(TextOptT[Value - HalfL + SO]);
end;
DoSelection(HalfL);
@@ -311,14 +360,71 @@ begin
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
- DrawTexture(Texture);
- DrawTexture(TextureSBG);
+ 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
@@ -338,7 +444,7 @@ var
maxlength: real;
I: integer;
begin
- SetFontStyle(0{Text.Style});
+ SetFontStyle(ftNormal{Text.Style});
SetFontSize(Text.Size);
maxlength := 0;
@@ -352,7 +458,7 @@ begin
if (oneItemOnly = false) then
begin
//show all items
- Lines := floor((TextureSBG.W-40) / (maxlength+7));
+ Lines := floor((TextureSBG.W - MinSideSpacing * 2) / (maxlength + MinItemSpacing));
if (Lines > Length(TextOptT)) then
Lines := Length(TextOptT);
@@ -369,40 +475,67 @@ begin
for I := Low(TextOpt) to High(TextOpt) do
TextOpt[I].Free;
- setLength (TextOpt, Lines);
+ SetLength (TextOpt, Lines);
for I := Low(TextOpt) to High(TextOpt) do
begin
TextOpt[I] := TText.Create;
TextOpt[I].Size := Text.Size;
- //TextOpt[I].Align := 1;
- TextOpt[I].Align := 0;
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].X := TextureSBG.X + 20 + (TextureSBG.W / Lines) * (I + 0.5);
- if (I <> High(TextOpt)) or (High(TextOpt) = 0) or (Length(TextOptT) = Lines) then
- TextOpt[I].X := TextureSBG.X + 20 + (TextureSBG.W / Lines) * I
- else
- TextOpt[I].X := TextureSBG.X + TextureSBG.W - maxlength;
-
+ // generate positions
TextOpt[I].Y := TextureSBG.Y + (TextureSBG.H - Text.Size) / 2;
- //Better Look with 2 Options
- if (Lines = 2) and (Length(TextOptT) = 2) then
+ // 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;
-
- if (Lines = 1) then
+ TextOpt[I].Align := 0;
+ end
+ else if (Lines = 1) then
begin
- TextOpt[I].Align := 1; //center text
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/cmake/src/menu/UMenuText.pas b/cmake/src/menu/UMenuText.pas
index b5507327..ab180b77 100644
--- a/cmake/src/menu/UMenuText.pas
+++ b/cmake/src/menu/UMenuText.pas
@@ -45,8 +45,8 @@ type
TText = class
private
SelectBool: boolean;
- TextString: string;
- TextTiles: array of string;
+ TextString: UTF8String;
+ TextTiles: array of UTF8String;
STicks: cardinal;
SelectBlink: boolean;
@@ -75,22 +75,23 @@ type
procedure SetSelect(Value: boolean);
property Selected: boolean read SelectBool write SetSelect;
- procedure SetText(Value: string);
- property Text: string read TextString write SetText;
+ procedure SetText(Value: UTF8String);
+ property Text: UTF8String read TextString write SetText;
- procedure DeleteLastL; // procedure to delete last letter
+ procedure DeleteLastLetter; //< Deletes the rightmost letter
procedure Draw;
constructor Create; overload;
- constructor Create(X, Y: real; Text: string); overload;
- constructor Create(ParX, ParY, ParW: real; ParStyle: integer; ParSize, ParColR, ParColG, ParColB: real; ParAlign: integer; ParText: string; ParReflection: boolean; ParReflectionSpacing: real; ParZ: real); 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
- StrUtils,
- UGraphic;
+ UGraphic,
+ UUnicodeUtils,
+ StrUtils;
procedure TText.SetSelect(Value: boolean);
begin
@@ -101,7 +102,7 @@ begin
STicks := SDL_GetTicks() div 550;
end;
-procedure TText.SetText(Value: string);
+procedure TText.SetText(Value: UTF8String);
var
NextPos: cardinal; // next pos of a space etc.
LastPos: cardinal; // last pos "
@@ -244,23 +245,15 @@ begin
AddBreak(LastBreak, Length(Value)+1);
end;
-procedure TText.DeleteLastL;
-var
- S: string;
- L: integer;
+procedure TText.DeleteLastLetter;
begin
- S := TextString;
- L := Length(S);
- if (L > 0) then
- SetLength(S, L-1);
-
- SetText(S);
+ SetText(UTF8Copy(TextString, 1, LengthUTF8(TextString)-1));
end;
procedure TText.Draw;
var
X2, Y2: real;
- Text2: string;
+ Text2: UTF8String;
I: integer;
Ticks: cardinal;
begin
@@ -304,7 +297,7 @@ begin
SetFontPos(X2, Y);
glPrint(Text2);
- SetFontStyle(0); // reset to default
+ SetFontStyle(ftNormal); // reset to default
end
else
begin}
@@ -333,12 +326,12 @@ begin
{if Size >= 10 then
Y2 := Y2 + Size * 0.93
else}
- if (Style = 1) then
+ if (Style = ftBold) then
Y2 := Y2 + Size * 0.93
else
Y2 := Y2 + Size * 0.72;
end;
- SetFontStyle(0); // reset to default
+ SetFontStyle(ftNormal); // reset to default
//end;
end;
@@ -349,19 +342,19 @@ begin
Create(0, 0, '');
end;
-constructor TText.Create(X, Y: real; Text: string);
+constructor TText.Create(X, Y: real; const Text: UTF8String);
begin
- Create(X, Y, 0, 0, 30, 0, 0, 0, 0, Text, false, 0, 0);
+ 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;
- ParText: string;
- ParReflection: boolean;
- ParReflectionSpacing: real;
- ParZ: real);
+ ParSize, ParColR, ParColG, ParColB: real;
+ ParAlign: integer;
+ const ParText: UTF8String;
+ ParReflection: boolean;
+ ParReflectionSpacing: real;
+ ParZ: real);
begin
inherited Create;
Alpha := 1;
diff --git a/cmake/src/screens/UScreenCredits.pas b/cmake/src/screens/UScreenCredits.pas
index def6b7de..b1333b4a 100644
--- a/cmake/src/screens/UScreenCredits.pas
+++ b/cmake/src/screens/UScreenCredits.pas
@@ -35,15 +35,16 @@ interface
uses
SysUtils,
- UMenu,
SDL,
SDL_Image,
+ gl,
+ UMenu,
UDisplay,
UTexture,
- gl,
UMusic,
UFiles,
UThemes,
+ UPath,
UGraphicClasses;
type
@@ -98,10 +99,10 @@ type
Fadeout: boolean;
constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
function Draw: boolean; override;
- procedure onShow; override;
- procedure onHide; override;
+ procedure OnShow; override;
+ procedure OnHide; override;
procedure DrawCredits;
procedure Draw_FunkyText;
end;
@@ -138,17 +139,17 @@ const
OUTRO_EXD_FILE = 'outro-exit-dark.png';
Timings: array[0..21] of cardinal=(
- 20, // 0 Delay vor Start
+ 20, // 0 Delay before Start
- 149, // 1 Ende erster Intro Zoom
- 155, // 2 Start 2. Action im Intro
- 170, // 3 Ende Separation im Intro
- 271, // 4 Anfang Zoomout im Intro
+ 149, // 1 End first Intro Zoom
+ 155, // 2 Start 2. Action in Intro
+ 170, // 3 End Separation in Intro
+ 271, // 4 beginning Zoomout in Intro
0, // 5 unused
- 261, // 6 Start fade-to-white im Intro
+ 261, // 6 Start fade-to-white in Intro
271, // 7 Start Main Part
- 280, // 8 Start On-Beat-Sternchen Main Part
+ 280, // 8 Start On-Beat-Star Main Part
396, // 9 Start BlindGuard
666, // 10 Start blindy
@@ -162,7 +163,7 @@ const
2826, // 18 Ende Whiteshark
3096, // 19 Start FadeOut Mainscreen
3366, // 20 Ende Credits Tune
- 60); // 21 start flare im intro
+ 60); // 21 start flare in intro
implementation
@@ -176,9 +177,9 @@ uses
Textgl,
ULanguage,
UCommon,
- UPath;
+ UPathUtils;
-function TScreenCredits.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+function TScreenCredits.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
begin
Result := true;
if (PressedDown) then
@@ -204,38 +205,38 @@ end;
constructor TScreenCredits.Create;
var
- CreditsPath: string;
+ CreditsPath: IPath;
begin
inherited Create;
- CreditsPath := ResourcesPath + 'credits/';
-
- credits_bg_tex := Texture.LoadTexture(CreditsPath + CRDTS_BG_FILE, TEXTURE_TYPE_PLAIN, 0);
- credits_bg_ovl := Texture.LoadTexture(CreditsPath + CRDTS_OVL_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
-
- credits_blindguard := Texture.LoadTexture(CreditsPath + CRDTS_blindguard_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- credits_blindy := Texture.LoadTexture(CreditsPath + CRDTS_blindy_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- credits_canni := Texture.LoadTexture(CreditsPath + CRDTS_canni_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- credits_commandio := Texture.LoadTexture(CreditsPath + CRDTS_commandio_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- credits_lazyjoker := Texture.LoadTexture(CreditsPath + CRDTS_lazyjoker_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- credits_mog := Texture.LoadTexture(CreditsPath + CRDTS_mog_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- credits_mota := Texture.LoadTexture(CreditsPath + CRDTS_mota_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- credits_skillmaster := Texture.LoadTexture(CreditsPath + CRDTS_skillmaster_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- credits_whiteshark := Texture.LoadTexture(CreditsPath + CRDTS_whiteshark_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
-
- intro_layer01 := Texture.LoadTexture(CreditsPath + INTRO_L01_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- intro_layer02 := Texture.LoadTexture(CreditsPath + INTRO_L02_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- intro_layer03 := Texture.LoadTexture(CreditsPath + INTRO_L03_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- intro_layer04 := Texture.LoadTexture(CreditsPath + INTRO_L04_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- intro_layer05 := Texture.LoadTexture(CreditsPath + INTRO_L05_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- intro_layer06 := Texture.LoadTexture(CreditsPath + INTRO_L06_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- intro_layer07 := Texture.LoadTexture(CreditsPath + INTRO_L07_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- intro_layer08 := Texture.LoadTexture(CreditsPath + INTRO_L08_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- intro_layer09 := Texture.LoadTexture(CreditsPath + INTRO_L09_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
-
- outro_bg := Texture.LoadTexture(CreditsPath + OUTRO_BG_FILE, TEXTURE_TYPE_PLAIN, 0);
- outro_esc := Texture.LoadTexture(CreditsPath + OUTRO_ESC_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- outro_exd := Texture.LoadTexture(CreditsPath + OUTRO_EXD_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
+ 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);
+
+ credits_blindguard := Texture.LoadTexture(CreditsPath.Append(CRDTS_blindguard_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ credits_blindy := Texture.LoadTexture(CreditsPath.Append(CRDTS_blindy_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ credits_canni := Texture.LoadTexture(CreditsPath.Append(CRDTS_canni_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ credits_commandio := Texture.LoadTexture(CreditsPath.Append(CRDTS_commandio_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ credits_lazyjoker := Texture.LoadTexture(CreditsPath.Append(CRDTS_lazyjoker_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ credits_mog := Texture.LoadTexture(CreditsPath.Append(CRDTS_mog_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ credits_mota := Texture.LoadTexture(CreditsPath.Append(CRDTS_mota_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ credits_skillmaster := Texture.LoadTexture(CreditsPath.Append(CRDTS_skillmaster_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ credits_whiteshark := Texture.LoadTexture(CreditsPath.Append(CRDTS_whiteshark_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+
+ 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;
@@ -246,7 +247,7 @@ begin
Draw := true;
end;
-procedure TScreenCredits.onShow;
+procedure TScreenCredits.OnShow;
begin
inherited;
@@ -255,13 +256,13 @@ begin
deluxe_slidein := 0;
Credits_Alpha := 0;
// Music.SetLoop(true); loop loops not, shit
- AudioPlayback.Open(soundpath + 'wome-credits-tune.mp3'); // thank you wetue
+ AudioPlayback.Open(soundpath.Append('wome-credits-tune.mp3')); // thank you wetue
// Music.Play;
CTime := 0;
// setlength(CTime_hold,0);
end;
-procedure TScreenCredits.onHide;
+procedure TScreenCredits.OnHide;
begin
AudioPlayback.Stop;
end;
@@ -1386,7 +1387,7 @@ begin
begin
CTime_hold := 0;
AudioPlayback.Stop;
- AudioPlayback.Open(soundpath + 'credits-outro-tune.mp3');
+ AudioPlayback.Open(SoundPath.Append('credits-outro-tune.mp3'));
AudioPlayback.SetVolume(0.2);
AudioPlayback.SetLoop(true);
AudioPlayback.Play;
diff --git a/cmake/src/screens/UScreenEdit.pas b/cmake/src/screens/UScreenEdit.pas
index 5112e17a..12e2948c 100644
--- a/cmake/src/screens/UScreenEdit.pas
+++ b/cmake/src/screens/UScreenEdit.pas
@@ -45,8 +45,7 @@ type
TextDescriptionLong: integer;
constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar;
- PressedDown: boolean): boolean; override;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
procedure InteractNext; override;
procedure InteractPrev; override;
procedure InteractInc; override;
@@ -60,10 +59,10 @@ uses
UGraphic,
UMusic,
USkins,
+ UUnicodeUtils,
SysUtils;
-function TScreenEdit.ParseInput(PressedKey: cardinal; CharCode: WideChar;
- PressedDown: boolean): boolean;
+function TScreenEdit.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
var
SDL_ModState: word;
begin
@@ -75,8 +74,8 @@ begin
if (PressedDown) then
begin // Key Down
// check normal keys
- case WideCharUpperCase(CharCode)[1] of
- 'Q':
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'):
begin
Result := false;
Exit;
@@ -158,8 +157,8 @@ end;
procedure TScreenEdit.SetAnimationProgress(Progress: real);
begin
- Static[0].Texture.ScaleW := Progress;
- Static[0].Texture.ScaleH := Progress;
+ Statics[0].Texture.ScaleW := Progress;
+ Statics[0].Texture.ScaleH := Progress;
end;
end.
diff --git a/cmake/src/screens/UScreenEditConvert.pas b/cmake/src/screens/UScreenEditConvert.pas
index e4a691cf..8b13d410 100644
--- a/cmake/src/screens/UScreenEditConvert.pas
+++ b/cmake/src/screens/UScreenEditConvert.pas
@@ -25,6 +25,29 @@
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}
@@ -45,10 +68,11 @@ uses
USongs,
USong,
UMusic,
- UThemes;
+ UThemes,
+ UPath;
type
- TNote = record
+ TMidiNote = record
Event: integer;
EventType: integer;
Channel: integer;
@@ -56,70 +80,65 @@ type
Len: real;
Data1: integer;
Data2: integer;
- Str: string;
+ Str: UTF8String; // normally ASCII
end;
+ TLyricType = (ltKMIDI, ltSMFLyric);
+
TTrack = record
- Note: array of TNote;
- Name: string;
- Hear: boolean;
- Status: set of (notes, lyrics);
+ 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;
- TNuta = record
+ TNote = record
Start: integer;
Len: integer;
Tone: integer;
- Lyric: string;
+ Lyric: UTF8String;
NewSentence: boolean;
end;
TArrayTrack = array of TTrack;
TScreenEditConvert = class(TMenu)
- public
- ATrack: TArrayTrack; // actual track
-// Track: TArrayTrack;
- Channel: TArrayTrack;
+ 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;
- Sel: integer;
- Selected: boolean;
-// FileName: string;
+ SelTrack: integer; // index of selected track
+ fFileName: IPath;
{$IFDEF UseMIDIPort}
MidiFile: TMidiFile;
- MidiTrack: TMidiTrack;
- MidiEvent: pMidiEvent;
MidiOut: TMidiOutput;
{$ENDIF}
-
- Song: TSong;
- Lines: TLines;
+
BPM: real;
Ticks: real;
- Note: array of TNuta;
+ Note: array of TNote;
- procedure AddLyric(Start: integer; Text: string);
- procedure Extract;
+ procedure AddLyric(Start: integer; LyricType: TLyricType; Text: UTF8String);
+ procedure Extract(out Song: TSong; out Lines: TLines);
{$IFDEF UseMIDIPort}
procedure MidiFile1MidiEvent(event: PMidiEvent);
{$ENDIF}
-
- function SelectedNumber: integer;
+
+ function CountSelectedTracks: integer;
+
+ public
constructor Create; override;
- procedure onShow; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
+ procedure OnShow; override;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
function Draw: boolean; override;
- procedure onHide; override;
+ procedure OnHide; override;
end;
-var
- ConversionFileName: string;
-
implementation
uses
@@ -131,17 +150,42 @@ uses
UGraphic,
UIni,
UMain,
- UPath,
- USkins;
-
-function TScreenEditConvert.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+ 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 WideCharUpperCase(CharCode)[1] of
- 'Q':
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'):
begin
Result := false;
Exit;
@@ -153,9 +197,10 @@ begin
SDLK_ESCAPE,
SDLK_BACKSPACE :
begin
- {$IFDEF UseMIDIPort}
- MidiFile.StopPlaying;
- {$ENDIF}
+ {$IFDEF UseMIDIPort}
+ if (MidiFile <> nil) then
+ MidiFile.StopPlaying;
+ {$ENDIF}
AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenEdit);
end;
@@ -165,70 +210,97 @@ begin
if Interaction = 0 then
begin
AudioPlayback.PlaySound(SoundLib.Start);
+ ScreenOpen.Filename := GamePath.Append('file.mid');
ScreenOpen.BackScreen := @ScreenEditConvert;
FadeTo(@ScreenOpen);
- end;
-
- if Interaction = 1 then
+ end
+ else if Interaction = 1 then
begin
- Selected := false;
- {$IFDEF UseMIDIPort}
- MidiFile.OnMidiEvent := MidiFile1MidiEvent;
-// MidiFile.GoToTime(MidiFile.GetTrackLength div 2);
- MidiFile.StartPlaying;
+ {$IFDEF UseMIDIPort}
+ if (MidiFile <> nil) then
+ begin
+ MidiFile.OnMidiEvent := MidiFile1MidiEvent;
+ //MidiFile.GoToTime(MidiFile.GetTrackLength div 2);
+ MidiFile.StartPlaying;
+ end;
{$ENDIF}
- end;
-
- if Interaction = 2 then
+ end
+ else if Interaction = 2 then
begin
- Selected := true;
{$IFDEF UseMIDIPort}
- MidiFile.OnMidiEvent := nil;
- {$ENDIF}
- {for T := 0 to High(ATrack) do
+ if (MidiFile <> nil) then
begin
- if ATrack[T].Hear then
- begin
- MidiTrack := MidiFile.GetTrack(T);
- MidiTrack.OnMidiEvent := MidiFile1MidiEvent;
- end;
+ MidiFile.OnMidiEvent := nil;
+ MidiFile.StartPlaying;
end;
- MidiFile.StartPlaying;//}
- end;
-
- if Interaction = 3 then
+ {$ENDIF}
+ end
+ else if Interaction = 3 then
begin
- if SelectedNumber > 0 then
+ {$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
- Extract;
- SaveSong(Song, Lines, ChangeFileExt(ConversionFileName, '.txt'), false);
+ ScreenPopupError.ShowPopup(Language.Translate('EDITOR_ERROR_NO_TRACK_SELECTED'));
end;
+ {$ENDIF}
end;
end;
SDLK_SPACE:
begin
-// ATrack[Sel].Hear := not ATrack[Sel].Hear;
- if Notes in ATrack[Sel].Status then
+ {$IFDEF UseMIDIPort}
+ if (MidiFile <> nil) then
begin
- ATrack[Sel].Status := ATrack[Sel].Status - [Notes];
- if Lyrics in ATrack[Sel].Status then
- ATrack[Sel].Status := ATrack[Sel].Status - [Lyrics]
- else
- ATrack[Sel].Status := ATrack[Sel].Status + [Lyrics];
- end
- else
- ATrack[Sel].Status := ATrack[Sel].Status + [Notes];
+ 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;
-{ if Selected then
- begin
- MidiTrack := MidiFile.GetTrack(Sel);
- if Track[Sel].Hear then
+ Playing := (MidiFile.GetCurrentTime > 0);
+ MidiFile.StopPlaying();
+ MidiTrack := MidiFile.GetTrack(SelTrack);
+ if tsNotes in Tracks[SelTrack].Status then
MidiTrack.OnMidiEvent := MidiFile1MidiEvent
else
MidiTrack.OnMidiEvent := nil;
- end;}
+ if (Playing) then
+ MidiFile.ContinuePlaying();
+ end;
+ {$ENDIF}
end;
SDLK_RIGHT:
@@ -243,102 +315,161 @@ begin
SDLK_DOWN:
begin
- Inc(Sel);
- if Sel > High(ATrack) then
- Sel := 0;
+ Inc(SelTrack);
+ if SelTrack > High(Tracks) then
+ SelTrack := 0;
end;
SDLK_UP:
begin
- Dec(Sel);
- if Sel < 0 then
- Sel := High(ATrack);
+ Dec(SelTrack);
+ if SelTrack < 0 then
+ SelTrack := High(Tracks);
end;
end;
end;
end;
-procedure TScreenEditConvert.AddLyric(Start: integer; Text: string);
+procedure TScreenEditConvert.AddLyric(Start: integer; LyricType: TLyricType; Text: UTF8String);
var
N: integer;
begin
- for N := 0 to High(Note) do
+ // find corresponding note
+ N := 0;
+ while (N <= High(Note)) do
begin
if Note[N].Start = Start then
- begin
- // check for new sentece
- if Copy(Text, 1, 1) = '\' then
- Delete(Text, 1, 1);
- if Copy(Text, 1, 1) = '/' then
- begin
- Delete(Text, 1, 1);
- Note[N].NewSentence := true;
- end;
+ Break;
+ Inc(N);
+ end;
- // overwrite lyric od append
- if Note[N].Lyric = '-' then
- Note[N].Lyric := Text
- else
- Note[N].Lyric := Note[N].Lyric + Text;
+ // 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;
+procedure TScreenEditConvert.Extract(out Song: TSong; out Lines: TLines);
+
var
T: integer;
C: integer;
N: integer;
Nu: integer;
- NoteTemp: TNuta;
+ NoteTemp: TNote;
Move: integer;
Max, Min: integer;
+ LyricType: TLyricType;
+ Text: UTF8String;
begin
// song info
- Song.Title := '';
- Song.Artist := '';
- Song.Mp3 := '';
+ 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(ATrack) do
+ for T := 0 to High(Tracks) do
begin
-// if ATrack[T].Hear then
-// begin
- if Notes in ATrack[T].Status then
+ if tsNotes in Tracks[T].Status then
begin
- for N := 0 to High(ATrack[T].Note) do
+ for N := 0 to High(Tracks[T].Note) do
begin
- if (ATrack[T].Note[N].EventType = 9) and (ATrack[T].Note[N].Data2 > 0) then
+ 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(ATrack[T].Note[N].Start / Ticks);
- Note[Nu].Len := Round(ATrack[T].Note[N].Len / Ticks);
- Note[Nu].Tone := ATrack[T].Note[N].Data1 - 12*5;
+ 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
- for T := 0 to High(ATrack) do
+ // extract lyrics (and artist + title info)
+ for T := 0 to High(Tracks) do
begin
-// if ATrack[T].Hear then
-// begin
- if Lyrics in ATrack[T].Status then
+ if not (tsLyrics in Tracks[T].Status) then
+ Continue;
+
+ for N := 0 to High(Tracks[T].Note) do
begin
- for N := 0 to High(ATrack[T].Note) do
+ if (Tracks[T].Note[N].Event = MIDI_EVENT_META) then
begin
- if (ATrack[T].Note[N].EventType = 15) then
+ // determine and validate lyric meta tag
+ if (ltKMIDI in Tracks[T].LyricType) and
+ (Tracks[T].Note[N].Data1 = MIDI_META_TEXT) then
begin
-// Log.LogStatus('<' + Track[T].Note[N].Str + '>', 'MIDI');
- AddLyric(Round(ATrack[T].Note[N].Start / Ticks), ATrack[T].Note[N].Str);
+ 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;
@@ -360,8 +491,12 @@ begin
// copy notes
SetLength(Lines.Line, 1);
- Lines.Number := 1;
- Lines.High := 0;
+ Lines.Number := 1;
+ Lines.High := 0;
+ Lines.Current := 0;
+ Lines.Resolution := 0;
+ Lines.NotesGAP := 0;
+ Lines.ScoreValue := 0;
C := 0;
N := 0;
@@ -403,35 +538,37 @@ begin
// 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 := Note[Nu].Lyric;
- //All Notes are Freestyle when Converted Fix:
+ 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.SelectedNumber: integer;
+function TScreenEditConvert.CountSelectedTracks: integer;
var
T: integer; // track
begin
Result := 0;
- for T := 0 to High(ATrack) do
-// if ATrack[T].Hear then
-// Inc(Result);
- if Notes in ATrack[T].Status then
+ 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');
- MidiOut.PutShort(event.event, event.data1, event.data2);
+ //Log.LogStatus(IntToStr(event.event), 'MIDI');
+ try
+ MidiOut.PutShort(event.event, event.data1, event.data2);
+ except
+ MidiFile.StopPlaying();
+ end;
end;
{$ENDIF}
@@ -442,7 +579,7 @@ 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;
+ //Button[High(Button)].Text[0].Size := 11;
AddButton(160, 20, 100, 40, Skin.GetTextureFileName('ButtonF'));
AddButtonText(25, 5, 0, 0, 0, 'Play');
@@ -453,19 +590,7 @@ begin
AddButton(500, 20, 100, 40, Skin.GetTextureFileName('ButtonF'));
AddButtonText(20, 5, 0, 0, 0, 'Save');
-{ MidiOut := TMidiOutput.Create(nil);
-// MidiOut.Close;
-// MidiOut.DeviceID := 0;
- if Ini.Debug = 1 then
- MidiOut.ProductName := 'Microsoft GS Wavetable SW Synth'; // for my kxproject without midi table
- Log.LogStatus(MidiOut.ProductName, 'MIDI');
- MidiOut.Open;
-// MidiOut.SetVolume(100, 100); // temporary}
-
- ConversionFileName := GamePath + 'file.mid';
- {$IFDEF UseMIDIPort}
- MidiFile := TMidiFile.Create(nil);
- {$ENDIF}
+ fFileName := PATH_NONE;
for P := 0 to 100 do
begin
@@ -476,96 +601,124 @@ begin
end;
-procedure TScreenEditConvert.onShow;
+procedure TScreenEditConvert.OnShow;
+{$IFDEF UseMIDIPort}
var
T: integer; // track
N: integer; // note
- C: integer; // channel
- CN: integer; // channel note
+ MidiTrack: TMidiTrack;
+ MidiEvent: PMidiEvent;
+ FileOpened: boolean;
+ KMIDITrackIndex, SMFTrackIndex: integer;
+{$ENDIF}
begin
inherited;
+ Interaction := 0;
+
{$IFDEF UseMIDIPort}
MidiOut := TMidiOutput.Create(nil);
- if Ini.Debug = 1 then
- MidiOut.ProductName := 'Microsoft GS Wavetable SW Synth'; // for my kxproject without midi table
- Log.LogStatus(MidiOut.ProductName, 'MIDI');
+ 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;
- if FileExists(ConversionFileName) then
+ FileOpened := false;
+ if fFileName.Exists then
begin
- MidiFile.Filename := ConversionFileName;
- MidiFile.ReadFile;
+ MidiFile := TMidiFile.Create(nil);
+ MidiFile.Filename := fFileName;
+ try
+ MidiFile.ReadFile;
+ FileOpened := true;
+ except
+ MidiFile.Free;
+ end;
+ end;
- Len := 0;
- Sel := 0;
- BPM := MidiFile.Bpm;
- Ticks := MidiFile.TicksPerQuarter / 4;
+ if (not FileOpened) then
+ begin
+ ScreenPopupError.ShowPopup(Language.Translate('ERROR_FILE_NOT_FOUND'));
+ Exit;
+ end;
-{ for T := 0 to MidiFile.NumberOfTracks-1 do
- begin
- SetLength(Track, Length(Track)+1);
- MidiTrack := MidiFile.GetTrack(T);
- MidiTrack.OnMidiEvent := MidiFile1MidiEvent;
- Track[T].Name := MidiTrack.getName;
+ Len := 0;
+ SelTrack := 0;
+ BPM := MidiFile.Bpm;
+ Ticks := MidiFile.TicksPerQuarter / 4;
- for N := 0 to MidiTrack.getEventCount-1 do
- begin
- SetLength(Track[T].Note, Length(Track[T].Note)+1);
- MidiEvent := MidiTrack.GetEvent(N);
- Track[T].Note[N].Start := MidiEvent.time;
- Track[T].Note[N].Len := MidiEvent.len;
- Track[T].Note[N].Event := MidiEvent.event;
- Track[T].Note[N].EventType := MidiEvent.event div 16;
- Track[T].Note[N].Channel := MidiEvent.event and 15;
- Track[T].Note[N].Data1 := MidiEvent.data1;
- Track[T].Note[N].Data2 := MidiEvent.data2;
- Track[T].Note[N].Str := MidiEvent.str;
-
- if Track[T].Note[N].Start + Track[T].Note[N].Len > Len then
- Len := Track[T].Note[N].Start + Track[T].Note[N].Len;
- end;
- end;}
+ KMIDITrackIndex := -1;
+ SMFTrackIndex := -1;
- SetLength(Channel, 16);
- for T := 0 to 15 do
- begin
- Channel[T].Name := IntToStr(T+1);
- SetLength(Channel[T].Note, 0);
- Channel[T].Status := [];
- end;
+ SetLength(Tracks, MidiFile.NumberOfTracks);
+ for T := 0 to MidiFile.NumberOfTracks-1 do
+ Tracks[T].LyricType := [];
- for T := 0 to MidiFile.NumberOfTracks-1 do
+ 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
- MidiTrack := MidiFile.GetTrack(T);
- MidiTrack.OnMidiEvent := MidiFile1MidiEvent;
-
- for N := 0 to MidiTrack.getEventCount-1 do
+ 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
- MidiEvent := MidiTrack.GetEvent(N);
- C := MidiEvent.event and 15;
-
- CN := Length(Channel[C].Note);
- SetLength(Channel[C].Note, CN+1);
-
- Channel[C].Note[CN].Start := MidiEvent.time;
- Channel[C].Note[CN].Len := MidiEvent.len;
- Channel[C].Note[CN].Event := MidiEvent.event;
- Channel[C].Note[CN].EventType := MidiEvent.event div 16;
- Channel[C].Note[CN].Channel := MidiEvent.event and 15;
- Channel[C].Note[CN].Data1 := MidiEvent.data1;
- Channel[C].Note[CN].Data2 := MidiEvent.data2;
- Channel[C].Note[CN].Str := MidiEvent.str;
-
- if Channel[C].Note[CN].Start + Channel[C].Note[CN].Len > Len then
- Len := Channel[C].Note[CN].Start + Channel[C].Note[CN].Len;
+ // notes available
+ Tracks[T].NoteType := ntAvail;
end;
- end;
- ATrack := Channel;
+ 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;
- Interaction := 0;
+ // 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;
@@ -584,35 +737,37 @@ begin
Y := 100;
- Height := min(480, 40 * Length(ATrack));
+ Height := min(480, 40 * Length(Tracks));
Bottom := Y + Height;
- if Length(ATrack) = 0 then // prevent crash with uncomplete code.
- begin
- Log.LogDebug ('UScreenEditConvert -> TScreenEditConvert.Draw:', 'Length(ATrack) = 0');
- YSkip := 40;
- end
- else
- YSkip := Height / Length(ATrack);
+ YSkip := Height / Length(Tracks);
- // select
- DrawQuad(10, Y + Sel*YSkip, 780, YSkip, 0.8, 0.8, 0.8);
+ // highlight selected track
+ DrawQuad(10, Y+SelTrack*YSkip, 780, YSkip, 0.8, 0.8, 0.8);
- // selected - now me use Status System
- for Count := 0 to High(ATrack) do
- if ATrack[Count].Hear then
+ // 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(ATrack) do
+ for Count := 0 to High(Tracks) do
begin
- if Notes in ATrack[Count].Status then
+ 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 Lyrics in ATrack[Count].Status then
+ 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');
@@ -623,51 +778,48 @@ begin
DrawLine( 60, Y, 60, Bottom, 0, 0, 0);
DrawLine(790, Y, 790, Bottom, 0, 0, 0);
- for Count := 0 to Length(ATrack) do
+ for Count := 0 to Length(Tracks) do
DrawLine(10, Y + Count*YSkip, 790, Y + Count*YSkip, 0, 0, 0);
- for Count := 0 to High(ATrack) do
+ for Count := 0 to High(Tracks) do
begin
- SetFontPos(11, Y + 10 + Count*YSkip);
+ SetFontPos(65, Y + Count*YSkip);
SetFontSize(15);
- glPrint(ATrack[Count].Name);
+ glPrint(Tracks[Count].Name);
end;
- for Count := 0 to High(ATrack) do
- for Count2 := 0 to High(ATrack[Count].Note) do
+ for Count := 0 to High(Tracks) do
+ begin
+ for Count2 := 0 to High(Tracks[Count].Note) do
begin
- if ATrack[Count].Note[Count2].EventType = 9 then
- DrawQuad(60 + ATrack[Count].Note[Count2].Start/Len*725,
- Y + (Count+1)*YSkip - ATrack[Count].Note[Count2].Data1*35/127,
- 3,
- 3,
- ColR[Count],
- ColG[Count],
- ColB[Count]);
- if ATrack[Count].Note[Count2].EventType = 15 then
- DrawLine(60 + ATrack[Count].Note[Count2].Start/Len*725,
- Y + 0.75*YSkip + Count*YSkip,
- 60 + ATrack[Count].Note[Count2].Start/Len*725,
- Y + YSkip + Count*YSkip,
- ColR[Count],
- ColG[Count],
- ColB[Count]);
+ 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}
- X := 60 + MidiFile.GetCurrentTime/MidiFile.GetTrackLength*730;
+ 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;
+procedure TScreenEditConvert.OnHide;
begin
{$IFDEF UseMIDIPort}
+ FreeAndNil(MidiFile);
MidiOut.Close;
- MidiOut.Free;
+ FreeAndNil(MidiOut);
{$ENDIF}
end;
diff --git a/cmake/src/screens/UScreenEditHeader.pas b/cmake/src/screens/UScreenEditHeader.pas
index ad0fc40a..1d697bc9 100644
--- a/cmake/src/screens/UScreenEditHeader.pas
+++ b/cmake/src/screens/UScreenEditHeader.pas
@@ -38,6 +38,7 @@ uses
SDL,
USongs,
USong,
+ UPath,
UThemes;
type
@@ -72,8 +73,8 @@ type
procedure SetRoundButtons;
constructor Create; override;
- procedure onShow; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
+ procedure OnShow; override;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
{ function Draw: boolean; override;
procedure Finish;}
end;
@@ -86,17 +87,18 @@ uses
SysUtils,
UFiles,
USkins,
- UTexture;
+ UTexture,
+ UUnicodeUtils;
-function TScreenEditHeader.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+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 WideCharUpperCase(CharCode)[1] of
- 'Q':
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'):
begin
Result := false;
Exit;
@@ -105,10 +107,10 @@ begin
// check special keys
case PressedKey of
- SDLK_ESCAPE :
+ SDLK_ESCAPE:
begin
-// Music.PlayBack;
-// FadeTo(@MainScreen);
+ //Music.PlayBack;
+ //FadeTo(@MainScreen);
Result := false;
end;
@@ -116,7 +118,7 @@ begin
begin
if Interaction = 1 then
begin
-// Save;
+ //Save;
end;
end;
@@ -159,19 +161,19 @@ begin
T := Interaction - 2 + TextTitle;
if (Interaction >= 2) and (Interaction <= 13) and (Length(Text[T].Text) >= 1) then
begin
- Text[T].DeleteLastL;
+ Text[T].DeleteLastLetter;
SetRoundButtons;
end;
end;
end;
case CharCode of
- #32..#255:
+ 32..255:
begin
if (Interaction >= 2) and (Interaction <= 13) then
begin
Text[Interaction - 2 + TextTitle].Text :=
- Text[Interaction - 2 + TextTitle].Text + CharCode;
+ Text[Interaction - 2 + TextTitle].Text + UCS4ToUTF8String(CharCode);
SetRoundButtons;
end;
end;
@@ -223,18 +225,18 @@ begin
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, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
- StaticArtist := AddStatic(130, 115 + 1*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
- StaticMp3 := AddStatic(130, 115 + 2*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
- StaticBackground := AddStatic(130, 115 + 4*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
- StaticVideo := AddStatic(130, 115 + 5*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
- StaticVideoGAP := AddStatic(130, 115 + 6*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
- StaticRelative := AddStatic(130, 115 + 8*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
- StaticResolution := AddStatic(130, 115 + 9*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
- StaticNotesGAP := AddStatic(130, 115 + 10*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
- StaticStart := AddStatic(130, 115 + 12*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
- StaticGAP := AddStatic(130, 115 + 13*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
- StaticBPM := AddStatic(130, 115 + 14*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+ 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);
@@ -250,7 +252,7 @@ begin
AddInteraction(iText, TextBPM);
end;
-procedure TScreenEditHeader.onShow;
+procedure TScreenEditHeader.OnShow;
begin
inherited;
@@ -347,90 +349,90 @@ end;*)
procedure TScreenEditHeader.SetRoundButtons;
begin
if Length(Text[TextTitle].Text) > 0 then
- Static[StaticTitle].Visible := true
+ Statics[StaticTitle].Visible := true
else
- Static[StaticTitle].Visible := false;
+ Statics[StaticTitle].Visible := false;
if Length(Text[TextArtist].Text) > 0 then
- Static[StaticArtist].Visible := true
+ Statics[StaticArtist].Visible := true
else
- Static[StaticArtist].Visible := false;
+ Statics[StaticArtist].Visible := false;
if Length(Text[TextMp3].Text) > 0 then
- Static[StaticMp3].Visible := true
+ Statics[StaticMp3].Visible := true
else
- Static[StaticMp3].Visible := false;
+ Statics[StaticMp3].Visible := false;
if Length(Text[TextBackground].Text) > 0 then
- Static[StaticBackground].Visible := true
+ Statics[StaticBackground].Visible := true
else
- Static[StaticBackground].Visible := false;
+ Statics[StaticBackground].Visible := false;
if Length(Text[TextVideo].Text) > 0 then
- Static[StaticVideo].Visible := true
+ Statics[StaticVideo].Visible := true
else
- Static[StaticVideo].Visible := false;
+ Statics[StaticVideo].Visible := false;
try
StrToFloat(Text[TextVideoGAP].Text);
if StrToFloat(Text[TextVideoGAP].Text)<> 0 then
- Static[StaticVideoGAP].Visible := true
+ Statics[StaticVideoGAP].Visible := true
else
- Static[StaticVideoGAP].Visible := false;
+ Statics[StaticVideoGAP].Visible := false;
except
- Static[StaticVideoGAP].Visible := false;
+ Statics[StaticVideoGAP].Visible := false;
end;
if LowerCase(Text[TextRelative].Text) = 'yes' then
- Static[StaticRelative].Visible := true
+ Statics[StaticRelative].Visible := true
else
- Static[StaticRelative].Visible := false;
+ Statics[StaticRelative].Visible := false;
try
StrToInt(Text[TextResolution].Text);
if (StrToInt(Text[TextResolution].Text) <> 0) and (StrToInt(Text[TextResolution].Text) >= 1) then
- Static[StaticResolution].Visible := true
+ Statics[StaticResolution].Visible := true
else
- Static[StaticResolution].Visible := false;
+ Statics[StaticResolution].Visible := false;
except
- Static[StaticResolution].Visible := false;
+ Statics[StaticResolution].Visible := false;
end;
try
StrToInt(Text[TextNotesGAP].Text);
- Static[StaticNotesGAP].Visible := true;
+ Statics[StaticNotesGAP].Visible := true;
except
- Static[StaticNotesGAP].Visible := false;
+ Statics[StaticNotesGAP].Visible := false;
end;
// start
try
StrToFloat(Text[TextStart].Text);
if (StrToFloat(Text[TextStart].Text) > 0) then
- Static[StaticStart].Visible := true
+ Statics[StaticStart].Visible := true
else
- Static[StaticStart].Visible := false;
+ Statics[StaticStart].Visible := false;
except
- Static[StaticStart].Visible := false;
+ Statics[StaticStart].Visible := false;
end;
// GAP
try
StrToFloat(Text[TextGAP].Text);
- Static[StaticGAP].Visible := true;
+ Statics[StaticGAP].Visible := true;
except
- Static[StaticGAP].Visible := false;
+ Statics[StaticGAP].Visible := false;
end;
// BPM
try
StrToFloat(Text[TextBPM].Text);
if (StrToFloat(Text[TextBPM].Text) > 0) then
- Static[StaticBPM].Visible := true
+ Statics[StaticBPM].Visible := true
else
- Static[StaticBPM].Visible := false;
+ Statics[StaticBPM].Visible := false;
except
- Static[StaticBPM].Visible := false;
+ Statics[StaticBPM].Visible := false;
end;
end;
diff --git a/cmake/src/screens/UScreenEditSub.pas b/cmake/src/screens/UScreenEditSub.pas
index 3e1f3c1c..7956b127 100644
--- a/cmake/src/screens/UScreenEditSub.pas
+++ b/cmake/src/screens/UScreenEditSub.pas
@@ -56,6 +56,7 @@ uses
type
TScreenEditSub = class(TMenu)
private
+ AktBeat: integer;
//Variable is True if no Song is loaded
Error: boolean;
@@ -90,6 +91,7 @@ type
MidiLastNote: integer;
TextEditMode: boolean;
+ editText: UTF8String; //backup of current text in text-edit-mode
Lyric: TEditorLyrics;
@@ -110,17 +112,19 @@ type
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: WideChar; PressedDown: boolean): boolean; override;
- function ParseInputEditText(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+ 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;
+ procedure OnHide; override;
end;
implementation
@@ -130,14 +134,44 @@ uses
UDraw,
UNote,
USkins,
- ULanguage;
+ 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: WideChar; PressedDown: boolean): boolean;
+function TScreenEditSub.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
var
SDL_ModState: word;
R: real;
+ SResult: TSaveSongResult;
begin
Result := true;
@@ -152,40 +186,68 @@ begin
+ KMOD_LCTRL + KMOD_RCTRL + KMOD_LALT + KMOD_RALT {+ KMOD_CAPS});
if (PressedDown) then // Key Down
- begin // check normal keys
- case WideCharUpperCase(CharCode)[1] of
- 'Q':
+ begin
+ // check normal keys
+ case PressedKey of
+ SDLK_Q:
begin
Result := false;
Exit;
end;
- 'S':
+ SDLK_S:
begin
// Save Song
- if SDL_ModState = KMOD_LSHIFT then
- SaveSong(CurrentSong, Lines[0], CurrentSong.Path + CurrentSong.FileName, true)
+ 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
- SaveSong(CurrentSong, Lines[0], CurrentSong.Path + CurrentSong.FileName, false);
+ begin
+ ScreenPopupError.ShowPopup(Language.Translate('ERROR_SAVE_FILE_FAILED'));
+ end;
+ Exit;
+ end;
- {if SDL_ModState = KMOD_LSHIFT or KMOD_LCTRL + KMOD_LALT then
- // Save Song
- SaveSongDebug(CurrentSong, Lines[0], 'C:\song.asm', false);}
+ SDLK_R: //reload
+ begin
+ AudioPlayback.Stop;
+ {$IFDEF UseMIDIPort}
+ MidiOut.Close;
+ MidiOut.Free;
+ {$ENDIF}
+ Lyric.Free;
- Exit;
+ onShow;
+ Text[TextDebug].Text := 'song reloaded'; //TODO: Language.Translate('SONG_RELOADED');
end;
- 'D':
+
+ SDLK_D:
begin
// Divide lengths by 2
- DivideBPM;
- Exit;
+ if (SDL_ModState = KMOD_LSHIFT) then
+ begin
+ DivideBPM;
+ Exit;
+ end;
end;
- 'M':
+ SDLK_M:
begin
// Multiply lengths by 2
- MultiplyBPM;
- Exit;
+ if (SDL_ModState = KMOD_LSHIFT) then
+ begin
+ MultiplyBPM;
+ Exit;
+ end;
end;
- 'C':
+ SDLK_C:
begin
// Capitalize letter at the beginning of line
if SDL_ModState = 0 then
@@ -201,7 +263,7 @@ begin
Exit;
end;
- 'V':
+ SDLK_V:
begin
// Paste text
if SDL_ModState = KMOD_LCTRL then
@@ -217,13 +279,13 @@ begin
CopySentence(CopySrc, Lines[0].Current);
end;
end;
- 'T':
+ SDLK_T:
begin
// Fixes timings between sentences
FixTimings;
Exit;
end;
- 'P':
+ SDLK_P:
begin
if SDL_ModState = 0 then
begin
@@ -269,8 +331,8 @@ begin
Exit;
end;
- // Golden Note Patch
- 'G':
+ // 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
@@ -280,8 +342,8 @@ begin
Exit;
end;
- // Freestyle Note Patch
- 'F':
+ // 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
@@ -424,22 +486,40 @@ begin
SDLK_F4:
begin
// Enter Text Edit Mode
+ editText := Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text;
TextEditMode := true;
end;
SDLK_SPACE:
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;
+ 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:
@@ -466,11 +546,11 @@ begin
// right
if SDL_ModState = 0 then
begin
- Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 0;
+ 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 := 1;
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2;
Lyric.Selected := CurrentNote;
end;
@@ -521,11 +601,11 @@ begin
// left
if SDL_ModState = 0 then
begin
- Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 0;
+ 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 := 1;
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2;
Lyric.Selected := CurrentNote;
end;
@@ -580,17 +660,18 @@ begin
// skip to next sentence
if SDL_ModState = 0 then
- begin {$IFDEF UseMIDIPort}
+ begin
+ {$IFDEF UseMIDIPort}
MidiOut.PutShort($81, Lines[0].Line[Lines[0].Current].Note[MidiLastNote].Tone + 60, 127);
PlaySentenceMidi := false;
- {$endif}
+ {$ENDIF}
- Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 0;
+ 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 := 1;
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2;
Lyric.AddLine(Lines[0].Current);
Lyric.Selected := 0;
@@ -617,12 +698,12 @@ begin
PlaySentenceMidi := false;
{$endif}
- Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 0;
+ 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 := 1;
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2;
Lyric.AddLine(Lines[0].Current);
Lyric.Selected := 0;
@@ -642,7 +723,7 @@ begin
end; // if
end;
-function TScreenEditSub.ParseInputEditText(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+function TScreenEditSub.ParseInputEditText(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
var
SDL_ModState: word;
begin
@@ -653,39 +734,51 @@ begin
+ KMOD_LCTRL + KMOD_RCTRL + KMOD_LALT + KMOD_RALT {+ KMOD_CAPS});
if (PressedDown) then
- begin // Key Down
- case PressedKey of
+ 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
- FadeTo(@ScreenSong);
+ 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_0..SDLK_9, SDLK_A..SDLK_Z, SDLK_SPACE, SDLK_MINUS, SDLK_EXCLAIM, SDLK_COMMA, SDLK_SLASH, SDLK_ASTERISK, SDLK_QUESTION, SDLK_QUOTE, SDLK_QUOTEDBL:
- begin
- Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text :=
- Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text + CharCode;
- end;
SDLK_BACKSPACE:
begin
- Delete(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text,
- Length(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text), 1);
+ 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 := 0;
+ 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 := 1;
+ 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:
@@ -693,12 +786,13 @@ begin
// left
if SDL_ModState = 0 then
begin
- Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 0;
+ 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 := 1;
+ 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;
@@ -719,15 +813,17 @@ procedure TScreenEditSub.DivideBPM;
var
C: integer;
N: integer;
-begin
+
+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].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
@@ -758,9 +854,11 @@ var
S: string;
begin
// temporary
-{ for C := 0 to Lines[0].High do
+ {
+ 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 := AnsiLowerCase(Lines[0].Line[C].Note[N].Text);}
+ Lines[0].Line[C].Note[N].Text := UTF8LowerCase(Lines[0].Line[C].Note[N].Text);
+ }
for C := 0 to Lines[0].High do
begin
@@ -890,7 +988,7 @@ begin
begin
Inc(HighNote);
SetLength(Note, HighNote + 1);
- Note[HighNote] := Note[N];
+ Note[HighNote] := Lines[0].Line[CStart].Note[N];
End_ := Note[HighNote].Start + Note[HighNote].Length;
if Note[HighNote].Tone < BaseNote then
@@ -916,7 +1014,7 @@ begin
Lines[0].Current := Lines[0].Current + 1;
CurrentNote := 0;
- Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 1;
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2;
Lyric.AddLine(Lines[0].Current);
end;
@@ -979,7 +1077,7 @@ begin
Inc(Note[CurrentNote+1].Start);
Dec(Note[CurrentNote+1].Length);
Note[CurrentNote+1].Text := '- ';
- Note[CurrentNote+1].Color := 0;
+ Note[CurrentNote+1].Color := 1;
end;
end;
@@ -1009,7 +1107,7 @@ begin
if CurrentNote > Lines[0].Line[C].HighNote then
Dec(CurrentNote);
- Lines[0].Line[C].Note[CurrentNote].Color := 1;
+ Lines[0].Line[C].Note[CurrentNote].Color := 2;
end
//Last Note of current Sentence Deleted - > Delete Sentence
else
@@ -1029,7 +1127,7 @@ begin
else
Lines[0].Current := 0;
- Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 1;
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2;
end;
end;
end;
@@ -1085,14 +1183,16 @@ var
N: integer;
NHigh: integer;
begin
-{ C := Lines[0].Current;
+ {
+ 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 := '- ';}
+ Lines[0].Line[C].Note[0].Text := '- ';
+ }
C := Lines[0].Current;
NHigh := Lines[0].Line[C].HighNote;
@@ -1181,73 +1281,288 @@ begin
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;
+ ww: integer;
+
+ pos: real;
+ br: real;
+
+ line, note: integer;
+ numLines, numNotes: integer;
+
+begin
+ numLines := Length(Lines[0].Line);
+
+ if(numLines=0) then
+ Exit;
+
+ start := Lines[0].Line[0].Start;
+ end_ := Lines[0].Line[numLines-1].End_;
+ ww := end_ - start;
+
+ 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/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;
+ {
+ numNotes := Length(Lines[0].Line[line].Nuta);
+
+ for note := 0 to numNotes - 1 do
+ begin
+
+ end; }
+ end;
+
+ if(PlaySentence or PlaySentenceMidi) then
+ begin
+ glColor4f(0, 0, 0, 0.5);
+ pos := 0;
+ br := AktBeat/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/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
- AddStatic(20, 10, 80, 30, 0, 0, 0, Skin.GetTextureFileName('ButtonF'), TEXTURE_TYPE_COLORIZED);
- AddText(40, 17, 1, 18, 1, 1, 1, 'Line');
- TextSentence := AddText(120, 14, 1, 24, 0, 0, 0, '0 / 0');
+ AddText(40, 11, 1, 30, 0, 0, 0, 'Line:');
+ TextSentence := AddText(110, 11, 1, 30, 0, 0, 0, '0 / 0');
+
// Note
- AddStatic(220, 10, 80, 30, 0, 0, 0, Skin.GetTextureFileName('ButtonF'), TEXTURE_TYPE_COLORIZED);
- AddText(242, 17, 1, 18, 1, 1, 1, 'Note');
- TextNote := AddText(320, 14, 1, 24, 0, 0, 0, '0 / 0');
+ AddText(282, 11, 1, 30, 0, 0, 0, 'Note:');
+ TextNote := AddText(360, 11, 1, 30, 0, 0, 0, '0 / 0');
// file info
- AddStatic(150, 50, 500, 150, 0, 0, 0, Skin.GetTextureFileName('MainBar'), TEXTURE_TYPE_COLORIZED);
- AddStatic(151, 52, 498, 146, 1, 1, 1, Skin.GetTextureFileName('MainBar'), TEXTURE_TYPE_COLORIZED);
- AddText(180, 65, 0, 24, 0, 0, 0, 'Title:');
- AddText(180, 90, 0, 24, 0, 0, 0, 'Artist:');
- AddText(180, 115, 0, 24, 0, 0, 0, 'Mp3:');
- AddText(180, 140, 0, 24, 0, 0, 0, 'BPM:');
- AddText(180, 165, 0, 24, 0, 0, 0, 'GAP:');
-
- TextTitle := AddText(250, 65, 0, 24, 0, 0, 0, 'a');
- TextArtist := AddText(250, 90, 0, 24, 0, 0, 0, 'b');
- TextMp3 := AddText(250, 115, 0, 24, 0, 0, 0, 'c');
- TextBPM := AddText(250, 140, 0, 24, 0, 0, 0, 'd');
- TextGAP := AddText(250, 165, 0, 24, 0, 0, 0, 'e');
-
-{ AddInteraction(2, TextTitle);
- AddInteraction(2, TextArtist);
- AddInteraction(2, TextMp3);
- AddInteraction(2, TextBPM);
- AddInteraction(2, TextGAP);}
+ 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(20, 190, 0, 24, 0, 0, 0, 'Start:');
- AddText(20, 215, 0, 24, 0, 0, 0, 'Duration:');
- AddText(20, 240, 0, 24, 0, 0, 0, 'Tone:');
- AddText(20, 265, 0, 24, 0, 0, 0, 'Text:');
+ 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');
- TextNStart := AddText(120, 190, 0, 24, 0, 0, 0, 'a');
- TextNLength := AddText(120, 215, 0, 24, 0, 0, 0, 'b');
- TextNTon := AddText(120, 240, 0, 24, 0, 0, 0, 'c');
- TextNText := AddText(120, 265, 0, 24, 0, 0, 0, 'd');
+ //TextVideoGap := AddText(600, 265, 0, 24, 0, 0, 0, 'e');
// debug
- TextDebug := AddText(30, 550, 0, 8, 0, 0, 0, '');
+ TextDebug := AddText(30, 550, 0, 27, 0, 0, 0, '');
end;
-procedure TScreenEditSub.onShow;
+procedure TScreenEditSub.OnShow;
+var
+ FileExt: IPath;
begin
inherited;
- Log.LogStatus('Initializing', 'TEditScreen.onShow');
+ AudioPlayback.Stop;
+ PlaySentence := false;
+ PlaySentenceMidi := false;
+
+ Log.LogStatus('Initializing', 'TEditScreen.OnShow');
Lyric := TEditorLyrics.Create;
ResetSingTemp;
try
- //Check if File is XML
- if copy(CurrentSong.FileName,length(CurrentSong.FileName)-3,4) = '.xml' then
- Error := not CurrentSong.LoadXMLSong()
- else
- Error := not CurrentSong.LoadSong();
+ //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;
@@ -1263,18 +1578,16 @@ begin
begin
{$IFDEF UseMIDIPort}
MidiOut := TMidiOutput.Create(nil);
- if Ini.Debug = 1 then
- MidiOut.ProductName := 'Microsoft GS Wavetable SW Synth'; // for my kxproject without midi table
MidiOut.Open;
{$ENDIF}
Text[TextTitle].Text := CurrentSong.Title;
Text[TextArtist].Text := CurrentSong.Artist;
- Text[TextMp3].Text := CurrentSong.Mp3;
+ Text[TextMp3].Text := CurrentSong.Mp3.ToUTF8;
Lines[0].Current := 0;
CurrentNote := 0;
- Lines[0].Line[0].Note[0].Color := 1;
- AudioPlayback.Open(CurrentSong.Path + CurrentSong.Mp3);
+ 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);
@@ -1304,8 +1617,8 @@ end;
function TScreenEditSub.Draw: boolean;
var
Pet: integer;
- AktBeat: integer;
begin
+
glClearColor(1,1,1,1);
// midi music
@@ -1395,15 +1708,17 @@ begin
Text[TextNText].Text := Text[TextNText].Text + '|';
// draw static menu
- inherited Draw;
-
+ DrawStatics;
+ DrawInfoBar(20, 460, 760, 20);
+ //inherited Draw;
+ DrawFG;
// draw notes
- SingDrawNoteLines(20, 300, 780, 15);
+ SingDrawNoteLines(20, 305, 780, 15);
//Error Drawing when no Song is loaded
if not Error then
begin
- SingDrawBeatDelimeters(40, 300, 760, 0);
- EditDrawLine(40, 405, 760, 0, 15);
+ SingDrawBeatDelimeters(40, 305, 760, 0);
+ EditDrawLine(40, 410, 760, 0, 15);
end;
// draw text
@@ -1412,7 +1727,7 @@ begin
Result := true;
end;
-procedure TScreenEditSub.onHide;
+procedure TScreenEditSub.OnHide;
begin
{$IFDEF UseMIDIPort}
MidiOut.Close;
@@ -1463,4 +1778,4 @@ begin
end;
end;
-end.
+end. \ No newline at end of file
diff --git a/cmake/src/screens/UScreenLevel.pas b/cmake/src/screens/UScreenLevel.pas
index b41a8535..1ead9773 100644
--- a/cmake/src/screens/UScreenLevel.pas
+++ b/cmake/src/screens/UScreenLevel.pas
@@ -46,8 +46,8 @@ type
TScreenLevel = class(TMenu)
public
constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
- procedure onShow; override;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+ procedure OnShow; override;
procedure SetAnimationProgress(Progress: real); override;
end;
@@ -58,29 +58,34 @@ uses
UMain,
UIni,
USong,
- UTexture;
+ UTexture,
+ UUnicodeUtils;
-function TScreenLevel.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+function TScreenLevel.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
begin
Result := true;
if (PressedDown) then
begin // Key Down
// check normal keys
- case WideCharUpperCase(CharCode)[1] of
- 'Q':
+ 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(@ScreenName);
+
+ if Ini.OnSongClick = sSelectPlayer then
+ FadeTo(@ScreenMain)
+ else
+ FadeTo(@ScreenName);
end;
SDLK_RETURN:
@@ -105,8 +110,6 @@ begin
end;
constructor TScreenLevel.Create;
-//var
-// I: integer; // Auto Removed, Unused Variable
begin
inherited Create;
@@ -119,7 +122,7 @@ begin
Interaction := 0;
end;
-procedure TScreenLevel.onShow;
+procedure TScreenLevel.OnShow;
begin
inherited;
diff --git a/cmake/src/screens/UScreenLoading.pas b/cmake/src/screens/UScreenLoading.pas
index ea639ba3..e368f181 100644
--- a/cmake/src/screens/UScreenLoading.pas
+++ b/cmake/src/screens/UScreenLoading.pas
@@ -43,10 +43,11 @@ uses
type
TScreenLoading = class(TMenu)
public
- Fadeout: boolean;
+ Fadeout: boolean;
+
constructor Create; override;
- procedure onShow; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
+ procedure OnShow; override;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
end;
implementation
@@ -55,7 +56,7 @@ uses
UGraphic,
UTime;
-function TScreenLoading.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+function TScreenLoading.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
begin
Result := true;
end;
@@ -69,7 +70,7 @@ begin
Fadeout := false;
end;
-procedure TScreenLoading.onShow;
+procedure TScreenLoading.OnShow;
begin
inherited;
end;
diff --git a/cmake/src/screens/UScreenMain.pas b/cmake/src/screens/UScreenMain.pas
index a4e6009f..8bb9365b 100644
--- a/cmake/src/screens/UScreenMain.pas
+++ b/cmake/src/screens/UScreenMain.pas
@@ -49,9 +49,9 @@ type
TextDescriptionLong: integer;
constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: widechar;
+ function ParseInput(PressedKey: Cardinal; CharCode: UCS4Char;
PressedDown: boolean): boolean; override;
- procedure onShow; override;
+ procedure OnShow; override;
procedure SetInteraction(Num: integer); override;
procedure SetAnimationProgress(Progress: real); override;
end;
@@ -67,11 +67,11 @@ uses
Textgl,
ULanguage,
UParty,
- UDLLManager,
UScreenCredits,
- USkins;
+ USkins,
+ UUnicodeUtils;
-function TScreenMain.ParseInput(PressedKey: cardinal; CharCode: widechar;
+function TScreenMain.ParseInput(PressedKey: Cardinal; CharCode: UCS4Char;
PressedDown: boolean): boolean;
var
SDL_ModState: word;
@@ -84,37 +84,32 @@ begin
if (PressedDown) then
begin // Key Down
// check normal keys
- case WideCharUpperCase(CharCode)[1] of
- 'Q':
- begin
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'): begin
Result := false;
Exit;
end;
- 'C':
- begin
+ Ord('C'): begin
if (SDL_ModState = KMOD_LALT) then
begin
FadeTo(@ScreenCredits, SoundLib.Start);
Exit;
end;
end;
- 'M':
- begin
- if (Ini.Players >= 1) and (Length(DLLMan.Plugins) >= 1) then
+ Ord('M'): begin
+ if (Ini.Players >= 1) and (Party.ModesAvailable) then
begin
FadeTo(@ScreenPartyOptions, SoundLib.Start);
Exit;
end;
end;
- 'S':
- begin
+ Ord('S'): begin
FadeTo(@ScreenStatMain, SoundLib.Start);
Exit;
end;
- 'E':
- begin
+ Ord('E'): begin
FadeTo(@ScreenEdit, SoundLib.Start);
Exit;
end;
@@ -140,8 +135,13 @@ begin
if (Ini.Players = 4) then
PlayersPlay := 6;
- ScreenName.Goto_SingScreen := false;
- FadeTo(@ScreenName, SoundLib.Start);
+ 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'));
@@ -152,12 +152,7 @@ begin
begin
if (Songs.SongList.Count >= 1) then
begin
- if (Length(DLLMan.Plugins) >= 1) then
- begin
- FadeTo(@ScreenPartyOptions, SoundLib.Start);
- end
- else //show error message, No Plugins Loaded
- ScreenPopupError.ShowPopup(Language.Translate('ERROR_NO_PLUGINS'));
+ FadeTo(@ScreenPartyOptions, SoundLib.Start);
end
else //show error message, No Songs Loaded
ScreenPopupError.ShowPopup(Language.Translate('ERROR_NO_SONGS'));
@@ -172,7 +167,11 @@ begin
//Editor
if Interaction = 3 then
begin
+ {$IFDEF UseMIDIPort}
FadeTo(@ScreenEdit, SoundLib.Start);
+ {$ELSE}
+ ScreenPopupError.ShowPopup(Language.Translate('ERROR_NO_EDITOR'));
+ {$ENDIF}
end;
//Options
@@ -232,17 +231,14 @@ begin
Interaction := 0;
end;
-procedure TScreenMain.onShow;
+procedure TScreenMain.OnShow;
begin
inherited;
-
- { display cursor (on moved) }
- Display.SetCursor;
-
-{**
- * Start background music
- *}
- SoundLib.StartBgMusic;
+ {**
+ * Clean up TPartyGame here
+ * at the moment there is no better place for this
+ *}
+ Party.Clear;
end;
procedure TScreenMain.SetInteraction(Num: integer);
@@ -254,8 +250,8 @@ end;
procedure TScreenMain.SetAnimationProgress(Progress: real);
begin
- Static[0].Texture.ScaleW := Progress;
- Static[0].Texture.ScaleH := Progress;
+ Statics[0].Texture.ScaleW := Progress;
+ Statics[0].Texture.ScaleH := Progress;
end;
end.
diff --git a/cmake/src/screens/UScreenName.pas b/cmake/src/screens/UScreenName.pas
index d13db170..42af50d7 100644
--- a/cmake/src/screens/UScreenName.pas
+++ b/cmake/src/screens/UScreenName.pas
@@ -47,8 +47,8 @@ type
public
Goto_SingScreen: boolean; //If true then next Screen in SingScreen
constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
- procedure onShow; override;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+ procedure OnShow; override;
procedure SetAnimationProgress(Progress: real); override;
end;
@@ -59,9 +59,11 @@ uses
UGraphic,
UIni,
UNote,
- UTexture;
+ UTexture,
+ UUnicodeUtils;
-function TScreenName.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+
+function TScreenName.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
var
I: integer;
SDL_ModState: word;
@@ -74,10 +76,10 @@ begin
+ KMOD_LCTRL + KMOD_RCTRL + KMOD_LALT + KMOD_RALT);
// check normal keys
- if (IsAlphaNumericChar(CharCode) or
- {(CharCode in [' ','-','_','!',',','<','/','*','?','''','"']))} IsPunctuationChar(CharCode)) then
+ if (IsPrintableChar(CharCode)) then
begin
- Button[Interaction].Text[0].Text := Button[Interaction].Text[0].Text + CharCode;
+ Button[Interaction].Text[0].Text := Button[Interaction].Text[0].Text +
+ UCS4ToUTF8String(CharCode);
Exit;
end;
@@ -195,7 +197,7 @@ begin
SDLK_BACKSPACE:
begin
- Button[Interaction].Text[0].DeleteLastL;
+ Button[Interaction].Text[0].DeleteLastLetter();
end;
SDLK_ESCAPE :
@@ -248,7 +250,7 @@ begin
Interaction := 0;
end;
-procedure TScreenName.onShow;
+procedure TScreenName.OnShow;
var
I: integer;
begin
diff --git a/cmake/src/screens/UScreenOpen.pas b/cmake/src/screens/UScreenOpen.pas
index a854e81b..70b883c4 100644
--- a/cmake/src/screens/UScreenOpen.pas
+++ b/cmake/src/screens/UScreenOpen.pas
@@ -34,10 +34,13 @@ interface
{$I switches.inc}
uses
+ Math,
+ SysUtils,
+ gl,
+ SDL,
+ UPath,
UMenu,
UMusic,
- SDL,
- SysUtils,
UFiles,
UTime,
USongs,
@@ -46,26 +49,31 @@ uses
UTexture,
UMenuText,
ULyrics,
- Math,
- gl,
UThemes;
type
TScreenOpen = class(TMenu)
private
- TextF: array[0..1] of integer;
- TextN: integer;
- public
- Tex_Background: TTexture;
- FadeOut: boolean;
- Path: string;
- BackScreen: pointer;
+ //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: WideChar; PressedDown: boolean): boolean; override;
-// function Draw: boolean; override;
-// procedure Finish;
+ 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
@@ -75,45 +83,41 @@ uses
UDraw,
UMain,
UScreenEditConvert,
- USkins;
+ USkins,
+ UUnicodeUtils;
-function TScreenOpen.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+function TScreenOpen.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
begin
Result := true;
if (PressedDown) then // Key Down
begin
// check normal keys
- case CharCode of
- '0'..'9', 'a'..'z', 'A'..'Z', ' ', '-', '.', ':', '\':
- begin
- if Interaction = 0 then
- begin
- Text[TextN].Text := Text[TextN].Text + CharCode;
- end;
- end;
+ 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_Q:
- begin
- Result := false;
- end;
- 8: // del
+ SDLK_BACKSPACE: // del
begin
if Interaction = 0 then
begin
- Text[TextN].DeleteLastL;
+ Text[fTextN].DeleteLastLetter;
end;
end;
SDLK_ESCAPE:
begin
//Empty Filename and go to last Screen
- ConversionFileName := '';
+ fFileName := PATH_NONE;
AudioPlayback.PlaySound(SoundLib.Back);
- FadeTo(BackScreen);
+ FadeTo(fBackScreen);
end;
SDLK_RETURN:
@@ -121,16 +125,16 @@ begin
if (Interaction = 2) then
begin
//Update Filename and go to last Screen
- ConversionFileName := Text[TextN].Text;
+ fFileName := Path(Text[fTextN].Text);
AudioPlayback.PlaySound(SoundLib.Back);
- FadeTo(BackScreen);
+ FadeTo(fBackScreen);
end
else if (Interaction = 1) then
begin
//Empty Filename and go to last Screen
- ConversionFileName := '';
+ fFileName := PATH_NONE;
AudioPlayback.PlaySound(SoundLib.Back);
- FadeTo(BackScreen);
+ FadeTo(fBackScreen);
end;
end;
@@ -165,21 +169,25 @@ constructor TScreenOpen.Create;
begin
inherited Create;
+ fFilename := PATH_NONE;
+
// line
-{ AddStatic(20, 10, 80, 30, 0, 0, 0, 'MainBar', 'JPG', TEXTURE_TYPE_COLORIZED);
+ {
+ 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');}
+ TextSentence := AddText(120, 14, 1, 24, 0, 0, 0, '0 / 0');
+ }
// file list
-// AddBox(400, 100, 350, 450);
+ //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');
+ //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);
- TextN := AddText(50, 548, 0, 24, 0, 0, 0, ConversionFileName);
- AddInteraction(iText, TextN);
+ fTextN := AddText(50, 548, 0, 24, 0, 0, 0, fFileName.ToUTF8);
+ AddInteraction(iText, fTextN);
// buttons
{AddButton(540, 540, 100, 40, Skin.SkinPath + Skin.ButtonF);
@@ -196,11 +204,12 @@ begin
end;
-procedure TScreenOpen.onShow;
+procedure TScreenOpen.OnShow;
begin
inherited;
Interaction := 0;
+ Text[fTextN].Text := fFilename.ToUTF8();
end;
(*
diff --git a/cmake/src/screens/UScreenOptions.pas b/cmake/src/screens/UScreenOptions.pas
index a6486075..bdb37701 100644
--- a/cmake/src/screens/UScreenOptions.pas
+++ b/cmake/src/screens/UScreenOptions.pas
@@ -34,9 +34,9 @@ interface
{$I switches.inc}
uses
- UMenu,
SDL,
SysUtils,
+ UMenu,
UDisplay,
UMusic,
UFiles,
@@ -48,8 +48,8 @@ type
public
TextDescription: integer;
constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
- procedure onShow; override;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+ procedure OnShow; override;
procedure InteractNext; override;
procedure InteractPrev; override;
procedure InteractNextRow; override;
@@ -60,16 +60,17 @@ type
implementation
uses
- UGraphic;
+ UGraphic,
+ UUnicodeUtils;
-function TScreenOptions.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+function TScreenOptions.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
begin
Result := true;
if (PressedDown) then
begin // Key Down
// check normal keys
- case WideCharUpperCase(CharCode)[1] of
- 'Q':
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'):
begin
Result := false;
Exit;
@@ -145,8 +146,6 @@ begin
end;
constructor TScreenOptions.Create;
-//var
-// I: integer; // Auto Removed, Unused Variable
begin
inherited Create;
@@ -189,7 +188,7 @@ begin
Interaction := 0;
end;
-procedure TScreenOptions.onShow;
+procedure TScreenOptions.OnShow;
begin
inherited;
end;
diff --git a/cmake/src/screens/UScreenOptionsAdvanced.pas b/cmake/src/screens/UScreenOptionsAdvanced.pas
index 0fb8153c..dd727dd8 100644
--- a/cmake/src/screens/UScreenOptionsAdvanced.pas
+++ b/cmake/src/screens/UScreenOptionsAdvanced.pas
@@ -34,8 +34,8 @@ interface
{$I switches.inc}
uses
- UMenu,
SDL,
+ UMenu,
UDisplay,
UMusic,
UFiles,
@@ -46,24 +46,25 @@ type
TScreenOptionsAdvanced = class(TMenu)
public
constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
- procedure onShow; 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: WideChar; PressedDown: boolean): boolean;
+function TScreenOptionsAdvanced.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
begin
Result := true;
if (PressedDown) then
begin // Key Down
// check normal keys
- case WideCharUpperCase(CharCode)[1] of
- 'Q':
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'):
begin
Result := false;
Exit;
@@ -75,8 +76,7 @@ begin
SDLK_ESCAPE,
SDLK_BACKSPACE :
begin
- // Escape -> save nothing - just leave this screen
-
+ Ini.Save;
AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenOptions);
end;
@@ -120,8 +120,6 @@ begin
end;
constructor TScreenOptionsAdvanced.Create;
-//var
-// I: integer; // Auto Removed, Unused Variable
begin
inherited Create;
@@ -155,12 +153,12 @@ begin
AddButton(Theme.OptionsAdvanced.ButtonExit);
if (Length(Button[0].Text)=0) then
- AddButtonText(14, 20, Theme.Options.Description[7]);
+ AddButtonText(20, 5, Theme.Options.Description[7]);
Interaction := 0;
end;
-procedure TScreenOptionsAdvanced.onShow;
+procedure TScreenOptionsAdvanced.OnShow;
begin
inherited;
diff --git a/cmake/src/screens/UScreenOptionsGame.pas b/cmake/src/screens/UScreenOptionsGame.pas
index 1d741d25..39de61e4 100644
--- a/cmake/src/screens/UScreenOptionsGame.pas
+++ b/cmake/src/screens/UScreenOptionsGame.pas
@@ -35,40 +35,39 @@ interface
uses
SDL,
+ UMenu,
UDisplay,
+ UMusic,
UFiles,
UIni,
- UMenu,
- UMusic,
- USongs,
- UThemes;
+ UThemes,
+ USongs;
type
TScreenOptionsGame = class(TMenu)
public
old_Tabs, old_Sorting: integer;
constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
- procedure onShow; override;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+ procedure OnShow; override;
procedure RefreshSongs;
end;
implementation
uses
- SysUtils,
- UGraphic;
+ UGraphic,
+ UUnicodeUtils,
+ SysUtils;
-function TScreenOptionsGame.ParseInput(PressedKey: cardinal;
- CharCode: WideChar;
- PressedDown: boolean): boolean;
+function TScreenOptionsGame.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
begin
Result := true;
if PressedDown then
begin // Key Down
// check normal keys
- case WideCharUpperCase(CharCode)[1] of
- 'Q':
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'):
begin
Result := false;
Exit;
@@ -137,7 +136,7 @@ begin
Theme.OptionsGame.SelectLanguage.showArrows := true;
Theme.OptionsGame.SelectLanguage.oneItemOnly := true;
- AddSelectSlide(Theme.OptionsGame.SelectLanguage, Ini.Language, ILanguage);
+ AddSelectSlide(Theme.OptionsGame.SelectLanguage, Ini.Language, ILanguageTranslated);
Theme.OptionsGame.SelectTabs.showArrows := true;
Theme.OptionsGame.SelectTabs.oneItemOnly := true;
@@ -155,7 +154,7 @@ begin
AddButton(Theme.OptionsGame.ButtonExit);
if (Length(Button[0].Text) = 0) then
- AddButtonText(14, 20, Theme.Options.Description[7]);
+ AddButtonText(20, 5, Theme.Options.Description[7]);
end;
@@ -166,7 +165,7 @@ begin
ScreenSong.Refresh;
end;
-procedure TScreenOptionsGame.onShow;
+procedure TScreenOptionsGame.OnShow;
begin
inherited;
diff --git a/cmake/src/screens/UScreenOptionsGraphics.pas b/cmake/src/screens/UScreenOptionsGraphics.pas
index ba1465b2..e2aacccd 100644
--- a/cmake/src/screens/UScreenOptionsGraphics.pas
+++ b/cmake/src/screens/UScreenOptionsGraphics.pas
@@ -46,26 +46,25 @@ type
TScreenOptionsGraphics = class(TMenu)
public
constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
- procedure onShow; override;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+ procedure OnShow; override;
end;
implementation
uses
UGraphic,
- UMain,
- SysUtils,
- TypInfo;
+ UUnicodeUtils,
+ SysUtils;
-function TScreenOptionsGraphics.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+function TScreenOptionsGraphics.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
begin
Result := true;
if (PressedDown) then
begin // Key Down
// check normal keys
- case WideCharUpperCase(CharCode)[1] of
- 'Q':
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'):
begin
Result := false;
Exit;
@@ -77,17 +76,12 @@ begin
SDLK_ESCAPE,
SDLK_BACKSPACE :
begin
- // Escape -> save nothing - just leave this screen
-
+ Ini.Save;
AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenOptions);
end;
SDLK_RETURN:
begin
-{ if SelInteraction <= 1 then
- begin
- Restart := true;
- end;}
if SelInteraction = 6 then
begin
Ini.Save;
@@ -126,8 +120,6 @@ begin
end;
constructor TScreenOptionsGraphics.Create;
-//var
-// I: integer; // Auto Removed, Unused Variable
begin
inherited Create;
LoadFromTheme(Theme.OptionsGraphics);
@@ -158,11 +150,11 @@ begin
AddButton(Theme.OptionsGraphics.ButtonExit);
if (Length(Button[0].Text)=0) then
- AddButtonText(14, 20, Theme.Options.Description[7]);
+ AddButtonText(20, 5, Theme.Options.Description[7]);
end;
-procedure TScreenOptionsGraphics.onShow;
+procedure TScreenOptionsGraphics.OnShow;
begin
inherited;
diff --git a/cmake/src/screens/UScreenOptionsLyrics.pas b/cmake/src/screens/UScreenOptionsLyrics.pas
index 035b0089..468082de 100644
--- a/cmake/src/screens/UScreenOptionsLyrics.pas
+++ b/cmake/src/screens/UScreenOptionsLyrics.pas
@@ -46,24 +46,25 @@ type
TScreenOptionsLyrics = class(TMenu)
public
constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
- procedure onShow; 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: WideChar; PressedDown: boolean): boolean;
+function TScreenOptionsLyrics.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
begin
Result := true;
if (PressedDown) then
begin // Key Down
// check normal keys
- case WideCharUpperCase(CharCode)[1] of
- 'Q':
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'):
begin
Result := false;
Exit;
@@ -75,8 +76,7 @@ begin
SDLK_ESCAPE,
SDLK_BACKSPACE :
begin
- // Escape -> save nothing - just leave this screen
-
+ Ini.Save;
AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenOptions);
end;
@@ -133,11 +133,11 @@ begin
AddButton(Theme.OptionsLyrics.ButtonExit);
if (Length(Button[0].Text)=0) then
- AddButtonText(14, 20, Theme.Options.Description[7]);
+ AddButtonText(20, 5, Theme.Options.Description[7]);
end;
-procedure TScreenOptionsLyrics.onShow;
+procedure TScreenOptionsLyrics.OnShow;
begin
inherited;
diff --git a/cmake/src/screens/UScreenOptionsRecord.pas b/cmake/src/screens/UScreenOptionsRecord.pas
index cf799204..0f9cd49a 100644
--- a/cmake/src/screens/UScreenOptionsRecord.pas
+++ b/cmake/src/screens/UScreenOptionsRecord.pas
@@ -61,8 +61,8 @@ type
PreviewDeviceIndex: integer;
// string arrays for select-slide options
- InputSourceNames: array of string;
- InputDeviceNames: array of string;
+ InputSourceNames: array of UTF8String;
+ InputDeviceNames: array of UTF8String;
// dynamic generated themes for channel select-sliders
SelectSlideChannelTheme: array of TThemeSelectSlide;
@@ -95,9 +95,9 @@ type
public
constructor Create; override;
function Draw: boolean; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
- procedure onShow; override;
- procedure onHide; override;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+ procedure OnShow; override;
+ procedure OnHide; override;
end;
const
@@ -126,33 +126,34 @@ uses
UFiles,
UDisplay,
UIni,
+ UUnicodeUtils,
ULog;
-function TScreenOptionsRecord.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+function TScreenOptionsRecord.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
begin
Result := true;
if (PressedDown) then
begin // Key Down
// check normal keys
- case WideCharUpperCase(CharCode)[1] of
- 'Q':
+ 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;
- 'T':
+ Ord('T'):
begin
if ((SDL_GetModState() and KMOD_SHIFT) <> 0) then
Ini.ThresholdIndex := (Ini.ThresholdIndex + Length(IThresholdVals) - 1) mod Length(IThresholdVals)
@@ -167,17 +168,23 @@ begin
SDLK_BACKSPACE:
begin
// TODO: Show Save/Abort screen
- Ini.Save;
- AudioPlayback.PlaySound(SoundLib.Back);
- FadeTo(@ScreenOptions);
+ if (AudioInputProcessor.ValidateSettings()) then
+ begin
+ Ini.Save;
+ AudioPlayback.PlaySound(SoundLib.Back);
+ FadeTo(@ScreenOptions);
+ end;
end;
SDLK_RETURN:
begin
if (SelInteraction = ExitButtonIID) then
begin
- Ini.Save;
- AudioPlayback.PlaySound(SoundLib.Back);
- FadeTo(@ScreenOptions);
+ if (AudioInputProcessor.ValidateSettings()) then
+ begin
+ Ini.Save;
+ AudioPlayback.PlaySound(SoundLib.Back);
+ FadeTo(@ScreenOptions);
+ end;
end;
end;
SDLK_DOWN:
@@ -299,7 +306,7 @@ begin
// add slider
SelectSlideChannelID[ChannelIndex] := AddSelectSlide(ChannelTheme^,
- InputDeviceCfg.ChannelToPlayerMap[ChannelIndex], IChannelPlayer);
+ InputDeviceCfg.ChannelToPlayerMap[ChannelIndex], IChannelPlayerTranslated);
end
else
begin
@@ -307,7 +314,7 @@ begin
// add slider but hide it and assign a dummy variable to it
SelectSlideChannelID[ChannelIndex] := AddSelectSlide(ChannelTheme^,
- ChannelToPlayerMapDummy, IChannelPlayer);
+ ChannelToPlayerMapDummy, IChannelPlayerTranslated);
SelectsS[SelectSlideChannelID[ChannelIndex]].Visible := false;
end;
end;
@@ -322,7 +329,7 @@ begin
// <mog> I uncommented the stuff above, because it's not skinable :X
AddButton(Theme.OptionsRecord.ButtonExit);
if (Length(Button[0].Text) = 0) then
- AddButtonText(14, 20, Theme.Options.Description[7]);
+ AddButtonText(20, 5, Theme.Options.Description[7]);
// store InteractionID
if (Length(AudioInputProcessor.DeviceList) > 0) then
ExitButtonIID := MaxChannelCount + 2
@@ -373,7 +380,7 @@ begin
// show slider
UpdateSelectSlideOptions(SelectSlideChannelTheme[ChannelIndex],
- SelectSlideChannelID[ChannelIndex], IChannelPlayer,
+ SelectSlideChannelID[ChannelIndex], IChannelPlayerTranslated,
InputDeviceCfg.ChannelToPlayerMap[ChannelIndex]);
SelectsS[SelectSlideChannelID[ChannelIndex]].Visible := true;
end
@@ -383,7 +390,7 @@ begin
// hide slider and assign a dummy variable to it
UpdateSelectSlideOptions(SelectSlideChannelTheme[ChannelIndex],
- SelectSlideChannelID[ChannelIndex], IChannelPlayer,
+ SelectSlideChannelID[ChannelIndex], IChannelPlayerTranslated,
ChannelToPlayerMapDummy);
SelectsS[SelectSlideChannelID[ChannelIndex]].Visible := false;
end;
@@ -418,7 +425,7 @@ begin
NextVolumePollTime := 0;
end;
-procedure TScreenOptionsRecord.onShow;
+procedure TScreenOptionsRecord.OnShow;
var
ChannelIndex: integer;
begin
@@ -433,10 +440,10 @@ begin
SetLength(ChannelPeak, MaxChannelCount);
- StartPreview();
+ UpdateInputDevice();
end;
-procedure TScreenOptionsRecord.onHide;
+procedure TScreenOptionsRecord.OnHide;
var
ChannelIndex: integer;
begin
diff --git a/cmake/src/screens/UScreenOptionsSound.pas b/cmake/src/screens/UScreenOptionsSound.pas
index aa87ceb4..c0efa4d8 100644
--- a/cmake/src/screens/UScreenOptionsSound.pas
+++ b/cmake/src/screens/UScreenOptionsSound.pas
@@ -34,8 +34,8 @@ interface
{$I switches.inc}
uses
- UMenu,
SDL,
+ UMenu,
UDisplay,
UMusic,
UFiles,
@@ -46,26 +46,27 @@ type
TScreenOptionsSound = class(TMenu)
public
constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: widechar;
+ function ParseInput(PressedKey: Cardinal; CharCode: UCS4Char;
PressedDown: boolean): boolean; override;
- procedure onShow; override;
+ procedure OnShow; override;
end;
implementation
uses
UGraphic,
+ UUnicodeUtils,
SysUtils;
function TScreenOptionsSound.ParseInput(PressedKey: cardinal;
- CharCode: widechar; PressedDown: boolean): boolean;
+ CharCode: UCS4Char; PressedDown: boolean): boolean;
begin
Result := true;
if (PressedDown) then
begin // Key Down
// check normal keys
- case WideCharUpperCase(CharCode)[1] of
- 'Q':
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'):
begin
Result := false;
Exit;
@@ -77,7 +78,7 @@ begin
SDLK_ESCAPE,
SDLK_BACKSPACE:
begin
- // Escape -> save nothing - just leave this screen
+ Ini.Save;
AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenOptions);
end;
@@ -172,12 +173,12 @@ begin
AddButton(Theme.OptionsSound.ButtonExit);
if (Length(Button[0].Text) = 0) then
- AddButtonText(14, 20, Theme.Options.Description[7]);
+ AddButtonText(20, 5, Theme.Options.Description[7]);
Interaction := 0;
end;
-procedure TScreenOptionsSound.onShow;
+procedure TScreenOptionsSound.OnShow;
begin
inherited;
Interaction := 0;
diff --git a/cmake/src/screens/UScreenOptionsThemes.pas b/cmake/src/screens/UScreenOptionsThemes.pas
index 1e7407f1..94475cc7 100644
--- a/cmake/src/screens/UScreenOptionsThemes.pas
+++ b/cmake/src/screens/UScreenOptionsThemes.pas
@@ -49,8 +49,8 @@ type
public
SkinSelect: integer;
constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
- procedure onShow; override;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+ procedure OnShow; override;
procedure InteractInc; override;
procedure InteractDec; override;
end;
@@ -61,17 +61,18 @@ uses
SysUtils,
UGraphic,
UMain,
- UPath,
+ UPathUtils,
+ UUnicodeUtils,
USkins;
-function TScreenOptionsThemes.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+function TScreenOptionsThemes.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
begin
Result := true;
if (PressedDown) then
begin // Key Down
// check normal keys
- case WideCharUpperCase(CharCode)[1] of
- 'Q':
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'):
begin
Result := false;
Exit;
@@ -83,7 +84,12 @@ begin
SDLK_ESCAPE,
SDLK_BACKSPACE :
begin
- // Escape -> save nothing - just leave this screen
+ Ini.Save;
+
+ // Reload all screens, after Theme changed
+ // Todo : JB - Check if theme was actually changed
+ UGraphic.UnLoadScreens();
+ UGraphic.LoadScreens();
AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenOptions);
@@ -135,7 +141,16 @@ begin
if (SelInteraction = 0) then
begin
Skin.OnThemeChange;
- UpdateSelectSlideOptions (Theme.OptionsThemes.SelectSkin, SkinSelect, ISkin, Ini.SkinNo);
+ 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();
@@ -150,6 +165,15 @@ begin
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();
@@ -175,10 +199,10 @@ begin
AddButton(Theme.OptionsThemes.ButtonExit);
if (Length(Button[0].Text)=0) then
- AddButtonText(14, 20, Theme.Options.Description[7]);
+ AddButtonText(20, 5, Theme.Options.Description[7]);
end;
-procedure TScreenOptionsThemes.onShow;
+procedure TScreenOptionsThemes.OnShow;
begin
inherited;
@@ -187,7 +211,7 @@ end;
procedure TScreenOptionsThemes.ReloadTheme;
begin
- Theme.LoadTheme(ThemePath + ITheme[Ini.Theme] + '.ini', Ini.Color);
+ Theme.LoadTheme(Ini.Theme, Ini.Color);
ScreenOptionsThemes := TScreenOptionsThemes.create();
ScreenOptionsThemes.onshow;
diff --git a/cmake/src/screens/UScreenPartyNewRound.pas b/cmake/src/screens/UScreenPartyNewRound.pas
index 03a72fa9..8024108c 100644
--- a/cmake/src/screens/UScreenPartyNewRound.pas
+++ b/cmake/src/screens/UScreenPartyNewRound.pas
@@ -34,33 +34,21 @@ interface
{$I switches.inc}
uses
- UMenu,
SDL,
+ SysUtils,
+ UMenu,
UDisplay,
UMusic,
UFiles,
- SysUtils,
UThemes;
type
TScreenPartyNewRound = class(TMenu)
public
//Texts:
- TextRound1: cardinal;
- TextRound2: cardinal;
- TextRound3: cardinal;
- TextRound4: cardinal;
- TextRound5: cardinal;
- TextRound6: cardinal;
- TextRound7: cardinal;
-
- TextWinner1: cardinal;
- TextWinner2: cardinal;
- TextWinner3: cardinal;
- TextWinner4: cardinal;
- TextWinner5: cardinal;
- TextWinner6: cardinal;
- TextWinner7: cardinal;
+ TextRound: array [0..6] of cardinal;
+
+ TextWinner: array [0..6] of cardinal;
TextNextRound: cardinal;
TextNextRoundNo: cardinal;
@@ -69,13 +57,7 @@ type
TextNextPlayer3: cardinal;
//Statics
- StaticRound1: cardinal;
- StaticRound2: cardinal;
- StaticRound3: cardinal;
- StaticRound4: cardinal;
- StaticRound5: cardinal;
- StaticRound6: cardinal;
- StaticRound7: cardinal;
+ StaticRound: array [0..6] of cardinal;
//Scores
TextScoreTeam1: cardinal;
@@ -99,8 +81,8 @@ type
constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
- procedure onShow; override;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+ procedure OnShow; override;
procedure SetAnimationProgress(Progress: real); override;
end;
@@ -112,19 +94,19 @@ uses
UIni,
UTexture,
UParty,
- UDLLManager,
ULanguage,
USong,
- ULog;
+ ULog,
+ UUnicodeUtils;
-function TScreenPartyNewRound.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+function TScreenPartyNewRound.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
begin
Result := true;
if (PressedDown) then
begin // Key Down
// check normal keys
- case WideCharUpperCase(CharCode)[1] of
- 'Q':
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'):
begin
Result := false;
Exit;
@@ -143,16 +125,7 @@ begin
SDLK_RETURN:
begin
AudioPlayback.PlaySound(SoundLib.Start);
- if DLLMan.Selected.LoadSong then
- begin
- //Select PartyMode ScreenSong
- ScreenSong.Mode := smPartyMode;
- FadeTo(@ScreenSong);
- end
- else
- begin
- FadeTo(@ScreenSingModi);
- end;
+ Party.CallBeforeSongSelect;
end;
end;
end;
@@ -162,21 +135,21 @@ constructor TScreenPartyNewRound.Create;
begin
inherited Create;
- TextRound1 := AddText (Theme.PartyNewRound.TextRound1);
- TextRound2 := AddText (Theme.PartyNewRound.TextRound2);
- TextRound3 := AddText (Theme.PartyNewRound.TextRound3);
- TextRound4 := AddText (Theme.PartyNewRound.TextRound4);
- TextRound5 := AddText (Theme.PartyNewRound.TextRound5);
- TextRound6 := AddText (Theme.PartyNewRound.TextRound6);
- TextRound7 := AddText (Theme.PartyNewRound.TextRound7);
-
- TextWinner1 := AddText (Theme.PartyNewRound.TextWinner1);
- TextWinner2 := AddText (Theme.PartyNewRound.TextWinner2);
- TextWinner3 := AddText (Theme.PartyNewRound.TextWinner3);
- TextWinner4 := AddText (Theme.PartyNewRound.TextWinner4);
- TextWinner5 := AddText (Theme.PartyNewRound.TextWinner5);
- TextWinner6 := AddText (Theme.PartyNewRound.TextWinner6);
- TextWinner7 := AddText (Theme.PartyNewRound.TextWinner7);
+ 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);
@@ -184,13 +157,13 @@ begin
TextNextPlayer2 := AddText (Theme.PartyNewRound.TextNextPlayer2);
TextNextPlayer3 := AddText (Theme.PartyNewRound.TextNextPlayer3);
- StaticRound1 := AddStatic (Theme.PartyNewRound.StaticRound1);
- StaticRound2 := AddStatic (Theme.PartyNewRound.StaticRound2);
- StaticRound3 := AddStatic (Theme.PartyNewRound.StaticRound3);
- StaticRound4 := AddStatic (Theme.PartyNewRound.StaticRound4);
- StaticRound5 := AddStatic (Theme.PartyNewRound.StaticRound5);
- StaticRound6 := AddStatic (Theme.PartyNewRound.StaticRound6);
- StaticRound7 := AddStatic (Theme.PartyNewRound.StaticRound7);
+ 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);
@@ -215,21 +188,21 @@ begin
LoadFromTheme(Theme.PartyNewRound);
end;
-procedure TScreenPartyNewRound.onShow;
+procedure TScreenPartyNewRound.OnShow;
var
I: integer;
- function GetTeamPlayers(const Num: byte): string;
+ function GetTeamPlayers(const Num: integer): UTF8String;
var
- Players: array of string;
- J: byte;
+ Players: array of UTF8String;
+ J: integer;
begin
- if (Num-1 >= PartySession.Teams.NumTeams) then
+ if (Num > High(Party.Teams)) or (Num < 0) then
exit;
//Create Players array
- SetLength(Players, PartySession.Teams.TeamInfo[Num-1].NumPlayers);
- for J := 0 to PartySession.Teams.TeamInfo[Num-1].NumPlayers-1 do
- Players[J] := string(PartySession.Teams.TeamInfo[Num-1].PlayerInfo[J].Name);
+ 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);
@@ -237,215 +210,114 @@ var
begin
inherited;
- PartySession.StartRound;
-
//Set Visibility of Round Infos
- I := Length(PartySession.Rounds);
- if (I >= 1) then
- begin
- Static[StaticRound1].Visible := true;
- Text[TextRound1].Visible := true;
- Text[TextWinner1].Visible := true;
-
- //Texts:
- Text[TextRound1].Text := Language.Translate(DllMan.Plugins[PartySession.Rounds[0].Plugin].Name);
- Text[TextWinner1].Text := PartySession.GetWinnerString(0);
- end
- else
- begin
- Static[StaticRound1].Visible := false;
- Text[TextRound1].Visible := false;
- Text[TextWinner1].Visible := false;
- end;
-
- if (I >= 2) then
- begin
- Static[StaticRound2].Visible := true;
- Text[TextRound2].Visible := true;
- Text[TextWinner2].Visible := true;
-
- //Texts:
- Text[TextRound2].Text := Language.Translate(DllMan.Plugins[PartySession.Rounds[1].Plugin].Name);
- Text[TextWinner2].Text := PartySession.GetWinnerString(1);
- end
- else
- begin
- Static[StaticRound2].Visible := false;
- Text[TextRound2].Visible := false;
- Text[TextWinner2].Visible := false;
- end;
-
- if (I >= 3) then
- begin
- Static[StaticRound3].Visible := true;
- Text[TextRound3].Visible := true;
- Text[TextWinner3].Visible := true;
-
- //Texts:
- Text[TextRound3].Text := Language.Translate(DllMan.Plugins[PartySession.Rounds[2].Plugin].Name);
- Text[TextWinner3].Text := PartySession.GetWinnerString(2);
- end
- else
- begin
- Static[StaticRound3].Visible := false;
- Text[TextRound3].Visible := false;
- Text[TextWinner3].Visible := false;
- end;
-
- if (I >= 4) then
+ for I := 0 to 6 do
begin
- Static[StaticRound4].Visible := true;
- Text[TextRound4].Visible := true;
- Text[TextWinner4].Visible := true;
-
- //Texts:
- Text[TextRound4].Text := Language.Translate(DllMan.Plugins[PartySession.Rounds[3].Plugin].Name);
- Text[TextWinner4].Text := PartySession.GetWinnerString(3);
- end
- else
- begin
- Static[StaticRound4].Visible := false;
- Text[TextRound4].Visible := false;
- Text[TextWinner4].Visible := false;
- end;
-
- if (I >= 5) then
- begin
- Static[StaticRound5].Visible := true;
- Text[TextRound5].Visible := true;
- Text[TextWinner5].Visible := true;
-
- //Texts:
- Text[TextRound5].Text := Language.Translate(DllMan.Plugins[PartySession.Rounds[4].Plugin].Name);
- Text[TextWinner5].Text := PartySession.GetWinnerString(4);
- end
- else
- begin
- Static[StaticRound5].Visible := false;
- Text[TextRound5].Visible := false;
- Text[TextWinner5].Visible := false;
- end;
-
- if (I >= 6) then
- begin
- Static[StaticRound6].Visible := true;
- Text[TextRound6].Visible := true;
- Text[TextWinner6].Visible := true;
-
- //Texts:
- Text[TextRound6].Text := Language.Translate(DllMan.Plugins[PartySession.Rounds[5].Plugin].Name);
- Text[TextWinner6].Text := PartySession.GetWinnerString(5);
- end
- else
- begin
- Static[StaticRound6].Visible := false;
- Text[TextRound6].Visible := false;
- Text[TextWinner6].Visible := false;
+ 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;
- if (I >= 7) then
- begin
- Static[StaticRound7].Visible := true;
- Text[TextRound7].Visible := true;
- Text[TextWinner7].Visible := true;
-
- //Texts:
- Text[TextRound7].Text := Language.Translate(DllMan.Plugins[PartySession.Rounds[6].Plugin].Name);
- Text[TextWinner7].Text := PartySession.GetWinnerString(6);
- end
- else
- begin
- Static[StaticRound7].Visible := false;
- Text[TextRound7].Visible := false;
- Text[TextWinner7].Visible := false;
- end;
//Display Scores
- if (PartySession.Teams.NumTeams >= 1) then
+ if (Length(Party.Teams) >= 1) then
begin
- Text[TextScoreTeam1].Text := InttoStr(PartySession.Teams.TeamInfo[0].Score);
- Text[TextNameTeam1].Text := string(PartySession.Teams.TeamInfo[0].Name);
- Text[TextTeam1Players].Text := GetTeamPlayers(1);
+ 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;
- Static[StaticTeam1].Visible := true;
- Static[StaticNextPlayer1].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;
- Static[StaticTeam1].Visible := false;
- Static[StaticNextPlayer1].Visible := false;
+ Statics[StaticTeam1].Visible := false;
+ Statics[StaticNextPlayer1].Visible := false;
end;
- if (PartySession.Teams.NumTeams >= 2) then
+ if (Length(Party.Teams) >= 2) then
begin
- Text[TextScoreTeam2].Text := InttoStr(PartySession.Teams.TeamInfo[1].Score);
- Text[TextNameTeam2].Text := string(PartySession.Teams.TeamInfo[1].Name);
- Text[TextTeam2Players].Text := GetTeamPlayers(2);
+ 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;
- Static[StaticTeam2].Visible := true;
- Static[StaticNextPlayer2].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;
- Static[StaticTeam2].Visible := false;
- Static[StaticNextPlayer2].Visible := false;
+ Statics[StaticTeam2].Visible := false;
+ Statics[StaticNextPlayer2].Visible := false;
end;
- if (PartySession.Teams.NumTeams >= 3) then
+ if (Length(Party.Teams) >= 3) then
begin
- Text[TextScoreTeam3].Text := InttoStr(PartySession.Teams.TeamInfo[2].Score);
- Text[TextNameTeam3].Text := string(PartySession.Teams.TeamInfo[2].Name);
- Text[TextTeam3Players].Text := GetTeamPlayers(3);
+ 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;
- Static[StaticTeam3].Visible := true;
- Static[StaticNextPlayer3].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;
- Static[StaticTeam3].Visible := false;
- Static[StaticNextPlayer3].Visible := false;
- end;
+ Statics[StaticTeam3].Visible := false;
+ Statics[StaticNextPlayer3].Visible := false;
+ end;
//nextRound Texts
- Text[TextNextRound].Text := Language.Translate(DllMan.Selected.PluginDesc);
- Text[TextNextRoundNo].Text := InttoStr(PartySession.CurRound + 1);
- if (PartySession.Teams.NumTeams >= 1) then
+ 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 := PartySession.Teams.Teaminfo[0].Playerinfo[PartySession.Teams.Teaminfo[0].CurPlayer].Name;
+ Text[TextNextPlayer1].Text := Party.Teams[0].Players[Party.Teams[0].NextPlayer].Name;
Text[TextNextPlayer1].Visible := true;
end
else
Text[TextNextPlayer1].Visible := false;
-
- if (PartySession.Teams.NumTeams >= 2) then
+
+ if (Length(Party.Teams) >= 2) then
begin
- Text[TextNextPlayer2].Text := PartySession.Teams.Teaminfo[1].Playerinfo[PartySession.Teams.Teaminfo[1].CurPlayer].Name;
+ Text[TextNextPlayer2].Text := Party.Teams[1].Players[Party.Teams[1].NextPlayer].Name;
Text[TextNextPlayer2].Visible := true;
end
else
Text[TextNextPlayer2].Visible := false;
- if (PartySession.Teams.NumTeams >= 3) then
+ if (Length(Party.Teams) >= 3) then
begin
- Text[TextNextPlayer3].Text := PartySession.Teams.Teaminfo[2].Playerinfo[PartySession.Teams.Teaminfo[2].CurPlayer].Name;
+ Text[TextNextPlayer3].Text := Party.Teams[2].Players[Party.Teams[2].NextPlayer].Name;
Text[TextNextPlayer3].Visible := true;
end
else
diff --git a/cmake/src/screens/UScreenPartyOptions.pas b/cmake/src/screens/UScreenPartyOptions.pas
index 5f7f1d9e..f63b37fb 100644
--- a/cmake/src/screens/UScreenPartyOptions.pas
+++ b/cmake/src/screens/UScreenPartyOptions.pas
@@ -44,38 +44,26 @@ uses
type
TScreenPartyOptions = class(TMenu)
- public
+ private
SelectLevel: cardinal;
SelectPlayList: cardinal;
SelectPlayList2: cardinal;
SelectRounds: cardinal;
- SelectTeams: cardinal;
- SelectPlayers1: cardinal;
- SelectPlayers2: cardinal;
- SelectPlayers3: cardinal;
+
+ IPlaylist: array[0..2] of UTF8String;
+ IPlaylist2: array of UTF8String;
PlayList: integer;
PlayList2: integer;
- Rounds: integer;
- NumTeams: integer;
- NumPlayer1, NumPlayer2, NumPlayer3: integer;
-
+
+ procedure SetPlaylist2;
+ public
constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
- procedure onShow; override;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+ procedure OnShow; override;
procedure SetAnimationProgress(Progress: real); override;
- procedure SetPlaylist2;
end;
-var
- IPlaylist: array[0..2] of string;
- IPlaylist2: array of string;
-
- const
- ITeams: array[0..1] of string = ('2', '3');
- IPlayers: array[0..3] of string = ('1', '2', '3', '4');
- IRounds: array[0..5] of string = ('2', '3', '4', '5', '6', '7');
-
implementation
uses
@@ -86,21 +74,20 @@ uses
ULanguage,
UParty,
USong,
- UDLLManager,
UPlaylist,
- USongs;
+ USongs,
+ UUnicodeUtils;
-function TScreenPartyOptions.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+function TScreenPartyOptions.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
var
I, J: integer;
- OnlyMultiPlayer: boolean;
begin
Result := true;
if (PressedDown) then
begin // Key Down
// check normal keys
- case WideCharUpperCase(CharCode)[1] of
- 'Q':
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'):
begin
Result := false;
Exit;
@@ -121,27 +108,11 @@ begin
//Don'T start when Playlist is Selected and there are no Playlists
if (Playlist = 2) and (Length(PlaylistMan.Playlists) = 0) then
Exit;
- // Don't start when SinglePlayer Teams but only Multiplayer Plugins available
- OnlyMultiPlayer := true;
- for I := 0 to High(DLLMan.Plugins) do
- begin
- OnlyMultiPlayer := (OnlyMultiPlayer and DLLMan.Plugins[I].TeamModeOnly);
- end;
- if (OnlyMultiPlayer) and ((NumPlayer1 = 0) or (NumPlayer2 = 0) or ((NumPlayer3 = 0) and (NumTeams = 1))) then
- begin
- ScreenPopupError.ShowPopup(Language.Translate('ERROR_NO_PLUGINS'));
- Exit;
- end;
+
//Save Difficulty
Ini.Difficulty := SelectsS[SelectLevel].SelectedOption;
Ini.SaveLevel;
- //Save Num Teams:
- PartySession.Teams.NumTeams := NumTeams + 2;
- PartySession.Teams.Teaminfo[0].NumPlayers := NumPlayer1+1;
- PartySession.Teams.Teaminfo[1].NumPlayers := NumPlayer2+1;
- PartySession.Teams.Teaminfo[2].NumPlayers := NumPlayer3+1;
-
//Save Playlist
PlaylistMan.Mode := TSingMode( Playlist );
PlaylistMan.CurPlayList := High(cardinal);
@@ -168,9 +139,6 @@ begin
else
PlaylistMan.CurPlayList := Playlist2;
- //Start Party
- PartySession.StartNewParty(Rounds + 2);
-
AudioPlayback.PlaySound(SoundLib.Start);
//Go to Player Screen
FadeTo(@ScreenPartyPlayer);
@@ -190,10 +158,6 @@ begin
if (Interaction = 1) then
begin
SetPlaylist2;
- end //Change Team3 Players visibility
- else if (Interaction = 4) then
- begin
- SelectsS[7].Visible := (NumTeams = 1);
end;
end;
SDLK_LEFT:
@@ -205,10 +169,6 @@ begin
if (Interaction = 1) then
begin
SetPlaylist2;
- end //Change Team3 Players visibility
- else if (Interaction = 4) then
- begin
- SelectsS[7].Visible := (NumTeams = 1);
end;
end;
end;
@@ -228,30 +188,25 @@ begin
IPlaylist2[0] := '---';
//Clear all Selects
- NumTeams := 0;
- NumPlayer1 := 0;
- NumPlayer2 := 0;
- NumPlayer3 := 0;
- Rounds := 5;
PlayList := 0;
PlayList2 := 0;
//Load Screen From Theme
LoadFromTheme(Theme.PartyOptions);
- SelectLevel := AddSelectSlide (Theme.PartyOptions.SelectLevel, Ini.Difficulty, Theme.ILevel);
- SelectPlayList := AddSelectSlide (Theme.PartyOptions.SelectPlayList, PlayList, IPlaylist);
- SelectPlayList2 := AddSelectSlide (Theme.PartyOptions.SelectPlayList2, PlayList2, IPlaylist2);
- SelectRounds := AddSelectSlide (Theme.PartyOptions.SelectRounds, Rounds, IRounds);
- SelectTeams := AddSelectSlide (Theme.PartyOptions.SelectTeams, NumTeams, ITeams);
- SelectPlayers1 := AddSelectSlide (Theme.PartyOptions.SelectPlayers1, NumPlayer1, IPlayers);
- SelectPlayers2 := AddSelectSlide (Theme.PartyOptions.SelectPlayers2, NumPlayer2, IPlayers);
- SelectPlayers3 := AddSelectSlide (Theme.PartyOptions.SelectPlayers3, NumPlayer3, IPlayers);
+ Theme.PartyOptions.SelectLevel.oneItemOnly := true;
+ Theme.PartyOptions.SelectLevel.showArrows := true;
+ SelectLevel := AddSelectSlide(Theme.PartyOptions.SelectLevel, Ini.Difficulty, Theme.ILevel);
- Interaction := 0;
+ 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);
- //Hide Team3 Players
- SelectsS[7].Visible := false;
+ Interaction := 0;
end;
procedure TScreenPartyOptions.SetPlaylist2;
@@ -301,11 +256,23 @@ begin
UpdateSelectSlideOptions(Theme.PartyOptions.SelectPlayList2, 2, IPlaylist2, Playlist2);
end;
-procedure TScreenPartyOptions.onShow;
+procedure TScreenPartyOptions.OnShow;
begin
inherited;
- Randomize;
+ 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);
diff --git a/cmake/src/screens/UScreenPartyPlayer.pas b/cmake/src/screens/UScreenPartyPlayer.pas
index c2070fce..a7f4d627 100644
--- a/cmake/src/screens/UScreenPartyPlayer.pas
+++ b/cmake/src/screens/UScreenPartyPlayer.pas
@@ -44,6 +44,14 @@ uses
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;
@@ -64,11 +72,15 @@ type
Player12Name: cardinal;
constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
- procedure onShow; 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
@@ -76,24 +88,96 @@ uses
UMain,
UIni,
UTexture,
- UParty;
+ 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);
-function TScreenPartyPlayer.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+ 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;
- I, J: integer;
-
procedure IntNext;
begin
repeat
InteractNext;
- until Button[Interaction].Visible;
+ until ((Interactions[Interaction].Typ = iSelectS) and
+ SelectsS[Interactions[Interaction].Num].Visible) or
+ (Button[Interactions[Interaction].Num].Visible);
end;
procedure IntPrev;
begin
repeat
InteractPrev;
- until Button[Interaction].Visible;
+ until ((Interactions[Interaction].Typ = iSelectS) and
+ SelectsS[Interactions[Interaction].Num].Visible) or
+ (Button[Interactions[Interaction].Num].Visible);
end;
begin
Result := true;
@@ -104,166 +188,178 @@ begin
else
SDL_ModState := 0;
- begin // Key Down
- // check normal keys
+ // Key Down
+ // check normal keys
+ if (Interactions[Interaction].Typ = iButton) then
+ begin
case CharCode of
- '0'..'9', 'a'..'z', 'A'..'Z', ' ', '-', '_', '!', ',', '<', '/', '*', '?', '''', '"':
+ 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[Interaction].Text[0].Text := Button[Interaction].Text[0].Text + CharCode;
+ 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[Interaction].Text[0].Text;
+ Ini.NameTemplate[0] := Button[Interactions[Interaction].Num].Text[0].Text;
end
else
begin
- Button[Interaction].Text[0].Text := Ini.NameTemplate[0];
+ Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[0];
end;
SDLK_F2:
if (SDL_ModState = KMOD_LALT) then
begin
- Ini.NameTemplate[1] := Button[Interaction].Text[0].Text;
+ Ini.NameTemplate[1] := Button[Interactions[Interaction].Num].Text[0].Text;
end
else
begin
- Button[Interaction].Text[0].Text := Ini.NameTemplate[1];
+ Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[1];
end;
SDLK_F3:
if (SDL_ModState = KMOD_LALT) then
begin
- Ini.NameTemplate[2] := Button[Interaction].Text[0].Text;
+ Ini.NameTemplate[2] := Button[Interactions[Interaction].Num].Text[0].Text;
end
else
begin
- Button[Interaction].Text[0].Text := Ini.NameTemplate[2];
+ Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[2];
end;
SDLK_F4:
if (SDL_ModState = KMOD_LALT) then
begin
- Ini.NameTemplate[3] := Button[Interaction].Text[0].Text;
+ Ini.NameTemplate[3] := Button[Interactions[Interaction].Num].Text[0].Text;
end
else
begin
- Button[Interaction].Text[0].Text := Ini.NameTemplate[3];
+ Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[3];
end;
SDLK_F5:
if (SDL_ModState = KMOD_LALT) then
begin
- Ini.NameTemplate[4] := Button[Interaction].Text[0].Text;
+ Ini.NameTemplate[4] := Button[Interactions[Interaction].Num].Text[0].Text;
end
else
begin
- Button[Interaction].Text[0].Text := Ini.NameTemplate[4];
+ Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[4];
end;
SDLK_F6:
if (SDL_ModState = KMOD_LALT) then
begin
- Ini.NameTemplate[5] := Button[Interaction].Text[0].Text;
+ Ini.NameTemplate[5] := Button[Interactions[Interaction].Num].Text[0].Text;
end
else
begin
- Button[Interaction].Text[0].Text := Ini.NameTemplate[5];
+ Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[5];
end;
SDLK_F7:
if (SDL_ModState = KMOD_LALT) then
begin
- Ini.NameTemplate[6] := Button[Interaction].Text[0].Text;
+ Ini.NameTemplate[6] := Button[Interactions[Interaction].Num].Text[0].Text;
end
else
begin
- Button[Interaction].Text[0].Text := Ini.NameTemplate[6];
+ Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[6];
end;
SDLK_F8:
if (SDL_ModState = KMOD_LALT) then
begin
- Ini.NameTemplate[7] := Button[Interaction].Text[0].Text;
+ Ini.NameTemplate[7] := Button[Interactions[Interaction].Num].Text[0].Text;
end
else
begin
- Button[Interaction].Text[0].Text := Ini.NameTemplate[7];
+ Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[7];
end;
SDLK_F9:
if (SDL_ModState = KMOD_LALT) then
begin
- Ini.NameTemplate[8] := Button[Interaction].Text[0].Text;
+ Ini.NameTemplate[8] := Button[Interactions[Interaction].Num].Text[0].Text;
end
else
begin
- Button[Interaction].Text[0].Text := Ini.NameTemplate[8];
+ Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[8];
end;
SDLK_F10:
if (SDL_ModState = KMOD_LALT) then
begin
- Ini.NameTemplate[9] := Button[Interaction].Text[0].Text;
+ Ini.NameTemplate[9] := Button[Interactions[Interaction].Num].Text[0].Text;
end
else
begin
- Button[Interaction].Text[0].Text := Ini.NameTemplate[9];
+ Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[9];
end;
SDLK_F11:
if (SDL_ModState = KMOD_LALT) then
begin
- Ini.NameTemplate[10] := Button[Interaction].Text[0].Text;
+ Ini.NameTemplate[10] := Button[Interactions[Interaction].Num].Text[0].Text;
end
else
begin
- Button[Interaction].Text[0].Text := Ini.NameTemplate[10];
+ Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[10];
end;
SDLK_F12:
if (SDL_ModState = KMOD_LALT) then
begin
- Ini.NameTemplate[11] := Button[Interaction].Text[0].Text;
+ Ini.NameTemplate[11] := Button[Interactions[Interaction].Num].Text[0].Text;
end
else
begin
- Button[Interaction].Text[0].Text := Ini.NameTemplate[11];
+ Button[Interactions[Interaction].Num].Text[0].Text := Ini.NameTemplate[11];
end;
SDLK_BACKSPACE:
begin
- Button[Interaction].Text[0].DeleteLastL;
+ Button[Interactions[Interaction].Num].Text[0].DeleteLastLetter;
end;
+ end;
+ end;
- SDLK_ESCAPE:
+ 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
- Ini.SaveNames;
- AudioPlayback.PlaySound(SoundLib.Back);
- FadeTo(@ScreenPartyOptions);
- end;
+ AudioPlayback.PlaySound(SoundLib.Option);
+ InteractInc;
- SDLK_RETURN:
+ UpdateInterface;
+ end;
+ end;
+ SDLK_LEFT:
+ begin
+ if (Interaction in [0,2,8,14]) then
begin
+ AudioPlayback.PlaySound(SoundLib.Option);
+ InteractDec;
- //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;
-
- AudioPlayback.PlaySound(SoundLib.Start);
- FadeTo(@ScreenPartyNewRound);
+ UpdateInterface;
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: IntNext;
- SDLK_UP: IntPrev;
- SDLK_RIGHT: IntNext;
- SDLK_LEFT: IntPrev;
- end;
+ end;
end;
end;
@@ -273,28 +369,50 @@ begin
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;
+procedure TScreenPartyPlayer.OnShow;
var
I: integer;
begin
@@ -314,66 +432,18 @@ begin
Button[5].Text[0].Text := Ini.NameTeam[1];
Button[10].Text[0].Text := Ini.NameTeam[2];
// Templates for Names Mod end
-
- if (PartySession.Teams.NumTeams>=1) then
- begin
- Button[0].Visible := true;
- Button[1].Visible := (PartySession.Teams.Teaminfo[0].NumPlayers >=1);
- Button[2].Visible := (PartySession.Teams.Teaminfo[0].NumPlayers >=2);
- Button[3].Visible := (PartySession.Teams.Teaminfo[0].NumPlayers >=3);
- Button[4].Visible := (PartySession.Teams.Teaminfo[0].NumPlayers >=4);
- end
- else
- begin
- Button[0].Visible := false;
- Button[1].Visible := false;
- Button[2].Visible := false;
- Button[3].Visible := false;
- Button[4].Visible := false;
- end;
- if (PartySession.Teams.NumTeams>=2) then
- begin
- Button[5].Visible := true;
- Button[6].Visible := (PartySession.Teams.Teaminfo[1].NumPlayers >=1);
- Button[7].Visible := (PartySession.Teams.Teaminfo[1].NumPlayers >=2);
- Button[8].Visible := (PartySession.Teams.Teaminfo[1].NumPlayers >=3);
- Button[9].Visible := (PartySession.Teams.Teaminfo[1].NumPlayers >=4);
- end
- else
- begin
- Button[5].Visible := false;
- Button[6].Visible := false;
- Button[7].Visible := false;
- Button[8].Visible := false;
- Button[9].Visible := false;
- end;
-
- if (PartySession.Teams.NumTeams>=3) then
- begin
- Button[10].Visible := true;
- Button[11].Visible := (PartySession.Teams.Teaminfo[2].NumPlayers >=1);
- Button[12].Visible := (PartySession.Teams.Teaminfo[2].NumPlayers >=2);
- Button[13].Visible := (PartySession.Teams.Teaminfo[2].NumPlayers >=3);
- Button[14].Visible := (PartySession.Teams.Teaminfo[2].NumPlayers >=4);
- end
- else
- begin
- Button[10].Visible := false;
- Button[11].Visible := false;
- Button[12].Visible := false;
- Button[13].Visible := false;
- Button[14].Visible := false;
- 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;
+ {for I := 0 to high(Button) do
+ Button[I].Texture.ScaleW := Progress; }
end;
end.
diff --git a/cmake/src/screens/UScreenPartyRounds.pas b/cmake/src/screens/UScreenPartyRounds.pas
new file mode 100644
index 00000000..070c9eb8
--- /dev/null
+++ b/cmake/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/cmake/src/screens/UScreenPartyScore.pas b/cmake/src/screens/UScreenPartyScore.pas
index 23cf666d..32ca5db2 100644
--- a/cmake/src/screens/UScreenPartyScore.pas
+++ b/cmake/src/screens/UScreenPartyScore.pas
@@ -34,11 +34,11 @@ interface
{$I switches.inc}
uses
- UMenu,
SDL,
+ SysUtils,
+ UMenu,
UDisplay,
UMusic,
- SysUtils,
UThemes;
type
@@ -69,8 +69,8 @@ type
MaxScore: word;
constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
- procedure onShow; override;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+ procedure OnShow; override;
procedure SetAnimationProgress(Progress: real); override;
end;
@@ -80,19 +80,19 @@ uses
UGraphic,
UMain,
UParty,
- UScreenSingModi,
ULanguage,
UTexture,
- USkins;
+ USkins,
+ UUnicodeUtils;
-function TScreenPartyScore.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+function TScreenPartyScore.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
begin
Result := true;
if (PressedDown) then
begin // Key Down
// check normal keys
- case WideCharUpperCase(CharCode)[1] of
- 'Q':
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'):
begin
Result := false;
Exit;
@@ -102,33 +102,28 @@ begin
// check special keys
case PressedKey of
SDLK_ESCAPE,
- SDLK_BACKSPACE :
+ SDLK_BACKSPACE,
+ SDLK_RETURN :
begin
AudioPlayback.PlaySound(SoundLib.Start);
- if (PartySession.CurRound < High(PartySession.Rounds)) then
- FadeTo(@ScreenPartyNewRound)
+
+ Party.NextRound; //< go to next round
+
+ if (not Party.GameFinished) then
+ begin
+ FadeTo(@ScreenPartyNewRound);
+ end
else
begin
- PartySession.EndRound;
FadeTo(@ScreenPartyWin);
end;
end;
-
- SDLK_RETURN:
- begin
- AudioPlayback.PlaySound(SoundLib.Start);
- if (PartySession.CurRound < High(PartySession.Rounds)) then
- FadeTo(@ScreenPartyNewRound)
- else
- FadeTo(@ScreenPartyWin);
- end;
end;
end;
end;
constructor TScreenPartyScore.Create;
var
-// I: integer; // Auto Removed, Unused Variable
Tex: TTexture;
R, G, B: real;
Color: integer;
@@ -165,7 +160,9 @@ begin
DecoColor[0].B := B;
//Load Texture
- Tex := Texture.LoadTexture(pchar(Skin.GetTextureFileName(Theme.PartyScore.DecoTextures.FirstTexture)), Theme.PartyScore.DecoTextures.FirstTyp, Color);
+ Tex := Texture.LoadTexture(
+ Skin.GetTextureFileName(Theme.PartyScore.DecoTextures.FirstTexture),
+ Theme.PartyScore.DecoTextures.FirstTyp, Color);
DecoTex[0] := Tex.TexNum;
//Get Second Color
@@ -176,7 +173,9 @@ begin
DecoColor[1].B := B;
//Load Second Texture
- Tex := Texture.LoadTexture(pchar(Skin.GetTextureFileName(Theme.PartyScore.DecoTextures.SecondTexture)), Theme.PartyScore.DecoTextures.SecondTyp, Color);
+ Tex := Texture.LoadTexture(
+ Skin.GetTextureFileName(Theme.PartyScore.DecoTextures.SecondTexture),
+ Theme.PartyScore.DecoTextures.SecondTyp, Color);
DecoTex[1] := Tex.TexNum;
//Get Third Color
@@ -187,150 +186,146 @@ begin
DecoColor[2].B := B;
//Load Third Texture
- Tex := Texture.LoadTexture(pchar(Skin.GetTextureFileName(Theme.PartyScore.DecoTextures.ThirdTexture)), Theme.PartyScore.DecoTextures.ThirdTyp, Color);
+ 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;
+procedure TScreenPartyScore.OnShow;
var
- I, J: integer;
- Placings: array [0..5] of byte;
+ Ranking: AParty_TeamRanking;
begin
inherited;
- //Get Maxscore
-
- MaxScore := 0;
- for I := 0 to ScreenSingModi.PlayerInfo.NumPlayers - 1 do
- begin
- if (ScreenSingModi.PlayerInfo.Playerinfo[I].Score > MaxScore) then
- MaxScore := ScreenSingModi.PlayerInfo.Playerinfo[I].Score;
- end;
+ // indicate that round is finished
+ Party.RoundPlayed;
- //Get Placings
- for I := 0 to ScreenSingModi.PlayerInfo.NumPlayers - 1 do
- begin
- Placings[I] := 0;
- for J := 0 to ScreenSingModi.PlayerInfo.NumPlayers - 1 do
- if (ScreenSingModi.PlayerInfo.Playerinfo[J].Score > ScreenSingModi.PlayerInfo.Playerinfo[I].Score) then
- Inc(Placings[I]);
- end;
+ // get rankings for current round
+ Ranking := Party.Rounds[Party.CurrentRound].Ranking;
- //Set Static Length
- Static[StaticTeam1].Texture.ScaleW := ScreenSingModi.PlayerInfo.Playerinfo[0].Percentage / 100;
- Static[StaticTeam2].Texture.ScaleW := ScreenSingModi.PlayerInfo.Playerinfo[1].Percentage / 100;
- Static[StaticTeam3].Texture.ScaleW := ScreenSingModi.PlayerInfo.Playerinfo[2].Percentage / 100;
- //fix: prevents static from drawn out of bounds.
- if Static[StaticTeam1].Texture.ScaleW > 99 then Static[StaticTeam1].Texture.ScaleW := 99;
- if Static[StaticTeam2].Texture.ScaleW > 99 then Static[StaticTeam2].Texture.ScaleW := 99;
- if Static[StaticTeam3].Texture.ScaleW > 99 then Static[StaticTeam3].Texture.ScaleW := 99;
+ {//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;
- //End Last Round
- PartySession.EndRound;
+ //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'), [PartySession.GetWinnerString(PartySession.CurRound)]);
+ Text[TextWinner].Text := Format(Language.Translate('PARTY_SCORE_WINS'), [Party.GetWinnerString(Party.CurrentRound)]);
- if (ScreenSingModi.PlayerInfo.NumPlayers >= 1) then
+ if (Length(Party.Teams) >= 1) then
begin
- Text[TextScoreTeam1].Text := InttoStr(ScreenSingModi.PlayerInfo.Playerinfo[0].Score);
- Text[TextNameTeam1].Text := string(ScreenSingModi.TeamInfo.Teaminfo[0].Name);
+ 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
- Static[StaticTeam1Deco].Texture.TexNum := DecoTex[Placings[0]];
- Static[StaticTeam1Deco].Texture.ColR := DecoColor[Placings[0]].R;
- Static[StaticTeam1Deco].Texture.ColG := DecoColor[Placings[0]].G;
- Static[StaticTeam1Deco].Texture.ColB := DecoColor[Placings[0]].B;
+ 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;
- Static[StaticTeam1].Visible := true;
- Static[StaticTeam1BG].Visible := true;
- Static[StaticTeam1Deco].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;
- Static[StaticTeam1].Visible := false;
- Static[StaticTeam1BG].Visible := false;
- Static[StaticTeam1Deco].Visible := false;
+ Statics[StaticTeam1].Visible := false;
+ Statics[StaticTeam1BG].Visible := false;
+ Statics[StaticTeam1Deco].Visible := false;
end;
- if (ScreenSingModi.PlayerInfo.NumPlayers >= 2) then
+ if (Length(Party.Teams) >= 2) then
begin
- Text[TextScoreTeam2].Text := InttoStr(ScreenSingModi.PlayerInfo.Playerinfo[1].Score);
- Text[TextNameTeam2].Text := string(ScreenSingModi.TeamInfo.Teaminfo[1].Name);
+ 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
- Static[StaticTeam2Deco].Texture.TexNum := DecoTex[Placings[1]];
- Static[StaticTeam2Deco].Texture.ColR := DecoColor[Placings[1]].R;
- Static[StaticTeam2Deco].Texture.ColG := DecoColor[Placings[1]].G;
- Static[StaticTeam2Deco].Texture.ColB := DecoColor[Placings[1]].B;
+ 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;
- Static[StaticTeam2].Visible := true;
- Static[StaticTeam2BG].Visible := true;
- Static[StaticTeam2Deco].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;
- Static[StaticTeam2].Visible := false;
- Static[StaticTeam2BG].Visible := false;
- Static[StaticTeam2Deco].Visible := false;
+ Statics[StaticTeam2].Visible := false;
+ Statics[StaticTeam2BG].Visible := false;
+ Statics[StaticTeam2Deco].Visible := false;
end;
- if (ScreenSingModi.PlayerInfo.NumPlayers >= 3) then
+ if (Length(Party.Teams) >= 3) then
begin
- Text[TextScoreTeam3].Text := InttoStr(ScreenSingModi.PlayerInfo.Playerinfo[2].Score);
- Text[TextNameTeam3].Text := string(ScreenSingModi.TeamInfo.Teaminfo[2].Name);
+ 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
- Static[StaticTeam3Deco].Texture.TexNum := DecoTex[Placings[2]];
- Static[StaticTeam3Deco].Texture.ColR := DecoColor[Placings[2]].R;
- Static[StaticTeam3Deco].Texture.ColG := DecoColor[Placings[2]].G;
- Static[StaticTeam3Deco].Texture.ColB := DecoColor[Placings[2]].B;
+ 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;
- Static[StaticTeam3].Visible := true;
- Static[StaticTeam3BG].Visible := true;
- Static[StaticTeam3Deco].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;
- Static[StaticTeam3].Visible := false;
- Static[StaticTeam3BG].Visible := false;
- Static[StaticTeam3Deco].Visible := false;
+ Statics[StaticTeam3].Visible := false;
+ Statics[StaticTeam3BG].Visible := false;
+ Statics[StaticTeam3Deco].Visible := false;
end;
end;
procedure TScreenPartyScore.SetAnimationProgress(Progress: real);
begin
- if (ScreenSingModi.PlayerInfo.NumPlayers >= 1) then
- Static[StaticTeam1].Texture.ScaleW := Progress * ScreenSingModi.PlayerInfo.Playerinfo[0].Percentage / 100;
+ {if (ScreenSingModi.PlayerInfo.NumPlayers >= 1) then
+ Statics[StaticTeam1].Texture.ScaleW := Progress * ScreenSingModi.PlayerInfo.Playerinfo[0].Percentage / 100;
if (ScreenSingModi.PlayerInfo.NumPlayers >= 2) then
- Static[StaticTeam2].Texture.ScaleW := Progress * ScreenSingModi.PlayerInfo.Playerinfo[1].Percentage / 100;
+ Statics[StaticTeam2].Texture.ScaleW := Progress * ScreenSingModi.PlayerInfo.Playerinfo[1].Percentage / 100;
if (ScreenSingModi.PlayerInfo.NumPlayers >= 3) then
- Static[StaticTeam3].Texture.ScaleW := Progress * ScreenSingModi.PlayerInfo.Playerinfo[2].Percentage / 100;
+ Statics[StaticTeam3].Texture.ScaleW := Progress * ScreenSingModi.PlayerInfo.Playerinfo[2].Percentage / 100;}
end;
end.
diff --git a/cmake/src/screens/UScreenPartyWin.pas b/cmake/src/screens/UScreenPartyWin.pas
index 3c105c7d..ed8d017c 100644
--- a/cmake/src/screens/UScreenPartyWin.pas
+++ b/cmake/src/screens/UScreenPartyWin.pas
@@ -34,10 +34,11 @@ interface
{$I switches.inc}
uses
+ SDL,
+ SysUtils,
UMenu,
- SDL, UDisplay,
+ UDisplay,
UMusic,
- SysUtils,
UThemes;
type
@@ -61,28 +62,28 @@ type
TextWinner: cardinal;
constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
- procedure onShow; override;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+ procedure OnShow; override;
procedure SetAnimationProgress(Progress: real); override;
end;
implementation
-uses
+uses
UGraphic,
UMain,
UParty,
- UScreenSingModi,
- ULanguage;
+ ULanguage,
+ UUnicodeUtils;
-function TScreenPartyWin.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+function TScreenPartyWin.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
begin
Result := true;
if (PressedDown) then
begin // Key Down
// check normal keys
- case WideCharUpperCase(CharCode)[1] of
- 'Q':
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'):
begin
Result := false;
Exit;
@@ -92,13 +93,8 @@ begin
// check special keys
case PressedKey of
SDLK_ESCAPE,
- SDLK_BACKSPACE :
- begin
- AudioPlayback.PlaySound(SoundLib.Start);
- FadeTo(@ScreenMain);
- end;
-
- SDLK_RETURN:
+ SDLK_BACKSPACE,
+ SDLK_RETURN :
begin
AudioPlayback.PlaySound(SoundLib.Start);
FadeTo(@ScreenMain);
@@ -108,8 +104,6 @@ begin
end;
constructor TScreenPartyWin.Create;
-//var
-// I: integer; // Auto Removed, Unused Variable
begin
inherited Create;
@@ -135,12 +129,12 @@ begin
LoadFromTheme(Theme.PartyWin);
end;
-procedure TScreenPartyWin.onShow;
+procedure TScreenPartyWin.OnShow;
var
- I: integer;
- Placing: TeamOrderArray;
+ I: integer;
+ Ranking: AParty_TeamRanking;
- Function GetTeamColor(Team: byte): cardinal;
+ Function GetTeamColor(Team: integer): cardinal;
var
NameString: string;
begin
@@ -152,42 +146,43 @@ var
begin
inherited;
- //Get Team Placing
- Placing := PartySession.GetTeamOrder;
+ // get team ranking
+ // Ranking is sorted by score
+ Ranking := Party.GetTeamRanking;
//Set Winnertext
- Text[TextWinner].Text := Format(Language.Translate('PARTY_SCORE_WINS'), [PartySession.Teams.Teaminfo[Placing[0]].Name]);
- if (PartySession.Teams.NumTeams >= 1) then
+ Text[TextWinner].Text := Format(Language.Translate('PARTY_SCORE_WINS'), [Party.GetWinnerString(-1)]);
+ if (Length(Party.Teams) >= 1) then
begin
- Text[TextScoreTeam1].Text := InttoStr(PartySession.Teams.TeamInfo[Placing[0]].Score);
- Text[TextNameTeam1].Text := string(PartySession.Teams.TeamInfo[Placing[0]].Name);
+ 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;
- Static[StaticTeam1].Visible := true;
- Static[StaticTeam1BG].Visible := true;
- Static[StaticTeam1Deco].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(Placing[0]);
+ I := GetTeamColor(Ranking[0].Team);
if (I <> -1) then
begin
- Static[StaticTeam1BG].Texture.ColR := Color[I].RGB.R;
- Static[StaticTeam1BG].Texture.ColG := Color[I].RGB.G;
- Static[StaticTeam1BG].Texture.ColB := Color[I].RGB.B;
+ 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(Placing[0]);
+ I := GetTeamColor(Ranking[0].Team);
if (I <> -1) then
begin
- Static[StaticTeam1].Texture.ColR := Color[I].RGB.R;
- Static[StaticTeam1].Texture.ColG := Color[I].RGB.G;
- Static[StaticTeam1].Texture.ColB := Color[I].RGB.B;
+ 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
@@ -195,42 +190,42 @@ begin
begin
Text[TextScoreTeam1].Visible := false;
Text[TextNameTeam1].Visible := false;
- Static[StaticTeam1].Visible := false;
- Static[StaticTeam1BG].Visible := false;
- Static[StaticTeam1Deco].Visible := false;
+ Statics[StaticTeam1].Visible := false;
+ Statics[StaticTeam1BG].Visible := false;
+ Statics[StaticTeam1Deco].Visible := false;
end;
- if (PartySession.Teams.NumTeams >= 2) then
+ if (Length(Party.Teams) >= 2) then
begin
- Text[TextScoreTeam2].Text := InttoStr(PartySession.Teams.TeamInfo[Placing[1]].Score);
- Text[TextNameTeam2].Text := string(PartySession.Teams.TeamInfo[Placing[1]].Name);
+ 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;
- Static[StaticTeam2].Visible := true;
- Static[StaticTeam2BG].Visible := true;
- Static[StaticTeam2Deco].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(Placing[1]);
+ I := GetTeamColor(Ranking[1].Team);
if (I <> -1) then
begin
- Static[StaticTeam2BG].Texture.ColR := Color[I].RGB.R;
- Static[StaticTeam2BG].Texture.ColG := Color[I].RGB.G;
- Static[StaticTeam2BG].Texture.ColB := Color[I].RGB.B;
+ 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(Placing[1]);
+ I := GetTeamColor(Ranking[1].Team);
if (I <> -1) then
begin
- Static[StaticTeam2].Texture.ColR := Color[I].RGB.R;
- Static[StaticTeam2].Texture.ColG := Color[I].RGB.G;
- Static[StaticTeam2].Texture.ColB := Color[I].RGB.B;
+ 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
@@ -238,42 +233,42 @@ begin
begin
Text[TextScoreTeam2].Visible := false;
Text[TextNameTeam2].Visible := false;
- Static[StaticTeam2].Visible := false;
- Static[StaticTeam2BG].Visible := false;
- Static[StaticTeam2Deco].Visible := false;
+ Statics[StaticTeam2].Visible := false;
+ Statics[StaticTeam2BG].Visible := false;
+ Statics[StaticTeam2Deco].Visible := false;
end;
- if (PartySession.Teams.NumTeams >= 3) then
+ if (Length(Party.Teams) >= 3) then
begin
- Text[TextScoreTeam3].Text := InttoStr(PartySession.Teams.TeamInfo[Placing[2]].Score);
- Text[TextNameTeam3].Text := string(PartySession.Teams.TeamInfo[Placing[2]].Name);
+ 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;
- Static[StaticTeam3].Visible := true;
- Static[StaticTeam3BG].Visible := true;
- Static[StaticTeam3Deco].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(Placing[2]);
+ I := GetTeamColor(Ranking[2].Team);
if (I <> -1) then
begin
- Static[StaticTeam3BG].Texture.ColR := Color[I].RGB.R;
- Static[StaticTeam3BG].Texture.ColG := Color[I].RGB.G;
- Static[StaticTeam3BG].Texture.ColB := Color[I].RGB.B;
+ 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(Placing[2]);
+ I := GetTeamColor(Ranking[2].Team);
if (I <> -1) then
begin
- Static[StaticTeam3].Texture.ColR := Color[I].RGB.R;
- Static[StaticTeam3].Texture.ColG := Color[I].RGB.G;
- Static[StaticTeam3].Texture.ColB := Color[I].RGB.B;
+ 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
@@ -281,20 +276,20 @@ begin
begin
Text[TextScoreTeam3].Visible := false;
Text[TextNameTeam3].Visible := false;
- Static[StaticTeam3].Visible := false;
- Static[StaticTeam3BG].Visible := false;
- Static[StaticTeam3Deco].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
- Static[StaticTeam1].Texture.ScaleW := Progress * ScreenSingModi.PlayerInfo.Playerinfo[0].Score / maxScore;
+ Statics[StaticTeam1].Texture.ScaleW := Progress * ScreenSingModi.PlayerInfo.Playerinfo[0].Score / maxScore;
if (ScreenSingModi.PlayerInfo.NumPlayers >= 2) then
- Static[StaticTeam2].Texture.ScaleW := Progress * ScreenSingModi.PlayerInfo.Playerinfo[1].Score / maxScore;
+ Statics[StaticTeam2].Texture.ScaleW := Progress * ScreenSingModi.PlayerInfo.Playerinfo[1].Score / maxScore;
if (ScreenSingModi.PlayerInfo.NumPlayers >= 3) then
- Static[StaticTeam3].Texture.ScaleW := Progress * ScreenSingModi.PlayerInfo.Playerinfo[2].Score / maxScore;}
+ Statics[StaticTeam3].Texture.ScaleW := Progress * ScreenSingModi.PlayerInfo.Playerinfo[2].Score / maxScore;}
end;
end.
diff --git a/cmake/src/screens/UScreenPopup.pas b/cmake/src/screens/UScreenPopup.pas
index 7e4671d6..fdf4a69c 100644
--- a/cmake/src/screens/UScreenPopup.pas
+++ b/cmake/src/screens/UScreenPopup.pas
@@ -34,42 +34,61 @@ interface
{$I switches.inc}
uses
- UMenu,
SDL,
+ SysUtils,
+ UMenu,
UMusic,
UFiles,
- SysUtils,
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
+ Visible: boolean; // whether the menu should be drawn
constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
- procedure onShow; override;
- procedure ShowPopup(msg: string);
+ 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
- TScreenPopupError = class(TMenu)
-{ private
- CurMenu: byte; //Num of the cur. Shown Menu}
+ 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: WideChar; PressedDown: boolean): boolean; override;
- procedure onShow; override;
- procedure onHide; override;
- procedure ShowPopup(msg: string);
+ 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;
+ //ISelections: array of string;
SelectValue: integer;
implementation
@@ -82,70 +101,57 @@ uses
ULanguage,
UParty,
UPlaylist,
- UDisplay;
+ UDisplay,
+ UUnicodeUtils;
-function TScreenPopupCheck.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+{ TScreenPopupCheck }
+
+function TScreenPopupCheck.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+var
+ Value: boolean;
begin
Result := true;
if (PressedDown) then
begin // Key Down
- // check normal keys
- case WideCharUpperCase(CharCode)[1] of
- 'Q':
- begin
- Result := false;
- Exit;
- end;
- end;
-
// check special keys
case PressedKey of
SDLK_ESCAPE,
SDLK_BACKSPACE :
begin
- Display.CheckOK := false;
- Display.NextScreenWithCheck := NIL;
+ Value := false;
Visible := false;
Result := false;
end;
SDLK_RETURN:
begin
- case Interaction of
- 0: 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;
-
- Display.CheckOK := true;
- end;
- 1: begin
- Display.CheckOK := false;
- Display.NextScreenWithCheck := NIL;
- end;
- end;
+ Value := (Interaction = 0);
Visible := false;
Result := false;
end;
- SDLK_DOWN: InteractNext;
- SDLK_UP: InteractPrev;
-
+ SDLK_DOWN: InteractNext;
+ SDLK_UP: InteractPrev;
+
SDLK_RIGHT: InteractNext;
- SDLK_LEFT: InteractPrev;
+ 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);
@@ -163,18 +169,24 @@ end;
function TScreenPopupCheck.Draw: boolean;
begin
- Draw:=inherited Draw;
+ Result := inherited Draw;
end;
-procedure TScreenPopupCheck.onShow;
+procedure TScreenPopupCheck.OnShow;
begin
inherited;
end;
-procedure TScreenPopupCheck.ShowPopup(msg: string);
+procedure TScreenPopupCheck.ShowPopup(const Msg: UTF8String; Handler: TPopupCheckHandler;
+ HandlerData: Pointer; DefaultValue: boolean);
begin
- Interaction := 0; //Reset Interaction
+ if (DefaultValue) then
+ Interaction := 0
+ else
+ Interaction := 1;
Visible := true; //Set Visible
+ fHandler := Handler;
+ fHandlerData := HandlerData;
Text[0].Text := Language.Translate(msg);
@@ -187,9 +199,9 @@ begin
Background.OnShow
end;
-// error popup
+{ TScreenPopup }
-function TScreenPopupError.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+function TScreenPopup.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
begin
Result := true;
if (PressedDown) then
@@ -223,7 +235,7 @@ begin
end;
end;
-constructor TScreenPopupError.Create;
+constructor TScreenPopup.Create;
begin
inherited Create;
@@ -238,22 +250,22 @@ begin
Interaction := 0;
end;
-function TScreenPopupError.Draw: boolean;
+function TScreenPopup.Draw: boolean;
begin
Draw := inherited Draw;
end;
-procedure TScreenPopupError.onShow;
+procedure TScreenPopup.OnShow;
begin
inherited;
end;
-procedure TScreenPopupError.onHide;
+procedure TScreenPopup.OnHide;
begin
end;
-procedure TScreenPopupError.ShowPopup(msg: string);
+procedure TScreenPopup.ShowPopup(const Msg: UTF8String);
begin
Interaction := 0; //Reset Interaction
Visible := true; //Set Visible
@@ -277,4 +289,20 @@ begin
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/cmake/src/screens/UScreenScore.pas b/cmake/src/screens/UScreenScore.pas
index a01c7691..de7675bf 100644
--- a/cmake/src/screens/UScreenScore.pas
+++ b/cmake/src/screens/UScreenScore.pas
@@ -51,9 +51,10 @@ const
EaseOut_MaxSteps: real = 10; // that's the speed of the bars (10 is fast | 100 is slower)
- BarRaiseSpeed: cardinal = 0; // Time for raising the bar one step higher (in ms)
+ 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
@@ -64,6 +65,8 @@ type
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
@@ -79,11 +82,27 @@ type
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;
- ArrayStartModifier: integer;
- public
+
aPlayerScoreScreenTextures: array[1..6] of TPlayerScoreScreenTexture;
aPlayerScoreScreenDatas: array[1..6] of TPlayerScoreScreenData;
aPlayerScoreScreenRatings: array[1..6] of TPlayerScoreRatingPics;
@@ -110,42 +129,77 @@ type
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;
- constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; 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;
+ procedure MapPlayersToPosition;
+
procedure FillPlayer(Item, P: integer);
+ procedure FillPlayerItems(PlayerNumber: integer);
- procedure EaseBarIn(PlayerNumber: integer; BarType: string);
- procedure EaseScoreIn(PlayerNumber: integer; ScoreType: string);
+ procedure UpdateAnimation;
+ {****
+ * helpers for bar easing
+ *}
+ procedure EaseBarIn(PlayerNumber: integer; BarType: TScoreBarType);
+ procedure EaseScoreIn(PlayerNumber: integer; ScoreType: TScoreBarType);
- procedure FillPlayerItems(PlayerNumber: integer; ScoreType: string);
+ procedure DrawPlayerBars;
- procedure DrawBar(BarType: string; PlayerNumber: integer; BarStartPosY: single; NewHeight: real);
+ procedure DrawBar(BarType: TScoreBarType; PlayerNumber: integer; BarStartPosY: single; NewHeight: real);
- //Rating Picture
+ {****
+ * 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
@@ -156,18 +210,21 @@ uses
UMenuStatic,
UTime,
UIni,
+ USkins,
ULog,
ULanguage,
- UNote;
+ UNote,
+ UUnicodeUtils;
-function TScreenScore.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+
+function TScreenScore.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
begin
Result := true;
if (PressedDown) then
begin
// check normal keys
- case WideCharUpperCase(CharCode)[1] of
- 'Q':
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'):
begin
Result := false;
Exit;
@@ -197,7 +254,189 @@ begin
Result := True;
if (MouseButton = SDL_BUTTON_LEFT) and BtnDown then begin
//left-click anywhere sends return
- ParseInput(SDLK_RETURN, #0, true);
+ 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;
@@ -224,6 +463,8 @@ begin
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]);
@@ -247,6 +488,7 @@ begin
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];
@@ -257,25 +499,18 @@ begin
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.onShow;
-var
- P: integer; // player
- I: integer;
- V: array[1..6] of boolean; // visibility array
-
+procedure TScreenScore.MapPlayersToPosition;
+ var
+ ArrayStartModifier: integer;
+ PlayersPerScreen: integer;
+ I: integer;
begin
-
-{**
- * Turn backgroundmusic on
- *}
- SoundLib.StartBgMusic;
-
- inherited;
-
// 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)
@@ -285,21 +520,122 @@ begin
// 3 Player -> Player[0..5].Score
// -> Statics[4..6]
case PlayersPlay of
- 1: ArrayStartModifier := 0;
- 2, 4: ArrayStartModifier := 1;
- 3, 6: ArrayStartModifier := 3;
+ 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[P + ArrayStartModifier].Y;
+ 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;
@@ -349,9 +685,9 @@ begin
Text[TextGoldenNotesScore[P]].Alpha := 0;
Text[TextTotal[P]].Alpha := 0;
Text[TextTotalScore[P]].Alpha := 0;
- Static[StaticBoxLightest[P]].Texture.Alpha := 0;
- Static[StaticBoxLight[P]].Texture.Alpha := 0;
- Static[StaticBoxDark[P]].Texture.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];
@@ -363,21 +699,27 @@ begin
Text[TextTotalScore[P]].Visible := V[P];
for I := 0 to high(PlayerStatic[P]) do
- Static[PlayerStatic[P, I]].Visible := V[P];
+ Statics[PlayerStatic[P, I]].Visible := V[P];
for I := 0 to high(PlayerTexts[P]) do
Text[PlayerTexts[P, I]].Visible := V[P];
- Static[StaticBoxLightest[P]].Visible := V[P];
- Static[StaticBoxLight[P]].Visible := V[P];
- Static[StaticBoxDark[P]].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
- Static[StaticBackLevel[P]].Visible := false;
- Static[StaticBackLevelRound[P]].Visible := false;
- Static[StaticLevel[P]].Visible := false;
- Static[StaticLevelRound[P]].Visible := false;
+ 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;
@@ -391,17 +733,12 @@ begin
TextGolden_ActualValue[index] := 0;
end;
- BarScore_EaseOut_Step := 1;
- BarPhrase_EaseOut_Step := 1;
- BarGolden_EaseOut_Step := 1;
+ BarTime := SDL_GetTicks();
end;
function TScreenScore.Draw: boolean;
var
- CurrentTime: cardinal;
PlayerCounter: integer;
- PStart: integer;
- PHigh: integer;
begin
{*
player[0].ScoreInt := 7000;
@@ -413,94 +750,33 @@ begin
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;
- //Calculate first and last Player on this Screen
- if (PlayersPlay > 3) then
- begin
- case PlayersPlay of
- 4: begin
- PStart := 1 + ((ScreenAct-1) * 2);
- PHigh := 2 + ((ScreenAct-1) * 2);
- end;
-
- 6: begin
- PStart := 1 + ((ScreenAct-1) * 3);
- PHigh := 3 + ((ScreenAct-1) * 3);
- end;
- end;
- end
- else
- begin
- PStart := 1;
- PHigh := PlayersPlay;
- end;
-
// Let's start to arise the bars
- CurrentTime := SDL_GetTicks();
- if((CurrentTime >= BarTime) and ShowFinish) then
- begin
- BarTime := CurrentTime + BarRaiseSpeed;
-
- for PlayerCounter := PStart to PHigh do
- begin
- // 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
- if (BarScore_EaseOut_Step >= (EaseOut_MaxSteps * 10)) then
- begin
- if (BarPhrase_EaseOut_Step < EaseOut_MaxSteps * 10) then
- BarPhrase_EaseOut_Step := BarPhrase_EaseOut_Step + 1;
-
- // GoldenNotebonus
- if (BarPhrase_EaseOut_Step >= (EaseOut_MaxSteps * 10)) then
- begin
- if (BarGolden_EaseOut_Step < EaseOut_MaxSteps * 10) then
- BarGolden_EaseOut_Step := BarGolden_EaseOut_Step + 1;
-
- // Draw golden score bar #
- EaseBarIn(PlayerCounter, 'Golden');
- EaseScoreIn(PlayerCounter,'Golden');
- end;
-
- // Draw phrase score bar #
- EaseBarIn(PlayerCounter, 'Line');
- EaseScoreIn(PlayerCounter,'Line');
- end;
-
- // Draw plain score bar #
- EaseBarIn(PlayerCounter, 'Note');
- EaseScoreIn(PlayerCounter,'Note');
+ UpdateAnimation;
- if (PlayersPlay <= 3) then
- //If we play w/ 3 or less players they fit in one screen
- //so we don't have to swap the values of themeobjects
- //on every draw
- FillPlayerItems(PlayerCounter,'Funky');
-
- end;
+ // 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 (PlayersPlay > 3) then
- //more then 3 players don't fit the screen
- //so we have to swap the themeobjects values on every draw
- for PlayerCounter := PStart to PHigh do
- begin
- FillPlayerItems(PlayerCounter,'Funky');
- 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(Static) - 1 do
- Static[I].Draw;
+ for I := 0 to Length(Statics) - 1 do
+ Statics[I].Draw;
for I := 0 to Length(Text) - 1 do
Text[I].Draw;
*)
@@ -508,54 +784,48 @@ begin
Result := true;
end;
-procedure TscreenScore.FillPlayerItems(PlayerNumber: integer; ScoreType: string);
+procedure TscreenScore.FillPlayerItems(PlayerNumber: integer);
var
ThemeIndex: integer;
begin
- // todo: take the name from player[PlayerNumber].Name instead of the ini when this is done (mog)
- Text[TextName[PlayerNumber + ArrayStartModifier]].Text := Ini.Name[PlayerNumber - 1];
- // end todo
-
- // We have to do this here because we use the same Theme Object
- // for players on the first and second screen
- case PlayersPlay of
- 1, 2, 3: ThemeIndex := PlayerNumber + ArrayStartModifier;
- 4: ThemeIndex := ((PlayerNumber-1) mod 2) + 1 + ArrayStartModifier;
- 6: ThemeIndex := ((PlayerNumber-1) mod 3) + 1 + ArrayStartModifier;
- end;
-
- //golden
- Text[TextGoldenNotesScore[ThemeIndex]].Text := IntToStr(TextGolden_ActualValue[PlayerNumber]);
- Text[TextGoldenNotesScore[ThemeIndex]].Alpha := (BarGolden_EaseOut_Step / 100);
+ 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
- Static[StaticBoxLightest[ThemeIndex]].Texture.Alpha := (BarGolden_EaseOut_Step / 100);
- Text[TextGoldenNotes[ThemeIndex]].Alpha := (BarGolden_EaseOut_Step / 100);
+ //golden
+ Text[TextGoldenNotesScore[ThemeIndex]].Text := IntToStr(TextGolden_ActualValue[PlayerNumber]);
+ Text[TextGoldenNotesScore[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[StaticBoxLightest[ThemeIndex]].Texture.Alpha := (BarGolden_EaseOut_Step / 100);
+ Text[TextGoldenNotes[ThemeIndex]].Alpha := (BarGolden_EaseOut_Step / 100);
- Static[StaticBoxLight[ThemeIndex]].Texture.Alpha := (BarPhrase_EaseOut_Step / 100);
- Text[TextLineBonus[ThemeIndex]].Alpha := (BarPhrase_EaseOut_Step / 100);
+ // line bonus
+ Text[TextLineBonusScore[ThemeIndex]].Text := IntToStr(TextPhrase_ActualValue[PlayerNumber]);
+ Text[TextLineBonusScore[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[StaticBoxLight[ThemeIndex]].Texture.Alpha := (BarPhrase_EaseOut_Step / 100);
+ Text[TextLineBonus[ThemeIndex]].Alpha := (BarPhrase_EaseOut_Step / 100);
- Static[StaticBoxDark[ThemeIndex]].Texture.Alpha := (BarScore_EaseOut_Step / 100);
- Text[TextNotesScore[ThemeIndex]].Alpha := (BarScore_EaseOut_Step / 100);
+ // plain score
+ Text[TextNotesScore[ThemeIndex]].Text := IntToStr(TextScore_ActualValue[PlayerNumber]);
+ Text[TextNotes[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);
+ Statics[StaticBoxDark[ThemeIndex]].Texture.Alpha := (BarScore_EaseOut_Step / 100);
+ Text[TextNotesScore[ThemeIndex]].Alpha := (BarScore_EaseOut_Step / 100);
- Text[TextTotal[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);
+ Text[TextTotal[ThemeIndex]].Alpha := (BarScore_EaseOut_Step / 100);
- if(BarGolden_EaseOut_Step = 100) then
- begin
- ShowRating(PlayerNumber);
+ if(BarGolden_EaseOut_Step = 100) then
+ begin
+ ShowRating(PlayerNumber);
+ end;
end;
end;
@@ -564,68 +834,63 @@ 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;
- // We have to do this here because we use the same Theme Object
- // for players on the first and second screen
- case PlayersPlay of
- 1, 2, 3: ThemeIndex := PlayerNumber + ArrayStartModifier;
- 4: ThemeIndex := ((PlayerNumber-1) mod 2) + 1 + ArrayStartModifier;
- 6: ThemeIndex := ((PlayerNumber-1) mod 3) + 1 + ArrayStartModifier;
- end;
-
- 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
- //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;
+ DrawRating(PlayerNumber, Rating);
end;
- // end todo
-
- DrawRating(PlayerNumber, Rating);
end;
procedure TscreenScore.DrawRating(PlayerNumber: integer; Rating: integer);
@@ -633,12 +898,12 @@ var
Posx: real;
Posy: real;
Width: real;
+ ThemeIndex: integer;
begin
+ ThemeIndex := PlayerPositionMap[PlayerNumber-1].Position;
- CalculateBouncing(PlayerNumber);
-
- PosX := Theme.Score.StaticRatings[PlayerNumber + ArrayStartModifier].X + (Theme.Score.StaticRatings[PlayerNumber + ArrayStartModifier].W * 0.5);
- PosY := Theme.Score.StaticRatings[PlayerNumber + ArrayStartModifier].Y + (Theme.Score.StaticRatings[PlayerNumber + ArrayStartModifier].H * 0.5); ;
+ 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;
@@ -661,14 +926,16 @@ end;
function TscreenScore.CalculateBouncing(PlayerNumber: integer): real;
var
- ReturnValue: real;
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[PlayerNumber + ArrayStartModifier].W;
+ MaxVal := Theme.Score.StaticRatings[ThemeIndex].W;
RaiseStep := EaseOut_Step;
@@ -677,23 +944,21 @@ begin
if (RaiseStep = 1) then
begin
- ReturnValue := MaxVal;
+ Result := MaxVal;
end
else
begin
p := MaxVal * 0.4;
s := p/(2*PI) * arcsin (1);
- ReturnValue := MaxVal * power(2,-5 * RaiseStep) * sin( (RaiseStep * MaxVal - s) * (2 * PI) / p) + MaxVal;
+ Result := MaxVal * power(2,-5 * RaiseStep) * sin( (RaiseStep * MaxVal - s) * (2 * PI) / p) + MaxVal;
inc(aPlayerScoreScreenRatings[PlayerNumber].RateEaseStep);
- aPlayerScoreScreenRatings[PlayerNumber].RateEaseValue := ReturnValue;
+ aPlayerScoreScreenRatings[PlayerNumber].RateEaseValue := Result;
end;
-
- Result := ReturnValue;
end;
-procedure TscreenScore.EaseBarIn(PlayerNumber: integer; BarType: string);
+procedure TscreenScore.EaseBarIn(PlayerNumber: integer; BarType: TScoreBarType);
const
RaiseSmoothness: integer = 100;
var
@@ -706,34 +971,31 @@ var
lTmp: real;
Score: integer;
+ ThemeIndex: integer;
begin
- MaxHeight := Theme.Score.StaticBackLevel[PlayerNumber + ArrayStartModifier].H;
+ 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 = 'Note') then
+ if (BarType = sbtScore) then
begin
Score := Player[PlayerNumber - 1].ScoreInt;
RaiseStep := BarScore_EaseOut_Step;
- BarStartPosY := Theme.Score.StaticBackLevel[PlayerNumber + ArrayStartModifier].Y + MaxHeight;
+ BarStartPosY := Theme.Score.StaticBackLevel[ThemeIndex].Y + MaxHeight;
end
- else if (BarType = 'Line') then
+ else if (BarType = sbtLine) then
begin
Score := Player[PlayerNumber - 1].ScoreLineInt;
RaiseStep := BarPhrase_EaseOut_Step;
- BarStartPosY := Theme.Score.StaticBackLevel[PlayerNumber + ArrayStartModifier].Y - aPlayerScoreScreenDatas[PlayerNumber].BarScore_ActualHeight + MaxHeight;
+ BarStartPosY := Theme.Score.StaticBackLevel[ThemeIndex].Y - aPlayerScoreScreenDatas[PlayerNumber].BarScore_ActualHeight + MaxHeight;
end
- else if (BarType = 'Golden') then
+ else if (BarType = sbtGolden) then
begin
Score := Player[PlayerNumber - 1].ScoreGoldenInt;
RaiseStep := BarGolden_EaseOut_Step;
- BarStartPosY := Theme.Score.StaticBackLevel[PlayerNumber + ArrayStartModifier].Y - aPlayerScoreScreenDatas[PlayerNumber].BarScore_ActualHeight - aPlayerScoreScreenDatas[PlayerNumber].BarLine_ActualHeight + MaxHeight;
- end
- else
- begin
- Log.LogCritical('Unknown bar-type: ' + BarType, 'TScreenScore.EaseBarIn');
- Exit; // suppress warnings
+ BarStartPosY := Theme.Score.StaticBackLevel[ThemeIndex].Y - aPlayerScoreScreenDatas[PlayerNumber].BarScore_ActualHeight - aPlayerScoreScreenDatas[PlayerNumber].BarLine_ActualHeight + MaxHeight;
end;
// the height dependend of the score
@@ -758,31 +1020,34 @@ begin
DrawBar(BarType, PlayerNumber, BarStartPosY, NewHeight);
- if (BarType = 'Note') then
+ if (BarType = sbtScore) then
aPlayerScoreScreenDatas[PlayerNumber].BarScore_ActualHeight := NewHeight
- else if (BarType = 'Line') then
+ else if (BarType = sbtLine) then
aPlayerScoreScreenDatas[PlayerNumber].BarLine_ActualHeight := NewHeight
- else if (BarType = 'Golden') then
+ else if (BarType = sbtGolden) then
aPlayerScoreScreenDatas[PlayerNumber].BarGolden_ActualHeight := NewHeight;
end;
-procedure TscreenScore.DrawBar(BarType: string; PlayerNumber: integer; BarStartPosY: single; NewHeight: real);
+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[PlayerNumber + ArrayStartModifier].W;
- BarStartPosX := Theme.Score.StaticBackLevel[PlayerNumber + ArrayStartModifier].X;
+ 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 = 'Note') then
+ if (BarType = sbtScore) then
glBindTexture(GL_TEXTURE_2D, aPlayerScoreScreenTextures[PlayerNumber].Score_NoteBarLevel_Dark.TexNum);
- if (BarType = 'Line') then
+ if (BarType = sbtLine) then
glBindTexture(GL_TEXTURE_2D, aPlayerScoreScreenTextures[PlayerNumber].Score_NoteBarLevel_Light.TexNum);
- if (BarType = 'Golden') then
+ if (BarType = sbtGolden) then
glBindTexture(GL_TEXTURE_2D, aPlayerScoreScreenTextures[PlayerNumber].Score_NoteBarLevel_Lightest.TexNum);
//draw it
@@ -801,11 +1066,11 @@ begin
glDisable(GL_TEXTURE_2d);
//the round thing on top
- if (BarType = 'Note') then
+ if (BarType = sbtScore) then
glBindTexture(GL_TEXTURE_2D, aPlayerScoreScreenTextures[PlayerNumber].Score_NoteBarRound_Dark.TexNum);
- if (BarType = 'Line') then
+ if (BarType = sbtLine) then
glBindTexture(GL_TEXTURE_2D, aPlayerScoreScreenTextures[PlayerNumber].Score_NoteBarRound_Light.TexNum);
- if (BarType = 'Golden') then
+ if (BarType = sbtGolden) then
glBindTexture(GL_TEXTURE_2D, aPlayerScoreScreenTextures[PlayerNumber].Score_NoteBarRound_Lightest.TexNum);
glEnable(GL_TEXTURE_2D);
@@ -813,8 +1078,8 @@ begin
glEnable(GL_BLEND);
glBegin(GL_QUADS);
- glTexCoord2f(0, 0); glVertex3f(BarStartPosX, (BarStartPosY - Static[StaticLevelRound[PlayerNumber + ArrayStartModifier]].Texture.h) - NewHeight, ZBars);
- glTexCoord2f(1, 0); glVertex3f(BarStartPosX + Width, (BarStartPosY - Static[StaticLevelRound[PlayerNumber + ArrayStartModifier]].Texture.h) - NewHeight, ZBars);
+ 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;
@@ -823,7 +1088,7 @@ begin
glDisable(GL_TEXTURE_2d);
end;
-procedure TScreenScore.EaseScoreIn(PlayerNumber: integer; ScoreType: string);
+procedure TScreenScore.EaseScoreIn(PlayerNumber: integer; ScoreType: TScoreBarType);
const
RaiseSmoothness: integer = 100;
var
@@ -833,19 +1098,19 @@ var
EaseOut_Step: real;
ActualScoreValue: integer;
begin
- if (ScoreType = 'Note') then
+ if (ScoreType = sbtScore) then
begin
EaseOut_Step := BarScore_EaseOut_Step;
ActualScoreValue := TextScore_ActualValue[PlayerNumber];
ScoreReached := Player[PlayerNumber-1].ScoreInt;
end;
- if (ScoreType = 'Line') then
+ if (ScoreType = sbtLine) then
begin
EaseOut_Step := BarPhrase_EaseOut_Step;
ActualScoreValue := TextPhrase_ActualValue[PlayerNumber];
ScoreReached := Player[PlayerNumber-1].ScoreLineInt;
end;
- if (ScoreType = 'Golden') then
+ if (ScoreType = sbtGolden) then
begin
EaseOut_Step := BarGolden_EaseOut_Step;
ActualScoreValue := TextGolden_ActualValue[PlayerNumber];
@@ -866,21 +1131,21 @@ begin
if ( lTmpA > 0 ) and
( RaiseSmoothness > 0 ) then
begin
- if (ScoreType = 'Note') then
+ if (ScoreType = sbtScore) then
TextScore_ActualValue[PlayerNumber] := floor( lTmpA / RaiseSmoothness);
- if (ScoreType = 'Line') then
+ if (ScoreType = sbtLine) then
TextPhrase_ActualValue[PlayerNumber] := floor( lTmpA / RaiseSmoothness);
- if (ScoreType = 'Golden') then
+ if (ScoreType = sbtGolden) then
TextGolden_ActualValue[PlayerNumber] := floor( lTmpA / RaiseSmoothness);
end;
end
else
begin
- if (ScoreType = 'Note') then
+ if (ScoreType = sbtScore) then
TextScore_ActualValue[PlayerNumber] := ScoreReached;
- if (ScoreType = 'Line') then
+ if (ScoreType = sbtLine) then
TextPhrase_ActualValue[PlayerNumber] := ScoreReached;
- if (ScoreType = 'Golden') then
+ if (ScoreType = sbtGolden) then
TextGolden_ActualValue[PlayerNumber] := ScoreReached;
end;
end;
diff --git a/cmake/src/screens/UScreenSing.pas b/cmake/src/screens/UScreenSing.pas
index ae75c74d..233f1e38 100644
--- a/cmake/src/screens/UScreenSing.pas
+++ b/cmake/src/screens/UScreenSing.pas
@@ -35,9 +35,9 @@ interface
uses
SysUtils,
- gl,
SDL,
TextGL,
+ gl,
UFiles,
UGraphicClasses,
UIni,
@@ -49,19 +49,30 @@ uses
USongs,
UTexture,
UThemes,
- UTime;
+ UPath,
+ UTime,
+ UHookableEvent;
type
TLyricsSyncSource = class(TSyncSource)
function GetClock(): real; override;
end;
+ TMusicSyncSource = class(TSyncSource)
+ function GetClock(): real; override;
+ end;
+
type
TScreenSing = class(TMenu)
+ private
+ fShowVisualization: boolean;
+ fCurrentVideo: IVideo;
+ fVideoClip: IVideo;
+ fLyricsSync: TLyricsSyncSource;
+ fMusicSync: TMusicSyncSource;
protected
- VideoLoaded: boolean;
- Paused: boolean; // pause mod
- LyricsSync: TLyricsSyncSource;
+ eSongLoaded: THookableEvent; //< event is called after lyrics of a song are loaded on OnShow
+ Paused: boolean; //pause Mod
NumEmptySentences: integer;
public
// timebar fields
@@ -97,15 +108,28 @@ type
// score manager:
Scores: TSingScores;
- fShowVisualization: boolean;
- fCurrentVideoPlaybackEngine: IVideoPlayback;
+ //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;
+ procedure OnShow; override;
+ procedure OnShowFinish; override;
+ procedure OnHide; override;
- function ParseInput(PressedKey: cardinal; CharCode: widechar;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char;
PressedDown: boolean): boolean; override;
function Draw: boolean; override;
@@ -127,20 +151,22 @@ uses
UNote,
URecord,
USong,
- UDisplay;
+ 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: widechar;
+function TScreenSing.ParseInput(PressedKey: Cardinal; CharCode: UCS4Char;
PressedDown: boolean): boolean;
begin
Result := true;
if (PressedDown) then
begin // key down
// check normal keys
- case WideCharUpperCase(CharCode)[1] of
- 'Q':
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'):
begin
// when not ask before exit then finish now
if (Ini.AskbeforeDel <> 1) then
@@ -152,21 +178,22 @@ begin
Result := false;
Exit;
end;
- 'V': // show visualization
+ Ord('V'): // show visualization
begin
fShowVisualization := not fShowVisualization;
if fShowVisualization then
- fCurrentVideoPlaybackEngine := Visualization
+ begin
+ fCurrentVideo := Visualization.Open(PATH_NONE);
+ fCurrentVideo.play;
+ end
else
- fCurrentVideoPlaybackEngine := VideoPlayback;
-
- if fShowVisualization then
- fCurrentVideoPlaybackEngine.play;
-
+ begin
+ fCurrentVideo := fVideoClip;
+ end;
Exit;
end;
- 'P':
+ Ord('P'):
begin
Pause;
Exit;
@@ -194,7 +221,7 @@ begin
SDLK_TAB: // change visualization preset
begin
if fShowVisualization then
- fCurrentVideoPlaybackEngine.Position := now; // move to a random position
+ fCurrentVideo.Position := now; // move to a random position
end;
SDLK_RETURN:
@@ -228,22 +255,20 @@ begin
AudioPlayback.Pause;
// pause video
- if (CurrentSong.Video <> '') and FileExists(CurrentSong.Path +
- CurrentSong.Video) then
- fCurrentVideoPlaybackEngine.Pause;
+ if (fCurrentVideo <> nil) then
+ fCurrentVideo.Pause;
end
else // disable pause
begin
- LyricsState.Resume();
+ LyricsState.Start();
// play music
AudioPlayback.Play;
// video
- if (CurrentSong.Video <> '') and FileExists(CurrentSong.Path +
- CurrentSong.Video) then
- fCurrentVideoPlaybackEngine.Pause;
+ if (fCurrentVideo <> nil) then
+ fCurrentVideo.Pause;
Paused := false;
end;
@@ -259,7 +284,7 @@ begin
fShowVisualization := false;
- fCurrentVideoPlaybackEngine := VideoPlayback;
+ fCurrentVideo := nil;
// create score class
Scores := TSingScores.Create;
@@ -298,16 +323,21 @@ begin
StaticPausePopup := AddStatic(Theme.Sing.PausePopUp);
// <note> pausepopup is not visibile at the beginning </note>
- Static[StaticPausePopup].Visible := false;
+ 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);
- LyricsSync := TLyricsSyncSource.Create();
+ fLyricsSync := TLyricsSyncSource.Create();
+ fMusicSync := TMusicSyncSource.Create();
+
+ eSongLoaded := THookableEvent.Create('ScreenSing.SongLoaded');
+
+ ClearSettings;
end;
-procedure TScreenSing.onShow;
+procedure TScreenSing.OnShow;
var
Index: integer;
V1: boolean;
@@ -317,16 +347,21 @@ var
V2M: boolean;
V3R: boolean;
Color: TRGB;
-
+ VideoFile, BgFile: IPath;
success: boolean;
begin
inherited;
- Log.LogStatus('Begin', 'onShow');
+ Log.LogStatus('Begin', 'OnShow');
FadeOut := false;
- // reset video playback engine, to play video clip ...
- fCurrentVideoPlaybackEngine := VideoPlayback;
+ //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
@@ -395,24 +430,24 @@ begin
end;
// this one is shown in 1P mode
- Static[StaticP1].Visible := V1;
+ Statics[StaticP1].Visible := V1;
Text[TextP1].Visible := V1;
// this one is shown in 2/4P mode
- Static[StaticP1TwoP].Visible := V1TwoP;
+ Statics[StaticP1TwoP].Visible := V1TwoP;
Text[TextP1TwoP].Visible := V1TwoP;
- Static[StaticP2R].Visible := V2R;
+ Statics[StaticP2R].Visible := V2R;
Text[TextP2R].Visible := V2R;
// this one is shown in 3/6P mode
- Static[StaticP1ThreeP].Visible := V1ThreeP;
+ Statics[StaticP1ThreeP].Visible := V1ThreeP;
Text[TextP1ThreeP].Visible := V1ThreeP;
- Static[StaticP2M].Visible := V2M;
+ Statics[StaticP2M].Visible := V2M;
Text[TextP2M].Visible := V2M;
- Static[StaticP3R].Visible := V3R;
+ Statics[StaticP3R].Visible := V3R;
Text[TextP3R].Visible := V3R;
// FIXME: sets path and filename to ''
@@ -423,7 +458,7 @@ begin
// FIXME: bad style, put the try-except into loadsong() and not here
try
// check if file is xml
- if copy(CurrentSong.FileName, length(CurrentSong.FileName) - 3, 4) = '.xml' then
+ if CurrentSong.FileName.GetExtension.ToUTF8 = '.xml' then
success := CurrentSong.LoadXMLSong()
else
success := CurrentSong.LoadSong();
@@ -433,8 +468,8 @@ begin
if (not success) then
begin
- // error loading song -> go back to song screen and show some error message
- FadeTo(@ScreenSong);
+ // 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();
@@ -447,10 +482,6 @@ begin
Exit;
end;
- // reset video playback engine, to play video clip ...
- fCurrentVideoPlaybackEngine.Close;
- fCurrentVideoPlaybackEngine := VideoPlayback;
-
{*
* == Background ==
* We have four types of backgrounds:
@@ -465,32 +496,34 @@ begin
{*
* set background to: video
*}
- VideoLoaded := false;
fShowVisualization := false;
- if (CurrentSong.Video <> '') and FileExists(CurrentSong.Path + CurrentSong.Video) then
+ VideoFile := CurrentSong.Path.Append(CurrentSong.Video);
+ if (CurrentSong.Video.IsSet) and VideoFile.IsFile then
begin
- if (fCurrentVideoPlaybackEngine.Open(CurrentSong.Path + CurrentSong.Video)) then
+ fVideoClip := VideoPlayback.Open(VideoFile);
+ fCurrentVideo := fVideoClip;
+ if (fVideoClip <> nil) then
begin
fShowVisualization := false;
- fCurrentVideoPlaybackEngine := VideoPlayback;
- fCurrentVideoPlaybackEngine.Position := CurrentSong.VideoGAP + CurrentSong.Start;
- fCurrentVideoPlaybackEngine.Play;
- VideoLoaded := true;
+ fCurrentVideo.Position := CurrentSong.VideoGAP + CurrentSong.Start;
+ fCurrentVideo.Play;
end;
end;
{*
* set background to: picture
*}
- if (CurrentSong.Background <> '') and (VideoLoaded = false)
+ 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(CurrentSong.Path + CurrentSong.Background);
+ Tex_Background := Texture.LoadTexture(BgFile);
except
- Log.LogError('Background could not be loaded: ' + CurrentSong.Path +
- CurrentSong.Background);
+ Log.LogError('Background could not be loaded: ' + BgFile.ToNative);
Tex_Background.TexNum := 0;
end
+ end
else
begin
Tex_Background.TexNum := 0;
@@ -502,21 +535,21 @@ begin
if (TVisualizerOption(Ini.VisualizerOption) in [voOn]) then
begin
fShowVisualization := true;
- fCurrentVideoPlaybackEngine := Visualization;
- if (fCurrentVideoPlaybackEngine <> nil) then
- fCurrentVideoPlaybackEngine.Play;
+ 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
- (VideoLoaded = false)) then
+ (fVideoClip = nil)) then
begin
fShowVisualization := true;
- fCurrentVideoPlaybackEngine := Visualization;
- if (fCurrentVideoPlaybackEngine <> nil) then
- fCurrentVideoPlaybackEngine.Play;
+ fCurrentVideo := Visualization.Open(PATH_NONE);
+ if (fCurrentVideo <> nil) then
+ fCurrentVideo.Play;
end;
// prepare lyrics timer
@@ -529,12 +562,6 @@ begin
LyricsState.TotalTime := AudioPlayback.Length;
LyricsState.UpdateBeats();
- // prepare music
- AudioPlayback.Stop();
- AudioPlayback.Position := CurrentSong.Start;
- // synchronize music to the lyrics
- AudioPlayback.SetSyncSource(LyricsSync);
-
// prepare and start voice-capture
AudioInput.CaptureStart;
@@ -564,7 +591,7 @@ begin
case Ini.LyricsFont of
0: // normal fonts
begin
- Lyrics.FontStyle := 0;
+ Lyrics.FontStyle := ftNormal;
Lyrics.LineColor_en.R := Skin_FontR;
Lyrics.LineColor_en.G := Skin_FontG;
@@ -581,9 +608,12 @@ begin
Lyrics.LineColor_act.B := 0.8;
Lyrics.LineColor_act.A := 1;
end;
- 1, 2: // outline fonts (is TScalableOutlineFont)
+ 1, 2: // outline fonts
begin
- Lyrics.FontStyle := Ini.LyricsFont + 1;
+ if (Ini.LyricsFont = 1) then
+ Lyrics.FontStyle := ftOutline1
+ else
+ Lyrics.FontStyle := ftOutline2;
Lyrics.LineColor_en.R := 0.75;
Lyrics.LineColor_en.G := 0.75;
@@ -622,16 +652,37 @@ begin
if Lines[0].Line[Index].TotalNotes = 0 then
Inc(NumEmptySentences);
- Log.LogStatus('End', 'onShow');
+ 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.Resume();
+ LyricsState.Start(true);
// start music
AudioPlayback.Play();
@@ -640,7 +691,26 @@ begin
CountSkipTimeSet;
end;
-procedure TScreenSing.onHide;
+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
@@ -659,6 +729,9 @@ var
Sec: integer;
T: integer;
CurLyricsTime: real;
+ VideoFrameTime: Extended;
+ Line: TLyricLine;
+ LastWord: TLyricWord;
begin
Background.Draw;
@@ -704,23 +777,23 @@ begin
// will move the statics and texts to the correct screen here.
// FIXME: clean up this weird stuff. Commenting this stuff out, nothing
// was missing on screen w/ 6 players - so do we even need this stuff?
- {Static[StaticP1].Texture.X := Static[StaticP1].Texture.X + 10 * ScreenX;
+ {Statics[StaticP1].Texture.X := Statics[StaticP1].Texture.X + 10 * ScreenX;
Text[TextP1].X := Text[TextP1].X + 10 * ScreenX; }
- {Static[StaticP1ScoreBG].Texture.X := Static[StaticP1ScoreBG].Texture.X + 10*ScreenX;
+ {Statics[StaticP1ScoreBG].Texture.X := Statics[StaticP1ScoreBG].Texture.X + 10*ScreenX;
Text[TextP1Score].X := Text[TextP1Score].X + 10*ScreenX;}
- {Static[StaticP2R].Texture.X := Static[StaticP2R].Texture.X + 10 * ScreenX;
+ {Statics[StaticP2R].Texture.X := Statics[StaticP2R].Texture.X + 10 * ScreenX;
Text[TextP2R].X := Text[TextP2R].X + 10 * ScreenX; }
- {Static[StaticP2RScoreBG].Texture.X := Static[StaticP2RScoreBG].Texture.X + 10*ScreenX;
+ {Statics[StaticP2RScoreBG].Texture.X := Statics[StaticP2RScoreBG].Texture.X + 10*ScreenX;
Text[TextP2RScore].X := Text[TextP2RScore].X + 10*ScreenX;}
// end of weird stuff
{
- Static[1].Texture.X := Static[1].Texture.X + 10 * ScreenX; }
+ Statics[1].Texture.X := Statics[1].Texture.X + 10 * ScreenX; }
{ for T := 0 to 1 do
Text[T].X := Text[T].X + 10 * ScreenX; }
@@ -744,18 +817,37 @@ begin
// Note: there is no menu and the animated background brakes the video playback
//DrawBG;
+ //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 (ShowFinish and (VideoLoaded or fShowVisualization)) then
+ if Assigned(fCurrentVideo) then
begin
- if assigned(fCurrentVideoPlaybackEngine) then
+ // Just call this once
+ // when Screens = 2
+ if (ScreenAct = 1) then
begin
- // Just call this once
- // when Screens = 2
- if (ScreenAct = 1) then
- fCurrentVideoPlaybackEngine.GetFrame(CurrentSong.VideoGAP + LyricsState.GetCurrentTime());
-
- fCurrentVideoPlaybackEngine.DrawGL(ScreenAct);
+ 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.DrawGL(ScreenAct);
end;
// draw static menu (FG)
@@ -766,11 +858,14 @@ begin
if ShowFinish then
begin
if (not AudioPlayback.Finished) and ((CurrentSong.Finish = 0) or
- (LyricsState.GetCurrentTime() * 1000 <= CurrentSong.Finish)) then
+ (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
@@ -778,7 +873,6 @@ begin
begin
Finish;
FadeOut := true;
- FadeTo(@ScreenScore);
end;
end;
end;
@@ -800,15 +894,15 @@ begin
// will move the statics and texts to the correct screen here.
// FIXME: clean up this weird stuff
- {Static[StaticP1].Texture.X := Static[StaticP1].Texture.X - 10 * ScreenX;
+ {Statics[StaticP1].Texture.X := Statics[StaticP1].Texture.X - 10 * ScreenX;
Text[TextP1].X := Text[TextP1].X - 10 * ScreenX;
- Static[StaticP2R].Texture.X := Static[StaticP2R].Texture.X - 10 * ScreenX;
+ Statics[StaticP2R].Texture.X := Statics[StaticP2R].Texture.X - 10 * ScreenX;
Text[TextP2R].X := Text[TextP2R].X - 10 * ScreenX;
// end of weird
- Static[1].Texture.X := Static[1].Texture.X - 10 * ScreenX;
+ Statics[1].Texture.X := Statics[1].Texture.X - 10 * ScreenX;
for T := 0 to 1 do
Text[T].X := Text[T].X - 10 * ScreenX; }
@@ -818,9 +912,9 @@ begin
// maybe someone could find a better solution
if Paused then
begin
- Static[StaticPausePopup].Visible := true;
- Static[StaticPausePopup].Draw;
- Static[StaticPausePopup].Visible := false;
+ Statics[StaticPausePopup].Visible := true;
+ Statics[StaticPausePopup].Draw;
+ Statics[StaticPausePopup].Visible := false;
end;
Result := true;
@@ -832,14 +926,12 @@ begin
AudioPlayback.Stop;
AudioPlayback.SetSyncSource(nil);
- if (VideoPlayback <> nil) then
- VideoPlayback.Close;
+ LyricsState.Stop();
+ LyricsState.SetSyncSource(nil);
- if (Visualization <> nil) then
- Visualization.Close;
-
- // to prevent drawing closed video
- VideoLoaded := false;
+ // close video files
+ fVideoClip := nil;
+ fCurrentVideo := nil;
// kill all stars and effects
GoldenRec.KillAll;
@@ -855,11 +947,13 @@ begin
end;
SetFontItalic(false);
+
+ Party.CallAfterSing;
end;
procedure TScreenSing.OnSentenceEnd(SentenceIndex: cardinal);
var
- PlayerIndex: integer;
+ PlayerIndex: byte;
CurrentPlayer: PPLayer;
CurrentScore: real;
Line: PLine;
@@ -898,10 +992,14 @@ begin
// points for this line
LineScore := CurrentScore - CurrentPlayer.ScoreLast;
- // 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 + 2) / MaxLineScore;
+ // 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
@@ -928,7 +1026,9 @@ begin
// spawn rating pop-up
Rating := Round(LinePerfection * MAX_LINE_RATING);
Scores.SpawnPopUp(PlayerIndex, Rating, CurrentPlayer.ScoreTotalInt);
- end;
+ end
+ else
+ Scores.RaiseScore(PlayerIndex, CurrentPlayer.ScoreTotalInt);
// PerfectLineTwinkle (effect), part 1
if (Ini.EffectSing = 1) then
@@ -967,5 +1067,10 @@ begin
Result := LyricsState.GetCurrentTime();
end;
+function TMusicSyncSource.GetClock(): real;
+begin
+ Result := AudioPlayback.Position;
+end;
+
end.
diff --git a/cmake/src/screens/UScreenSingModi.pas b/cmake/src/screens/UScreenSingModi.pas
deleted file mode 100644
index eeb06004..00000000
--- a/cmake/src/screens/UScreenSingModi.pas
+++ /dev/null
@@ -1,580 +0,0 @@
-{* 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 UScreenSingModi;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-
-uses
- UMenu,
- UMusic,
- SDL,
- SysUtils,
- UFiles,
- UTime,
- USongs,
- UIni,
- ULog,
- UTexture,
- ULyrics,
- TextGL,
- gl,
-
- UThemes,
- UScreenSing,
- ModiSDK;
-
-type
- TScreenSingModi = class(TScreenSing)
- protected
-
- public
- Winner: byte; //Who Wins
- PlayerInfo: TPlayerInfo;
- TeamInfo: TTeamInfo;
-
- constructor Create; override;
- procedure onShow; override;
- //procedure onShowFinish; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
- function Draw: boolean; override;
- procedure Finish; override;
- end;
-
-type
- TCustomSoundEntry = record
- Filename : string;
- Stream : TAudioPlaybackStream;
- end;
-
-var
- //Custom Sounds
- CustomSounds: array of TCustomSoundEntry;
-
-//Procedured for Plugin
-function LoadTex(const Name: PChar; Typ: TTextureType): TsmallTexture;
- {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-//function Translate (const Name: PChar): PChar;
-// {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-//Procedure to Print Text
-procedure Print(const Style, Size: byte; const X, Y: real; const Text: PChar);
- {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-//Procedure that loads a Custom Sound
-function LoadSound(const Name: PChar): cardinal;
- {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-//Plays a Custom Sound
-procedure PlaySound(const Index: cardinal);
- {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
-
-//Utilys
-function ToSentences(Const Lines: TLines): TSentences;
-
-implementation
-
-uses
- Classes,
- Math,
- UDLLManager,
- UDraw,
- UGraphic,
- UGraphicClasses,
- ULanguage,
- UNote,
- UPath,
- URecord,
- USkins;
-
-// Method for input parsing. If false is returned, GetNextWindow
-// should be checked to know the next window to load;
-function TScreenSingModi.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
-begin
- Result := true;
- if (PressedDown) then
- begin // Key Down
- case PressedKey of
-
- SDLK_ESCAPE,
- SDLK_BACKSPACE :
- begin
- Finish;
- AudioPlayback.PlaySound(SoundLib.Back);
- FadeTo(@ScreenPartyScore);
- end;
-
- else
- Result := inherited ParseInput(PressedKey, CharCode, PressedDown);
- end;
- end;
-end;
-
-constructor TScreenSingModi.Create;
-begin
- inherited Create;
-
-end;
-
-function ToSentences(Const Lines: TLines): TSentences;
-var
- I, J: integer;
-begin
- Result.Current := Lines.Current;
- Result.High := Lines.High;
- Result.Number := Lines.Number;
- Result.Resolution := Lines.Resolution;
- Result.NotesGAP := Lines.NotesGAP;
- Result.TotalLength := Lines.ScoreValue;
-
- SetLength(Result.Sentence, Length(Lines.Line));
- for I := low(Result.Sentence) to high(Result.Sentence) do
- begin
- Result.Sentence[I].Start := Lines.Line[I].Start;
- Result.Sentence[I].StartNote := Lines.Line[I].Note[0].Start;
- Result.Sentence[I].Lyric := Lines.Line[I].Lyric;
- Result.Sentence[I].End_ := Lines.Line[I].End_;
- Result.Sentence[I].BaseNote := Lines.Line[I].BaseNote;
- Result.Sentence[I].HighNote := Lines.Line[I].HighNote;
- Result.Sentence[I].TotalNotes := Lines.Line[I].TotalNotes;
-
- SetLength(Result.Sentence[I].Note, Length(Lines.Line[I].Note));
- for J := low(Result.Sentence[I].Note) to high(Result.Sentence[I].Note) do
- begin
- Result.Sentence[I].Note[J].Color := Lines.Line[I].Note[J].Color;
- Result.Sentence[I].Note[J].Start := Lines.Line[I].Note[J].Start;
- Result.Sentence[I].Note[J].Length := Lines.Line[I].Note[J].Length;
- Result.Sentence[I].Note[J].Tone := Lines.Line[I].Note[J].Tone;
- //Result.Sentence[I].Note[J].Text := Lines.Line[I].Note[J].Text;
- Result.Sentence[I].Note[J].FreeStyle := (Lines.Line[I].Note[J].NoteType = ntFreestyle);
- end;
- end;
-end;
-
-procedure TScreenSingModi.onShow;
-var
- I: integer;
-begin
- inherited;
-
- PlayersPlay := TeamInfo.NumTeams;
-
- if DLLMan.Selected.LoadSong then //Start with Song
- begin
- inherited;
- end
- else //Start Without Song
- begin
- AudioInput.CaptureStart;
- end;
-
-//Set Playerinfo
- PlayerInfo.NumPlayers := PlayersPlay;
- for I := 0 to PlayerInfo.NumPlayers-1 do
- begin
- PlayerInfo.Playerinfo[I].Name := PChar(Ini.Name[I]);
- PlayerInfo.Playerinfo[I].Score := 0;
- PlayerInfo.Playerinfo[I].Bar := 50;
- PlayerInfo.Playerinfo[I].Enabled := true;
- end;
-
- for I := PlayerInfo.NumPlayers to high(PlayerInfo.Playerinfo) do
- begin
- PlayerInfo.Playerinfo[I].Score:= 0;
- PlayerInfo.Playerinfo[I].Bar := 0;
- PlayerInfo.Playerinfo[I].Enabled := false;
- end;
-
- {Case PlayersPlay of
- 1: begin
- PlayerInfo.Playerinfo[0].PosX := Static[StaticP1ScoreBG].Texture.X;
- PlayerInfo.Playerinfo[0].PosY := Static[StaticP1ScoreBG].Texture.Y + Static[StaticP1ScoreBG].Texture.H;
- end;
- 2,4: begin
- PlayerInfo.Playerinfo[0].PosX := Static[StaticP1TwoPScoreBG].Texture.X;
- PlayerInfo.Playerinfo[0].PosY := Static[StaticP1TwoPScoreBG].Texture.Y + Static[StaticP1TwoPScoreBG].Texture.H;
- PlayerInfo.Playerinfo[2].PosX := Static[StaticP1TwoPScoreBG].Texture.X;
- PlayerInfo.Playerinfo[2].PosY := Static[StaticP1TwoPScoreBG].Texture.Y + Static[StaticP1TwoPScoreBG].Texture.H;
- PlayerInfo.Playerinfo[1].PosX := Static[StaticP2RScoreBG].Texture.X;
- PlayerInfo.Playerinfo[1].PosY := Static[StaticP2RScoreBG].Texture.Y + Static[StaticP2RScoreBG].Texture.H;
- PlayerInfo.Playerinfo[3].PosX := Static[StaticP2RScoreBG].Texture.X;
- PlayerInfo.Playerinfo[3].PosY := Static[StaticP2RScoreBG].Texture.Y + Static[StaticP2RScoreBG].Texture.H;
- end;
- 3,6: begin
- PlayerInfo.Playerinfo[0].PosX := Static[StaticP1ThreePScoreBG].Texture.X;
- PlayerInfo.Playerinfo[0].PosY := Static[StaticP1ThreePScoreBG].Texture.Y + Static[StaticP1ThreePScoreBG].Texture.H;
- PlayerInfo.Playerinfo[3].PosX := Static[StaticP1ThreePScoreBG].Texture.X;
- PlayerInfo.Playerinfo[3].PosY := Static[StaticP1ThreePScoreBG].Texture.Y + Static[StaticP1ThreePScoreBG].Texture.H;
- PlayerInfo.Playerinfo[1].PosX := Static[StaticP2MScoreBG].Texture.X;
- PlayerInfo.Playerinfo[1].PosY := Static[StaticP2MScoreBG].Texture.Y + Static[StaticP2MScoreBG].Texture.H;
- PlayerInfo.Playerinfo[4].PosX := Static[StaticP2MScoreBG].Texture.X;
- PlayerInfo.Playerinfo[4].PosY := Static[StaticP2MScoreBG].Texture.Y + Static[StaticP2MScoreBG].Texture.H;
- PlayerInfo.Playerinfo[2].PosX := Static[StaticP3RScoreBG].Texture.X;
- PlayerInfo.Playerinfo[2].PosY := Static[StaticP3RScoreBG].Texture.Y + Static[StaticP3RScoreBG].Texture.H;
- PlayerInfo.Playerinfo[5].PosX := Static[StaticP3RScoreBG].Texture.X;
- PlayerInfo.Playerinfo[5].PosY := Static[StaticP3RScoreBG].Texture.Y + Static[StaticP3RScoreBG].Texture.H;
- end;
- end; }
-
- // play music (I)
- //Music.CaptureStart;
- //Music.MoveTo(AktSong.Start);
-
- //Init Plugin
- if not DLLMan.PluginInit(TeamInfo, PlayerInfo, ToSentences(Lines[0]), LoadTex, Print, LoadSound, PlaySound) then
- begin
- //Fehler
- Log.LogError('Could not Init Plugin');
- Halt;
- end;
-
- // Set Background (Little Workaround, maybe change sometime)
- if (DLLMan.Selected.LoadBack) and (DLLMan.Selected.LoadSong) then
- ScreenSing.Tex_Background := Tex_Background;
-
- Winner := 0;
-
- //Set Score Visibility
- Scores.Visible := DLLMan.Selected.ShowScore;
-
- {if PlayersPlay = 1 then
- begin
- Text[TextP1Score].Visible := DLLMan.Selected.ShowScore;
- Static[StaticP1ScoreBG].Visible := DLLMan.Selected.ShowScore;
- end;
-
- if (PlayersPlay = 2) or (PlayersPlay = 4) then
- begin
- Text[TextP1TwoPScore].Visible := DLLMan.Selected.ShowScore;
- Static[StaticP1TwoPScoreBG].Visible := DLLMan.Selected.ShowScore;
-
- Text[TextP2RScore].Visible := DLLMan.Selected.ShowScore;
- Static[StaticP2RScoreBG].Visible := DLLMan.Selected.ShowScore;
- end;
-
- if (PlayersPlay = 3) or (PlayersPlay = 6) then
- begin
- Text[TextP1ThreePScore].Visible := DLLMan.Selected.ShowScore;
- Static[StaticP1ThreePScoreBG].Visible := DLLMan.Selected.ShowScore;
-
- Text[TextP2MScore].Visible := DLLMan.Selected.ShowScore;
- Static[StaticP2MScoreBG].Visible := DLLMan.Selected.ShowScore;
-
- Text[TextP3RScore].Visible := DLLMan.Selected.ShowScore;
- Static[StaticP3RScoreBG].Visible := DLLMan.Selected.ShowScore;
- end; }
-end;
-
-function TScreenSingModi.Draw: boolean;
-var
- Min: integer;
- Sec: integer;
- TextStr: string;
- S, I: integer;
- T: integer;
- CurLyricsTime: real;
-begin
- Result := false;
-
- //Set Playerinfo
- PlayerInfo.NumPlayers := PlayersPlay;
- for I := 0 to PlayerInfo.NumPlayers-1 do
- begin
- PlayerInfo.Playerinfo[I].Name := PChar(Player[I].Name);
- if PlayerInfo.Playerinfo[I].Enabled then
- begin
- if (Player[I].ScoreTotalInt <= MAX_SONG_SCORE) then
- PlayerInfo.Playerinfo[I].Score:= Player[I].ScoreTotalInt;
- PlayerInfo.Playerinfo[I].Bar := Round(Scores.Players[I].RBPos * 100);
- end;
- end;
-
- 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 (DllMan.Selected.LoadSong) and (DllMan.Selected.LoadBack) and (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'; // added for ps3 skin
- Text[TextP1ThreeP].Text := 'P1'; // added for ps3 skin
- Text[TextP2R].Text := 'P2';
- Text[TextP2M].Text := 'P2';
- Text[TextP3R].Text := 'P3';
- end
-
- Else 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
-
- // stereo <- and where iss P2M? or P3?
- Static[StaticP1].Texture.X := Static[StaticP1].Texture.X + 10*ScreenX;
- Text[TextP1].X := Text[TextP1].X + 10*ScreenX;
-
- {Static[StaticP1ScoreBG].Texture.X := Static[StaticP1ScoreBG].Texture.X + 10*ScreenX;
- Text[TextP1Score].X := Text[TextP1Score].X + 10*ScreenX;}
-
- Static[StaticP2R].Texture.X := Static[StaticP2R].Texture.X + 10*ScreenX;
- Text[TextP2R].X := Text[TextP2R].X + 10*ScreenX;
-
- for S := 1 to 1 do
- Static[S].Texture.X := Static[S].Texture.X + 10*ScreenX;
-
- for T := 0 to 1 do
- Text[T].X := Text[T].X + 10*ScreenX;
-
- if DLLMan.Selected.LoadSong then
- begin
- // update static menu with time ...
- CurLyricsTime := LyricsState.GetCurrentTime();
- Min := Round(CurLyricsTime) div 60;
- Sec := Round(CurLyricsTime) mod 60;
-
- Text[TextTimeText].Text := '';
- if Min < 10 then Text[TextTimeText].Text := '0';
- Text[TextTimeText].Text := Text[TextTimeText].Text + IntToStr(Min) + ':';
- if Sec < 10 then Text[TextTimeText].Text := Text[TextTimeText].Text + '0';
- Text[TextTimeText].Text := Text[TextTimeText].Text + IntToStr(Sec);
- end;
-
- // update and draw movie
-{ if ShowFinish and CurrentSong.VideoLoaded and DllMan.Selected.LoadVideo then
- begin
- UpdateSmpeg; // this only draws
- end;}
-
- // update and draw movie
- if (ShowFinish and (VideoLoaded or fShowVisualization) and DllMan.Selected.LoadVideo) then
- begin
- if assigned(fCurrentVideoPlaybackEngine) then
- begin
- // Just call this once
- // when Screens = 2
- if (ScreenAct = 1) then
- fCurrentVideoPlaybackEngine.GetFrame(CurrentSong.VideoGAP + LyricsState.GetCurrentTime());
-
- fCurrentVideoPlaybackEngine.DrawGL(ScreenAct);
- end;
- end;
-
- // draw static menu (FG)
- DrawFG;
-
- if ShowFinish then
- begin
- if DllMan.Selected.LoadSong then
- begin
- if (not AudioPlayback.Finished) and ((CurrentSong.Finish = 0) or (LyricsState.GetCurrentTime*1000 <= CurrentSong.Finish)) then
- begin
- //Pause Mod:
- if not Paused then
- Sing(Self); // analyze song
- end
- else
- begin
- if not FadeOut then
- begin
- Finish;
- FadeOut := true;
- FadeTo(@ScreenPartyScore);
- end;
- end;
- end;
- end;
-
- // draw custom items
- SingModiDraw(PlayerInfo); // always draw
-
- //GoldenNoteStarsTwinkle Mod
- GoldenRec.SpawnRec;
- //GoldenNoteStarsTwinkle Mod
-
- //Draw Score
- Scores.Draw;
-
- //Update PlayerInfo
- for I := 0 to PlayerInfo.NumPlayers-1 do
- begin
- if PlayerInfo.Playerinfo[I].Enabled then
- begin
- //PlayerInfo.Playerinfo[I].Bar := Player[I].ScorePercent;
- PlayerInfo.Playerinfo[I].Score := Player[I].ScoreTotalInt;
- end;
- end;
-
- if ((ShowFinish) and (not Paused)) then
- begin
- if not DLLMan.PluginDraw(Playerinfo, Lines[0].Current) then
- begin
- if not FadeOut then
- begin
- Finish;
- FadeOut := true;
- FadeTo(@ScreenPartyScore);
- end;
- end;
- end;
-
- //Change PlayerInfo/Changeables
- for I := 0 to PlayerInfo.NumPlayers-1 do
- begin
- if (Player[I].ScoreTotalInt <> PlayerInfo.Playerinfo[I].Score) then
- begin
- //Player[I].ScoreTotal := Player[I].ScoreTotal + (PlayerInfo.Playerinfo[I].Score - Player[I].ScoreTotalI);
- Player[I].ScoreTotalInt := PlayerInfo.Playerinfo[I].Score;
- end;
- {if (PlayerInfo.Playerinfo[I].Bar <> Player[I].ScorePercent) then
- Player[I].ScorePercentTarget := PlayerInfo.Playerinfo[I].Bar; }
- end;
-
- // back stereo
- Static[StaticP1].Texture.X := Static[StaticP1].Texture.X - 10*ScreenX;
- Text[TextP1].X := Text[TextP1].X - 10*ScreenX;
-
- {Static[StaticP1ScoreBG].Texture.X := Static[StaticP1ScoreBG].Texture.X - 10*ScreenX;
- Text[TextP1Score].X := Text[TextP1Score].X - 10*ScreenX;}
-
- Static[StaticP2R].Texture.X := Static[StaticP2R].Texture.X - 10*ScreenX;
- Text[TextP2R].X := Text[TextP2R].X - 10*ScreenX;
-
- {Static[StaticP2RScoreBG].Texture.X := Static[StaticP2RScoreBG].Texture.X - 10*ScreenX;
- Text[TextP2RScore].X := Text[TextP2RScore].X - 10*ScreenX;}
-
- for S := 1 to 1 do
- Static[S].Texture.X := Static[S].Texture.X - 10*ScreenX;
-
- for T := 0 to 1 do
- Text[T].X := Text[T].X - 10*ScreenX;
-
- Result := true;
-end;
-
-procedure TScreenSingModi.Finish;
-begin
-inherited Finish;
-
-Winner := DllMan.PluginFinish(PlayerInfo);
-
-//Log.LogError('Winner: ' + InttoStr(Winner));
-
-//DLLMan.UnLoadPlugin;
-end;
-
-function LoadTex(const Name: PChar; Typ: TTextureType): TsmallTexture;
-var
- Texname, EXT: string;
- Tex: TTexture;
-begin
- //Get texture Name
- TexName := Skin.GetTextureFileName(string(Name));
- //Get File Typ
- Ext := ExtractFileExt(TexName);
- if (uppercase(Ext) = '.JPG') then
- Ext := 'JPG'
- else
- Ext := 'BMP';
-
- Tex := Texture.LoadTexture(false, PChar(TexName), UTEXTURE.TTextureType(Typ), 0);
-
- Result.TexNum := Tex.TexNum;
- Result.W := Tex.W;
- Result.H := Tex.H;
-end;
-{
-function Translate (const Name: PChar): PChar; stdcall;
-begin
- Result := PChar(Language.Translate(string(Name)));
-end; }
-
-//Procedure to Print Text
-procedure Print(const Style, Size: byte; const X, Y: real; const Text: PChar);
-begin
- SetFontItalic ((Style and 128) = 128);
- SetFontStyle(Style and 7);
- // FIXME: FONTSIZE
- // used by Hold_The_Line / TeamDuell
- SetFontSize(Size);
- SetFontPos (X, Y);
- glPrint (Language.Translate(string(Text)));
-end;
-
-//Procedure that loads a Custom Sound
-function LoadSound(const Name: PChar): cardinal;
-var
- Stream: TAudioPlaybackStream;
- i: integer;
- Filename: string;
-begin
- //Search for Sound in already loaded Sounds
- Filename := UpperCase(SoundPath + Name);
- for i := 0 to High(CustomSounds) do
- begin
- if (UpperCase(CustomSounds[i].Filename) = Filename) then
- begin
- Result := i;
- Exit;
- end;
- end;
-
- Stream := AudioPlayback.OpenSound(SoundPath + string(Name));
- if (Stream = nil) then
- begin
- Result := 0;
- Exit;
- end;
-
- SetLength(CustomSounds, Length(CustomSounds)+1);
- CustomSounds[High(CustomSounds)].Stream := Stream;
- Result := High(CustomSounds);
-end;
-
-//Plays a Custom Sound
-procedure PlaySound(const Index: cardinal);
-begin
- if (Index <= High(CustomSounds)) then
- AudioPlayback.PlaySound(CustomSounds[Index].Stream);
-end;
-
-end.
-
diff --git a/cmake/src/screens/UScreenSong.pas b/cmake/src/screens/UScreenSong.pas
index fa3c836e..6b83d522 100644
--- a/cmake/src/screens/UScreenSong.pas
+++ b/cmake/src/screens/UScreenSong.pas
@@ -38,6 +38,7 @@ uses
SDL,
UCommon,
UDisplay,
+ UPath,
UFiles,
UIni,
ULanguage,
@@ -56,6 +57,11 @@ type
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
+
procedure StartMusicPreview();
procedure StopMusicPreview();
public
@@ -75,7 +81,6 @@ type
HighSpeed: boolean;
CoverFull: boolean;
CoverTime: real;
- MusicPreviewTimer: PSDL_TimerID;
CoverX: integer;
CoverY: integer;
@@ -118,19 +123,19 @@ type
procedure SetScroll4;
procedure SetScroll5;
procedure SetScroll6;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
+ 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 onHide; override;
+ procedure OnShow; 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: string);// Show Custom Text 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;
@@ -141,9 +146,12 @@ type
//procedures for Menu
procedure StartSong;
procedure OpenEditor;
- procedure DoJoker(Team: byte);
+ 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
@@ -156,7 +164,6 @@ uses
Math,
gl,
UCovers,
- UDLLManager,
UGraphic,
UMain,
UMenuButton,
@@ -164,7 +171,8 @@ uses
UParty,
UPlaylist,
UScreenSongMenu,
- USkins;
+ USkins,
+ UUnicodeUtils;
// ***** Public methods ****** //
@@ -211,11 +219,11 @@ begin
end;
//Show Wrong Song when Tabs on Fix End
-procedure TScreenSong.ShowCatTLCustom(Caption: string);// Show Custom Text in Top left
+procedure TScreenSong.ShowCatTLCustom(Caption: UTF8String);// Show Custom Text in Top left
begin
Text[TextCat].Text := Caption;
Text[TextCat].Visible := true;
- Static[StaticCat].Visible := false;
+ Statics[StaticCat].Visible := false;
end;
//Show Cat in Top Left Mod
@@ -223,18 +231,18 @@ procedure TScreenSong.ShowCatTL(Cat: integer);
begin
//Change
Text[TextCat].Text := CatSongs.Song[Cat].Artist;
- Static[StaticCat].Texture := Texture.GetTexture(Button[Cat].Texture.Name, TEXTURE_TYPE_PLAIN, true);
+ //Statics[StaticCat].Texture := Texture.GetTexture(Button[Cat].Texture.Name, TEXTURE_TYPE_PLAIN, true);
//Show
Text[TextCat].Visible := true;
- Static[StaticCat].Visible := true;
+ Statics[StaticCat].Visible := true;
end;
procedure TScreenSong.HideCatTL;
begin
//Hide
//Text[TextCat].Visible := false;
- Static[StaticCat].Visible := false;
+ Statics[StaticCat].Visible := false;
//New -> Show Text specified in Theme
Text[TextCat].Visible := true;
Text[TextCat].Text := Theme.Song.TextCat.Text;
@@ -243,12 +251,13 @@ 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: WideChar; PressedDown: boolean): boolean;
+function TScreenSong.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
var
I: integer;
I2: integer;
SDL_ModState: word;
- Letter: WideChar;
+ UpperLetter: UCS4Char;
+ TempStr: UTF8String;
begin
Result := true;
@@ -273,9 +282,10 @@ begin
//Jump to Artist/Titel
if ((SDL_ModState and KMOD_LALT <> 0) and (Mode = smNormal)) then
begin
- if (WideCharUpperCase(CharCode)[1] in ([WideChar('A')..WideChar('Z'), WideChar('0') .. WideChar('9')]) ) then
+ UpperLetter := UCS4UpperCase(CharCode);
+
+ if (UpperLetter in ([Ord('A')..Ord('Z'), Ord('0') .. Ord('9')]) ) then
begin
- Letter := WideCharUpperCase(CharCode)[1];
I2 := Length(CatSongs.Song);
//Jump To Titel
@@ -283,18 +293,20 @@ begin
begin
for I := 1 to High(CatSongs.Song) do
begin
- if (CatSongs.Song[(I + Interaction) mod I2].Visible) and
- (Length(CatSongs.Song[(I + Interaction) mod I2].Title)>0) and
- (WideStringUpperCase(CatSongs.Song[(I + Interaction) mod I2].Title)[1] = Letter) then
+ if (CatSongs.Song[(I + Interaction) mod I2].Visible) then
begin
- SkipTo(CatSongs.VisibleIndex((I + Interaction) mod I2));
+ 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);
+ AudioPlayback.PlaySound(SoundLib.Change);
- ChangeMusic;
- SetScroll4;
- //Break and Exit
- Exit;
+ SetScroll4;
+ //Break and Exit
+ Exit;
+ end;
end;
end;
end
@@ -303,19 +315,21 @@ begin
begin
for I := 1 to High(CatSongs.Song) do
begin
- if (CatSongs.Song[(I + Interaction) mod I2].Visible) and
- (Length(CatSongs.Song[(I + Interaction) mod I2].Artist)>0) and
- (WideStringUpperCase(CatSongs.Song[(I + Interaction) mod I2].Artist)[1] = Letter) then
+ if (CatSongs.Song[(I + Interaction) mod I2].Visible) then
begin
- SkipTo(CatSongs.VisibleIndex((I + Interaction) mod I2));
+ 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);
+ AudioPlayback.PlaySound(SoundLib.Change);
- ChangeMusic;
- SetScroll4;
+ SetScroll4;
- //Break and Exit
- Exit;
+ //Break and Exit
+ Exit;
+ end;
end;
end;
end;
@@ -324,15 +338,22 @@ begin
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 WideCharUpperCase(CharCode)[1] of
- 'Q':
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'):
begin
Result := false;
Exit;
end;
- 'M': //Show SongMenu
+ Ord('M'): //Show SongMenu
begin
if (Songs.SongList.Count > 0) then
begin
@@ -342,41 +363,41 @@ begin
begin
if CatSongs.CatNumShow = -3 then
begin
- ScreenSongMenu.onShow;
+ ScreenSongMenu.OnShow;
ScreenSongMenu.MenuShow(SM_Playlist);
end
else
begin
- ScreenSongMenu.onShow;
+ ScreenSongMenu.OnShow;
ScreenSongMenu.MenuShow(SM_Main);
end;
end
else
begin
- ScreenSongMenu.onShow;
+ ScreenSongMenu.OnShow;
ScreenSongMenu.MenuShow(SM_Playlist_Load);
end;
end //Party Mode -> Show Party Menu
else
begin
- ScreenSongMenu.onShow;
+ ScreenSongMenu.OnShow;
ScreenSongMenu.MenuShow(SM_Party_Main);
end;
end;
Exit;
end;
- 'P': //Show Playlist Menu
+ Ord('P'): //Show Playlist Menu
begin
if (Songs.SongList.Count > 0) and (Mode = smNormal) then
begin
- ScreenSongMenu.onShow;
+ ScreenSongMenu.OnShow;
ScreenSongMenu.MenuShow(SM_Playlist_Load);
end;
Exit;
end;
- 'J': //Show Jumpto Menu
+ Ord('J'): //Show Jumpto Menu
begin
if (Songs.SongList.Count > 0) and (Mode = smNormal) then
begin
@@ -385,13 +406,13 @@ begin
Exit;
end;
- 'E':
+ Ord('E'):
begin
OpenEditor;
Exit;
end;
- 'R':
+ Ord('R'):
begin
if (Songs.SongList.Count > 0) and
(Mode = smNormal) then
@@ -464,7 +485,6 @@ begin
end;
AudioPlayback.PlaySound(SoundLib.Change);
- ChangeMusic;
SetScroll4;
end;
Exit;
@@ -505,7 +525,7 @@ begin
//Show Wrong Song when Tabs on Fix
SelectNext;
FixSelected;
- //SelectPrev;
+ //SelectPrev(true);
//CatSongs.Song[0].Visible := false;
end
else
@@ -515,7 +535,7 @@ begin
if (CatSongs.CatNumShow < -1) then
begin
//Atm: Set Empty Filter
- CatSongs.SetFilter('', 0);
+ CatSongs.SetFilter('', fltAll);
//Show Cat in Top Left Mod
HideCatTL;
@@ -524,8 +544,6 @@ begin
//Show Wrong Song when Tabs on Fix
SelectNext;
FixSelected;
-
- ChangeMusic;
end
else
begin
@@ -564,9 +582,6 @@ begin
//Show Wrong Song when Tabs on Fix
SelectNext;
FixSelected;
-
- //Play Music:
- ChangeMusic;
end
else
begin // clicked on song
@@ -589,7 +604,7 @@ begin
if (Ini.PartyPopup = 1) then
ScreenSongMenu.MenuShow(SM_Party_Main)
else
- ScreenSong.StartSong;
+ Party.CallAfterSongSelect;
end;
end;
end;
@@ -627,8 +642,6 @@ begin
//Play Music:
AudioPlayback.PlaySound(SoundLib.Change);
- ChangeMusic;
-
end;
//
@@ -671,7 +684,6 @@ begin
//Play Music:
AudioPlayback.PlaySound(SoundLib.Change);
- ChangeMusic;
end;
end;
//Cat Change Hack End}
@@ -684,9 +696,6 @@ begin
begin
AudioPlayback.PlaySound(SoundLib.Change);
SelectNext;
- //InteractNext;
- //SongTarget := Interaction;
- ChangeMusic;
SetScroll4;
end;
end;
@@ -697,65 +706,116 @@ begin
begin
AudioPlayback.PlaySound(SoundLib.Change);
SelectPrev;
- ChangeMusic;
SetScroll4;
end;
end;
SDLK_1:
begin //Joker
- if (Mode = smPartyMode) and (PartySession.Teams.NumTeams >= 1) and (PartySession.Teams.Teaminfo[0].Joker > 0) then
- begin
- //Use Joker
- Dec(PartySession.Teams.Teaminfo[0].Joker);
- SelectRandomSong;
- SetJoker;
- end;
+ DoJoker(0);
end;
SDLK_2:
begin //Joker
- if (Mode = smPartyMode) and (PartySession.Teams.NumTeams >= 2) and (PartySession.Teams.Teaminfo[1].Joker > 0) then
- begin
- //Use Joker
- Dec(PartySession.Teams.Teaminfo[1].Joker);
- SelectRandomSong;
- SetJoker;
- end;
+ DoJoker(1);
end;
SDLK_3:
begin //Joker
- if (Mode = smPartyMode) and (PartySession.Teams.NumTeams >= 3) and (PartySession.Teams.Teaminfo[2].Joker > 0) then
- begin
- //Use Joker
- Dec(PartySession.Teams.Teaminfo[2].Joker);
- SelectRandomSong;
- SetJoker;
- end;
+ 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 RightMbESC and (MouseButton = SDL_BUTTON_RIGHT) and BtnDown then
- //if RightMbESC is set, send ESC keypress
- Result:=ParseInput(SDLK_ESCAPE, #0, 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)
- //song scrolling with mousewheel
- if (MouseButton = SDL_BUTTON_WHEELDOWN) and BtnDown then
- ParseInput(SDLK_RIGHT, #0, true);
+ else if (MouseButton = SDL_BUTTON_WHEELUP) then
+ ParseInput(SDLK_LEFT, 0, true)
- if (MouseButton = SDL_BUTTON_WHEELUP) and BtnDown 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);
- //LMB anywhere starts
- if (MouseButton = SDL_BUTTON_LEFT) and BtnDown then
- ParseInput(SDLK_RETURN, #0, true);
+ 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;
@@ -824,8 +884,8 @@ begin
Equalizer := Tms_Equalizer.Create(AudioPlayback, Theme.Song.Equalizer);
- if (Length(CatSongs.Song) > 0) then
- Interaction := 0;
+ PreviewOpened := -1;
+ isScrolling := false;
end;
procedure TScreenSong.GenerateThumbnails();
@@ -833,9 +893,9 @@ var
I: integer;
CoverButtonIndex: integer;
CoverButton: TButton;
- CoverName: string;
CoverTexture: TTexture;
Cover: TCover;
+ CoverFile: IPath;
Song: TSong;
begin
if (Length(CatSongs.Song) <= 0) then
@@ -850,7 +910,7 @@ begin
CoverButton := nil;
// create a clickable cover
- CoverButtonIndex := AddButton(300 + I*250, 140, 200, 200, '', TEXTURE_TYPE_PLAIN, Theme.Song.Cover.Reflections);
+ 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
@@ -858,19 +918,17 @@ begin
Song := CatSongs.Song[I];
- // if cover-image is not found then show 'no cover'
- if (not FileExists(Song.Path + Song.Cover)) then
- Song.Cover := '';
+ CoverFile := Song.Path.Append(Song.Cover);
+ if (not CoverFile.IsFile()) then
+ Song.Cover := PATH_NONE;
- if (Song.Cover = '') then
- CoverName := Skin.GetTextureFileName('SongCover')
- else
- CoverName := Song.Path + Song.Cover;
+ if (Song.Cover.IsUnset) then
+ CoverFile := Skin.GetTextureFileName('SongCover');
// load cover and cache its texture
- Cover := Covers.FindCover(CoverName);
+ Cover := Covers.FindCover(CoverFile);
if (Cover = nil) then
- Cover := Covers.AddCover(CoverName);
+ Cover := Covers.AddCover(CoverFile);
// use the cached texture
// TODO: this is a workaround until the new song-loading works.
@@ -883,10 +941,39 @@ 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;
+ end;
+
+ // fade in detailed cover
+ CoverTime := 0;
+end;
+
+{ called before current song is deselected }
+procedure TScreenSong.OnSongDeSelect;
+begin
+ CoverTime := 10;
+ UnLoadDetailedCover;
+
+ StopMusicPreview();
+ PreviewOpened := -1;
end;
procedure TScreenSong.SetScroll;
@@ -899,18 +986,13 @@ begin
// Set Positions
case Theme.Song.Cover.Style of
3: SetScroll3;
- 5:begin
- if VS > 5 then
- SetScroll5
- else
- SetScroll4;
- end;
+ 5: SetScroll5;
6: SetScroll6;
else SetScroll4;
end;
// Set visibility of video icon
- Static[VideoIcon].Visible := (CatSongs.Song[Interaction].Video <> '');
+ Statics[VideoIcon].Visible := CatSongs.Song[Interaction].Video.IsSet;
// Set texts
Text[TextArtist].Text := CatSongs.Song[Interaction].Artist;
@@ -944,8 +1026,6 @@ end;
procedure TScreenSong.SetScroll1;
var
B: integer; // button
- //BMin: integer; // button min // Auto Removed, Unused Variable
- //BMax: integer; // button max // Auto Removed, Unused Variable
Src: integer;
//Dst: integer;
Count: integer; // Dst is not used. Count is used.
@@ -1097,7 +1177,7 @@ begin
end;
if Length(Button) > 0 then
- Static[1].Texture.Y := Button[Interaction].Y - 5; // selection texture
+ Statics[1].Texture.Y := Button[Interaction].Y - 5; // selection texture
end;
procedure TScreenSong.SetScroll2;
@@ -1251,7 +1331,7 @@ begin
// Use an alternate position for the five front covers.
if (Abs(Pos) < 2.5) then
begin
- Angle := Pi * (Pos / 5); // Range: (-1/4*Pi .. +1/4*Pi)
+ 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;
@@ -1265,14 +1345,25 @@ begin
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
- else
+ { 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..-1/2, +1/2..+1]
+ // 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/VS - 0.5
+ Pos := (Pos - 2 + ceil(VS/2))/8 - 0.75
else
- Pos := Pos/VS + 0.5;
+ Pos := (Pos + 2 - floor(VS/2))/8 + 0.75;
// angle in radians [-2Pi..-Pi, +Pi..+2Pi]
Angle := 2*Pi * Pos;
@@ -1286,9 +1377,14 @@ begin
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;
+ end
+ { all other covers are not visible }
+ else
+ Button[B].Visible := false;
end;
end;
end;
@@ -1399,7 +1495,7 @@ begin
end;
end;
-procedure TScreenSong.onShow;
+procedure TScreenSong.OnShow;
begin
inherited;
{**
@@ -1408,6 +1504,7 @@ begin
SoundLib.PauseBgMusic;
AudioPlayback.Stop;
+ PreviewOpened := -1;
if Ini.Players <= 3 then PlayersPlay := Ini.Players + 1;
if Ini.Players = 4 then PlayersPlay := 6;
@@ -1423,10 +1520,6 @@ begin
if Length(CatSongs.Song) > 0 then
begin
- //Load Music only when Song Preview is activated
- if ( Ini.PreviewVolume <> 0 ) then
- StartMusicPreview();
-
SetScroll;
end;
@@ -1437,7 +1530,6 @@ begin
if (CatSongs.CatNumShow = -3) then
begin
SelectNext;
- ChangeMusic;
end;
end
//Party Mode
@@ -1452,25 +1544,18 @@ begin
end;
end;
+ isScrolling := true;
SetJoker;
SetStatics;
end;
-procedure TScreenSong.onHide;
+procedure TScreenSong.OnHide;
begin
// turn music volume to 100%
AudioPlayback.SetVolume(1.0);
- // if preview is deactivated: load musicfile now
- if (IPreviewVolumeVals[Ini.PreviewVolume] = 0) then
- AudioPlayback.Open(CatSongs.Song[Interaction].Path + CatSongs.Song[Interaction].Mp3);
-
- // if hide then stop music (for party mode popup on exit)
- if (Display.NextScreen <> @ScreenSing) and
- (Display.NextScreen <> @ScreenSingModi) then
- begin
- StopMusicPreview();
- end;
+ // stop preview
+ StopMusicPreview();
end;
procedure TScreenSong.DrawExtensions;
@@ -1492,13 +1577,23 @@ var
dt: real;
I: integer;
begin
- dx := SongTarget-SongCurrent;
- dt := TimeSkip * 7;
+ if isScrolling then
+ begin
+ dx := SongTarget-SongCurrent;
+ dt := TimeSkip * 7;
- if dt > 1 then
- dt := 1;
-
- SongCurrent := SongCurrent + dx*dt;
+ 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
@@ -1552,8 +1647,8 @@ begin
Button[I].Draw;
// Statics
- for I := 0 to Length(Static) - 1 do
- Static[I].Draw;
+ for I := 0 to Length(Statics) - 1 do
+ Statics[I].Draw;
// and texts
for I := 0 to Length(Text) - 1 do
@@ -1575,7 +1670,11 @@ begin
if VS > 0 then
begin
- UnLoadDetailedCover;
+ if (not isScrolling) and (VS > 0) then
+ begin
+ isScrolling := true;
+ OnSongDeselect;
+ end;
Skip := 1;
@@ -1610,7 +1709,11 @@ begin
if VS > 0 then
begin
- UnLoadDetailedCover;
+ if (not isScrolling) and (VS > 0) then
+ begin
+ isScrolling := true;
+ OnSongDeselect;
+ end;
Skip := 1;
@@ -1638,12 +1741,21 @@ var
begin
AudioPlayback.Close();
+ if CatSongs.VisibleSongs = 0 then
+ Exit;
+
Song := CatSongs.Song[Interaction];
if not assigned(Song) then
Exit;
- if AudioPlayback.Open(Song.Path + Song.Mp3) then
+ //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;
+
AudioPlayback.Position := AudioPlayback.Length / 4;
// set preview volume
if (Ini.PreviewFading = 0) then
@@ -1663,51 +1775,22 @@ end;
procedure TScreenSong.StopMusicPreview();
begin
- // Cancel pending preview requests
- SDL_RemoveTimer(MusicPreviewTimer);
-
// Stop preview of previous song
AudioPlayback.Stop;
end;
-procedure StartMusicPreview(data: Pointer);
-var
- ScreenSong: TScreenSong;
-begin
- ScreenSong := TScreenSong(data);
- if (ScreenSong <> nil) then
- ScreenSong.StartMusicPreview();
-end;
-
-function MusicPreviewTimerCallback(interval: UInt32; param: Pointer): UInt32; cdecl;
-begin
- // delegate execution to main-thread
- MainThreadExec(@StartMusicPreview, param);
- // stop timer
- Result := 0;
-end;
-
// Changes previewed song
procedure TScreenSong.ChangeMusic;
begin
StopMusicPreview();
-
- // Preview song if activated and current selection is not a category cover
- if (CatSongs.VisibleSongs > 0) and
- (not CatSongs.Song[Interaction].Main) and
- (Ini.PreviewVolume <> 0) then
- begin
- // Delay song fading to prevent the song from being played while scrolling
- MusicPreviewTimer := SDL_AddTimer(200, MusicPreviewTimerCallback, Self);
- end;
+ PreviewOpened := -1;
+ StartMusicPreview();
end;
procedure TScreenSong.SkipTo(Target: cardinal);
var
i: integer;
begin
- UnLoadDetailedCover;
-
Interaction := High(CatSongs.Song);
SongTarget := 0;
@@ -1776,7 +1859,6 @@ begin
end;
AudioPlayback.PlaySound(SoundLib.Change);
- ChangeMusic;
SetScroll;
end;
@@ -1785,76 +1867,76 @@ begin
// If Party Mode
if Mode = smPartyMode then //Show Joker that are available
begin
- if (PartySession.Teams.NumTeams >= 1) then
+ if (Length(Party.Teams) >= 1) then
begin
- Static[StaticTeam1Joker1].Visible := (PartySession.Teams.Teaminfo[0].Joker >= 1);
- Static[StaticTeam1Joker2].Visible := (PartySession.Teams.Teaminfo[0].Joker >= 2);
- Static[StaticTeam1Joker3].Visible := (PartySession.Teams.Teaminfo[0].Joker >= 3);
- Static[StaticTeam1Joker4].Visible := (PartySession.Teams.Teaminfo[0].Joker >= 4);
- Static[StaticTeam1Joker5].Visible := (PartySession.Teams.Teaminfo[0].Joker >= 5);
+ 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
- Static[StaticTeam1Joker1].Visible := false;
- Static[StaticTeam1Joker2].Visible := false;
- Static[StaticTeam1Joker3].Visible := false;
- Static[StaticTeam1Joker4].Visible := false;
- Static[StaticTeam1Joker5].Visible := false;
+ Statics[StaticTeam1Joker1].Visible := false;
+ Statics[StaticTeam1Joker2].Visible := false;
+ Statics[StaticTeam1Joker3].Visible := false;
+ Statics[StaticTeam1Joker4].Visible := false;
+ Statics[StaticTeam1Joker5].Visible := false;
end;
- if (PartySession.Teams.NumTeams >= 2) then
+ if (Length(Party.Teams) >= 2) then
begin
- Static[StaticTeam2Joker1].Visible := (PartySession.Teams.Teaminfo[1].Joker >= 1);
- Static[StaticTeam2Joker2].Visible := (PartySession.Teams.Teaminfo[1].Joker >= 2);
- Static[StaticTeam2Joker3].Visible := (PartySession.Teams.Teaminfo[1].Joker >= 3);
- Static[StaticTeam2Joker4].Visible := (PartySession.Teams.Teaminfo[1].Joker >= 4);
- Static[StaticTeam2Joker5].Visible := (PartySession.Teams.Teaminfo[1].Joker >= 5);
+ 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
- Static[StaticTeam2Joker1].Visible := false;
- Static[StaticTeam2Joker2].Visible := false;
- Static[StaticTeam2Joker3].Visible := false;
- Static[StaticTeam2Joker4].Visible := false;
- Static[StaticTeam2Joker5].Visible := false;
+ Statics[StaticTeam2Joker1].Visible := false;
+ Statics[StaticTeam2Joker2].Visible := false;
+ Statics[StaticTeam2Joker3].Visible := false;
+ Statics[StaticTeam2Joker4].Visible := false;
+ Statics[StaticTeam2Joker5].Visible := false;
end;
- if (PartySession.Teams.NumTeams >= 3) then
+ if (Length(Party.Teams) >= 3) then
begin
- Static[StaticTeam3Joker1].Visible := (PartySession.Teams.Teaminfo[2].Joker >= 1);
- Static[StaticTeam3Joker2].Visible := (PartySession.Teams.Teaminfo[2].Joker >= 2);
- Static[StaticTeam3Joker3].Visible := (PartySession.Teams.Teaminfo[2].Joker >= 3);
- Static[StaticTeam3Joker4].Visible := (PartySession.Teams.Teaminfo[2].Joker >= 4);
- Static[StaticTeam3Joker5].Visible := (PartySession.Teams.Teaminfo[2].Joker >= 5);
+ 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
- Static[StaticTeam3Joker1].Visible := false;
- Static[StaticTeam3Joker2].Visible := false;
- Static[StaticTeam3Joker3].Visible := false;
- Static[StaticTeam3Joker4].Visible := false;
- Static[StaticTeam3Joker5].Visible := false;
+ 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
- Static[StaticTeam1Joker1].Visible := false;
- Static[StaticTeam1Joker2].Visible := false;
- Static[StaticTeam1Joker3].Visible := false;
- Static[StaticTeam1Joker4].Visible := false;
- Static[StaticTeam1Joker5].Visible := false;
-
- Static[StaticTeam2Joker1].Visible := false;
- Static[StaticTeam2Joker2].Visible := false;
- Static[StaticTeam2Joker3].Visible := false;
- Static[StaticTeam2Joker4].Visible := false;
- Static[StaticTeam2Joker5].Visible := false;
-
- Static[StaticTeam3Joker1].Visible := false;
- Static[StaticTeam3Joker2].Visible := false;
- Static[StaticTeam3Joker3].Visible := false;
- Static[StaticTeam3Joker4].Visible := false;
- Static[StaticTeam3Joker5].Visible := false;
+ 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;
@@ -1867,7 +1949,7 @@ begin
Visible := (Mode = smPartyMode);
for I := 0 to High(StaticParty) do
- Static[StaticParty[I]].Visible := Visible;
+ Statics[StaticParty[I]].Visible := Visible;
for I := 0 to High(TextParty) do
Text[TextParty[I]].Visible := Visible;
@@ -1876,7 +1958,7 @@ begin
Visible := not Visible;
for I := 0 to High(StaticNonParty) do
- Static[StaticNonParty[I]].Visible := Visible;
+ Statics[StaticNonParty[I]].Visible := Visible;
for I := 0 to High(TextNonParty) do
Text[TextNonParty[I]].Visible := Visible;
@@ -1892,7 +1974,7 @@ begin
//Party Mode
if (Mode = smPartyMode) then
begin
- FadeTo(@ScreenSingModi);
+ FadeTo(@ScreenSing);
end
else
begin
@@ -1923,14 +2005,14 @@ begin
end;
//Team No of Team (0-5)
-procedure TScreenSong.DoJoker (Team: byte);
+procedure TScreenSong.DoJoker (Team: integer);
begin
if (Mode = smPartyMode) and
- (PartySession.Teams.NumTeams >= Team + 1) and
- (PartySession.Teams.Teaminfo[Team].Joker > 0) then
+ (High(Party.Teams) >= Team) and
+ (Party.Teams[Team].JokersLeft > 0) then
begin
//Use Joker
- Dec(PartySession.Teams.Teaminfo[Team].Joker);
+ Dec(Party.Teams[Team].JokersLeft);
SelectRandomSong;
SetJoker;
end;
@@ -1939,8 +2021,6 @@ end;
//Detailed Cover Unloading. Unloads the Detailed, uncached Cover of the cur. Song
procedure TScreenSong.UnloadDetailedCover;
begin
- CoverTime := 0;
-
// show cached texture
Button[Interaction].Texture := Texture.GetTexture(Button[Interaction].Texture.Name, TEXTURE_TYPE_PLAIN, true);
Button[Interaction].Texture2.Alpha := 0;
@@ -1955,7 +2035,7 @@ begin
CatSongs.Refresh;
CatSongs.ShowCategoryList;
Interaction := 0;
- SelectNext;
+ SelectNext(true);
FixSelected;
}
end;
diff --git a/cmake/src/screens/UScreenSongJumpto.pas b/cmake/src/screens/UScreenSongJumpto.pas
index e55a6276..b3d48679 100644
--- a/cmake/src/screens/UScreenSongJumpto.pas
+++ b/cmake/src/screens/UScreenSongJumpto.pas
@@ -34,42 +34,39 @@ interface
{$I switches.inc}
uses
- UMenu,
SDL,
+ SysUtils,
+ UMenu,
UDisplay,
UMusic,
UFiles,
- SysUtils,
+ USongs,
UThemes;
type
TScreenSongJumpto = class(TMenu)
private
//For ChangeMusic
- LastPlayed: integer;
- VisibleBool: boolean;
- public
- VisSongs: integer;
+ fLastPlayed: integer;
+ fVisible: boolean;
+ fSelectType: TSongFilter;
+ fVisSongs: integer;
- constructor Create; override;
+ procedure SetTextFound(Count: Cardinal);
//Visible //Whether the Menu should be Drawn
//Whether the Menu should be Drawn
procedure SetVisible(Value: boolean);
- property Visible: boolean read VisibleBool write SetVisible;
+ public
+ constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
- procedure onShow; override;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+ procedure OnShow; override;
function Draw: boolean; override;
- procedure SetTextFound(const Count: cardinal);
+ property Visible: boolean read fVisible write SetVisible;
end;
-var
- IType: array [0..2] of string;
- SelectType: integer;
-
-
implementation
uses
@@ -79,26 +76,24 @@ uses
UTexture,
ULanguage,
UParty,
- USongs,
UScreenSong,
- ULog;
+ ULog,
+ UUnicodeUtils;
-function TScreenSongJumpto.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+function TScreenSongJumpto.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
begin
Result := true;
if (PressedDown) then
begin // Key Down
// check normal keys
- case CharCode of
- '0'..'9', 'a'..'z', 'A'..'Z', ' ', '-', '_', '!', ',', '<', '/', '*', '?', '''', '"',
- '[', '{', ';', ':':
- begin
- if Interaction = 0 then
- begin
- Button[0].Text[0].Text := Button[0].Text[0].Text + CharCode;
- SetTextFound(CatSongs.SetFilter(Button[0].Text[0].Text, SelectType));
- end;
- end;
+ 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
@@ -107,8 +102,8 @@ begin
begin
if (Interaction = 0) and (Length(Button[0].Text[0].Text) > 0) then
begin
- Button[0].Text[0].DeleteLastL;
- SetTextFound(CatSongs.SetFilter(Button[0].Text[0].Text, SelectType));
+ Button[0].Text[0].DeleteLastLetter();
+ SetTextFound(CatSongs.SetFilter(Button[0].Text[0].Text, fSelectType));
end;
end;
@@ -117,18 +112,15 @@ begin
begin
Visible := false;
AudioPlayback.PlaySound(SoundLib.Back);
- if (VisSongs = 0) and (Length(Button[0].Text[0].Text) > 0) then
+ if (fVisSongs = 0) and (Length(Button[0].Text[0].Text) > 0) then
begin
ScreenSong.UnLoadDetailedCover;
Button[0].Text[0].Text := '';
- CatSongs.SetFilter('', 0);
+ CatSongs.SetFilter('', fltAll);
SetTextFound(0);
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:
begin
{SelectNext;
@@ -146,7 +138,7 @@ begin
Interaction := 1;
InteractInc;
if (Length(Button[0].Text[0].Text) > 0) then
- SetTextFound(CatSongs.SetFilter(Button[0].Text[0].Text, SelectType));
+ SetTextFound(CatSongs.SetFilter(Button[0].Text[0].Text, fSelectType));
Interaction := 0;
end;
SDLK_LEFT:
@@ -154,7 +146,7 @@ begin
Interaction := 1;
InteractDec;
if (Length(Button[0].Text[0].Text) > 0) then
- SetTextFound(CatSongs.SetFilter(Button[0].Text[0].Text, SelectType));
+ SetTextFound(CatSongs.SetFilter(Button[0].Text[0].Text, fSelectType));
Interaction := 0;
end;
end;
@@ -162,8 +154,6 @@ begin
end;
constructor TScreenSongJumpto.Create;
-//var
-// I: integer; // Auto Removed, Unused Variable
begin
inherited Create;
@@ -175,23 +165,23 @@ begin
if (Length(Button[0].Text) = 0) then
AddButtonText(14, 20, '');
- SelectType := 0;
- AddSelectSlide(Theme.SongJumpto.SelectSlideType, SelectType, Theme.SongJumpto.IType);
+ fSelectType := fltAll;
+ AddSelectSlide(Theme.SongJumpto.SelectSlideType, PInteger(@fSelectType)^, Theme.SongJumpto.IType);
Interaction := 0;
- LastPlayed := 0;
+ fLastPlayed := 0;
end;
procedure TScreenSongJumpto.SetVisible(Value: boolean);
begin
-//If change from unvisible to Visible then OnShow
- if (VisibleBool = false) and (Value = true) then
+//If change from invisible to Visible then OnShow
+ if (fVisible = false) and (Value = true) then
OnShow;
- VisibleBool := Value;
+ fVisible := Value;
end;
-procedure TScreenSongJumpto.onShow;
+procedure TScreenSongJumpto.OnShow;
begin
inherited;
@@ -208,7 +198,7 @@ begin
Interaction := 0;
Button[0].Text[0].Selected := true;
- LastPlayed := ScreenSong.Interaction;
+ fLastPlayed := ScreenSong.Interaction;
end;
function TScreenSongJumpto.Draw: boolean;
@@ -216,7 +206,7 @@ begin
Result := inherited Draw;
end;
-procedure TScreenSongJumpto.SetTextFound(const Count: cardinal);
+procedure TScreenSongJumpto.SetTextFound(Count: cardinal);
begin
if (Count = 0) then
begin
@@ -235,7 +225,7 @@ begin
end;
//Set visSongs
- VisSongs := Count;
+ fVisSongs := Count;
//Fix SongSelection
ScreenSong.Interaction := high(CatSongs.Song);
@@ -243,9 +233,12 @@ begin
ScreenSong.FixSelected;
//Play Correct Music
- if (ScreenSong.Interaction <> LastPlayed) then
+ if (ScreenSong.Interaction <> fLastPlayed) or (CatSongs.VisibleSongs = 0) then
begin
- LastPlayed := ScreenSong.Interaction;
+ if (CatSongs.VisibleSongs > 0) then
+ fLastPlayed := ScreenSong.Interaction
+ else
+ fLastPlayed := -1;
ScreenSong.ChangeMusic;
end;
diff --git a/cmake/src/screens/UScreenSongMenu.pas b/cmake/src/screens/UScreenSongMenu.pas
index 0af94a8f..173ac2c8 100644
--- a/cmake/src/screens/UScreenSongMenu.pas
+++ b/cmake/src/screens/UScreenSongMenu.pas
@@ -50,8 +50,8 @@ type
Visible: boolean; // whether the menu should be drawn
constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
- procedure onShow; override;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+ procedure OnShow; override;
function Draw: boolean; override;
procedure MenuShow(sMenu: byte);
procedure HandleReturn;
@@ -73,7 +73,7 @@ const
SM_Party_Joker = 128 or 2;
var
- ISelections: array of string;
+ ISelections: array of UTF8String;
SelectValue: integer;
implementation
@@ -86,9 +86,10 @@ uses
ULanguage,
UParty,
UPlaylist,
- USongs;
+ USongs,
+ UUnicodeUtils;
-function TScreenSongMenu.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+function TScreenSongMenu.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
begin
Result := true;
if (PressedDown) then
@@ -96,27 +97,29 @@ begin
if (CurMenu = SM_Playlist_New) and (Interaction=0) then
begin
// check normal keys
- case WideCharUpperCase(CharCode)[1] of
- '0'..'9', 'A'..'Z', ' ', '-', '_', '!', ',', '<', '/', '*', '?', '''', '"':
- begin
- Button[Interaction].Text[0].Text := Button[Interaction].Text[0].Text + CharCode;
- exit;
- end;
+ 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].DeleteLastL;
+ Button[Interaction].Text[0].DeleteLastLetter;
exit;
end;
end;
end;
// check normal keys
- case WideCharUpperCase(CharCode)[1] of
- 'Q':
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'):
begin
Result := false;
Exit;
@@ -223,7 +226,7 @@ begin
Result := inherited Draw;
end;
-procedure TScreenSongMenu.onShow;
+procedure TScreenSongMenu.OnShow;
begin
inherited;
end;
@@ -398,16 +401,19 @@ begin
begin
CurMenu := sMenu;
Text[0].Text := Language.Translate('SONG_MENU_NAME_PARTY_JOKER');
-
- Button[0].Visible := (PartySession.Teams.NumTeams >= 1) and (PartySession.Teams.Teaminfo[0].Joker > 0);
- Button[1].Visible := (PartySession.Teams.NumTeams >= 2) and (PartySession.Teams.Teaminfo[1].Joker > 0);
- Button[2].Visible := (PartySession.Teams.NumTeams >= 3) and (PartySession.Teams.Teaminfo[2].Joker > 0);
- Button[3].Visible := true;
- SelectsS[0].Visible := false;
-
- Button[0].Text[0].Text := string(PartySession.Teams.Teaminfo[0].Name);
- Button[1].Text[0].Text := string(PartySession.Teams.Teaminfo[1].Name);
- Button[2].Text[0].Text := string(PartySession.Teams.Teaminfo[2].Name);
+ // 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
@@ -611,7 +617,7 @@ begin
0: // button 1
begin
// start singing
- ScreenSong.StartSong;
+ Party.CallAfterSongSelect;
Visible := false;
end;
diff --git a/cmake/src/screens/UScreenStatDetail.pas b/cmake/src/screens/UScreenStatDetail.pas
index bbbb4a1b..1638cd85 100644
--- a/cmake/src/screens/UScreenStatDetail.pas
+++ b/cmake/src/screens/UScreenStatDetail.pas
@@ -55,8 +55,8 @@ type
TotPages: cardinal;
constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
- procedure onShow; override;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+ procedure OnShow; override;
procedure SetAnimationProgress(Progress: real); override;
procedure SetTitle;
@@ -66,20 +66,21 @@ type
implementation
uses
- UGraphic,
- ULanguage,
Math,
Classes,
- ULog;
+ UGraphic,
+ ULanguage,
+ ULog,
+ UUnicodeUtils;
-function TScreenStatDetail.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+function TScreenStatDetail.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
begin
Result := true;
if (PressedDown) then
begin // Key Down
// check normal keys
- case WideCharUpperCase(CharCode)[1] of
- 'Q':
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'):
begin
Result := false;
Exit;
@@ -178,7 +179,7 @@ begin
Typ := TStatType(0);
end;
-procedure TScreenStatDetail.onShow;
+procedure TScreenStatDetail.OnShow;
begin
inherited;
@@ -233,7 +234,7 @@ begin
if (Score > 0) then
begin
Text[I].Text := Format(FormatStr,
- [Singer, Score, Theme.ILevel[Difficulty], SongArtist, SongTitle]);
+ [Singer, Score, Theme.ILevel[Difficulty], SongArtist, SongTitle, Date]);
end;
end;
end;
diff --git a/cmake/src/screens/UScreenStatMain.pas b/cmake/src/screens/UScreenStatMain.pas
index 2fd91288..204f40cd 100644
--- a/cmake/src/screens/UScreenStatMain.pas
+++ b/cmake/src/screens/UScreenStatMain.pas
@@ -47,14 +47,14 @@ type
private
//Some Stat Value that don't need to be calculated 2 times
SongsWithVid: cardinal;
- function FormatOverviewIntro(FormatStr: string): string;
- function FormatSongOverview(FormatStr: string): string;
- function FormatPlayerOverview(FormatStr: string): string;
+ 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: WideChar; PressedDown: boolean): boolean; override;
- procedure onShow; override;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+ procedure OnShow; override;
procedure SetAnimationProgress(Progress: real); override;
procedure SetOverview;
@@ -70,21 +70,17 @@ uses
ULanguage,
UCommon,
Classes,
- {$IFDEF win32}
- windows,
- {$ELSE}
- sysconst,
- {$ENDIF}
- ULog;
-
-function TScreenStatMain.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
+ 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 WideCharUpperCase(CharCode)[1] of
- 'Q':
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'):
begin
Result := false;
Exit;
@@ -170,11 +166,11 @@ begin
//Set Songs with Vid
SongsWithVid := 0;
for I := 0 to Songs.SongList.Count -1 do
- if (TSong(Songs.SongList[I]).Video <> '') then
+ if (TSong(Songs.SongList[I]).Video.IsSet) then
Inc(SongsWithVid);
end;
-procedure TScreenStatMain.onShow;
+procedure TScreenStatMain.OnShow;
begin
inherited;
@@ -182,7 +178,7 @@ begin
SetOverview;
end;
-function TScreenStatMain.FormatOverviewIntro(FormatStr: string): string;
+function TScreenStatMain.FormatOverviewIntro(FormatStr: UTF8String): UTF8String;
var
Year, Month, Day: word;
begin
@@ -203,10 +199,10 @@ begin
end;
end;
-function TScreenStatMain.FormatSongOverview(FormatStr: string): string;
+function TScreenStatMain.FormatSongOverview(FormatStr: UTF8String): UTF8String;
var
CntSongs, CntSungSongs, CntVidSongs: integer;
- MostPopSongArtist, MostPopSongTitle: string;
+ MostPopSongArtist, MostPopSongTitle: UTF8String;
StatList: TList;
MostSungSong: TStatResultMostSungSong;
begin
@@ -247,12 +243,12 @@ begin
end;
end;
-function TScreenStatMain.FormatPlayerOverview(FormatStr: string): string;
+function TScreenStatMain.FormatPlayerOverview(FormatStr: UTF8String): UTF8String;
var
CntPlayers: integer;
BestScoreStat: TStatResultBestScores;
BestSingerStat: TStatResultBestSingers;
- BestPlayer, BestScorePlayer: string;
+ BestPlayer, BestScorePlayer: UTF8String;
BestPlayerScore, BestScore: integer;
SingerStats, ScoreStats: TList;
begin
@@ -307,7 +303,7 @@ end;
procedure TScreenStatMain.SetOverview;
var
- Overview: string;
+ Overview: UTF8String;
begin
// Format overview
Overview := FormatOverviewIntro(Language.Translate('STAT_OVERVIEW_INTRO')) + '\n \n' +
diff --git a/cmake/src/screens/UScreenTop5.pas b/cmake/src/screens/UScreenTop5.pas
index 1013a9b5..705d1e35 100644
--- a/cmake/src/screens/UScreenTop5.pas
+++ b/cmake/src/screens/UScreenTop5.pas
@@ -47,18 +47,21 @@ type
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: WideChar; PressedDown: boolean): boolean; 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 OnShow; override;
+ procedure DrawScores(difficulty: integer);
function Draw: boolean; override;
end;
@@ -67,19 +70,19 @@ implementation
uses
UDataBase,
UGraphic,
+ UMain,
UIni,
- UNote;
+ UNote,
+ UUnicodeUtils;
-function TScreenTop5.ParseInput(PressedKey: cardinal;
- CharCode: WideChar;
- PressedDown: boolean): boolean;
+function TScreenTop5.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
begin
Result := true;
if PressedDown then
begin
// check normal keys
- case WideCharUpperCase(CharCode)[1] of
- 'Q':
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'):
begin
Result := false;
Exit;
@@ -98,6 +101,34 @@ begin
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;
@@ -113,7 +144,7 @@ begin
Result := true;
if (MouseButton = SDL_BUTTON_LEFT) and BtnDown then
//left-click anywhere sends return
- ParseInput(SDLK_RETURN, #0, true);
+ ParseInput(SDLK_RETURN, 0, true);
end;
constructor TScreenTop5.Create;
@@ -133,18 +164,22 @@ begin
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;
+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);
@@ -152,35 +187,74 @@ begin
if PMax = 4 then
PMax := 5;
for I := 0 to PMax do
- DataBase.AddScore(CurrentSong, Ini.Difficulty, Ini.Name[I], Round(Player[I].ScoreTotalInt));
+ 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;
- DataBase.WriteScore(CurrentSong);
+ 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
- Static[StaticNumber[I]].Visible := true;
+ 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
- Static[StaticNumber[I]].Visible := false;
+ 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[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
{
@@ -208,18 +282,18 @@ begin
if ScreenAct = 1 then
begin
LoadColor(
- Static[StaticBoxLightest[Item]].Texture.ColR,
- Static[StaticBoxLightest[Item]].Texture.ColG,
- Static[StaticBoxLightest[Item]].Texture.ColB,
+ Statics[StaticBoxLightest[Item]].Texture.ColR,
+ Statics[StaticBoxLightest[Item]].Texture.ColG,
+ Statics[StaticBoxLightest[Item]].Texture.ColB,
'P1Dark');
end;
if ScreenAct = 2 then
begin
LoadColor(
- Static[StaticBoxLightest[Item]].Texture.ColR,
- Static[StaticBoxLightest[Item]].Texture.ColG,
- Static[StaticBoxLightest[Item]].Texture.ColB,
+ Statics[StaticBoxLightest[Item]].Texture.ColR,
+ Statics[StaticBoxLightest[Item]].Texture.ColG,
+ Statics[StaticBoxLightest[Item]].Texture.ColB,
'P4Dark');
end;
}
diff --git a/cmake/src/screens/UScreenWelcome.pas b/cmake/src/screens/UScreenWelcome.pas
deleted file mode 100644
index a00a84e2..00000000
--- a/cmake/src/screens/UScreenWelcome.pas
+++ /dev/null
@@ -1,164 +0,0 @@
-{* 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 UScreenWelcome;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-
-uses
- UMenu,
- SDL,
- SysUtils,
- UThemes;
-
-type
- TScreenWelcome = class(TMenu)
- public
- Animation: real;
- Fadeout: boolean;
- constructor Create; override;
- function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
- function Draw: boolean; override;
- procedure onShow; override;
- end;
-
-implementation
-
-uses
- UGraphic,
- UTime,
- USkins,
- UTexture;
-
-function TScreenWelcome.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
-begin
- Result := true;
- if (PressedDown) then
- begin
- case PressedKey of
- SDLK_ESCAPE,
- SDLK_BACKSPACE :
- begin
- Result := false;
- end;
- SDLK_RETURN:
- begin
- FadeTo(@ScreenMain);
- Fadeout := true;
- end;
- end;
- end;
-end;
-
-constructor TScreenWelcome.Create;
-begin
- inherited Create;
- AddStatic(-10, -10, 0, 0, 1, 1, 1, Skin.GetTextureFileName('ButtonAlt'), TEXTURE_TYPE_TRANSPARENT);
- AddStatic(-500, 440, 200, 5, 0, 0, 0, Skin.GetTextureFileName('Rectangle'), TEXTURE_TYPE_COLORIZED);
- AddStatic(-500, 472, 200, 5, 0, 0, 0, Skin.GetTextureFileName('Rectangle'), TEXTURE_TYPE_COLORIZED);
- AddStatic(-500, 504, 200, 5, 0, 0, 0, Skin.GetTextureFileName('Rectangle'), TEXTURE_TYPE_COLORIZED);
- AddStatic(-500, 536, 200, 5, 0, 0, 0, Skin.GetTextureFileName('Rectangle'), TEXTURE_TYPE_COLORIZED);
- AddStatic(-500, 568, 200, 5, 0, 0, 0, Skin.GetTextureFileName('Rectangle'), TEXTURE_TYPE_COLORIZED);
- Animation := 0;
- Fadeout := false;
-end;
-
-procedure TScreenWelcome.onShow;
-begin
- inherited;
-
- CountSkipTimeSet;
-end;
-
-function TScreenWelcome.Draw: boolean;
-var
- Min: real;
- Max: real;
- Factor: real;
- Count: integer;
-begin
- // star animation
- Animation := Animation + TimeSkip*1000;
-
- // draw nothing
- Min := 0; Max := 1000;
- if (Animation >= Min) and (Animation < Max) then
- begin
- end;
-
- // popup
- Min := 1000; Max := 1120;
- if (Animation >= Min) and (Animation < Max) then
- begin
- Factor := (Animation - Min) / (Max - Min);
- Static[0].Texture.X := 600;
- Static[0].Texture.Y := 600 - Factor * 230;
- Static[0].Texture.W := 200;
- Static[0].Texture.H := Factor * 230;
- end;
-
- // bounce
- Min := 1120; Max := 1200;
- if (Animation >= Min) and (Animation < Max) then
- begin
- Factor := (Animation - Min) / (Max - Min);
- Static[0].Texture.Y := 370 + Factor * 50;
- Static[0].Texture.H := 230 - Factor * 50;
- end;
-
- // run
- Min := 1500; Max := 3500;
- if (Animation >= Min) and (Animation < Max) then
- begin
- Factor := (Animation - Min) / (Max - Min);
-
- Static[0].Texture.X := 600 - Factor * 1400;
- Static[0].Texture.H := 180;
-
- for Count := 1 to 5 do
- begin
- Static[Count].Texture.X := 770 - Factor * 1400;
- Static[Count].Texture.W := 150 + Factor * 200;
- Static[Count].Texture.Alpha := Factor * 0.5;
- end;
- end;
-
- Min := 3500;
- if (Animation >= Min) and (not Fadeout) then
- begin
- FadeTo(@ScreenMain);
- Fadeout := true;
- end;
-
- Result := inherited Draw;
-end;
-
-end.
diff --git a/cmake/src/switches.inc b/cmake/src/switches.inc
index 17ebd1b8..b9fcd2d6 100644
--- a/cmake/src/switches.inc
+++ b/cmake/src/switches.inc
@@ -9,14 +9,28 @@
{$ELSE}
{$DEFINE Delphi}
- // Delphi version numbers (ignore versions released before Delphi 6 as they miss the $IF directive):
- // Delphi 6 (VER140), Delphi 7 (VER150), Delphi 8 (VER160)
- // Delphi 9/2005 (VER170), Delphi 10/2006 (VER180)
+ // 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}
- // the inline-procedure directive was introduced with Delphi 2005
- {$IF not (Defined(VER140) or Defined(VER150) or Defined(VER160))}
+ // inline directive introduced with Delphi 2005
+ {$IFDEF DELPHI_9_UP}
{$DEFINE HasInline}
- {$IFEND}
+ {$ENDIF}
{$ENDIF}
@@ -59,8 +73,6 @@
{$DEFINE CONSOLE}
{$IFEND}
-{.$DEFINE UseFreetype}
-
// audio config
{$IF Defined(HaveBASS)}
{$DEFINE UseBASSPlayback}
diff --git a/cmake/src/ultrastardx.dpr b/cmake/src/ultrastardx.dpr
index 11796cfa..f6c9558c 100644
--- a/cmake/src/ultrastardx.dpr
+++ b/cmake/src/ultrastardx.dpr
@@ -26,7 +26,7 @@
program ultrastardx;
{$IFDEF MSWINDOWS}
- {$R '..\icons\ultrastardx-icon.res' '..\icons\ultrastardx-icon.rc'}
+ {$R '..\res\ultrastardx.res' '..\res\ultrastardx.rc'}
{$ENDIF}
{$IFDEF FPC}
@@ -50,11 +50,7 @@ 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 crashes in FPC 2.2.2 so do not use the cwstring stuff
- {.$IFNDEF DARWIN}
- {$IFDEF NOIGNORE}
- cwstring, // Enable Unicode support. MacOSX misses some references to iconv.
- {$ENDIF}
+ cwstring, // Enable Unicode support
{$ENDIF}
{$IFNDEF FPC}
@@ -71,16 +67,12 @@ uses
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',
-
- {$IFDEF UseFreetype}
freetype in 'lib\freetype\freetype.pas',
- UFont in 'base\UFont.pas',
- UTextEncoding in 'base\UTextEncoding.pas',
- {$ENDIF}
{$IFDEF UseBass}
bass in 'lib\bass\delphi\bass.pas',
@@ -136,10 +128,39 @@ uses
{$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
@@ -175,7 +196,6 @@ uses
UDraw in 'base\UDraw.pas',
URecord in 'base\URecord.pas',
UTime in 'base\UTime.pas',
- TextGL in 'base\TextGL.pas',
USong in 'base\USong.pas',
UXMLSong in 'base\UXMLSong.pas',
USongs in 'base\USongs.pas',
@@ -192,16 +212,23 @@ uses
UCatCovers in 'base\UCatCovers.pas',
UFiles in 'base\UFiles.pas',
UGraphicClasses in 'base\UGraphicClasses.pas',
- UDLLManager in 'base\UDLLManager.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',
- UPath in 'base\UPath.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
//------------------------------
@@ -275,7 +302,6 @@ uses
//Includes - Screens
//------------------------------
UScreenLoading in 'screens\UScreenLoading.pas',
- UScreenWelcome in 'screens\UScreenWelcome.pas',
UScreenMain in 'screens\UScreenMain.pas',
UScreenName in 'screens\UScreenName.pas',
UScreenLevel in 'screens\UScreenLevel.pas',
@@ -304,19 +330,13 @@ uses
UScreenPopup in 'screens\UScreenPopup.pas',
//Includes - Screens PartyMode
- UScreenSingModi in 'screens\UScreenSingModi.pas',
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',
-
- //------------------------------
- //Includes - Modi SDK
- //------------------------------
- ModiSDK in '..\plugins\SDK\ModiSDK.pas', //Old SDK, will be deleted soon
-
SysUtils;
begin
diff --git a/cmake/test/TestPortAudioDevice.pas b/cmake/test/TestPortAudioDevice.pas
new file mode 100644
index 00000000..ba394383
--- /dev/null
+++ b/cmake/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/cmake/test/TestSignAlgorithm.pas b/cmake/test/TestSignAlgorithm.pas
new file mode 100644
index 00000000..915e5681
--- /dev/null
+++ b/cmake/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