aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/ResourceExtractor/Makefile.in19
-rw-r--r--tools/ResourceExtractor/ResourceExtractor.lpi106
-rw-r--r--tools/ResourceExtractor/ResourceExtractor.pas152
-rw-r--r--tools/ScoreConverter/ScoreConverter.dpr17
-rw-r--r--tools/ScoreConverter/ScoreConverter.icobin0 -> 766 bytes
-rw-r--r--tools/ScoreConverter/ScoreConverter.resbin0 -> 876 bytes
-rw-r--r--tools/ScoreConverter/UScores.pas102
-rw-r--r--tools/ScoreConverter/USongs.pas160
-rw-r--r--tools/ScoreConverter/Umainform.dfm123
-rw-r--r--tools/ScoreConverter/Umainform.pas230
10 files changed, 909 insertions, 0 deletions
diff --git a/tools/ResourceExtractor/Makefile.in b/tools/ResourceExtractor/Makefile.in
new file mode 100644
index 00000000..709365d7
--- /dev/null
+++ b/tools/ResourceExtractor/Makefile.in
@@ -0,0 +1,19 @@
+PPC = @PPC@
+PFLAGS = -dRELEASE
+
+NAME = ResourceExtractor
+SRC = $(NAME).pas
+BIN = $(NAME)@EXEEXT@
+
+.PHONY: all clean distclean
+
+all: $(BIN)
+
+clean:
+ rm -f $(BIN) *.o *.ppu *.rst *.compiled
+
+distclean: clean
+ rm -rf Makefile *~ *.bak __history
+
+$(BIN): $(SRC)
+ $(PPC) $(PFLAGS) -o$@ $(SRC)
diff --git a/tools/ResourceExtractor/ResourceExtractor.lpi b/tools/ResourceExtractor/ResourceExtractor.lpi
new file mode 100644
index 00000000..82ecf87e
--- /dev/null
+++ b/tools/ResourceExtractor/ResourceExtractor.lpi
@@ -0,0 +1,106 @@
+<?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"/>
+ <IconPath Value="./"/>
+ <TargetFileExt Value=""/>
+ <ActiveEditorIndexAtStart Value="0"/>
+ </General>
+ <VersionInfo>
+ <ProjectVersion Value=""/>
+ <Language Value=""/>
+ <CharSet Value=""/>
+ </VersionInfo>
+ <PublishOptions>
+ <Version Value="2"/>
+ <IgnoreBinaries Value="False"/>
+ <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+ <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+ </PublishOptions>
+ <RunParams>
+ <local>
+ <FormatVersion Value="1"/>
+ <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+ </local>
+ </RunParams>
+ <Units Count="3">
+ <Unit0>
+ <Filename Value="ResourceExtractor.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="ResourceExtractor"/>
+ <CursorPos X="1" Y="131"/>
+ <TopLine Value="108"/>
+ <EditorIndex Value="0"/>
+ <UsageCount Value="21"/>
+ <Loaded Value="True"/>
+ </Unit0>
+ <Unit1>
+ <Filename Value="../USDXResCompiler.lpr"/>
+ <UnitName Value="USDXResCompiler"/>
+ <CursorPos X="17" Y="96"/>
+ <TopLine Value="89"/>
+ <UsageCount Value="10"/>
+ </Unit1>
+ <Unit2>
+ <Filename Value="../../Game/Code/resource.inc"/>
+ <CursorPos X="1" Y="1"/>
+ <TopLine Value="1"/>
+ <UsageCount Value="10"/>
+ </Unit2>
+ </Units>
+ <JumpHistory Count="8" HistoryIndex="7">
+ <Position1>
+ <Filename Value="ResourceExtractor.pas"/>
+ <Caret Line="144" Column="23" TopLine="104"/>
+ </Position1>
+ <Position2>
+ <Filename Value="ResourceExtractor.pas"/>
+ <Caret Line="120" Column="1" TopLine="99"/>
+ </Position2>
+ <Position3>
+ <Filename Value="ResourceExtractor.pas"/>
+ <Caret Line="140" Column="25" TopLine="105"/>
+ </Position3>
+ <Position4>
+ <Filename Value="ResourceExtractor.pas"/>
+ <Caret Line="146" Column="32" TopLine="103"/>
+ </Position4>
+ <Position5>
+ <Filename Value="ResourceExtractor.pas"/>
+ <Caret Line="139" Column="27" TopLine="105"/>
+ </Position5>
+ <Position6>
+ <Filename Value="ResourceExtractor.pas"/>
+ <Caret Line="140" Column="8" TopLine="105"/>
+ </Position6>
+ <Position7>
+ <Filename Value="ResourceExtractor.pas"/>
+ <Caret Line="139" Column="27" TopLine="106"/>
+ </Position7>
+ <Position8>
+ <Filename Value="ResourceExtractor.pas"/>
+ <Caret Line="144" Column="7" TopLine="106"/>
+ </Position8>
+ </JumpHistory>
+ </ProjectOptions>
+ <CompilerOptions>
+ <Version Value="5"/>
+ <SearchPaths>
+ <SrcPath Value="../../Game/Code/"/>
+ </SearchPaths>
+ <CodeGeneration>
+ <Generate Value="Faster"/>
+ </CodeGeneration>
+ <Other>
+ <CompilerPath Value="$(CompPath)"/>
+ </Other>
+ </CompilerOptions>
+</CONFIG>
diff --git a/tools/ResourceExtractor/ResourceExtractor.pas b/tools/ResourceExtractor/ResourceExtractor.pas
new file mode 100644
index 00000000..aa9cc3bc
--- /dev/null
+++ b/tools/ResourceExtractor/ResourceExtractor.pas
@@ -0,0 +1,152 @@
+program ResourceExtractor;
+
+{$ifdef FPC}
+ {$mode delphi}{$H+}
+{$endif}
+
+uses
+ Classes,
+ SysUtils,
+ StrUtils;
+
+
+var
+ ResCount: integer;
+ OutStream: TStringList;
+
+
+procedure Init();
+begin
+ OutStream := TStringList.Create();
+
+ OutStream.Add('const');
+ // placeholder for array-header (will be filled on file-saving)
+ OutStream.Add('');
+end;
+
+procedure SaveToFile(const OutFileName: string);
+begin
+ // add array-header
+ OutStream[1] := ' resources: array[0..'+IntToStr(ResCount-1)+', 0..2] of string = (';
+ // add trailer
+ OutStream.Add(' );');
+
+ // save file
+ try
+ OutStream.SaveToFile(OutFileName);
+ except
+ OutStream.Free();
+ raise Exception.Create('Could not save to file: "' + OutFileName + '"');
+ end;
+
+ OutStream.Free();
+end;
+
+function AddResource(Fields: TStringList; const RCFileDir, ResDir: string): boolean;
+var
+ ResName, ResType, ResFile: string;
+begin
+ if (Fields.Count < 3) or
+ (AnsiStartsStr('//', Fields[0])) or
+ (Length(Fields[2]) < 3) then
+ begin
+ Result := false;
+ Exit;
+ end;
+
+ // add a trailing comma to the last line
+ if (ResCount > 0) then
+ OutStream[OutStream.Count-1] := OutStream[OutStream.Count-1] + ',';
+
+ ResName := Fields[0];
+ ResType := Fields[1];
+ ResFile := Fields[2];
+
+ Writeln('ADD: [' + ResType + ':' + ResName + ' = ' +ResFile + ']');
+
+ // quote fields
+ ResName := AnsiQuotedStr(ResName, '''')+',';
+ ResType := AnsiQuotedStr(ResType, '''')+',';
+ // strip surrounding quotes of filename
+ ResFile := AnsiMidStr(ResFile, 2, Length(Fields[2])-2);
+ // now translate the resource filename (relative to the RC-file) to be relative to the resource-dir
+ // 1st step: get absolute path of the resource
+ ResFile := ExpandFileName(RCFileDir + ResFile);
+ // 2nd step: get path of the resource relative to the resource-dir
+ // Note: both paths must be absolute and the base-path must have a trailing '/' or '\'
+ ResFile := ExtractRelativepath(ResDir, ResFile);
+ // 3rd step: ... and quote
+ ResFile := AnsiQuotedStr(ResFile, '''');
+
+ // compose line
+ OutStream.Add(Format(' (%-20S%-8S%S)', [ResName, ResType, ResFile]));
+
+ Inc(ResCount);
+
+ Result := true;
+end;
+
+procedure ExtractResources(const InFileName, ResDir: string);
+var
+ Fields: TStringList;
+ LineIndex: integer;
+ Lines: TStringList;
+ RCFileDirAbs, ResDirAbs: string;
+begin
+ // get absolute paths
+ RCFileDirAbs := ExtractFilePath(ExpandFileName(InFileName));
+ ResDirAbs := ExpandFileName(ResDir) + '/';
+
+ Lines := TStringList.Create();
+ try
+ Lines.LoadFromFile(InFileName);
+ except
+ raise Exception.Create('Failed to open file: "' + InFileName + '"');
+ end;
+
+ Fields := TStringList.Create();
+ for LineIndex := 0 to Lines.Count-1 do
+ begin
+ Fields.Clear();
+ // split line into [Name, Type, File]
+ ExtractStrings([' ', #9], [], PChar(Lines[LineIndex]), Fields);
+ if (not AddResource(Fields, RCFileDirAbs, ResDirAbs)) then
+ Writeln( 'SKIP: "'+Lines[LineIndex]+'"');
+ end;
+
+ Lines.Free();
+ Fields.Free();
+end;
+
+var
+ ProgName: string;
+begin
+ if (ParamCount <> 3) then
+ begin
+ ProgName := ExtractFileName(ParamStr(0));
+ WriteLn('Usage: ' + ProgName + ' RC-File Resource-Dir Output-File');
+ Exit;
+ end;
+
+ WriteLn('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>');
+ WriteLn('Converting "' + ParamStr(1) + '" to "' + ParamStr(3) + '"');
+ WriteLn('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>');
+
+ try
+ Init();
+ ExtractResources(ParamStr(1), ParamStr(2));
+ SaveToFile(ParamStr(3));
+ except on E:Exception do
+ begin
+ WriteLn('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
+ WriteLn('Conversion failed: ' + E.Message + '!');
+ WriteLn('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
+ Exit;
+ end;
+ end;
+
+ WriteLn('<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<');
+ WriteLn('Conversion finished!');
+ WriteLn('<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<');
+end.
+
diff --git a/tools/ScoreConverter/ScoreConverter.dpr b/tools/ScoreConverter/ScoreConverter.dpr
new file mode 100644
index 00000000..2774cde4
--- /dev/null
+++ b/tools/ScoreConverter/ScoreConverter.dpr
@@ -0,0 +1,17 @@
+program ScoreConverter;
+
+uses
+ Forms,
+ Umainform in 'Umainform.pas' {mainform},
+ UScores in 'UScores.pas',
+ UDataBase in '..\Game\Code\Classes\UDataBase.pas',
+ USongs in 'USongs.pas';
+
+{$R *.res}
+
+begin
+ Application.Initialize;
+ Application.Title := 'Score Converter';
+ Application.CreateForm(Tmainform, mainform);
+ Application.Run;
+end.
diff --git a/tools/ScoreConverter/ScoreConverter.ico b/tools/ScoreConverter/ScoreConverter.ico
new file mode 100644
index 00000000..80319014
--- /dev/null
+++ b/tools/ScoreConverter/ScoreConverter.ico
Binary files differ
diff --git a/tools/ScoreConverter/ScoreConverter.res b/tools/ScoreConverter/ScoreConverter.res
new file mode 100644
index 00000000..2d3bea87
--- /dev/null
+++ b/tools/ScoreConverter/ScoreConverter.res
Binary files differ
diff --git a/tools/ScoreConverter/UScores.pas b/tools/ScoreConverter/UScores.pas
new file mode 100644
index 00000000..801d796e
--- /dev/null
+++ b/tools/ScoreConverter/UScores.pas
@@ -0,0 +1,102 @@
+unit UScores;
+
+interface
+
+uses USongs;
+
+procedure ReadScore(var Song: TSong);
+procedure WriteScore(var Song: TSong);
+procedure AddScore(var Song: TSong; Level: integer; Name: string; Score: integer);
+
+implementation
+
+uses IniFiles, SysUtils;
+
+procedure ReadScore(var Song: TSong);
+var
+ F: TIniFile;
+ S: string;
+ P: integer;
+ Lev: integer;
+ LevS: string;
+begin
+ F := TIniFile.Create(Song.Path + ChangeFileExt(Song.FileName, '.sco'));
+
+ for Lev := 0 to 2 do begin
+ case Lev of
+ 0: LevS := 'Easy';
+ 1: LevS := 'Normal';
+ 2: LevS := 'Hard';
+ end;
+
+ P := 1;
+ S := F.ReadString(LevS + IntToStr(P), 'Name', '');
+ while (S <> '') and (P<=5) do begin
+ SetLength(Song.Score[Lev], P);
+ Song.Score[Lev, P-1].Name := S;
+ Song.Score[Lev, P-1].Score := F.ReadInteger(LevS + IntToStr(P), 'Score', 0);
+
+ Inc(P);
+ S := F.ReadString(LevS + IntToStr(P), 'Name', '');
+ end;
+ end;
+end;
+
+procedure AddScore(var Song: TSong; Level: integer; Name: string; Score: integer);
+var
+ S: integer;
+ S2: integer;
+begin
+ S := 0;
+ while (S <= High(Song.Score[Level])) and (Score <= Song.Score[Level, S].Score) do
+ Inc(S);
+ // S has the number for new score
+
+
+ // we create new score
+ SetLength(Song.Score[Level], Length(Song.Score[Level]) + 1);
+
+ // we move down old scores
+ for S2 := High(Song.Score[Level])-1 downto S do
+ Song.Score[Level, S2+1] := Song.Score[Level, S2];
+
+ // we fill new score
+ Song.Score[Level, S].Name := Name;
+ Song.Score[Level, S].Score := Score;
+
+ if Length(Song.Score[Level]) > 5 then begin
+ SetLength(Song.Score[Level], 5);
+ end;
+end;
+
+procedure WriteScore(var Song: TSong);
+var
+ F: TIniFile;
+ S: integer;
+ Lev: integer;
+ LevS: string;
+ FileName: string;
+begin
+ FileName := Song.Path + ChangeFileExt(Song.FileName, '.sco');
+ if (not FileExists(FileName)) or (FileExists(FileName) and DeleteFile(FileName)) then begin
+ // file has been deleted -> creating new file
+ F := TIniFile.Create(FileName);
+
+ for Lev := 0 to 2 do begin
+ case Lev of
+ 0: LevS := 'Easy';
+ 1: LevS := 'Normal';
+ 2: LevS := 'Hard';
+ end;
+
+ for S := 0 to high(Song.Score[Lev]) do begin
+ F.WriteString(LevS + IntToStr(S+1), 'Name', Song.Score[Lev, S].Name);
+ F.WriteInteger(LevS + IntToStr(S+1), 'Score', Song.Score[Lev, S].Score);
+
+ end; // for S
+ end; // for Lev
+ F.Free;
+ end; // if
+end;
+
+end.
diff --git a/tools/ScoreConverter/USongs.pas b/tools/ScoreConverter/USongs.pas
new file mode 100644
index 00000000..8f20f44f
--- /dev/null
+++ b/tools/ScoreConverter/USongs.pas
@@ -0,0 +1,160 @@
+unit USongs;
+
+interface
+
+type
+ TScore = record
+ Name: string;
+ Score: integer;
+ Length: string;
+ end;
+
+ TSong = record
+ Path: string;
+ FileName: string;
+
+ Title: string;
+ Artist: string;
+
+ Score: array[0..2] of array of TScore;
+ end;
+
+ TSongs = class
+ LastCount: Integer;
+ Song: array of TSong; // array of songs
+
+ function ReadHeader(var rSong: TSong): boolean;
+ procedure BrowseDir(Dir: string); // Browse a dir + subdirs for songfiles
+ end;
+
+ var Songs: TSongs;
+
+implementation
+uses Sysutils, UMainForm, Dialogs;
+
+function TSongs.ReadHeader(var rSong: TSong): boolean;
+var
+ Line, Identifier, Value: String;
+ Temp: word;
+ Done: byte;
+ SongFile: Textfile;
+begin
+ Result := False;
+
+
+ //Open File and set File Pointer to the beginning
+ AssignFile(SongFile, rSong.Path + rSong.FileName);
+ Reset(SongFile);
+
+ //Read Header
+ Result := true;
+
+ //Read first Line
+ ReadLn (SongFile, Line);
+
+ if (Length(Line)<=0) then
+ begin
+ Result := False;
+ Exit;
+ end;
+ Done := 0;
+ //Read Lines while Line starts with #
+ While (Line[1] = '#') do
+ begin
+ Temp := Pos(':', Line);
+
+ //Line has a Seperator-> Headerline
+ if (Temp <> 0) then
+ begin
+ //Read Identifier and Value
+ Identifier := Uppercase(Trim(Copy(Line, 2, Temp - 2))); //Uppercase is for Case Insensitive Checks
+ Value := Trim(Copy(Line, Temp + 1,Length(Line) - Temp));
+
+ //Check the Identifier (If Value is given)
+ if (Length(Value) <> 0) then
+ begin
+
+ //-----------
+ //Required Attributes
+ //-----------
+
+ //Title
+ if (Identifier = 'TITLE') then
+ begin
+ rSong.Title := Value;
+
+ //Add Title Flag to Done
+ Done := Done or 1;
+ end
+
+ //Artist
+ else if (Identifier = 'ARTIST') then
+ begin
+ rSong.Artist := Value;
+
+ //Add Artist Flag to Done
+ Done := Done or 2;
+ end;
+
+ end;
+ end;
+
+ if not EOf(SongFile) then
+ ReadLn (SongFile, Line)
+ else
+ begin
+ Result := False;
+ break;
+ end;
+
+ //End on first empty Line
+ if (Length(Line) = 0) then
+ break;
+ end;
+
+ //Check if all Required Values are given
+ if (Done <> 3) then
+ begin
+ Result := False;
+ end;
+
+ //And Close File
+ CloseFile(SongFile);
+end;
+
+procedure TSongs.BrowseDir(Dir: string);
+var
+ SR: TSearchRec; // for parsing Songs Directory
+ SLen: integer;
+begin
+ if FindFirst(Dir + '*', faDirectory, SR) = 0 then begin
+ repeat
+ if (SR.Name <> '.') and (SR.Name <> '..') then
+ BrowseDir(Dir + Sr.Name + '\');
+ until FindNext(SR) <> 0;
+ end;
+ FindClose(SR);
+
+ if FindFirst(Dir + '*.txt', 0, SR) = 0 then begin
+ repeat
+ SLen := Length(Song);
+ SetLength(Song, SLen + 1);
+
+ Song[SLen].Path := Dir;
+ Song[SLen].FileName := SR.Name;
+
+ if (ReadHeader(Song[SLen]) = false) then SetLength(Song, SLen);
+
+ //update Songs Label
+ if LastCount <> SLen div 30 then
+ begin
+ LastCount := SLen div 30;
+ MainForm.UpdateLoadedSongs(Dir, SLen);
+ end;
+
+ until FindNext(SR) <> 0;
+ end; // if FindFirst
+ FindClose(SR);
+end;
+
+end.
diff --git a/tools/ScoreConverter/Umainform.dfm b/tools/ScoreConverter/Umainform.dfm
new file mode 100644
index 00000000..a4291e7b
--- /dev/null
+++ b/tools/ScoreConverter/Umainform.dfm
@@ -0,0 +1,123 @@
+object mainform: Tmainform
+ Left = 328
+ Top = 228
+ HorzScrollBar.Visible = False
+ VertScrollBar.Visible = False
+ BorderIcons = [biSystemMenu, biMinimize]
+ BorderStyle = bsSingle
+ Caption = 'Ultrastar Deluxe Score Converter'
+ ClientHeight = 159
+ ClientWidth = 449
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'MS Sans Serif'
+ Font.Style = []
+ OldCreateOrder = False
+ Position = poDesktopCenter
+ OnCreate = FormCreate
+ PixelsPerInch = 96
+ TextHeight = 13
+ object Label1: TLabel
+ Left = 8
+ Top = 8
+ Width = 60
+ Height = 13
+ Caption = 'SongFolder: '
+ end
+ object lFolder: TLabel
+ Left = 8
+ Top = 24
+ Width = 29
+ Height = 13
+ Caption = 'Folder'
+ end
+ object Label2: TLabel
+ Left = 8
+ Top = 48
+ Width = 49
+ Height = 13
+ Caption = 'Database:'
+ end
+ object lDatabase: TLabel
+ Left = 8
+ Top = 64
+ Width = 46
+ Height = 13
+ Caption = 'Database'
+ end
+ object lDatabase2: TLabel
+ Left = 72
+ Top = 48
+ Width = 54
+ Height = 13
+ Caption = 'lDatabase2'
+ end
+ object lFolder2: TLabel
+ Left = 72
+ Top = 8
+ Width = 37
+ Height = 13
+ Caption = 'lFolder2'
+ end
+ object lStatus: TLabel
+ Left = 0
+ Top = 96
+ Width = 449
+ Height = 13
+ Alignment = taCenter
+ AutoSize = False
+ Caption = 'lStatus'
+ end
+ object bFLoad: TButton
+ Left = 176
+ Top = 8
+ Width = 57
+ Height = 17
+ Caption = 'Load'
+ TabOrder = 0
+ OnClick = bFLoadClick
+ end
+ object bDLoad: TButton
+ Left = 176
+ Top = 48
+ Width = 57
+ Height = 17
+ Caption = 'Load'
+ TabOrder = 1
+ OnClick = bDLoadClick
+ end
+ object bToDB: TButton
+ Left = 16
+ Top = 112
+ Width = 153
+ Height = 17
+ Caption = 'Convert *.SCO to Database'
+ Enabled = False
+ TabOrder = 2
+ OnClick = bToDBClick
+ end
+ object bFromDB: TButton
+ Left = 288
+ Top = 112
+ Width = 145
+ Height = 17
+ Caption = 'Convert Database to *.SCO'
+ Enabled = False
+ TabOrder = 3
+ OnClick = bFromDBClick
+ end
+ object pProgress: TProgressBar
+ Left = 8
+ Top = 136
+ Width = 433
+ Height = 17
+ TabOrder = 4
+ end
+ object oDatabase: TOpenDialog
+ Filter = 'Ultrastar Deluxe Database|ultrastar.db'
+ Left = 136
+ Top = 48
+ end
+end
diff --git a/tools/ScoreConverter/Umainform.pas b/tools/ScoreConverter/Umainform.pas
new file mode 100644
index 00000000..647cf3a4
--- /dev/null
+++ b/tools/ScoreConverter/Umainform.pas
@@ -0,0 +1,230 @@
+unit Umainform;
+
+interface
+
+uses
+ Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+ Dialogs, StdCtrls, ComCtrls, UDataBase, ShellAPI, ShlObj, USongs;
+
+type
+ Tmainform = class(TForm)
+ Label1: TLabel;
+ lFolder: TLabel;
+ bFLoad: TButton;
+ Label2: TLabel;
+ lDatabase: TLabel;
+ bDLoad: TButton;
+ lDatabase2: TLabel;
+ lFolder2: TLabel;
+ bToDB: TButton;
+ bFromDB: TButton;
+ pProgress: TProgressBar;
+ oDatabase: TOpenDialog;
+ lStatus: TLabel;
+ procedure FormCreate(Sender: TObject);
+ procedure bDLoadClick(Sender: TObject);
+ function BrowseDialog (const Title: string; const Flag: integer): string;
+ procedure bFLoadClick(Sender: TObject);
+ procedure UpdateLoadedSongs(Path: String; Count: integer);
+ procedure bToDBClick(Sender: TObject);
+ procedure bFromDBClick(Sender: TObject);
+ private
+ { Private-Deklarationen }
+ public
+ { Public-Deklarationen }
+ end;
+
+var
+ mainform: Tmainform;
+ DBLoaded: Boolean;
+ SFLoaded: Boolean;
+
+
+implementation
+
+uses UScores;
+
+{$R *.dfm}
+
+function Tmainform.BrowseDialog
+ (const Title: string; const Flag: integer): string;
+var
+ lpItemID : PItemIDList;
+ BrowseInfo : TBrowseInfo;
+ DisplayName : array[0..MAX_PATH] of char;
+ TempPath : array[0..MAX_PATH] of char;
+begin
+ Result:='';
+ FillChar(BrowseInfo, sizeof(TBrowseInfo), #0);
+ with BrowseInfo do begin
+ hwndOwner := Application.Handle;
+ pszDisplayName := @DisplayName;
+ lpszTitle := PChar(Title);
+ ulFlags := Flag;
+ end;
+ lpItemID := SHBrowseForFolder(BrowseInfo);
+ if lpItemId <> nil then begin
+ SHGetPathFromIDList(lpItemID, TempPath);
+ Result := TempPath;
+ GlobalFreePtr(lpItemID);
+ end;
+end;
+
+procedure Tmainform.FormCreate(Sender: TObject);
+begin
+ Database := TDataBaseSystem.Create;
+ Songs := TSongs.Create;
+ lStatus.Caption := 'Welcome to USD Score Converter';
+ lFolder2.Caption := 'No Songs loaded';
+ lFolder.Caption := '';
+ lDataBase2.Caption := 'No Database loaded';
+ lDataBase.Caption := '';
+end;
+
+procedure Tmainform.bDLoadClick(Sender: TObject);
+begin
+ if oDatabase.Execute then
+ begin
+ try
+ Database.Init(oDataBase.FileName);
+ lDataBase2.Caption := 'Database loaded';
+ lDataBase.Caption := oDataBase.FileName;
+ DBLoaded := True;
+ except
+ lDataBase2.Caption := 'No Database loaded';
+ lDataBase.Caption := '';
+ DBLoaded := False;
+ end;
+ end;
+ bToDB.Enabled := DBLoaded and SFLoaded;
+ bFromDB.Enabled := bToDB.Enabled;
+end;
+
+procedure Tmainform.bFLoadClick(Sender: TObject);
+var
+ Path: String;
+begin
+ Path := BrowseDialog('Select UltraStar SongFolder', BIF_RETURNONLYFSDIRS);
+
+ if Path <> '' then
+ begin
+ SetLength(Songs.Song, 0);
+ try
+ Songs.BrowseDir(Path + '\');
+ lFolder2.Caption := Inttostr(Length(Songs.Song)) + ' Songs loaded';
+ lFolder.Caption := Path;
+ SFLoaded := True;
+ except
+ lFolder2.Caption := 'No Songs loaded';
+ lFolder.Caption := '';
+ SFLoaded := False;
+ end;
+ end;
+
+ bToDB.Enabled := DBLoaded and SFLoaded;
+ bFromDB.Enabled := bToDB.Enabled;
+end;
+
+procedure Tmainform.UpdateLoadedSongs(Path: String; Count: integer);
+begin
+ lFolder2.Caption := Inttostr(Count) + ' Songs loaded';
+ lFolder.Caption := Path;
+ Application.ProcessMessages;
+end;
+
+procedure Tmainform.bToDBClick(Sender: TObject);
+var
+ I, J, K: Integer;
+ LastI: integer;
+begin
+ if (Messagebox(0, PChar('If the same directory is added more than one time the Score-File will be useless. Contėnue ?'), PChar(Mainform.Caption), MB_ICONWARNING or MB_YESNO) = IDYes) then
+ begin
+ pProgress.Max := high(Songs.Song);
+ pProgress.Position := 0;
+ // Go through all Songs
+ For I := 0 to high(Songs.Song) do
+ begin
+ try
+ //Read Scores from .SCO File
+ ReadScore (Songs.Song[I]);
+
+ //Go from Easy to Difficult
+ For J := 0 to 2 do
+ begin
+ //Go through all Score Entrys with Difficulty J
+ For K := 0 to high(Songs.Song[I].Score[J]) do
+ begin
+ //Add to DataBase
+ DataBase.AddScore(Songs.Song[I], J, Songs.Song[I].Score[J][K].Name, Songs.Song[I].Score[J][K].Score);
+ end;
+ end;
+
+ except
+ showmessage ('Error Converting Score From Song: ' + Songs.Song[I].Path + Songs.Song[I].FileName);
+ end;
+
+ //Update ProgressBar
+ J := I div 30;
+ if (LastI <> J) then
+ begin
+ LastI := J;
+ pProgress.Position := I;
+ lStatus.Caption := 'Adding Songscore: ' + Songs.Song[I].Artist + ' - ' + Songs.Song[I].Title;
+ Application.ProcessMessages;
+ end;
+ end;
+
+ pProgress.Position := pProgress.Max;
+ lStatus.Caption := 'Finished';
+ end;
+end;
+
+procedure Tmainform.bFromDBClick(Sender: TObject);
+var
+ I, J: Integer;
+ LastI: integer;
+ anyScoreinthere: boolean;
+begin
+ if (Messagebox(0, PChar('All Score Entrys in the Song Directory having an equivalent will be Overwritten. Contėnue ?'), PChar(Mainform.Caption), MB_ICONWARNING or MB_YESNO) = IDYes) then
+ begin
+ pProgress.Max := high(Songs.Song);
+ pProgress.Position := 0;
+ // Go through all Songs
+ For I := 0 to high(Songs.Song) do
+ begin
+ try
+ //Not Write ScoreFile when there are no Scores for this File
+ anyScoreinthere := false;
+ //Read Scores from DB File
+ Database.ReadScore (Songs.Song[I]);
+
+ //Go from Easy to Difficult
+ For J := 0 to 2 do
+ begin
+ anyScoreinthere := anyScoreinthere or (Length(Songs.Song[I].Score[J]) > 0);
+ end;
+
+ if AnyScoreinThere then
+ WriteScore(Songs.Song[I]);
+
+ except
+ showmessage ('Error Converting Score From Song: ' + Songs.Song[I].Path + Songs.Song[I].FileName);
+ end;
+
+ //Update ProgressBar
+ J := I div 30;
+ if (LastI <> J) then
+ begin
+ LastI := J;
+ pProgress.Position := I;
+ lStatus.Caption := 'Writing ScoreFile: ' + Songs.Song[I].Artist + ' - ' + Songs.Song[I].Title;
+ Application.ProcessMessages;
+ end;
+ end;
+
+ pProgress.Position := pProgress.Max;
+ lStatus.Caption := 'Finished';
+ end;
+end;
+
+end.