aboutsummaryrefslogtreecommitdiffstats
path: root/Game/Code/Classes
diff options
context:
space:
mode:
authors_alexander <s_alexander@b956fd51-792f-4845-bead-9b4dfca2ff2c>2008-04-19 15:23:35 +0000
committers_alexander <s_alexander@b956fd51-792f-4845-bead-9b4dfca2ff2c>2008-04-19 15:23:35 +0000
commit6db1465f89985e8675db3fdac1aa7d662dda3722 (patch)
tree8525062ab6177f251777953f9d601c9f957dc29f /Game/Code/Classes
parentfece8a800270788455962ed4b99a023210daaaf9 (diff)
downloadusdx-6db1465f89985e8675db3fdac1aa7d662dda3722.tar.gz
usdx-6db1465f89985e8675db3fdac1aa7d662dda3722.tar.xz
usdx-6db1465f89985e8675db3fdac1aa7d662dda3722.zip
tried to make songloading working with the old loader and keep all changes that were made since
starting to work on a new one *hope that worked* you may delete your existing cover.cache (the cover cache is still NOT working) git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@1024 b956fd51-792f-4845-bead-9b4dfca2ff2c
Diffstat (limited to 'Game/Code/Classes')
-rw-r--r--Game/Code/Classes/UCovers.pas693
-rw-r--r--Game/Code/Classes/UDataBase.pas398
-rw-r--r--Game/Code/Classes/UGraphic.pas4
-rw-r--r--Game/Code/Classes/UMain.pas2
-rw-r--r--Game/Code/Classes/UPlaylist.pas18
-rw-r--r--Game/Code/Classes/USong.pas666
-rw-r--r--Game/Code/Classes/USong_TextFile.pas86
-rw-r--r--Game/Code/Classes/USong_Txt.pas436
-rw-r--r--Game/Code/Classes/USongs.pas76
-rw-r--r--Game/Code/Classes/UTexture.pas173
10 files changed, 639 insertions, 1913 deletions
diff --git a/Game/Code/Classes/UCovers.pas b/Game/Code/Classes/UCovers.pas
index 7a192e66..0e9ad689 100644
--- a/Game/Code/Classes/UCovers.pas
+++ b/Game/Code/Classes/UCovers.pas
@@ -1,23 +1,5 @@
unit UCovers;
-{********************
- UCover
- Contains Class managing Covers.Cache File
- File Structure:
- TCC_FileHeader
-
- TextureData
- * Array of TCC_TextureData
-
- Indexes
- * TCC_FileIndex Header Block
- * TCC_FileIndex
- * String containing Filename of Last IndexEntry. Ending with #0
- .
- .
- * TCC_FileIndex Footer Block
-*********************}
-
interface
{$IFDEF FPC}
@@ -36,15 +18,8 @@ uses OpenGL12,
{$IFNDEF FPC}
Graphics,
{$ENDIF}
- UThemes;
-
-const
- cCC_CoverW = 128;
- cCC_CoverH = 128;
- cCC_CoverSize = cCC_CoverW * cCC_CoverH * 3;
- cCC_HeaderText = 'USDxCo' + #0 + #1;
- cCC_HeaderVersion = 1000;
- cCC_IndexIndicator= 'I' + 'N' + 'D' + #0;
+ UThemes,
+ UTexture;
type
TCover = record
@@ -52,478 +27,223 @@ type
W: word;
H: word;
Size: integer;
- Position: integer; //position of picture in the cache file
+ Position: integer; // position of picture in the cache file
// Data: array of byte;
end;
- //-------------------------------------------------------------------
- //Covers.Cache File Parts
-
- TCC_Hash = Array [1..32] of Char;
- TCC_FileHeader = record
- FileTyp: Array [1..8] of Char; //Some String to detect if this is the file we want to open
- Version: DWord; //Version of Covers.Cache File
- Hash: TCC_Hash; //Some Randomly Created Alphanumeric String to Identify w/ SongDB
- CoverW: Word; //Width of all Covers in Cache
- CoverH: Word; //Height of all Covers in Cache
- DataStart: Cardinal; //Start Position in Bytes of Data Part
- DataLength: Cardinal; //Start Position in Bytes of Data Part
- IndexStart: Cardinal; //Start of Index Block in Bytes
- end;
-
- PCC_TextureData = ^TCC_TextureData;
- TCC_TextureData = Array [0..cCC_CoverSize - 1] of Byte;
-
- TCC_FileIndexHeader = record
- Indicator: Array [1..4] of Char; //Contains INDE
- HighestID: Integer; //Highest ID of a Cover
- end;
-
- TCC_FileIndex = record
- LastUpdated: Integer; //Time of LastFilechange
- DataStart: Cardinal; //Position of TextureData of this Cover in Bytes.
- //0 if this is empty slot(Deleted Cover)(Id not available)
- //1 if the Texture Data is not already loaded to Cache
- //High(Cardinal) if this is IndexFooter
- //Filename: String;
- end;
-
- TCC_IndexListItem = record
- Filename: String;
- TexID: Integer;
- FileIndex: TCC_FileIndex;
- end;
- TCC_IndexList = Array of TCC_IndexListItem;
-
TCovers = class
- private
- Filename: String;
-
- Header: TCC_FileHeader;
- HighestID: Integer;
- Count: Cardinal;
-
- Index: TCC_IndexList;
-
- IndexNeedRewrite: Boolean; //Index in CacheFile is overwritten by other Data
- CacheReadOnly: Boolean; //Cache File is read only
-
- Function WriteHeader(const ReWriteCache: Boolean = false):Boolean;
- Function ReadHeader: Boolean;
- Function ReadIndex: Boolean;
- Function WriteIndex(const ReWriteCache: Boolean = false): Boolean;
- Function AddTexData(Data: PCC_TextureData): Cardinal;
- public
- W: word;
- H: word;
- Size: integer;
- Data: array of byte;
- Cover: array of TCover;
-
- property Hash: TCC_Hash read Header.Hash;
-
- constructor Create(const Filename: String);
- procedure Load(const Filename: String);
- Function AddCover(FileName: string): Integer; //Returns ID, Checks Cover for Change, Updates Cover if required
- function CoverExists(FileName: string): Integer; //Returns ID by FilePath
- procedure PrepareData(FileName: string);
- Procedure LoadTextures;
- Function ReWriteCache: Boolean; //Deletes old cover.cache file and writes new one
-
- Function GetTexbyID(ID: Cardinal): Integer;
+ Cover: array of TCover;
+ W: word;
+ H: word;
+ Size: integer;
+ Data: array of byte;
+ WritetoFile: Boolean;
+
+ constructor Create;
+ procedure Load;
+ procedure Save;
+ procedure AddCover(Name: string);
+ function CoverExists(Name: string): boolean;
+ function CoverNumber(Name: string): integer;
+ procedure PrepareData(Name: string);
end;
var
Covers: TCovers;
- // to - do : new Song management
+
implementation
uses UMain,
// UFiles,
ULog,
- UTexture,
DateUtils;
-constructor TCovers.Create(const Filename: String);
+constructor TCovers.Create;
begin
- HighestID := -1;
- SetLength(Index, HighestID + 2);
- //Load(Filename);
+ W := 128;
+ H := 128;
+ Size := W*H*3;
+ Load;
+ WritetoFile := True;
end;
-//----------------------------------------------
-// Some File handling helpers
-
-//--------
-// Reads and Checks Header. Returns True if Header is correct
-//--------
-Function TCovers.ReadHeader: Boolean;
+procedure TCovers.Load;
var
- F: File of TCC_FileHeader;
+ F: File;
+ C: integer; // cover number
+ W: word;
+ H: word;
+ Bits: byte;
+ NLen: word;
+ Name: string;
+// Data: array of byte;
begin
- try
- //Read Header
- AssignFile(F, Filename);
-
- try
- Reset(F);
- Read(F, Header);
- finally
- CloseFile(F);
- end;
-
- //Check Header
- If (Header.FileTyp = cCC_HeaderText) AND
- (Header.Version = cCC_HeaderVersion) then
- begin
- Result := True;
- IndexNeedRewrite := True;
- end
- Else
- Result := False;
-
-
- except
- Result := False;
- end;
-end;
-
-//--------
-// Writes Header(Resets File). Returns True if Writing succeed
-//--------
-Function TCovers.WriteHeader(const ReWriteCache: Boolean):Boolean;
-var
- F: File of TCC_FileHeader;
-begin
- try
- Result := True;
- //Read Header
- AssignFile(F, Filename);
- try
- If (not FileExists(Filename)) OR (ReWriteCache) then
- ReWrite(F)
- else
- Reset(F);
-
- Write(F, Header);
- finally
- CloseFile(F);
- end;
- except
- Result := False;
- end;
-end;
-
-//--------
-// Reads and Checks Index. Returns True if Index is correct
-//--------
-Function TCovers.ReadIndex: Boolean;
-var
- F: File of Byte;
- IndexHeader: TCC_FileIndexHeader;
- I: Integer;
-
- Procedure mReadLn(var S: String);
- var
- Len: Integer;
+ if FileExists(GamePath + 'covers.cache') then
begin
- S := '';
+ AssignFile(F, GamePath + 'covers.cache');
+ Reset(F, 1);
- BlockRead(F, Len, 4); //Read Len of Filename String
+ WritetoFile := not FileIsReadOnly(GamePath + 'covers.cache');
- //Read Filename String
- SetLength(S, Len);
- BlockRead(F, S[1], Len);
- end;
-begin
- try
- //Read Header
- AssignFile(F, Filename);
- try
- Reset(F);
- Seek(F, Header.IndexStart);
-
- BlockRead(F, IndexHeader, SizeOf(TCC_FileIndexHeader));
-
- If (IndexHeader.Indicator = cCC_IndexIndicator) then
- begin
- Log.LogError('TCovers: loading Cover Index Header. HighestID: ' + InttoStr(IndexHeader.HighestID));
- HighestID := IndexHeader.HighestID;
- SetLength(Index, HighestID + 2);
-
- Count := 0;
- Result := True;
- If (HighestID >= 0) then
- begin
- //Read File Infos until (Eof or Footer)
- I := 0;
- //While (Not Eof(F)) AND ((I <= 0) OR (Index[I-1].FileIndex.DataStart <> High(Cardinal))) do
- Repeat
- Log.LogError('TCovers: loading Cover Index. Position #' + InttoStr(I));
- If (I > HighestID + 1) then
- begin //Header IndexCOunt was wrong, running out of array
- Log.LogError('TCovers: Wrong HighestID in Index Header. Running out of Array at Postion #' + InttoStr(I));
- Inc(HighestID);
- IndexNeedReWrite := True;
- SetLength(Index, HighestID + 2);
- end;
-
- BlockRead(F, Index[I].FileIndex, SizeOf(TCC_FileIndex));
- Index[I].TexID := -1;
-
- If (Index[I].FileIndex.DataStart = High(Cardinal)) then
- begin //Found Footer
- Log.LogError('TCovers: Found footer at Position #' + InttoStr(I));
- Break;
- end;
-
- If (Not Eof(F)) then
- begin
- //Read Filename
- mReadLn(Index[I].Filename);
-
- Log.LogError('TCovers: Cover loaded: ' + Index[I].Filename);
- If (Index[I].FileIndex.DataStart <> 0) AND (Index[I].FileIndex.DataStart <> 1) then
- Inc(Count);
- end;
-
- Inc(I);
- Until Eof(F);
-
- If (Index[HighestID + 1].FileIndex.DataStart = High(Cardinal)) then
- begin //No Footer found
- IndexNeedReWrite := True;
- end;
- end;
-
- end;
-
- finally
- CloseFile(F);
- end;
- except
- Result := False;
- end;
-end;
+ SetLength(Cover, 0);
-//--------
-// Writes Index. Returns True if Writing succeed
-//--------
-Function TCovers.WriteIndex(const ReWriteCache: Boolean): Boolean;
-var
- F: File of Byte;
- IndexHeader: TCC_FileIndexHeader;
- I: Integer;
+ while not EOF(F) do
+ begin
+ SetLength(Cover, Length(Cover)+1);
- Procedure mWriteLn(var S: String);
- var Len: Integer;
- begin
- //Write Length of String
- Len := Length(S);
- BlockWrite(F, Len, 4);
+ BlockRead(F, W, 2);
+ Cover[High(Cover)].W := W;
- //Write String
- BlockWrite(F, S[1], Len);
- end;
-begin
- Result := WriteHeader(ReWriteCache);
+ BlockRead(F, H, 2);
+ Cover[High(Cover)].H := H;
- If (Result) then
- begin
- try
- //Read Header
- AssignFile(F, Filename);
- try
- Reset(F);
+ BlockRead(F, Bits, 1);
- Seek(F, Header.IndexStart);
- //Write Header
- IndexHeader.Indicator := cCC_IndexIndicator;
- IndexHeader.HighestID := HighestID;
+ Cover[High(Cover)].Size := W * H * (Bits div 8);
- BlockWrite(F, IndexHeader, SizeOf(TCC_FileIndexHeader));
+ // test
+ // W := 128;
+ // H := 128;
+ // Bits := 24;
+ // Seek(F, FilePos(F) + 3);
- Count := 0;
- Result := True;
+ BlockRead(F, NLen, 2);
+ SetLength(Name, NLen);
- //Prepare Footer
- Index[HighestID + 1].FileIndex.DataStart := High(Cardinal);
+ BlockRead(F, Name[1], NLen);
+ Cover[High(Cover)].Name := Name;
- // Write Fileinfo
- For I := 0 to HighestID+1 do
- begin
- BlockWrite(F, Index[I].FileIndex, SizeOf(TCC_FileIndex));
- If (I <= HighestID) then
- mWriteLn(Index[I].Filename);
- end;
+ Cover[High(Cover)].Position := FilePos(F);
+ Seek(F, FilePos(F) + W*H*(Bits div 8));
- IndexNeedRewrite := False;
+ // SetLength(Cover[High(Cover)].Data, W*H*(Bits div 8));
+ // BlockRead(F, Cover[High(Cover)].Data[0], W*H*(Bits div 8));
- finally
- CloseFile(F);
- end;
- except
- Result := False;
- end;
- end;
+ end; // While
+
+ CloseFile(F);
+ end; // fileexists
end;
-//--------
-// Writes some Texture Data to the End of TextureData Block
-//--------
-Function TCovers.AddTexData(Data: PCC_TextureData): Cardinal;
+procedure TCovers.Save;
var
- F: File of Byte;
+ F: File;
+ C: integer; // cover number
+ W: word;
+ H: word;
+ NLen: word;
+ Bits: byte;
begin
- try
- AssignFile(F, Filename);
- try
- Reset(F);
- Seek(F, Header.DataStart + Header.DataLength);
-
- BlockWrite(F, Data^, SizeOf(TCC_TextureData));
-
- Result := Header.DataStart + Header.DataLength;
- Inc(Header.DataLength, SizeOf(TCC_TextureData));
-
- Header.IndexStart := Header.DataStart + Header.DataLength + 1;
- IndexNeedReWrite := True;
- finally
- CloseFile(F);
- end;
- except
- Result := 0;
+{ AssignFile(F, GamePath + 'covers.cache');
+ Rewrite(F, 1);
+
+ Bits := 24;
+ for C := 0 to High(Cover) do begin
+ W := Cover[C].W;
+ H := Cover[C].H;
+
+ BlockWrite(F, W, 2);
+ BlockWrite(F, H, 2);
+ BlockWrite(F, Bits, 1);
+
+ NLen := Length(Cover[C].Name);
+ BlockWrite(F, NLen, 2);
+ BlockWrite(F, Cover[C].Name[1], NLen);
+ BlockWrite(F, Cover[C].Data[0], W*H*(Bits div 8));
end;
+
+ CloseFile(F);}
end;
-procedure TCovers.Load(const Filename: String);
+procedure TCovers.AddCover(Name: string);
var
- Succeed: Boolean;
+ B: integer;
+ F: File;
+ C: integer; // cover number
+ NLen: word;
+ Bits: byte;
begin
- Log.LogError('TCovers: Load cache from file: ''' + Filename + '''');
-
- Self.Filename := Filename;
- Succeed := False;
- If (FileExists(Filename)) then
+ if not CoverExists(Name) then
begin
- CacheReadOnly := FileisReadOnly(Filename);
- If (ReadHeader) then
- begin //Header successful read
- If (ReadIndex) then
+ SetLength(Cover, Length(Cover)+1);
+ Cover[High(Cover)].Name := Name;
+
+ Cover[High(Cover)].W := W;
+ Cover[High(Cover)].H := H;
+ Cover[High(Cover)].Size := Size;
+
+ // do not copy data. write them directly to file
+// SetLength(Cover[High(Cover)].Data, Size);
+// for B := 0 to Size-1 do
+// Cover[High(Cover)].Data[B] := CacheMipmap[B];
+
+ if WritetoFile then
+ begin
+ AssignFile(F, GamePath + 'covers.cache');
+
+ if FileExists(GamePath + 'covers.cache') then
begin
- Succeed := True;
+ Reset(F, 1);
+ Seek(F, FileSize(F));
+ end
+ else
+ begin
+ Rewrite(F, 1);
end;
- end;
- end;
- If not Succeed and not CacheReadOnly then
- If not (ReWriteCache) then
- begin
- CacheReadOnly := True;
- Log.LogError('TCovers: Cache readonly!');
- end;
-end;
+ Bits := 24;
-Function TCovers.AddCover(FileName: string): Integer;
-var I: Integer;
-begin
- Result := CoverExists(Filename);
- If (Result = -1) then
- begin //Add Cover(Does not exist)
- Log.LogError('TCovers: Adding cover: ''' + Filename + '''');
- If (Count <= HighestID) then
- begin //There is an empty slot, Search It
- Log.LogError('TCovers: Searching for Empty Slot');
- For I := 0 to HighestID do
- If (Index[I].FileIndex.DataStart = 0) then
- begin //Found that Slot
- Result := I;
- Break;
- end;
- end;
+ BlockWrite(F, W, 2);
+ BlockWrite(F, H, 2);
+ BlockWrite(F, Bits, 1);
- If (Result = -1) then
- begin //Attach it to the End
- Log.LogError('TCovers: Attach Cover to the end');
- Inc(HighestID);
- SetLength(Index, HighestID + 2);
- Result := HighestID;
- end;
+ NLen := Length(Name);
+ BlockWrite(F, NLen, 2);
+ BlockWrite(F, Name[1], NLen);
- Index[Result].Filename := Filename;
- Index[Result].TexID := -1;
- Index[Result].FileIndex.DataStart := 1;
- Log.LogError('TCovers: Cover Added, ID: ' + InttoStr(Result));
- end
- else
- begin //Check if File has Changed
- If (Index[Result].FileIndex.LastUpdated < 0) then
- begin
+ Cover[High(Cover)].Position := FilePos(F);
+ BlockWrite(F, CacheMipmap[0], W*H*(Bits div 8));
+ CloseFile(F);
end;
- end;
+ end
+ else
+ Cover[High(Cover)].Position := 0;
end;
-Function TCovers.CoverExists(FileName: string): integer;
+function TCovers.CoverExists(Name: string): boolean;
var
- I: integer;
+ C: integer; // cover
begin
- Result := -1;
- {$IFDEF MSWINDOWS}
- Filename := Uppercase(Filename);
- {$ENDIF}
-
- For I := 0 to HighestID do
+ Result := false;
+ C := 0;
+
+ while (C <= High(Cover)) and (Result = false) do
begin
- If (Index[I].FileIndex.DataStart <> 0) AND
- {$IFDEF MSWINDOWS}
- (Uppercase(Index[I].Filename) = Filename)
- {$ELSE}
- (Index[I].Filename = Filename)
- {$ENDIF} then
- begin
- Result := I;
- Exit;
- end;
+ if Cover[C].Name = Name then
+ Result := true;
+
+ Inc(C);
end;
end;
-//--------
-// Deletes old cover.cache file and writes new one
-//--------
-Function TCovers.ReWriteCache: Boolean;
-
- Function MakeHash: TCC_Hash;
- const AlphaNumeric: Array[0..35] of Char = ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
- var I: Integer;
- begin
- For I := Low(Result) to High(Result) do
- Result[I] := AlphaNumeric[Random(Length(AlphaNumeric))];
- end;
+function TCovers.CoverNumber(Name: string): integer;
+var
+ C: integer;
begin
- If not CacheReadOnly then
+ Result := -1;
+ C := 0;
+
+ while (C <= High(Cover)) and (Result = -1) do
begin
- Log.LogError('TCovers: Rewriting Cache');
-
- Header.FileTyp := cCC_HeaderText;
- Header.Version := cCC_HeaderVersion;
- Header.Hash := MakeHash;
- Header.CoverW := cCC_CoverW;
- Header.CoverH := cCC_CoverH;
- Header.DataStart := SizeOf(TCC_FileHeader) + 4; //Total of 64 Bytes (4 Bytes Space)
- Header.DataLength := 0;
- Header.IndexStart := Header.DataStart + Header.DataLength + 4;
-
- HighestID := -1;
- SetLength(Index, HighestID + 2);
-
- Result := WriteIndex(True);
- end
- else
- Result := False;
+ if Cover[C].Name = Name then
+ Result := C;
+
+ Inc(C);
+ end;
end;
-procedure TCovers.PrepareData(FileName: string);
+procedure TCovers.PrepareData(Name: string);
var
F: File;
C: integer;
@@ -533,113 +253,12 @@ begin
AssignFile(F, GamePath + 'covers.cache');
Reset(F, 1);
- C := CoverExists(FileName);
+ C := CoverNumber(Name);
SetLength(Data, Cover[C].Size);
- if Length(Data) < 6 then
- Log.LogStatus('Length(Data) < 6', 'TCovers.PrepareData');
Seek(F, Cover[C].Position);
BlockRead(F, Data[0], Cover[C].Size);
CloseFile(F);
end;
end;
-Procedure TCovers.LoadTextures;
-var
- I: Integer;
- TexData: PCC_TextureData;
- CachedData: TCC_TextureData;
- F: File of Byte;
-
- Function LoadCover: Integer;
- begin
- Result := -1;
-
- If (Index[I].FileIndex.DataStart = 1) then
- begin //This Texture is new and has to be loaded
- TexData := Texture.GetCoverThumbnail(Index[I].Filename);
- If (TexData <> nil) then
- begin
- If not (CacheReadonly) then
- begin //Save this Tex to Cache
- Index[I].FileIndex.DataStart := AddTexData(TexData);
- If (Index[I].FileIndex.DataStart = 0) then
- begin
- CacheReadOnly := True; //Failed to write Data
- Log.LogError('Failed to Write TextureData to Cache');
- end;
- end;
-
- //Create Texture
- glGenTextures(1, @Result);
-
- glBindTexture(GL_TEXTURE_2D, Result);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- //glTexImage2D(GL_TEXTURE_2D, 0, 3, cCC_CoverW, cCC_CoverH, 0, GL_RGB, GL_UNSIGNED_BYTE, Data);
- glTexImage2D(GL_TEXTURE_2D, 0, 3, cCC_CoverW, cCC_CoverH, 0, GL_RGB, GL_UNSIGNED_BYTE, TexData);
- end
- else
- Log.LogError('Couldn''t get Thumbnail Data');
- end
- Else If (Index[I].FileIndex.DataStart > 1) then
- begin //This texture is already in Cache, Load it from there
- try
- Log.LogError('TCovers: Loading Cover #' + InttoStr(I) + ' from Cache at Position: ' + InttoStr(Index[I].FileIndex.DataStart));
- Assign(F, Filename);
- try
- Reset(F);
- Seek(F, Index[I].FileIndex.DataStart);
- BlockRead(F, CachedData, SizeOf(TCC_TextureData));
- finally
- CloseFile(F);
- end;
-
-
- //Create Texture
- glGenTextures(1, @Result);
-
- if (Result > 0) then
- begin
-
- glBindTexture(GL_TEXTURE_2D, Result);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- //glTexImage2D(GL_TEXTURE_2D, 0, 3, cCC_CoverW, cCC_CoverH, 0, GL_RGB, GL_UNSIGNED_BYTE, Data);
- glTexImage2D(GL_TEXTURE_2D, 0, 3, cCC_CoverW, cCC_CoverH, 0, GL_RGB, GL_UNSIGNED_BYTE, @CachedData[0]);
- end
- else
- Log.LogError('TCovers: Error Generating Texture');
- except
- Log.LogError('TCovers: Error during loading');
- end;
- end;
- end;
-begin
- Texture.SetCoverSize(cCC_CoverW, cCC_CoverH);
- Log.LogError('TCovers: LoadingTextures');
-
- For I := 0 to HighestID do
- begin //Load all the Covers
- If (Index[I].FileIndex.DataStart > 0) then
- Index[I].TexID := LoadCover; //No empty SLot -> Load the Texture
-
- Log.LogError('TCovers: Texture for ID#' + InttoStr(I) + ': ' + InttoStr(Index[I].TexID));
- end;
-
- If IndexNeedRewrite then
- WriteIndex;
-end;
-
-Function TCovers.GetTexbyID(ID: Cardinal): Integer;
-begin
- If (ID <= HighestID) then
- Result := Index[ID].TexID
- else
- Result := -1;
-end;
-
end.
diff --git a/Game/Code/Classes/UDataBase.pas b/Game/Code/Classes/UDataBase.pas
index ee0ca94b..dcf32315 100644
--- a/Game/Code/Classes/UDataBase.pas
+++ b/Game/Code/Classes/UDataBase.pas
@@ -35,106 +35,28 @@ type
TimesSungtot: Word);
end;
AStatResult = Array of TStatResult;
-
- PDBSongInfo = ^TDBSongInfo;
- TDBSongInfo = record
- FileName: String;
- FolderID: Integer;
- FullPath: String;
- LastChanged: Integer; //TimeStamp
-
- //Required Information
- Artist: widestring;
- Title: widestring;
-
- Mp3: widestring;
-
- //Some Files
- Cover: widestring; //Path to Cover
- CoverID: Integer; //ID of Cover in Covers Cache
- Video: widestring;
- VideoGAP: real;
-
-
- //Additional Information
- Start: real; // in seconds
-
- //Sorting
- Genre: widestring;
- Edition: widestring;
- Language: widestring;
- Year: widestring;
- Creator: widestring;
- TimesPlayed:Word;
- end;
-
- TSongListInfo = record //SongInfo used by Songscreen
- ID: Integer;
- Title: widestring;
- Artist: widestring;
-
- Mp3: widestring;
- Video: widestring;
- CoverID: Integer; //Cover ID in CoversCache
- end;
- ASongList = Array of TSongListInfo;
-
- TSongListFilter = record
- Field: Byte; //FieldID //See constants below
- isSearch: Boolean; //Search Mask(true) or exact Match(False)
- Filter: String;
- end;
- ASongListFilter = Array of TSongListFilter;
-
+
TDataBaseSystem = class
private
ScoreDB: TSqliteDatabase;
sFilename: string;
- UpdateFromVer1: Boolean;
-
+
public
property Filename: String read sFilename;
-
+
Destructor Free;
Procedure Init(const Filename: string);
- Function ReadScore(const Song: Integer; const Difficulty: Byte): AScore;
- procedure AddScore(Song: Integer; Level: integer; Name: string; Score: integer);
- procedure WriteScore(Song: Integer);
-
- Function GetIDbyPath(const Path: String): Integer;
- Function GetIDbyFileName(const Filename: String; FolderID: Integer): Integer;
- Function GetSongData(ID: Integer; const Info: PDBSongInfo): Boolean;
- Function SetSongData(ID: Integer; const Info: PDBSongInfo): Boolean;
- Function AddSong(ID: Integer; const Info: PDBSongInfo): Boolean;
- Function GetLastChangedbyID(const Song: Integer): Integer;
- Function GetLastChangedbyFileName(const Filename: String; FolderID: Integer): Integer;
-
- Function GetFolderIDbyPath(Path: String): Integer;
- Function GetFolderIDbyName(const Name: String; ParentFolder: Integer): Integer;
-
- Function GetSongList(var List: ASongList; const Filter: ASongListFilter): Integer;
+ procedure ReadScore(var Song: TSong);
+ procedure AddScore(var Song: TSong; Level: integer; Name: string; Score: integer);
+ procedure WriteScore(var Song: TSong);
Function GetStats(var Stats: AStatResult; const Typ, Count: Byte; const Page: Cardinal; const Reversed: Boolean): Boolean;
Function GetTotalEntrys(const Typ: Byte): Cardinal;
end;
-const
- //Filter FieldIDs
- SLF_Edition = 0;
- SLF_Genre = 1;
- SLF_Language = 2;
- SLF_Folder = 3;
- SLF_Title = 4;
- SLF_Artist = 5;
- SLF_Year = 6;
- SLF_Creator = 7;
- SLF_Video = 8; //Songs w/ Video are returned
- SLF_NoVideo = 9; //Songs w/o Video are returned
- Max_FilterFieldID = SLF_NoVideo;
-
var
DataBase: TDataBaseSystem;
@@ -148,9 +70,6 @@ uses
const
cUS_Scores = 'us_scores';
cUS_Songs = 'us_songs';
- cUS_Info = 'us_info';
- cUS_Directories = 'us_directories';
- cDB_Version = '2.0.0';
//--------------------
//Create - Opens Database and Create Tables if not Exist
@@ -161,79 +80,26 @@ begin
debugWriteln( 'TDataBaseSystem.Init ('+Filename+') @ '+ floattostr( now() ) );
//Open Database
- ScoreDB := TSqliteDatabase.Create( Filename );
- sFilename := Filename;
- UpdateFromVer1 := False;
+ ScoreDB := TSqliteDatabase.Create( Filename );
+ sFilename := Filename;
try
- //Check for Database Version
- if not ScoreDB.TableExists( cUS_Info ) then
- begin
- If (ScoreDB.TableExists( cUS_Scores ) And ScoreDB.TableExists( cUS_Songs )) And (Not ScoreDB.TableExists( cUS_Directories )) then
- begin //Update from a Ver. 1.0 - 1.0.1a Database
- UpdateFromVer1 := True; //This table should be Updated from before Database ver 2.0
- ScoreDb.ExecSQL('ALTER TABLE `' + cUS_Songs + '` RENAME TO ''' + cUS_Songs + '_old'''); //Rename old Song Table, to achieve old SongIDs
- debugWriteln( 'TDataBaseSystem.Init - Switched to "Update from DB Version 1" Mode' );
- end;
-
- //Create Info Table
- ScoreDB.ExecSQL('CREATE TABLE `' + cUS_Info + '` ( `Ident` varchar(32) PRIMARY KEY, `Value` varchar(64) NOT NULL default '''');');
-
- //Write Database Version to Table
- ScoreDB.ExecSQL('INSERT INTO `' + cUS_Info + '` VALUES (''version'', ''' + cDB_Version + ''');');
-
- debugWriteln( 'TDataBaseSystem.Init - CREATED US_Info' );
- end;
-
//Look for Tables => When not exist Create them
-
- if not ScoreDB.TableExists( cUS_Directories ) then
- begin
- ScoreDB.execsql('CREATE TABLE `' + cUS_Directories + '` ( `ID` integer NOT NULL PRIMARY KEY AUTOINCREMENT, `Name` varchar(255) NOT NULL default '''', `FullPath` text NOT NULL, `LastChange` int(10) NOT NULL default ''0'');');
-
- //Add Root Directory
- ScoreDB.ExecSQL('INSERT INTO `us_directories` VALUES (1, ''root'', '''', ''0'');');
-
- debugWriteln( 'TDataBaseSystem.Init - CREATED US_Directories' );
- end;
-
if not ScoreDB.TableExists( cUS_Scores ) then
begin
- ScoreDB.execsql('CREATE TABLE `'+cUS_Scores+'` (`SongID` INT( 10 ) NOT NULL , `Difficulty` INT( 1 ) NOT NULL , `Player` VARCHAR( 150 ) NOT NULL , `Score` INT( 5 ) NOT NULL );');
-
+ ScoreDB.execsql('CREATE TABLE `'+cUS_Scores+'` (`SongID` INT( 11 ) NOT NULL , `Difficulty` INT( 1 ) NOT NULL , `Player` VARCHAR( 150 ) NOT NULL , `Score` INT( 5 ) NOT NULL );');
debugWriteln( 'TDataBaseSystem.Init - CREATED US_Scores' );
end;
if not ScoreDB.TableExists( cUS_Songs ) then
begin
- // Old 1.0 Style: ScoreDB.execsql('CREATE TABLE `'+cUS_Songs+'` (`ID` INTEGER PRIMARY KEY, `Artist` VARCHAR( 255 ) NOT NULL , `Title` VARCHAR( 255 ) NOT NULL , `TimesPlayed` int(5) NOT NULL );');
- //New: Dataabse 2.0 Style
- ScoreDb.ExecSQL('CREATE TABLE `' + cUS_Songs + '` ( ' +
- '`ID` integer PRIMARY KEY AUTOINCREMENT, ' +
- '`Filename` varchar(255) NOT NULL default '''', ' +
- '`FolderID` int(10) NOT NULL default ''0'', ' +
- '`FullPath` text NOT NULL, ' +
- '`LastChanged` int(10) NOT NULL default ''0'', ' +
- '`Artist` varchar(255) NOT NULL default '''', ' +
- '`Title` varchar(255) NOT NULL default '''', ' +
- '`Mp3` text NOT NULL, ' +
- '`Cover` text NOT NULL, ' +
- '`CoverID` int(10) NOT NULL default ''0'', ' +
- '`Video` text NOT NULL, ' +
- '`VideoGap` float NOT NULL default ''0'', ' +
- '`Start` float NOT NULL default ''0'', ' +
- '`Genre` varchar(255) NOT NULL default '''', ' +
- '`Edition` varchar(255) NOT NULL default '''', ' +
- '`Language` varchar(255) NOT NULL default '''', ' +
- '`Year` varchar(255) NOT NULL default '''', ' +
- '`Creator` varchar(255) NOT NULL default '''', ' +
- '`TimesPlayed` int(5) NOT NULL default ''0'');');
-
- //Delete Score Table to avoid wrong IDS
- ScoreDb.ExecSQL('DELETE FROM `' + cUS_Scores + '`');
-
+ ScoreDB.execsql('CREATE TABLE `'+cUS_Songs+'` (`ID` INTEGER PRIMARY KEY, `Artist` VARCHAR( 255 ) NOT NULL , `Title` VARCHAR( 255 ) NOT NULL , `TimesPlayed` int(5) NOT NULL );');
debugWriteln( 'TDataBaseSystem.Init - CREATED US_Songs' );
end;
+
+ //Not possible because of String Limitation to 255 Chars //Need to rewrite Wrapper
+ {if not ScoreDB.TableExists('US_SongCache') then
+ ScoreDB.ExecSQL('CREATE TABLE `US_SongCache` (`Path` VARCHAR( 255 ) NOT NULL , `Filename` VARCHAR( 255 ) NOT NULL , `Title` VARCHAR( 255 ) NOT NULL , `Artist` VARCHAR( 255 ) NOT NULL , `Folder` VARCHAR( 255 ) NOT NULL , `Genre` VARCHAR( 255 ) NOT NULL , `Edition` VARCHAR( 255 ) NOT NULL , `Language` VARCHAR( 255 ) NOT NULL , `Creator` VARCHAR( 255 ) NOT NULL , `Cover` VARCHAR( 255 ) NOT NULL , `Background` VARCHAR( 255 ) NOT NULL , `Video` VARCHAR( 255 ) NOT NULL , `VideoGap` FLOAT NOT NULL , `Gap` FLOAT NOT NULL , `Start` FLOAT NOT NULL , `Finish` INT( 11 ) NOT NULL , `BPM` INT( 5 ) NOT NULL , `Relative` BOOLEAN NOT NULL , `NotesGap` INT( 11 ) NOT NULL);');}
finally
@@ -257,102 +123,109 @@ end;
//--------------------
//ReadScore - Read Scores into SongArray
//--------------------
-Function TDataBaseSystem.ReadScore(const Song: Integer; const Difficulty: Byte): AScore;
+procedure TDataBaseSystem.ReadScore(var Song: TSong);
var
TableData: TSqliteTable;
- I: Integer;
+ Difficulty: Integer;
begin
- if (assigned( ScoreDB )) AND (Difficulty < 2) then
- begin
+ if not assigned( ScoreDB ) then
+ exit;
+
- //ScoreDB := TSqliteDatabase.Create(sFilename);
+ //ScoreDB := TSqliteDatabase.Create(sFilename);
+ try
try
- try
- //Search Song in DB
- TableData := ScoreDB.GetTable('SELECT `Player`, `Score` FROM `'+cUS_Scores+'` WHERE (`SongID` = ''' + InttoStr(Song) + ''') AND (`Difficulty` = ''' + InttoStr(Difficulty) + ''') ORDER BY `Score` DESC LIMIT 5');
-
-
- I := 0;
- while not TableData.Eof do //Go through all Entrys
- begin //Add one Entry to Array
- Result[I].Name :=
- TableData.FieldAsString(TableData.FieldIndex['Player']);
- Result[I].Score :=
- StrtoInt(TableData.FieldAsString(TableData.FieldIndex['Score']));
-
- TableData.Next;
- Inc(I);
- end; // While not TableData.EOF
-
- If (I < 5) then
- Result[1].Score := 0; //Place ending Zero
-
- except
- Result[0].Name := 'Error Reading ScoreDB';
- Result[0].Score := -1;
- Result[1].Score := 0;
+ //Search Song in DB
+ TableData := ScoreDB.GetTable('SELECT `Difficulty`, `Player`, `Score` FROM `'+cUS_Scores+'` WHERE `SongID` = (SELECT `ID` FROM `us_songs` WHERE `Artist` = "' + Song.Artist + '" AND `Title` = "' + Song.Title + '" LIMIT 1) ORDER BY `Score` DESC LIMIT 15');
+
+ //Empty Old Scores
+ SetLength (Song.Score[0], 0);
+ SetLength (Song.Score[1], 0);
+ SetLength (Song.Score[2], 0);
+
+ while not TableData.Eof do //Go through all Entrys
+ begin //Add one Entry to Array
+ Difficulty := StrToIntDef(TableData.FieldAsString(TableData.FieldIndex['Difficulty']), -1);
+ if (Difficulty >= 0) AND (Difficulty <= 2) then
+ begin
+ SetLength(Song.Score[Difficulty], Length(Song.Score[Difficulty]) + 1);
+
+ Song.Score[Difficulty, high(Song.Score[Difficulty])].Name :=
+ TableData.FieldAsString(TableData.FieldIndex['Player']);
+ Song.Score[Difficulty, high(Song.Score[Difficulty])].Score :=
+ StrtoInt(TableData.FieldAsString(TableData.FieldIndex['Score']));
end;
+ TableData.Next;
+
+ end; // While not TableData.EOF
- finally
- //ScoreDb.Free;
+ except
+ for Difficulty := 0 to 2 do
+ begin
+ SetLength(Song.Score[Difficulty], 1);
+ Song.Score[Difficulty, 1].Name := 'Error Reading ScoreDB';
+ end;
end;
+
+ finally
+ //ScoreDb.Free;
end;
end;
//--------------------
//AddScore - Add one new Score to DB
//--------------------
-procedure TDataBaseSystem.AddScore(Song: Integer; Level: integer; Name: string; Score: integer);
+procedure TDataBaseSystem.AddScore(var Song: TSong; Level: integer; Name: string; Score: integer);
var
ID: Integer;
TableData: TSqliteTable;
begin
- if assigned( ScoreDB ) then
+ if not assigned( ScoreDB ) then
+ exit;
+
+ //ScoreDB := TSqliteDatabase.Create(sFilename);
+ try
+ //Prevent 0 Scores from being added
+ if (Score > 0) then
begin
- //ScoreDB := TSqliteDatabase.Create(sFilename);
- try
- //Prevent 0 Scores from being added
- if (Score > 0) then
- begin
- {ID := ScoreDB.GetTableValue('SELECT `ID` FROM `'+cUS_Songs+'` WHERE `Artist` = "' + Song.Artist + '" AND `Title` = "' + Song.Title + '"');
- if ID = 0 then //Song doesn't exist -> Create
- begin
- ScoreDB.ExecSQL ('INSERT INTO `'+cUS_Songs+'` ( `ID` , `Artist` , `Title` , `TimesPlayed` ) VALUES (NULL , "' + Song.Artist + '", "' + Song.Title + '", "0");');
- ID := ScoreDB.GetTableValue('SELECT `ID` FROM `US_Songs` WHERE `Artist` = "' + Song.Artist + '" AND `Title` = "' + Song.Title + '"');
- if ID = 0 then //Could not Create Table
- exit;
- end; }
- //Create new Entry
- ScoreDB.ExecSQL('INSERT INTO `'+cUS_Scores+'` ( `SongID` , `Difficulty` , `Player` , `Score` ) VALUES ("' + InttoStr(Song) + '", "' + InttoStr(Level) + '", "' + Name + '", "' + InttoStr(Score) + '");');
-
- //Delete Last Position when there are more than 5 Entrys
- if ScoreDB.GetTableValue('SELECT COUNT(`SongID`) FROM `'+cUS_Scores+'` WHERE `SongID` = "' + InttoStr(ID) + '" AND `Difficulty` = "' + InttoStr(Level) +'"') > 5 then
- begin
- TableData := ScoreDB.GetTable('SELECT `Player`, `Score` FROM `'+cUS_Scores+'` WHERE SongID = "' + InttoStr(ID) + '" AND `Difficulty` = "' + InttoStr(Level) +'" ORDER BY `Score` ASC LIMIT 1');
- ScoreDB.ExecSQL('DELETE FROM `US_Scores` WHERE SongID = "' + InttoStr(ID) + '" AND `Difficulty` = "' + InttoStr(Level) +'" AND `Player` = "' + TableData.FieldAsString(TableData.FieldIndex['Player']) + '" AND `Score` = "' + TableData.FieldAsString(TableData.FieldIndex['Score']) + '"');
- end;
+ ID := ScoreDB.GetTableValue('SELECT `ID` FROM `'+cUS_Songs+'` WHERE `Artist` = "' + Song.Artist + '" AND `Title` = "' + Song.Title + '"');
+ if ID = 0 then //Song doesn't exist -> Create
+ begin
+ ScoreDB.ExecSQL ('INSERT INTO `'+cUS_Songs+'` ( `ID` , `Artist` , `Title` , `TimesPlayed` ) VALUES (NULL , "' + Song.Artist + '", "' + Song.Title + '", "0");');
+ ID := ScoreDB.GetTableValue('SELECT `ID` FROM `US_Songs` WHERE `Artist` = "' + Song.Artist + '" AND `Title` = "' + Song.Title + '"');
+ if ID = 0 then //Could not Create Table
+ exit;
+ end;
+ //Create new Entry
+ ScoreDB.ExecSQL('INSERT INTO `'+cUS_Scores+'` ( `SongID` , `Difficulty` , `Player` , `Score` ) VALUES ("' + InttoStr(ID) + '", "' + InttoStr(Level) + '", "' + Name + '", "' + InttoStr(Score) + '");');
- end;
- finally
- //ScoreDB.Free;
+ //Delete Last Position when there are more than 5 Entrys
+ if ScoreDB.GetTableValue('SELECT COUNT(`SongID`) FROM `'+cUS_Scores+'` WHERE `SongID` = "' + InttoStr(ID) + '" AND `Difficulty` = "' + InttoStr(Level) +'"') > 5 then
+ begin
+ TableData := ScoreDB.GetTable('SELECT `Player`, `Score` FROM `'+cUS_Scores+'` WHERE SongID = "' + InttoStr(ID) + '" AND `Difficulty` = "' + InttoStr(Level) +'" ORDER BY `Score` ASC LIMIT 1');
+ ScoreDB.ExecSQL('DELETE FROM `US_Scores` WHERE SongID = "' + InttoStr(ID) + '" AND `Difficulty` = "' + InttoStr(Level) +'" AND `Player` = "' + TableData.FieldAsString(TableData.FieldIndex['Player']) + '" AND `Score` = "' + TableData.FieldAsString(TableData.FieldIndex['Score']) + '"');
end;
+
+ end;
+ finally
+ //ScoreDB.Free;
end;
end;
//--------------------
//WriteScore - Not needed with new System; But used for Increment Played Count
//--------------------
-procedure TDataBaseSystem.WriteScore(Song: Integer);
+procedure TDataBaseSystem.WriteScore(var Song: TSong);
begin
if not assigned( ScoreDB ) then
- begin
- try
- //Increase TimesPlayed
- ScoreDB.ExecSQL ('UPDATE `'+cUS_Songs+'` SET `TimesPlayed` = `TimesPlayed` + ''1'' WHERE `ID` = ''' + InttoStr(Song) + ''';');
- except
+ exit;
+
+ try
+ //Increase TimesPlayed
+ ScoreDB.ExecSQL ('UPDATE `'+cUS_Songs+'` SET `TimesPlayed` = `TimesPlayed` + "1" WHERE `Title` = "' + Song.Title + '" AND `Artist` = "' + Song.Artist + '";');
+ except
- end;
end;
end;
@@ -496,103 +369,4 @@ begin
end;
-Function TDataBaseSystem.GetIDbyPath(const Path: String): Integer;
-begin
-
-end;
-
-Function TDataBaseSystem.GetIDbyFileName(const Filename: String; FolderID: Integer): Integer;
-begin
- try
- Result := ScoreDB.GetTableValue('SELECT `ID` FROM `' + cUS_Songs + '` WHERE (`Filename` = ''' + Filename + ''') AND (`FolderID` = ''' + InttoStr(FolderID) + ''')');
- except
- Result := 0;
- end;
-end;
-
-Function TDataBaseSystem.GetSongData(ID: Integer; const Info: PDBSongInfo): Boolean;
-var
- TableData: TSqliteTable;
-begin
- Result := True;
- try
- TableData := ScoreDB.GetTable('SELECT Filename`, `FolderID`, `FullPath`, `LastChanged`, `Artist`, `Title`, `Mp3`, `Cover`, `CoverID`, `Video`, `VideoGap`, `Start`, `Genre`, `Edition`, `Language`, `Year`, `Creator`, `TimesPlayed` FROM `' + cUS_Songs + '` WHERE `ID` = ''' + InttoStr(ID) + ''' ');
- If (TableData.RowCount > 0) then //All Fieldnames are listed to ensure Field order
- begin //
- Info^.FileName := TableData.Fields[0];
- Info^.FolderID := StrToIntDef(TableData.Fields[1], -1);
- Info^.FullPath := TableData.Fields[2];
- Info^.LastChanged := StrToIntDef(TableData.Fields[3], 0);
- Info^.Artist := TableData.Fields[4];
- Info^.Title := TableData.Fields[5];
- Info^.Mp3 := TableData.Fields[6];
- Info^.Cover := TableData.Fields[7];
- Info^.CoverID := StrToIntDef(TableData.Fields[8], -1);
- Info^.Video := TableData.Fields[9];
- Info^.VideoGAP := StrToFloatDef(TableData.Fields[10], 0);
- Info^.Start := StrToFloatDef(TableData.Fields[11], 0);
- Info^.Genre := TableData.Fields[12];
- Info^.Edition := TableData.Fields[13];
- Info^.Language := TableData.Fields[14];
- Info^.Year := TableData.Fields[15];
- Info^.Creator := TableData.Fields[16];
- Info^.TimesPlayed := StrToIntDef(TableData.Fields[17], 0);
- end;
- except
- Result := False;
- end;
-end;
-
-Function TDataBaseSystem.AddSong(ID: Integer; const Info: PDBSongInfo): Boolean;
-var
- OldID: Integer;
-begin
- Result := True;
- try
- ScoreDB.ExecSQL('INSERT INTO `us_songs` ( `ID` , `Filename` , `FolderID` , `FullPath` , `LastChanged` , `Artist` , `Title` , `Mp3` , `Cover` , `CoverID` , `Video` , `VideoGap` , `Start` , `Genre` , `Edition` , `Language` , `Year` , `Creator` , `TimesPlayed` ) ' +
- 'VALUES ( '''', '''+ Info^.FileName +''', '''+ InttoStr(Info^.FolderID) +''', '''+ Info^.FullPath +''', '''+ InttoStr(Info^.LastChanged) +''', '''+ Info^.Artist +''', '''+ Info^.Title +''', '''+ Info^.Mp3 +''', '''+ Info^.Cover +''', '''+ InttoStr(Info^.CoverID) +''', '''+ Info^.Video + ''', '''+ FloattoStr(Info^.VideoGAP) + ''', '''+ FloattoStr(Info^.Start) +''', '''+ Info^.Genre +''', '''+ Info^.Edition +''', '''+ Info^.Language +''', '''+ Info^.Year +''', '''+ Info^.Creator +''', ''0'');');
-
- //Version 1.0 to 2.0 Update
- If UpdateFromVer1 then
- begin //Search for Song w/ same Artist and Title in Old DB
- OldID := ScoreDB.GetTableValue('SELECT `ID` FROM `US_Songs` WHERE `Artist` = "' + Info^.Artist + '" AND `Title` = "' + Info^.Title + '"');
- end;
- except
- Result := False;
- end;
-end;
-
-Function TDataBaseSystem.SetSongData(ID: Integer; const Info: PDBSongInfo): Boolean;
-begin
-
-end;
-
-Function TDataBaseSystem.GetLastChangedbyID(const Song: Integer): Integer;
-begin
-
-end;
-
-Function TDataBaseSystem.GetLastChangedbyFileName(const Filename: String; FolderID: Integer): Integer;
-begin
-
-end;
-
-
-Function TDataBaseSystem.GetFolderIDbyPath(Path: String): Integer;
-begin
-
-end;
-
-Function TDataBaseSystem.GetFolderIDbyName(const Name: String; ParentFolder: Integer): Integer;
-begin
-
-end;
-
-
-Function TDataBaseSystem.GetSongList(var List: ASongList; const Filter: ASongListFilter): Integer;
-begin
-
-end;
-
-
end.
diff --git a/Game/Code/Classes/UGraphic.pas b/Game/Code/Classes/UGraphic.pas
index 90772ca8..afb986e1 100644
--- a/Game/Code/Classes/UGraphic.pas
+++ b/Game/Code/Classes/UGraphic.pas
@@ -253,7 +253,6 @@ uses UMain,
UIni,
UDisplay,
UCommandLine,
- UCovers,
{$IFNDEF FPC}
Graphics,
{$ENDIF}
@@ -539,8 +538,7 @@ begin
// the mainthread have to know somehow what opengl function have to be called with which parameters like
// texturetype, textureobjekt, textur-buffer-adress, ...
- //Load Covers from Cache and new added/ Updated Covers
- Covers.LoadTextures;
+
// wait for loading thread to finish
// funktioniert so auch noch nicht - currently dos not work this way
diff --git a/Game/Code/Classes/UMain.pas b/Game/Code/Classes/UMain.pas
index 22aa4ad6..f5e1250f 100644
--- a/Game/Code/Classes/UMain.pas
+++ b/Game/Code/Classes/UMain.pas
@@ -234,7 +234,7 @@ begin
// Covers Cache
Log.BenchmarkStart(1);
Log.LogStatus('Creating Covers Cache', 'Initialization');
- Covers := TCovers.Create('covers.cache');
+ Covers := TCovers.Create;
Log.LogBenchmark('Loading Covers Cache Array', 1);
Log.BenchmarkStart(1);
diff --git a/Game/Code/Classes/UPlaylist.pas b/Game/Code/Classes/UPlaylist.pas
index c05460cf..4f181d73 100644
--- a/Game/Code/Classes/UPlaylist.pas
+++ b/Game/Code/Classes/UPlaylist.pas
@@ -267,13 +267,13 @@ begin
exit;
//Hide all Songs
- {For I := 0 to high(CatSongs.Song) do
- CatSongs.Song[I].Visible := False;}
+ For I := 0 to high(CatSongs.Song) do
+ CatSongs.Song[I].Visible := False;
//Show Songs in PL
For I := 0 to high(PlayLists[Index].Items) do
begin
- //CatSongs.Song[PlayLists[Index].Items[I].SongID].Visible := True;
+ CatSongs.Song[PlayLists[Index].Items[I].SongID].Visible := True;
end;
//Set CatSongsMode + Playlist Mode
@@ -335,8 +335,8 @@ Procedure TPlayListManager.DelPlaylist(const Index: Cardinal);
var
I: Integer;
Filename: String;
-begin // to - do : new Song management
- {If Int(Index) > High(Playlists) then
+begin
+ If Int(Index) > High(Playlists) then
Exit;
Filename := PlaylistPath + Playlists[Index].Filename;
@@ -368,7 +368,7 @@ begin // to - do : new Song management
ScreenSong.Interaction := 0;
ScreenSong.FixSelected;
ScreenSong.ChangeMusic;
- end; }
+ end;
end;
//----------
@@ -385,8 +385,8 @@ begin
P := iPlaylist
else
exit;
- // to - do : new Song management
- {if (Int(SongID) <= High(CatSongs.Song)) AND (NOT CatSongs.Song[SongID].Main) then
+
+ if (Int(SongID) <= High(CatSongs.Song)) AND (NOT CatSongs.Song[SongID].Main) then
begin
Len := Length(Playlists[P].Items);
SetLength(Playlists[P].Items, Len + 1);
@@ -401,7 +401,7 @@ begin
//Correct Display when Editing current Playlist
if (CatSongs.CatNumShow = -3) and (P = CurPlaylist) then
SetPlaylist(P);
- end; }
+ end;
end;
//----------
diff --git a/Game/Code/Classes/USong.pas b/Game/Code/Classes/USong.pas
index d878132a..66169ef0 100644
--- a/Game/Code/Classes/USong.pas
+++ b/Game/Code/Classes/USong.pas
@@ -42,7 +42,13 @@ type
StartBeat: real;
end;
- {TSong = class
+ TScore = record
+ Name: widestring;
+ Score: integer;
+ Length: string;
+ end;
+
+ TSong = class
FileLineNo : integer; //Line which is readed at Last, for error reporting
procedure ParseNote(LineNumber: integer; TypeP: char; StartP, DurationP, NoteP: integer; LyricS: string);
@@ -105,88 +111,6 @@ type
function Analyse(): boolean;
function AnalyseXML(): boolean;
procedure clear();
- end; }
-
- TScore = record
- Name: widestring;
- Score: integer;
- Length: string;
- end;
-
- AScore = Array[0..4] of TScore;
-
- {*******************
- New TSong Class.
- Containing some Methods for DB communication
- but none for Song laoding, saving, these should be
- implemented by child classes
- *******************}
- TSong = class
- protected
- SongID: Integer; //ID of this Song in the Song Database
- FolderID: Integer; //ID of the Folder containing this Song
- FileName: String; //Filename of this Song w/o Path
- FilePath: String; //Path of this Song
-
- Procedure ResetAttributes; virtual; //Reset all Attributes of this object
- Procedure ReadHeader; virtual; abstract; //Reads Fileheader (Implemented by Child only)
- Procedure ReadFile; virtual; abstract; //Reads complete File (Header + Notes) (Implemented by Child only)
- Procedure WriteFile; virtual; abstract; //Writes complete File (Header + Notes) (Implemented by Child only)
- Procedure ReadFromDB; virtual; //Reads all available Information from DB
- Function CheckDB: Integer; virtual; //Checks DB for Song. Result > 0 SongExists (ID Returned)
- Function UpdateDB: Integer; virtual; //Writes all Header Information set in this Song Object to DB. Returns ID (Required when Updated first Time)
-
- // procedures to manage the lyrics
- Procedure ResetLyrics;
- Procedure AddLyricLine(const PlayerID: Integer; const StartBeat: Integer; const RelativeBeat: Integer = -1);
- Procedure AddNote(const PlayerID: Integer; const NoteType: Char; const NoteStart, NoteLength, NoteTone: Integer; const NoteText: WideString);
- Function SolmizatLyrics(const NoteTone: Integer; const NoteText: WideString): WideString;
- Procedure AddBPM(const StartBeat: Integer; const NewBeat: Extended);
- public
- //Required Information
- Title: widestring;
- Artist: widestring;
-
- Mp3: widestring; //Full Path to MP3
-
- Creator: widestring;
-
- Resolution: integer;
- BPM: array of TBPM;
- GAP: real; // in miliseconds
-
- Base : array[0..1] of integer;
- Mult : integer;
- MultBPM : integer;
-
- //Some Files
- Cover: widestring; //Full Path to Cover
- CoverID: Integer; //ID of Cover in Covers Cache
- Background: widestring; //Full Path to BG
- Video: widestring; //Full Path to Video
- VideoGAP: real;
-
-
- //Additional Information
- NotesGAP: integer;
- Start: real; // in seconds
- Finish: integer; // in miliseconds
- Relative: boolean;
-
- //Sorting
- Genre: widestring;
- Edition: widestring;
- Language: widestring;
-
-
- constructor Create(const Path: String = ''; const FolderID: Integer = 0);
- Procedure LoadbyFile(const Path: String);
- Procedure LoadbyID(const ID: Integer);
- Procedure SavetoFile(const Filename: String = '');
-
- Function Score(const Difficulty: Byte): AScore;
-
- Procedure Clear;
end;
implementation
@@ -194,288 +118,10 @@ implementation
uses
TextGL,
UIni,
- UMusic; //needed for Lines
-
-var
- RelativPosition: array [0..1] of Integer;
-
-constructor TSong.Create(const Path: String = ''; const FolderID: Integer = 0);
-begin
- If (Length(Path) > 0) AND (FolderID > 0) then
- begin //Read Song Infos from File or DB
- FilePath := ExtractFilePath(Path);
- FileName := ExtractFileName(Path);
- Self.FolderID := FolderID;
- SongID := CheckDB;
-
- If (SongID = 0) then //Check if File has changed
- begin
- ResetAttributes;
- ReadHeader;
- SongID := UpdateDB;
- //Get CoverID from Covers by Covers.AddCover(Coverscache checks if the Cover requires update
- end;
- end
- else
- begin
- ResetAttributes;
- end;
-end;
-
-Procedure TSong.LoadbyFile(const Path: String);
-begin
- //Call all Functions to Load From File
- //Set Song and Folder ID and Update DB if required
- //Get CoverID from Covers by Covers.AddCover(Coverscache checks if the Cover requires update
-end;
-
-Procedure TSong.LoadbyID(const ID: Integer);
-begin
- //Call all Functions to Load Song by ID
- //Read all Information from file
- //Get CoverID from Covers by Covers.AddCover(Coverscache checks if the Cover requires update
-end;
-
-Procedure TSong.SavetoFile(const Filename: String = '');
-begin
- //Save HeaderInformation and Notes to File. If File = '' use File that was read from
-end;
-
-Function TSong.Score(const Difficulty: Byte): AScore;
-begin
- //Return Score of Difficulty(0..2) Easy to Difficult
-end;
-
-Procedure TSong.Clear;
-begin
- ResetAttributes;
-end;
-
-//--------
-// Reset all Attributes of this object
-//--------
-Procedure TSong.ResetAttributes;
-begin
- SongID := 0;
- FolderID := 0;
- FileName := '';
- FilePath := '';
-
- Title := '';
- Artist := '';
- Mp3 := '';
- SetLength(BPM, 0);
-
- Creator := '';
- Resolution := 0;
- GAP := 0;
-
- Base[0] := 100;
- Base[1] := 100;
-
- Mult := 1;
- MultBPM := 4;
-
- Cover := '';
- CoverID := 0;
- Background := '';
- Video := '';
- VideoGAP := 0;
-
- NotesGAP := 0;
- Start := 0;
- Finish := 0;
- Relative := False;
-
- Genre := '';
- Edition := '';
- Language := '';
-end;
-
-//--------
-// Reads all available Information from DB
-//--------
-Procedure TSong.ReadFromDB;
-begin
- // to- do
-end;
-
-
-//--------
-// Checks DB for Song. Result > 0 SongExists (ID Returned)
-//--------
-Function TSong.CheckDB: Integer;
-begin
- // to- do
-end;
-
-
-//--------
-// Writes all Header Information set in this Song Object to DB. Returns ID (Required when Updated first Time)
-//--------
-Function TSong.UpdateDB: Integer;
-begin
- // to- do
-end;
-
-Procedure TSong.ResetLyrics;
-var
- i: Integer;
-begin
- for i := 0 to High(Lines) do
- begin
- SetLength(Lines[i].Line, 0);
- Lines[i].High := -1;
- end;
-
- for i := 0 to High(RelativPosition) do
- begin
- RelativPosition[i] := 0;
- end;
-end;
-
-Procedure TSong.AddLyricLine(const PlayerID: Integer; const StartBeat: Integer; const RelativeBeat: Integer = -1);
-var
- NewLineIdx: Integer;
-begin
- NewLineIdx := High(Lines[PlayerID].Line) + 1;
-
- with Lines[PlayerID] do
- begin
- // recent added line is not the last of the song
- if (NewLineIdx > 0) then
- Lines[PlayerID].Line[NewLineIdx - 1].LastLine := False;
-
- // if last line, has no notes, ignore the new line (except for the RelativeBeat)
- if (NewLineIdx < 1) OR (Lines[PlayerID].Line[NewLineIdx - 1].HighNote > -1) then
- begin
- // create lyric line and update references
- SetLength(Line, NewLineIdx);
- High := NewLineIdx;
- Number := Number + 1;
- with Line[High] do
- begin
- // default values
- TotalNotes := 0;
- HighNote := -1;
- LastLine := True;
- BaseNote := 100;
-
- // set start beat count of this new line
- Start := (RelativPosition[PlayerID] + StartBeat) * Mult;
- end;
- end;
-
- if Relative then
- begin
- if RelativeBeat >= 0 then
- // if this is a relativ song, we have to update the relativ offset
- RelativPosition[PlayerID] := (RelativPosition[PlayerID] + RelativeBeat) * Mult
- else
- RelativPosition[PlayerID] := (RelativPosition[PlayerID] + StartBeat) * Mult;
- end;
- end;
-end;
-
-Procedure TSong.AddNote(const PlayerID: Integer; const NoteType: Char; const NoteStart, NoteLength, NoteTone: Integer; const NoteText: WideString);
-begin
- if (High(Lines[PlayerID].Line) < 0) then
- AddLyricLine(PlayerID, NoteStart, 0);
-
- with Lines[PlayerID].Line[Lines[PlayerID].High] do begin
- // array of Notes expand to have space for new Note
- HighNote := HighNote + 1;
- TotalNotes := TotalNotes + 1;
- SetLength(Note, HighNote + 1);
-
- with Note[HighNote] do
- begin
- Start := (RelativPosition[PlayerID] + NoteStart) * Mult;
- Length := NoteLength * Mult;
- Tone := NoteTone;
- Text := SolmizatLyrics(NoteTone, NoteText);
- Lyric := Lyric + Text;
-
- // identify lowest note of line
- if Tone < BaseNote then
- BaseNote := Tone;
- end;
-
- case NoteType of
- 'F': Note[HighNote].NoteType := ntFreestyle;
- ':': Note[HighNote].NoteType := ntNormal;
- '*': Note[HighNote].NoteType := ntGolden;
- end;
-
- // calculate total score value
- if (Note[HighNote].NoteType = ntNormal) then
- begin
- // normal notes
- Lines[PlayerID].ScoreValue := Lines[PlayerID].ScoreValue + Note[HighNote].Length;
- TotalNotes := TotalNotes + Note[HighNote].Length;
- end
- else if (Note[HighNote].NoteType = ntGolden) then
- begin
- // golden notes
- Lines[PlayerID].ScoreValue := Lines[PlayerID].ScoreValue + (Note[HighNote].Length * 2);
- TotalNotes := TotalNotes + (Note[HighNote].Length * 2);
- end;
-
- // finish of the line
- End_ := Note[HighNote].Start + Note[HighNote].Length;
- end; // with
-end;
+ UMusic, //needed for Lines
+ UMain; //needed for Player
-Function TSong.SolmizatLyrics(const NoteTone: Integer; const NoteText: WideString): WideString;
-begin
- Result := NoteText;
-
- case Ini.Solmization of
- 1: // european
- case (NoteTone mod 12) of
- 0..1: Result := 'do ';
- 2..3: Result := 're ';
- 4: Result := 'mi ';
- 5..6: Result := 'fa ';
- 7..8: Result := 'sol ';
- 9..10: Result := 'la ';
- 11: Result := 'si ';
- end;
-
- 2: // japanese
- case (NoteTone mod 12) of
- 0..1: Result := 'do ';
- 2..3: Result := 're ';
- 4: Result := 'mi ';
- 5..6: Result := 'fa ';
- 7..8: Result := 'so ';
- 9..10: Result := 'la ';
- 11: Result := 'shi ';
- end;
-
- 3: // american
- case (NoteTone mod 12) of
- 0..1: Result := 'do ';
- 2..3: Result := 're ';
- 4: Result := 'mi ';
- 5..6: Result := 'fa ';
- 7..8: Result := 'sol ';
- 9..10: Result := 'la ';
- 11: Result := 'ti ';
- end;
- end; // case Ini.Solmization
-end;
-
-Procedure TSong.AddBPM(const StartBeat: Integer; const NewBeat: Extended);
-begin
- SetLength(BPM, Length(BPM) + 1);
- BPM[High(BPM)].StartBeat := StartBeat;
- BPM[High(BPM)].StartBeat := BPM[High(BPM)].StartBeat + RelativPosition[0];
-
- BPM[High(BPM)].BPM := NewBeat * Mult * MultBPM;
-end;
-
-{constructor TSong.create( const aFileName : WideString );
+constructor TSong.create( const aFileName : WideString );
begin
Mult := 1;
@@ -512,8 +158,7 @@ begin
end;
end;
-}
-(*
+
//Load TXT Song
function TSong.LoadSong(): boolean;
@@ -540,7 +185,7 @@ begin
MultBPM := 4; // multiply beat-count of note by 4
Mult := 1; // accuracy of measurement of note
Base[0] := 100; // high number
- Lines[0].NoteType := 0;
+ Lines[0].ScoreValue := 0;
self.Relative := false;
Rel[0] := 0;
CP := 0;
@@ -589,7 +234,6 @@ begin
Lines[Count].Current := 0;
Lines[Count].Resolution := self.Resolution;
Lines[Count].NotesGAP := self.NotesGAP;
- Lines[Count].Line[0].IlNut := 0;
Lines[Count].Line[0].HighNote := -1;
Lines[Count].Line[0].LastLine := False;
end;
@@ -660,7 +304,11 @@ begin
Lines[CP].Line[Lines[CP].High].TotalNotes := 0;
for I := low(Lines[CP].Line[Lines[CP].High].Note) to high(Lines[CP].Line[Lines[CP].High].Note) do
begin
- Lines[CP].Line[Lines[CP].High].TotalNotes := Lines[CP].Line[Lines[CP].High].TotalNotes + Lines[CP].Line[Lines[CP].High].Note[I].Length * Lines[CP].Line[Lines[CP].High].Note[I].NoteType;
+ if (Lines[CP].Line[Lines[CP].High].Note[I].NoteType = ntGolden) then
+ Lines[CP].Line[Lines[CP].High].TotalNotes := Lines[CP].Line[Lines[CP].High].TotalNotes + Lines[CP].Line[Lines[CP].High].Note[I].Length;
+
+ if (Lines[CP].Line[Lines[CP].High].Note[I].NoteType <> ntFreestyle) then
+ Lines[CP].Line[Lines[CP].High].TotalNotes := Lines[CP].Line[Lines[CP].High].TotalNotes + Lines[CP].Line[Lines[CP].High].Note[I].Length;
end;
//Total Notes Patch End
end else begin
@@ -671,14 +319,17 @@ begin
Lines[Count].Line[Lines[Count].High].TotalNotes := 0;
for I := low(Lines[Count].Line[Lines[Count].High].Note) to high(Lines[Count].Line[Lines[Count].High].Note) do
begin
- Lines[Count].Line[Lines[Count].High].TotalNotes := Lines[Count].Line[Lines[Count].High].TotalNotes + Lines[Count].Line[Lines[Count].High].Note[I].Length * Lines[Count].Line[Lines[Count].High].Note[I].NoteType;
+ if (Lines[Count].Line[Lines[Count].High].Note[I].NoteType = ntGolden) then
+ Lines[Count].Line[Lines[Count].High].TotalNotes := Lines[Count].Line[Lines[Count].High].TotalNotes + Lines[Count].Line[Lines[Count].High].Note[I].Length;
+ if (Lines[Count].Line[Lines[Count].High].Note[I].NoteType <> ntFreestyle) then
+ Lines[Count].Line[Lines[Count].High].TotalNotes := Lines[Count].Line[Lines[Count].High].TotalNotes + Lines[Count].Line[Lines[Count].High].Note[I].Length;
end;
//Total Notes Patch End
end;
end;
Read(SongFile, TempC);
Inc(FileLineNo);
- end; // while} {
+ end; // while}
for Count := 0 to High(Lines) do begin
Lines[Count].Line[High(Lines[Count].Line)].LastLine := True;
@@ -728,7 +379,7 @@ begin
MultBPM := 4; // multiply beat-count of note by 4
Mult := 1; // accuracy of measurement of note
Base[0] := 100; // high number
- Lines[0].NoteType := 0;
+ Lines[0].ScoreValue := 0;
self.Relative := false;
Rel[0] := 0;
CP := 0;
@@ -739,7 +390,7 @@ begin
Parser := TParser.Create;
- Parser.Settings.DashReplacement := '~';
+ Parser.Settings.DashReplacement := '~';
for Count := 0 to High(Lines) do begin
@@ -749,7 +400,6 @@ begin
Lines[Count].Current := 0;
Lines[Count].Resolution := self.Resolution;
Lines[Count].NotesGAP := self.NotesGAP;
- Lines[Count].Line[0].IlNut := 0;
Lines[Count].Line[0].HighNote := -1;
Lines[Count].Line[0].LastLine := False;
end;
@@ -757,38 +407,38 @@ begin
//Try to Parse the Song
If Parser.ParseSong(Path + PathDelim + FileName) then
- begin
-// Writeln('XML Inputfile Parsed succesful');
- //Start write parsed information to Song
- //Notes Part
- For I := 0 to High(Parser.SongInfo.Sentences) do
- begin
- //Add Notes
- For J := 0 to High(Parser.SongInfo.Sentences[I].Notes) do
- begin
- Case Parser.SongInfo.Sentences[I].Notes[J].NoteTyp of
- NT_Normal: NoteType := ':';
- NT_Golden: NoteType := '*';
- NT_Freestyle: NoteType := 'F';
- end;
-
- Param1:=Parser.SongInfo.Sentences[I].Notes[J].Start; //Note Start
- Param2:=Parser.SongInfo.Sentences[I].Notes[J].Duration; //Note Duration
- Param3:=Parser.SongInfo.Sentences[I].Notes[J].Tone; //Note Tone
- ParamS:=' ' + Parser.SongInfo.Sentences[I].Notes[J].Lyric; //Note Lyric
-
-
- if not Both then
+ begin
+// Writeln('XML Inputfile Parsed succesful');
+ //Start write parsed information to Song
+ //Notes Part
+ For I := 0 to High(Parser.SongInfo.Sentences) do
+ begin
+ //Add Notes
+ For J := 0 to High(Parser.SongInfo.Sentences[I].Notes) do
+ begin
+ Case Parser.SongInfo.Sentences[I].Notes[J].NoteTyp of
+ NT_Normal: NoteType := ':';
+ NT_Golden: NoteType := '*';
+ NT_Freestyle: NoteType := 'F';
+ end;
+
+ Param1:=Parser.SongInfo.Sentences[I].Notes[J].Start; //Note Start
+ Param2:=Parser.SongInfo.Sentences[I].Notes[J].Duration; //Note Duration
+ Param3:=Parser.SongInfo.Sentences[I].Notes[J].Tone; //Note Tone
+ ParamS:=' ' + Parser.SongInfo.Sentences[I].Notes[J].Lyric; //Note Lyric
+
+
+ if not Both then
// P1
ParseNote(0, NoteType, (Param1+Rel[0]) * Mult, Param2 * Mult, Param3, ParamS)
else begin
// P1 + P2
ParseNote(0, NoteType, (Param1+Rel[0]) * Mult, Param2 * Mult, Param3, ParamS);
ParseNote(1, NoteType, (Param1+Rel[1]) * Mult, Param2 * Mult, Param3, ParamS);
- end;
-
-
- if not Both then
+ end;
+
+
+ if not Both then
begin
Lines[CP].Line[Lines[CP].High].BaseNote := Base[CP];
Lines[CP].Line[Lines[CP].High].LyricWidth := glTextWidth(PChar(Lines[CP].Line[Lines[CP].High].Lyric));
@@ -796,7 +446,11 @@ If Parser.ParseSong(Path + PathDelim + FileName) then
Lines[CP].Line[Lines[CP].High].TotalNotes := 0;
for X := low(Lines[CP].Line[Lines[CP].High].Note) to high(Lines[CP].Line[Lines[CP].High].Note) do
begin
- Lines[CP].Line[Lines[CP].High].TotalNotes := Lines[CP].Line[Lines[CP].High].TotalNotes + Lines[CP].Line[Lines[CP].High].Note[X].Length * Lines[CP].Line[Lines[CP].High].Note[X].NoteType;
+ if (Lines[CP].Line[Lines[CP].High].Note[I].NoteType = ntGolden) then
+ Lines[CP].Line[Lines[CP].High].TotalNotes := Lines[CP].Line[Lines[CP].High].TotalNotes + Lines[CP].Line[Lines[CP].High].Note[X].Length;
+
+ if (Lines[CP].Line[Lines[CP].High].Note[I].NoteType <> ntFreestyle) then
+ Lines[CP].Line[Lines[CP].High].TotalNotes := Lines[CP].Line[Lines[CP].High].TotalNotes + Lines[CP].Line[Lines[CP].High].Note[X].Length;
end;
//Total Notes Patch End
end else begin
@@ -807,35 +461,39 @@ If Parser.ParseSong(Path + PathDelim + FileName) then
Lines[Count].Line[Lines[Count].High].TotalNotes := 0;
for X := low(Lines[Count].Line[Lines[Count].High].Note) to high(Lines[Count].Line[Lines[Count].High].Note) do
begin
- Lines[Count].Line[Lines[Count].High].TotalNotes := Lines[Count].Line[Lines[Count].High].TotalNotes + Lines[Count].Line[Lines[Count].High].Note[X].Length * Lines[Count].Line[Lines[Count].High].Note[X].NoteType;
- end;
+ if (Lines[Count].Line[Lines[Count].High].Note[I].NoteType = ntGolden) then
+ Lines[Count].Line[Lines[Count].High].TotalNotes := Lines[Count].Line[Lines[Count].High].TotalNotes + Lines[Count].Line[Lines[Count].High].Note[X].Length;
+ if (Lines[Count].Line[Lines[Count].High].Note[I].NoteType <> ntFreestyle) then
+ Lines[Count].Line[Lines[Count].High].TotalNotes := Lines[Count].Line[Lines[Count].High].TotalNotes + Lines[Count].Line[Lines[Count].High].Note[X].Length;
+
+ end;
//Total Notes Patch End
end;
end;
-
-
-
- end; //J Forloop
-
- //Add Sentence break
- If (I < High(Parser.SongInfo.Sentences)) then
- begin
-
- SentenceEnd := Parser.SongInfo.Sentences[I].Notes[High(Parser.SongInfo.Sentences[I].Notes)].Start + Parser.SongInfo.Sentences[I].Notes[High(Parser.SongInfo.Sentences[I].Notes)].Duration;
- Rest := Parser.SongInfo.Sentences[I+1].Notes[0].Start - SentenceEnd;
-
- //Calculate Time
- Case Rest of
- 0, 1: Time := Parser.SongInfo.Sentences[I+1].Notes[0].Start;
- 2: Time := Parser.SongInfo.Sentences[I+1].Notes[0].Start - 1;
- 3: Time := Parser.SongInfo.Sentences[I+1].Notes[0].Start - 2;
- else
- If (Rest >= 4) then
- Time := SentenceEnd + 2
- Else //Sentence overlapping :/
- Time := Parser.SongInfo.Sentences[I+1].Notes[0].Start;
- end;
- // new sentence
+
+
+
+ end; //J Forloop
+
+ //Add Sentence break
+ If (I < High(Parser.SongInfo.Sentences)) then
+ begin
+
+ SentenceEnd := Parser.SongInfo.Sentences[I].Notes[High(Parser.SongInfo.Sentences[I].Notes)].Start + Parser.SongInfo.Sentences[I].Notes[High(Parser.SongInfo.Sentences[I].Notes)].Duration;
+ Rest := Parser.SongInfo.Sentences[I+1].Notes[0].Start - SentenceEnd;
+
+ //Calculate Time
+ Case Rest of
+ 0, 1: Time := Parser.SongInfo.Sentences[I+1].Notes[0].Start;
+ 2: Time := Parser.SongInfo.Sentences[I+1].Notes[0].Start - 1;
+ 3: Time := Parser.SongInfo.Sentences[I+1].Notes[0].Start - 2;
+ else
+ If (Rest >= 4) then
+ Time := SentenceEnd + 2
+ Else //Sentence overlapping :/
+ Time := Parser.SongInfo.Sentences[I+1].Notes[0].Start;
+ end;
+ // new sentence
if not Both then
// P1
NewSentence(0, (Time + Rel[0]) * Mult, Param2)
@@ -843,19 +501,19 @@ If Parser.ParseSong(Path + PathDelim + FileName) then
// P1 + P2
NewSentence(0, (Time + Rel[0]) * Mult, Param2);
NewSentence(1, (Time + Rel[1]) * Mult, Param2);
- end;
-
- end;
- end;
+ end;
+
+ end;
+ end;
//End write parsed information to Song
Parser.Free;
- end
- else
- begin
- Log.LogError('Could not parse Inputfile: ' + Path + PathDelim + FileName);
- exit;
- end;
-
+ end
+ else
+ begin
+ Log.LogError('Could not parse Inputfile: ' + Path + PathDelim + FileName);
+ exit;
+ end;
+
for Count := 0 to High(Lines) do begin
Lines[Count].Line[High(Lines[Count].Line)].LastLine := True;
end;
@@ -1022,10 +680,10 @@ begin
//Required Attributes
//-----------
- {$IFDEF UTF8_FILENAMES} {
+ {$IFDEF UTF8_FILENAMES}
if ((Identifier = 'MP3') or (Identifier = 'BACKGROUND') or (Identifier = 'COVER') or (Identifier = 'VIDEO')) then
Value := Utf8Encode(Value);
- {$ENDIF} {
+ {$ENDIF}
//Title
if (Identifier = 'TITLE') then
@@ -1169,6 +827,126 @@ begin
end;
+procedure TSong.ParseNote(LineNumber: integer; TypeP: char; StartP, DurationP, NoteP: integer; LyricS: string);
+//var
+// Space: boolean; // Auto Removed, Unused Variable
+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);
+ HighNote := High(Note);
+
+ Note[HighNote].Start := StartP;
+ if HighNote = 0 then begin
+ if Lines[LineNumber].Number = 1 then
+ Start := -100;
+// Start := Note[HighNote].Start;
+ end;
+
+ Note[HighNote].Length := DurationP;
+
+ // back to the normal system with normal, golden and now freestyle notes
+ case TypeP of
+ 'F': Note[HighNote].NoteType := ntFreestyle;
+ ':': Note[HighNote].NoteType := ntNormal;
+ '*': Note[HighNote].NoteType := ntGolden;
+ end;
+
+ if (Note[HighNote].NoteType = ntGolden) then
+ Lines[LineNumber].ScoreValue := Lines[LineNumber].ScoreValue + Note[HighNote].Length;
+
+ if (Note[HighNote].NoteType <> ntFreestyle) then
+ Lines[LineNumber].ScoreValue := Lines[LineNumber].ScoreValue + Note[HighNote].Length;
+
+ Note[HighNote].Tone := NoteP;
+ if Note[HighNote].Tone < Base[LineNumber] then Base[LineNumber] := Note[HighNote].Tone;
+
+ Note[HighNote].Text := Copy(LyricS, 2, 100);
+ Lyric := Lyric + Note[HighNote].Text;
+
+ End_ := Note[HighNote].Start + Note[HighNote].Length;
+ end; // with
+end;
+
+procedure TSong.NewSentence(LineNumberP: integer; Param1, Param2: integer);
+var
+I: Integer;
+begin
+
+ // stara czesc //Alter Satz //Update Old Part
+ Lines[LineNumberP].Line[Lines[LineNumberP].High].BaseNote := Base[LineNumberP];
+ Lines[LineNumberP].Line[Lines[LineNumberP].High].LyricWidth := glTextWidth(PChar(Lines[LineNumberP].Line[Lines[LineNumberP].High].Lyric));
+
+ //Total Notes Patch
+ Lines[LineNumberP].Line[Lines[LineNumberP].High].TotalNotes := 0;
+ for I := low(Lines[LineNumberP].Line[Lines[LineNumberP].High].Note) to high(Lines[LineNumberP].Line[Lines[LineNumberP].High].Note) do
+ begin
+ if (Lines[LineNumberP].Line[Lines[LineNumberP].High].Note[I].NoteType = ntGolden) then
+ Lines[LineNumberP].Line[Lines[LineNumberP].High].TotalNotes := Lines[LineNumberP].Line[Lines[LineNumberP].High].TotalNotes + Lines[LineNumberP].Line[Lines[LineNumberP].High].Note[I].Length;
+
+ if (Lines[LineNumberP].Line[Lines[LineNumberP].High].Note[I].NoteType <> ntFreestyle) then
+ Lines[LineNumberP].Line[Lines[LineNumberP].High].TotalNotes := Lines[LineNumberP].Line[Lines[LineNumberP].High].TotalNotes + Lines[LineNumberP].Line[Lines[LineNumberP].High].Note[I].Length;
+ end;
+ //Total Notes Patch End
+
+
+ // nowa czesc //Neuer Satz //Update New Part
+ SetLength(Lines[LineNumberP].Line, Lines[LineNumberP].Number + 1);
+ Lines[LineNumberP].High := Lines[LineNumberP].High + 1;
+ Lines[LineNumberP].Number := Lines[LineNumberP].Number + 1;
+ Lines[LineNumberP].Line[Lines[LineNumberP].High].HighNote := -1;
+
+ if self.Relative then
+ begin
+ Lines[LineNumberP].Line[Lines[LineNumberP].High].Start := Param1;
+ Rel[LineNumberP] := Rel[LineNumberP] + Param2;
+ end
+ else
+ Lines[LineNumberP].Line[Lines[LineNumberP].High].Start := Param1;
+
+ Lines[LineNumberP].Line[Lines[LineNumberP].High].LastLine := False;
+
+ Base[LineNumberP] := 100; // high number
+end;
+
procedure TSong.clear();
begin
//Main Information
@@ -1182,11 +960,11 @@ begin
//Required Information
Mp3 := '';
- {$IFDEF FPC} {
+ {$IFDEF FPC}
setlength( BPM, 0 );
- {$ELSE} {
+ {$ELSE}
BPM := nil;
- {$ENDIF} {
+ {$ENDIF}
GAP := 0;
Start := 0;
@@ -1242,6 +1020,6 @@ begin
//Read Header
Result := self.ReadXMLHeader( FileName );
-end; *)
+end;
end.
diff --git a/Game/Code/Classes/USong_TextFile.pas b/Game/Code/Classes/USong_TextFile.pas
deleted file mode 100644
index a3e605de..00000000
--- a/Game/Code/Classes/USong_TextFile.pas
+++ /dev/null
@@ -1,86 +0,0 @@
-unit USong_TextFile;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-
-uses
- Classes,
- SysUtils,
- USong;
-
-type
- {*******************
- Child of the new TSong class.
- implements filehandling to load a song from a text file
- *******************}
- TSong_TextFile = class(TSong)
- protected
- SongFile: TextFile;
-
- Function OpenSongFile: Boolean;
- Function IsDataAvailable: Boolean;
- Function GetNextLine(): String;
- Procedure CloseSongFile;
- end;
-
-implementation
-
-uses
- ULog;
-
-//--------
-// Open the SongFile
-//--------
-Function TSong_TextFile.OpenSongFile: Boolean;
-begin
- Result := False;
-
- if not FileExists(FilePath + FileName) then
- Log.LogError('File does not exsist', FilePath + FileName)
- else
- begin
- try
- AssignFile(SongFile, FilePath + FileName);
- Reset(SongFile);
- Result := True;
- except
- Log.LogError('Faild to open file', FilePath + FileName)
- end;
- end;
-end;
-
-//--------
-// More data in songfile available?
-//--------
-Function TSong_TextFile.IsDataAvailable: Boolean;
-begin
- Result := not eof(SongFile);
-end;
-
-//--------
-// Returns the next line from the SongFile
-//--------
-Function TSong_TextFile.GetNextLine(): String;
-begin
- ReadLn(SongFile, Result);
- Result := Trim(Result);
-end;
-
-//--------
-// Close the SongFile
-//--------
-Procedure TSong_TextFile.CloseSongFile;
-begin
- try
- CloseFile(SongFile);
- except
- Log.LogError('Error closing file', FilePath + FileName);
- end;
-end;
-
-end. \ No newline at end of file
diff --git a/Game/Code/Classes/USong_Txt.pas b/Game/Code/Classes/USong_Txt.pas
deleted file mode 100644
index a0259baf..00000000
--- a/Game/Code/Classes/USong_Txt.pas
+++ /dev/null
@@ -1,436 +0,0 @@
-unit USong_Txt;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-
-
-uses
- Classes,
- SysUtils,
- USong_TextFile;
-
-type
- {*******************
- Child of the new TSong class.
- implements methods to load a song form a txt file (ultrastar file format)
- *******************}
- TSong_Txt = class(TSong_TextFile)
- public
- Procedure ReadHeader; override; //Reads Fileheader (Implemented by Child only)
- Procedure ReadFile; override; //Reads complete File (Header + Notes) (Implemented by Child only)
- Procedure WriteFile; override; //Writes complete File (Header + Notes) (Implemented by Child only)
- end;
-
-implementation
-
-uses
- UMusic,
- UMain,
- UPlatform,
- ULog;
-
-type
- TTags = (ArtistTag, TitleTag, Mp3Tag, BPMTag);
-
-//--------
-// Reads Fileheader
-//--------
-Procedure TSong_Txt.ReadHeader;
-var
- started: Boolean;
- line, key, value: String;
- FloatValue: Real;
- FoundTags: Set of TTags;
-
- // splits a headerline in key an value
- // returns true on success and false if this is not a valid headerline
- Function SplitHeaderLine(const Line: String; var Key, Value: String): Boolean;
- var
- idx: Integer;
- begin
- Result := False;
-
- idx := Pos(':', Line);
- if idx > 0 then
- begin
- Key := Uppercase(Trim(Copy(Line, 2, idx - 2))); //Uppercase is for Case Insensitive Checks
- Value := Trim(Copy(Line, idx + 1,Length(Line) - idx));
-
- if (Length(Key) > 0) AND (Length(Value) > 0) then
- Result := True
- end;
- end;
-
- function song_StrToFloat(const aValue : String): Extended;
- var
- lValue: String;
- begin
- lValue := aValue;
-
- if (Pos(',', lValue) <> 0) then
- lValue[Pos(',', lValue)] := '.';
-
- Result := StrToFloatDef(lValue, 0);
- end;
-
-begin
- if not OpenSongFile then
- exit;
-
- started := False;
- FoundTags := [];
-
- while isDataAvailable do
- begin
- line := GetNextLine();
-
- // break if header has finished
- if started AND ((Length(line) > 0) AND (not (line[1] = '#'))) then
- break;
-
- // skip invalid lines at beginning
- if (not started) AND (line[1] = '#') then
- started := True;
-
- // parse line
- if started then
- begin
- if (Length(line) > 0) AND not SplitHeaderLine(line, key, value) then
- begin
- Log.LogError('Invalide line in Header of file: ' + FilePath + FileName);
- Log.LogError('Line: ' + line);
- break;
- end;
-
- {$IFDEF UTF8_FILENAMES}
- if ((Key = 'MP3') or (Key = 'BACKGROUND') or (Key = 'COVER') or (Key = 'VIDEO')) then
- Value := Utf8Encode(Value);
- {$ENDIF}
-
- //Title
- if (Key = 'TITLE') then
- begin
- Title := Value;
- FoundTags := FoundTags + [TitleTag];
- continue;
- end;
-
- //Artist
- if (Key = 'ARTIST') then
- begin
- Artist := Value;
- FoundTags := FoundTags + [ArtistTag];
- continue;
- end;
-
- //MP3 File //Test if Exists
- if (Key = 'MP3') then
- begin
- if FileExists(FilePath + Value) then
- begin
- Mp3 := FilePath + Value;
- FoundTags := FoundTags + [Mp3Tag];
- end
- else
- Log.LogError('Can''t find MP3 File: ' + FilePath + Value + ' in Song: ' + FilePath + FileName);
- continue;
- end;
-
- //Beats per Minute
- if (Key = 'BPM') then
- begin
- FloatValue := song_StrtoFloat( Value ) * Mult * MultBPM;
-
- if FloatValue <> 0 then
- begin
- SetLength(BPM, 1);
- BPM[0].StartBeat := 0;
- BPM[0].BPM := floatValue;
- FoundTags := FoundTags + [BPMTag];
- end;
-
- continue;
- end;
-
- //---------
- //Additional Header Information
- //---------
-
- // Gap
- if (Key = 'GAP') then
- begin
- GAP := song_StrtoFloat( Value );
-
- continue;
- end;
-
- //Cover Picture
- if (Key = 'COVER') then
- begin
- if FileExists(FilePath + Value) then
- Cover := FilePath + Value
- else
- Log.LogError('Can''t find Cover File: ' + FilePath + Value + ' in Song: ' + FilePath + FileName);
-
- continue;
- end;
-
- //Background Picture
- if (Key = 'BACKGROUND') then
- begin
- if FileExists(FilePath + Value) then
- Background := FilePath + Value
- else
- Log.LogError('Can''t find Background File: ' + FilePath + Value + ' in Song: ' + FilePath + FileName);
-
- continue;
- end;
-
- // Video File
- if (Key = 'VIDEO') then
- begin
- if FileExists(FilePath + Value) then
- Video := FilePath + Value
- else
- Log.LogError('Can''t find Video File: ' + FilePath + Value + ' in Song: ' + FilePath + FileName);
-
- continue;
- end;
-
- // Video Gap
- if (Key = 'VIDEOGAP') then
- begin
- VideoGAP := song_StrtoFloat(Value);
- continue;
- end;
-
- //Genre Sorting
- if (Key = 'GENRE') then
- begin
- Genre := Value;
- continue;
- end;
-
- //Edition Sorting
- if (Key = 'EDITION') then
- begin
- Edition := Value;
- continue;
- end;
-
- //Creator Tag
- if (Key = 'CREATOR') then
- begin
- Creator := Value;
- continue;
- end;
-
- //Language Sorting
- if (Key = 'LANGUAGE') then
- begin
- Language := Value;
- continue;
- end;
-
- // Song Start
- if (Key = 'START') then
- begin
- Start := song_StrtoFloat( Value );
- continue;
- end;
-
- // Song Ending
- if (Key = 'END') then
- begin
- TryStrtoInt(Value, Finish);
- continue;
- end;
-
- // Resolution
- if (Key = 'RESOLUTION') then
- begin
- TryStrtoInt(Value, Resolution);
- continue;
- end;
-
- // Notes Gap
- if (Key = 'NOTESGAP') then
- begin
- TryStrtoInt(Value, NotesGAP);
- continue;
- end;
-
- // Relative Notes
- if (Key = 'RELATIVE') AND (uppercase(Value) = 'YES') then
- begin
- Relative := True;
- continue;
- end;
-
- end; // if started
- end; // while
-
- if Cover = '' then
- begin
- Cover := platform.FindSongFile(FilePath, '*[CO].jpg');
- end;
-
- // check if all required infos are given
- if not (BPMTag in FoundTags) then
- Log.LogError('BPM Tag missing: ' + FilePath + FileName);
-
- if not (MP3Tag in FoundTags) then
- Log.LogError('MP3 Tag missing or invalid file: ' + FilePath + FileName);
-
- if not (ArtistTag in FoundTags) then
- Log.LogError('Artist Tag missing: ' + FilePath + FileName);
-
- if not (TitleTag in FoundTags) then
- Log.LogError('Title Tag missing: ' + FilePath + FileName);
-
- CloseSongFile();
-end;
-
-//--------
-// Reads complete File (Header + Notes)
-//--------
-Procedure TSong_Txt.ReadFile;
-var
- Line: String;
- NotesRead: Boolean;
- Values: TStringList;
-
- Procedure ParseDelimited(const StringList: TStringList; const Value: String; const Delimiter: String; const MaxParts: Integer);
- var
- idx: Integer;
- Source: String;
- Delta: Integer;
- begin
- Delta := Length(Delimiter);
- Source := Value;
- StringList.BeginUpdate;
- StringList.Clear;
- try
- while ((Pos(Delimiter, Source) > 0) OR ((MaxParts > 0) AND (StringList.count+1 >= MaxParts))) do
- begin
- idx := Pos(Delimiter, Source);
- StringList.Add(Copy(Source,0,idx-1));
- Source := Copy(Source,idx+Delta, MaxInt);
- end;
-
- if (Length(Source) > 0) then
- StringList.Add(Source);
- finally
- StringList.EndUpdate;
- end;
- end;
-
-begin
- // read Header
- Self.ReadHeader;
-
- OpenSongFile();
-
- ResetLyrics;
- NotesRead := False;
-
- while isDataAvailable do
- begin
- line := GetNextLine();
-
- // end of song
- if (line[1] = 'E') then
- break;
-
- // skip invalid lines
- if (line[1] <> ':') OR (line[1] <> 'F') OR (line[1] <> '*') OR (line[1] <> '-') OR (line[1] <> 'B') then
- continue;
-
- // aktuelle Zeile in einzelne Werte aufteilen
- Values := TStringList.Create;
- try
- ParseDelimited(Values, line, ' ', 5);
-
- try
- if (line[1] = '-') then
- if (not NotesRead) then
- // skip newline if no notes before
- continue
- else
- begin
- // new lyric line
- // param count: 1 (relative: 2)
-
- if (Values.Count > 2) then
- // relativ offset
- begin
- // P1
- AddLyricLine(0, StrToInt(Values[1]), StrToInt(Values[2]));
-
- // P2
- if Length(Player) = 2 Then
- AddLyricLine(1, StrToInt(Values[1]), StrToInt(Values[2]))
- end
- else
- begin
- AddLyricLine(0, StrToInt(Values[1]));
-
- // P2
- if Length(Player) = 2 then
- AddLyricLine(1, StrToInt(Values[1]))
- end;
- end;
-
- // new BPM set
- if (line[1] = 'B') then
- begin
- // param count: 2
- AddBPM(StrToInt(Values[1]), StrToFloat(Values[2]));
- end;
-
- if (line[1] = ':') OR (line[1] = '*') OR (line[1] = 'F') then
- begin
- // param count: 4
- if (Values.Count < 5) then
- Log.LogError('Error parsing line: ' + line, 'Not enough arguments.')
- else
- begin
- // Check for ZeroNote
- if StrToInt(Values[2]) = 0 then
- Log.LogError('Found ZeroNote: "' + line + '" -> Note ignored!')
- else
- begin
- // P1
- AddNote(0, line[1], StrToInt(Values[1]), StrToInt(Values[2]), StrToInt(Values[3]), Values[4]);
-
- // P2
- if Length(Player) = 2 then
- AddNote(1, line[1], StrToInt(Values[1]), StrToInt(Values[2]), StrToInt(Values[3]), Values[4]);
- end;
- end;
- end;
- except
- on E : Exception do
- Log.LogError('Error parsing line: ' + line, E.ClassName + ': ' + E.Message);
- end;
- finally
- Values.Free();
- end;
- end;
-
- CloseSongFile();
-end;
-
-//--------
-// Writes complete File (Header + Notes)
-//--------
-Procedure TSong_Txt.WriteFile;
-begin
-end;
-
-end. \ No newline at end of file
diff --git a/Game/Code/Classes/USongs.pas b/Game/Code/Classes/USongs.pas
index 5ae37d5d..df748e74 100644
--- a/Game/Code/Classes/USongs.pas
+++ b/Game/Code/Classes/USongs.pas
@@ -224,7 +224,7 @@ begin
CatCovers.Load;
if assigned( Covers ) then
- Covers.Load('covers.cache');
+ Covers.Load;
if assigned(ScreenSong) then
begin
@@ -259,8 +259,8 @@ var
Files : TDirectoryEntryArray;
lSong : TSong;
begin
- // to - do : new Song management
- {Files := Platform.DirectoryFindFiles( Dir, '.txt', true);
+
+ Files := Platform.DirectoryFindFiles( Dir, '.txt', true);
for i := 0 to Length(Files)-1 do
begin
@@ -282,7 +282,7 @@ begin
end;
end;
SetLength( Files, 0);
- }
+
end;
procedure TSongs.BrowseXMLFiles(Dir: widestring);
@@ -292,7 +292,7 @@ var
lSong : TSong;
begin
- {Files := Platform.DirectoryFindFiles( Dir, '.xml', true);
+ Files := Platform.DirectoryFindFiles( Dir, '.xml', true);
for i := 0 to Length(Files)-1 do
begin
@@ -313,7 +313,7 @@ begin
end;
end;
- SetLength( Files, 0); }
+ SetLength( Files, 0);
end;
@@ -323,7 +323,7 @@ var
S2: integer;
TempSong: TSong;
begin
- {case Order of
+ case Order of
sEdition: // by edition
begin
for S2 := 0 to SongList.Count -1 do
@@ -422,7 +422,7 @@ begin
end;
end;
- end; // case }
+ end; // case
end;
function TSongs.FindSongFile(Dir, Mask: widestring): widestring;
@@ -449,7 +449,7 @@ begin
CatNumShow := -1;
// Songs.Sort(0); // by title
-(*case Ini.Sorting of
+case Ini.Sorting of
sEdition: begin
Songs.Sort(sArtist);
Songs.Sort(sEdition);
@@ -514,7 +514,7 @@ begin
{// cover-patch
if FileExists(CoversPath + SS + '.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + SS + '.jpg'
- else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';//}{
+ else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';//}
CatSongs.Song[CatLen].Cover := CatCovers.GetCover(Ini.Sorting, SS);
@@ -541,7 +541,7 @@ begin
{// cover-patch
if FileExists(CoversPath + SS + '.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + SS + '.jpg'
- else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';}{
+ else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';}
CatSongs.Song[CatLen].Cover := CatCovers.GetCover(Ini.Sorting, SS);
//CatNumber Patch
@@ -567,7 +567,7 @@ begin
{// cover-patch
if FileExists(CoversPath + SS + '.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + SS + '.jpg'
- else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';}{
+ else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';}
CatSongs.Song[CatLen].Cover := CatCovers.GetCover(Ini.Sorting, SS);
//CatNumber Patch
@@ -597,7 +597,7 @@ begin
{// cover-patch
if FileExists(CoversPath + 'Title' + Letter + '.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'Title' + Letter + '.jpg'
- else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';}{
+ else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';}
CatSongs.Song[CatLen].Cover := CatCovers.GetCover(Ini.Sorting, Letter);
//CatNumber Patch
@@ -625,7 +625,7 @@ begin
{// cover-patch
if FileExists(CoversPath + 'Artist' + Letter + '.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'Artist' + Letter + '.jpg'
- else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';}{
+ else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';}
CatSongs.Song[CatLen].Cover := CatCovers.GetCover(Ini.Sorting, Letter);
//CatNumber Patch
@@ -651,7 +651,7 @@ begin
{// cover-patch
if FileExists(CoversPath + SS + '.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + SS + '.jpg'
- else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';}{
+ else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';}
CatSongs.Song[CatLen].Cover := CatCovers.GetCover(Ini.Sorting, SS);
//CatNumber Patch
@@ -680,7 +680,7 @@ begin
{// cover-patch
if FileExists(CoversPath + 'Title' + Letter + '.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'Title' + Letter + '.jpg'
- else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';}{
+ else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';}
CatSongs.Song[CatLen].Cover := CatCovers.GetCover(Ini.Sorting, Letter);
//CatNumber Patch
@@ -710,7 +710,7 @@ begin
{// cover-patch
if FileExists(CoversPath + 'Artist' + Letter + '.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'Artist' + Letter + '.jpg'
- else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';}{
+ else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';}
CatSongs.Song[CatLen].Cover := CatCovers.GetCover(Ini.Sorting, Letter);
//CatNumber Patch
@@ -719,7 +719,7 @@ begin
Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
CatNumber := 0;
end;
-
+
CatSongs.Song[CatLen].Visible := true;
end;
end;
@@ -744,45 +744,45 @@ begin
if (ini.Tabs_at_startup = 1) And (high(Song) >=1) then
Song[CatLen - CatNumber].CatNumber := CatNumber;//Set CatNumber of Categroy
//CatCount Patch
-CatCount := Order; *)
+CatCount := Order;
end;
procedure TCatSongs.ShowCategory(Index: integer);
var
S: integer; // song
-begin // to - do : new Song management
- { CatNumShow := Index;
+begin
+ CatNumShow := Index;
for S := 0 to high(CatSongs.Song) do
begin
if (CatSongs.Song[S].OrderNum = Index) AND (Not CatSongs.Song[S].Main) then
CatSongs.Song[S].Visible := true
else
CatSongs.Song[S].Visible := false;
- end; }
+ end;
end;
procedure TCatSongs.HideCategory(Index: integer); // hides all songs in category
var
S: integer; // song
-begin // to - do : new Song management
- {for S := 0 to high(CatSongs.Song) do begin
+begin
+ for S := 0 to high(CatSongs.Song) do begin
if not CatSongs.Song[S].Main then
CatSongs.Song[S].Visible := false // hides all at now
- end; }
+ end;
end;
procedure TCatSongs.ClickCategoryButton(Index: integer);
var
Num, S: integer;
begin
- { Num := CatSongs.Song[Index].OrderNum;
+ Num := CatSongs.Song[Index].OrderNum;
if Num <> CatNumShow then
begin
ShowCategory(Num);
end
else begin
ShowCategoryList;
- end; }
+ end;
end;
//Hide Categorys when in Category Hack
@@ -790,7 +790,7 @@ procedure TCatSongs.ShowCategoryList;
var
Num, S: integer;
begin
- {//Hide All Songs Show All Cats
+ //Hide All Songs Show All Cats
for S := 0 to high(CatSongs.Song) do begin
if CatSongs.Song[S].Main then
CatSongs.Song[S].Visible := true
@@ -798,7 +798,7 @@ begin
CatSongs.Song[S].Visible := false
end;
CatSongs.Selected := CatNumShow; //Show last shown Category
- CatNumShow := -1; }
+ CatNumShow := -1;
end;
//Hide Categorys when in Category Hack End
@@ -808,7 +808,7 @@ var
I: Integer;
begin
Result := -1;
- I := SearchFrom + 1; {
+ I := SearchFrom + 1;
while not CatSongs.Song[I].Visible do
begin
Inc (I);
@@ -816,7 +816,7 @@ var
I := low(CatSongs.Song);
if (I = SearchFrom) then //Make One Round and no song found->quit
break;
- end; }
+ end;
end;
//Wrong song selected when tabs on bug End
@@ -825,8 +825,8 @@ var
S: integer; // song
begin
Result := 0;
- {for S := 0 to high(CatSongs.Song) do
- if CatSongs.Song[S].Visible = true then Inc(Result); }
+ for S := 0 to high(CatSongs.Song) do
+ if CatSongs.Song[S].Visible = true then Inc(Result);
end;
function TCatSongs.VisibleIndex(Index: integer): integer;
@@ -834,8 +834,8 @@ var
S: integer; // song
begin
Result := 0;
- {for S := 0 to Index-1 do
- if CatSongs.Song[S].Visible = true then Inc(Result); }
+ for S := 0 to Index-1 do
+ if CatSongs.Song[S].Visible = true then Inc(Result);
end;
function TCatSongs.SetFilter(FilterStr: String; const fType: Byte): Cardinal;
@@ -847,7 +847,7 @@ begin
{fType: 0: All
1: Title
2: Artist}
- {FilterStr := Trim(FilterStr);
+ FilterStr := Trim(FilterStr);
if FilterStr<>'' then begin
Result := 0;
//Create Search Array
@@ -893,9 +893,9 @@ begin
for i:=0 to High(Song) do begin
Song[i].Visible:=(Ini.Tabs=1)=Song[i].Main;
CatNumShow := -1;
- end; }
+ end;
Result := 0;
- {end; }
+ end;
end;
diff --git a/Game/Code/Classes/UTexture.pas b/Game/Code/Classes/UTexture.pas
index 3fac0524..a56c0096 100644
--- a/Game/Code/Classes/UTexture.pas
+++ b/Game/Code/Classes/UTexture.pas
@@ -101,7 +101,6 @@ type
function GetTexture(const Name: string; Typ: TTextureType; FromCache: boolean = true): TTexture; overload;
function GetTexture(const Name: string; Typ: TTextureType; Col: LongWord; FromCache: boolean = true): TTexture; overload;
function FindTexture(const Name: string; Typ: TTextureType; Col: Cardinal): integer;
-
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;
@@ -112,8 +111,7 @@ type
Function GetCoverThumbnail(const Name: string): Pointer;
Procedure SetCoverSize(W, H: Integer);
-
-
+
Constructor Create;
Destructor Destroy; override;
end;
@@ -126,16 +124,61 @@ var
Mipmapping: Boolean;
+ CacheMipmap: array[0..256*256*3-1] of byte; // 3KB
+ CacheMipmapSurface: PSDL_Surface;
+
+
implementation
uses ULog,
DateUtils,
+ UCovers,
UThemes,
{$IFDEF DARWIN}
MacResources,
{$ENDIF}
- StrUtils;
+ StrUtils,
+ dialogs;
+const
+ fmt_rgba: TSDL_Pixelformat = (
+ palette: nil;
+ BitsPerPixel: 32;
+ BytesPerPixel: 4;
+ Rloss: 0;
+ Gloss: 0;
+ Bloss: 0;
+ Aloss: 0;
+ Rshift: 0;
+ Gshift: 8;
+ Bshift: 16;
+ Ashift: 24;
+ Rmask: $000000ff;
+ Gmask: $0000ff00;
+ Bmask: $00ff0000;
+ Amask: $ff000000;
+ ColorKey: 0;
+ Alpha: 255
+ );
+ fmt_rgb: TSDL_Pixelformat = (
+ palette: nil;
+ BitsPerPixel: 24;
+ BytesPerPixel: 3;
+ Rloss: 0;
+ Gloss: 0;
+ Bloss: 0;
+ Aloss: 0;
+ Rshift: 0;
+ Gshift: 8;
+ Bshift: 16;
+ Ashift: 0;
+ Rmask: $000000ff;
+ Gmask: $0000ff00;
+ Bmask: $00ff0000;
+ Amask: $00000000;
+ ColorKey: 0;
+ Alpha: 255
+ );
Constructor TTextureUnit.Create;
begin
@@ -308,6 +351,7 @@ begin
Result:=SDL_ScaleSurfaceRect(TempSurface,
0,0,TempSurface^.W,TempSurface^.H,
W,H);
+ SDL_FreeSurface(TempSurface);
end;
procedure TTextureUnit.ScaleTexture(var TexSurface: PSDL_Surface; W,H: Cardinal);
@@ -355,38 +399,85 @@ procedure TTextureUnit.ColorizeTexture(TexSurface: PSDL_Surface; Col: Cardinal);
hue := hue + 6.0;
Result := hue;
end;
- procedure ColorizePixel(Pix: PByteArray; hue: Double);
- var
- clr: array[0..2] of Double; // [0: R, 1: G, 2: B]
- hsv: array[0..2] of Double; // [0: H(ue), 1: S(aturation), 2: V(alue)]
+
+var
+ DestinationHue: Double;
+ PixelIndex: Cardinal;
+ Pixel: PByte;
+ PixelColors: PByteArray;
+// clr: array[0..2] of Double; // [0: R, 1: G, 2: B]
+ clr2: array[0..2] of Uint32;
+// hsv: array[0..2] of Double; // [0: H(ue), 1: S(aturation), 2: V(alue)]
+ hsv2: array[0..2] of UInt32;//LongInt;
+ dhue: UInt32;//LongInt;
h_int: Cardinal;
- delta, f, p, q, t: Double;
- max: Double;
- begin
- clr[0] := Pix[0]/255;
- clr[1] := Pix[1]/255;
- clr[2] := Pix[2]/255;
+// delta, f, p, q, t: Double;
+ delta2,f2,p2,q2,t2: Longint;//LongInt;
+// max: Double;
+ max2: Uint32;
+begin
+ DestinationHue := col2hue(Col);
+
+ dhue:=Trunc(DestinationHue*1024);
+
+ Pixel := TexSurface^.Pixels;
+ for PixelIndex := 0 to (TexSurface^.W * TexSurface^.H)-1 do
+ begin
+ PixelColors:=PByteArray(Pixel);
+ // inlined colorize per pixel
+
+ // uses fixed point math
+ // get color values
+ clr2[0]:=PixelColors[0] shl 10;
+ clr2[1]:=PixelColors[1] shl 10;
+ clr2[2]:=PixelColors[2] shl 10;
//calculate luminance and saturation from rgb
+
+ max2:=clr2[0];
+ if clr2[1]>max2 then max2:=clr2[1];
+ if clr2[2]>max2 then max2:=clr2[2];
+ delta2:=clr2[0];
+ if clr2[1]<delta2 then delta2:=clr2[1];
+ if clr2[2]<delta2 then delta2:=clr2[2];
+ delta2:=max2-delta2;
+ hsv2[0]:=dhue; // shl 8
+ hsv2[2]:=max2; // shl 8
+ if (max2=0) then hsv2[1] := 0
+ else hsv2[1] := (delta2 shl 10) div max2; // shl 8
+ h_int:= hsv2[0] and $fffffC00;
+ f2:= hsv2[0]-h_int; //shl 10
+ p2:= (hsv2[2]*(1024-hsv2[1])) shr 10;
+ q2:= (hsv2[2]*(1024-(hsv2[1]*f2) shr 10)) shr 10;
+ t2:= (hsv2[2]*(1024-(hsv2[1]*(1024-f2)) shr 10)) shr 10;
+ h_int:=h_int shr 10;
+ case h_int of
+ 0: begin clr2[0]:=hsv2[2]; clr2[1]:=t2; clr2[2]:=p2; end; // (v,t,p)
+ 1: begin clr2[0]:=q2; clr2[1]:=hsv2[2]; clr2[2]:=p2; end; // (q,v,p)
+ 2: begin clr2[0]:=p2; clr2[1]:=hsv2[2]; clr2[2]:=t2; end; // (p,v,t)
+ 3: begin clr2[0]:=p2; clr2[1]:=q2; clr2[2]:=hsv2[2]; end; // (p,q,v)
+ 4: begin clr2[0]:=t2; clr2[1]:=p2; clr2[2]:=hsv2[2]; end; // (t,p,v)
+ 5: begin clr2[0]:=hsv2[2]; clr2[1]:=p2; clr2[2]:=q2; end; // (v,p,q)
+ end;
+
+ PixelColors[0]:=clr2[0] shr 10;
+ PixelColors[1]:=clr2[1] shr 10;
+ PixelColors[2]:=clr2[2] shr 10;
+
+ // old floating point version
+(* clr[0] := PixelColors[0]/255;
+ clr[1] := PixelColors[1]/255;
+ clr[2] := PixelColors[2]/255;
max := maxvalue(clr);
delta := max - minvalue(clr);
- hsv[0] := hue; // set H(ue)
+ hsv[0] := DestinationHue; // set H(ue)
hsv[2] := max; // set V(alue)
// calc S(aturation)
if (max = 0.0) then hsv[1] := 0.0
else hsv[1] := delta/max;
- // HSV -> RGB (H from color, S ans V from pixel)
- // transformation according to Gonzalez and Woods
- { This part does not really improve speed, maybe even slows down
- if ((hsv[1] = 0.0) or (hsv[2] = 0.0)) then
- begin
- clr[0]:=hsv[2]; clr[1]:=hsv[2]; clr[2]:=hsv[2]; // (v,v,v)
- end
- else
- }
- begin
+// ColorizePixel(PByteArray(Pixel), DestinationHue);
h_int := trunc(hsv[0]); // h_int = |_h_|
f := hsv[0]-h_int; // f = h-h_int
p := hsv[2]*(1.0-hsv[1]); // p = v*(1-s)
@@ -400,24 +491,12 @@ procedure TTextureUnit.ColorizeTexture(TexSurface: PSDL_Surface; Col: Cardinal);
4: begin clr[0]:=t; clr[1]:=p; clr[2]:=hsv[2]; end; // (t,p,v)
5: begin clr[0]:=hsv[2]; clr[1]:=p; clr[2]:=q; end; // (v,p,q)
end;
- end;
// and store new rgb back into the image
- Pix[0] := trunc(255*clr[0]);
- Pix[1] := trunc(255*clr[1]);
- Pix[2] := trunc(255*clr[2]);
- end;
-
-var
- DestinationHue: Double;
- PixelIndex: Cardinal;
- Pixel: PByte;
-begin
- DestinationHue := col2hue(Col);
- Pixel := TexSurface^.Pixels;
- for PixelIndex := 0 to (TexSurface^.W * TexSurface^.H)-1 do
- begin
- ColorizePixel(PByteArray(Pixel), DestinationHue);
+ PixelColors[0] := trunc(255*clr[0]);
+ PixelColors[1] := trunc(255*clr[1]);
+ PixelColors[2] := trunc(255*clr[2]);
+*)
Inc(Pixel, TexSurface^.format.BytesPerPixel);
end;
end;
@@ -466,7 +545,7 @@ begin
// adjust texture size (scale down, if necessary)
newWidth := TexSurface.W;
newHeight := TexSurface.H;
-
+
if (newWidth > Limit) then
newWidth := Limit;
@@ -634,8 +713,8 @@ begin
Log.BenchmarkEnd(4);
if Log.BenchmarkTimeLength[4] >= 1 then
- Log.LogBenchmark('**********> Texture Load Time Warning - ' + Identifier + '/' + TextureTypeToStr(Typ), 4);
-
+ Log.LogBenchmark('**********> Texture Load Time Warning - ' + Identifier + '/' + TextureTypeToStr(Typ), 4)
+ else Log.LogBenchmark('**********> Texture Load Time ' + ExtractFileName(Identifier) + '/' + TextureTypeToStr(Typ), 4);
{$ifdef blindydebug}
Log.LogStatus('',' JB-8');
{$endif}
@@ -696,10 +775,10 @@ begin
Result := TextureDatabase.Texture[T].Texture;
end;
- {if FromCache and (Covers.CoverExists(Name) >= 0) then
+ if FromCache and Covers.CoverExists(Name) then
begin
// use cache texture
- C := Covers.CoverExists(Name);
+ C := Covers.CoverNumber(Name);
if TextureDatabase.Texture[T].TextureCache.TexNum = -1 then
begin
@@ -710,7 +789,7 @@ begin
// use texture
Result := TextureDatabase.Texture[T].TextureCache;
- end;}
+ end;
end;
//--------