diff options
36 files changed, 2619 insertions, 2113 deletions
diff --git a/Game/Code/Classes/UAudioInput_Bass.pas b/Game/Code/Classes/UAudioInput_Bass.pas index bf0c916e..adc3bf3e 100644 --- a/Game/Code/Classes/UAudioInput_Bass.pas +++ b/Game/Code/Classes/UAudioInput_Bass.pas @@ -1,267 +1,275 @@ -unit UAudioInput_Bass;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-
-
-uses
- Classes,
- SysUtils,
- URecord,
- UMusic;
-
-implementation
-
-uses
- UMain,
- UIni,
- ULog,
- UAudioCore_Bass,
- Windows,
- bass;
-
-type
- TAudioInput_Bass = class(TAudioInputBase)
- public
- function GetName: String; override;
- function InitializeRecord: boolean; override;
- destructor Destroy; override;
- end;
-
- TBassInputDevice = class(TAudioInputDevice)
- public
- DeviceIndex: integer; // index in TAudioInputProcessor.Device[]
- BassDeviceID: integer; // DeviceID used by BASS
- RecordStream: HSTREAM;
-
- function Init(): boolean;
- function Start(): boolean; override;
- procedure Stop(); override;
- end;
-
-var
- singleton_AudioInputBass : IAudioInput;
-
-
-{ Global }
-
-{*
- * Bass input capture callback.
- * Params:
- * stream - BASS input stream
- * buffer - buffer of captured samples
- * len - size of buffer in bytes
- * user - players associated with left/right channels
- *}
-function MicrophoneCallback(stream: HSTREAM; buffer: Pointer;
- len: Cardinal; Card: Cardinal): boolean; stdcall;
-begin
- AudioInputProcessor.HandleMicrophoneData(buffer, len,
- AudioInputProcessor.Device[Card]);
- Result := true;
-end;
-
-
-{ TBassInputDevice }
-
-function TBassInputDevice.Init(): boolean;
-begin
- Result := false;
-
- // TODO: Call once. Otherwise it's to slow
- if not BASS_RecordInit(BassDeviceID) then
- begin
- Log.LogError('TBassInputDevice.Start: Error initializing device['+IntToStr(DeviceIndex)+']: ' +
- TAudioCore_Bass.ErrorGetString());
- Exit;
- end;
-
- Result := true;
-end;
-
-{*
- * Start input-capturing on this device.
- * TODO: call BASS_RecordInit only once
- *}
-function TBassInputDevice.Start(): boolean;
-var
- flags: Word;
-const
- latency = 20; // 20ms callback period (= latency)
-begin
- Result := false;
-
- // recording already started -> stop first
- if (RecordStream <> 0) then
- Stop();
-
- if not Init() then
- Exit;
-
- case AudioFormat.Format of
- asfS16: flags := 0;
- asfFloat: flags := BASS_SAMPLE_FLOAT;
- asfU8: flags := BASS_SAMPLE_8BITS;
- else begin
- Log.LogError('Unhandled sample-format', 'TBassInputDevice.Start');
- Exit;
- end;
- end;
-
- // start capturing
- RecordStream := BASS_RecordStart(AudioFormat.SampleRate, AudioFormat.Channels,
- MakeLong(flags, latency),
- @MicrophoneCallback, DeviceIndex);
- if (RecordStream = 0) then
- begin
- BASS_RecordFree;
- Exit;
- end;
-
- Result := true;
-end;
-
-{*
- * Stop input-capturing on this device.
- *}
-procedure TBassInputDevice.Stop();
-begin
- if (RecordStream = 0) then
- Exit;
- // TODO: Don't free the device. Do this on close
- if (BASS_RecordSetDevice(BassDeviceID)) then
- BASS_RecordFree;
- RecordStream := 0;
-end;
-
-
-{ TAudioInput_Bass }
-
-function TAudioInput_Bass.GetName: String;
-begin
- result := 'BASS_Input';
-end;
-
-function TAudioInput_Bass.InitializeRecord(): boolean;
-var
- Descr: PChar;
- SourceName: PChar;
- Flags: integer;
- BassDeviceID: integer;
- BassDevice: TBassInputDevice;
- DeviceIndex: integer;
- SourceIndex: integer;
- RecordInfo: BASS_RECORDINFO;
-begin
- result := false;
-
- DeviceIndex := 0;
- BassDeviceID := 0;
- SetLength(AudioInputProcessor.Device, 0);
-
- // checks for recording devices and puts them into an array
- while true do
- begin
- Descr := BASS_RecordGetDeviceDescription(BassDeviceID);
- if (Descr = nil) then
- break;
-
- // try to intialize the device
- if not BASS_RecordInit(BassDeviceID) then
- begin
- Log.LogStatus('Failed to initialize BASS Capture-Device['+inttostr(BassDeviceID)+']',
- 'TAudioInput_Bass.InitializeRecord');
- end
- else
- begin
- SetLength(AudioInputProcessor.Device, DeviceIndex+1);
-
- // TODO: free object on termination
- BassDevice := TBassInputDevice.Create();
- AudioInputProcessor.Device[DeviceIndex] := BassDevice;
-
- BassDevice.DeviceIndex := DeviceIndex;
- BassDevice.BassDeviceID := BassDeviceID;
- BassDevice.Description := UnifyDeviceName(Descr, DeviceIndex);
-
- // retrieve recording device info
- BASS_RecordGetInfo(RecordInfo);
-
- // FIXME: does BASS use LSB/MSB or system integer values for 16bit?
-
- // check if BASS has capture-freq. info
- if (RecordInfo.freq > 0) then
- begin
- // use current input sample rate (available only on Windows Vista and OSX).
- // Recording at this rate will give the best quality and performance, as no resampling is required.
- BassDevice.AudioFormat := TAudioFormatInfo.Create(2, RecordInfo.freq, asfS16)
- end
- else
- begin
- // BASS does not provide an explizit input channel count (except BASS_RECORDINFO.formats)
- // but it doesn't fail if we use stereo input on a mono device
- // -> use stereo by default
- BassDevice.AudioFormat := TAudioFormatInfo.Create(2, 44100, asfS16)
- end;
-
- SetLength(BassDevice.CaptureChannel, BassDevice.AudioFormat.Channels);
-
- // get input sources
- SourceIndex := 0;
- BassDevice.MicSource := 0;
-
- // process each input
- while true do
- begin
- SourceName := BASS_RecordGetInputName(SourceIndex);
- if (SourceName = nil) then
- break;
-
- SetLength(BassDevice.Source, SourceIndex+1);
- BassDevice.Source[SourceIndex].Name :=
- UnifyDeviceSourceName(SourceName, BassDevice.Description);
-
- // set mic index
- Flags := BASS_RecordGetInput(SourceIndex);
- if ((Flags <> -1) and ((Flags and BASS_INPUT_TYPE_MIC) <> 0)) then
- begin
- BassDevice.MicSource := SourceIndex;
- end;
-
- Inc(SourceIndex);
- end;
-
- //Writeln('BASS_RecordFree');
- // FIXME: this call hangs in FPC (windows) every 2nd time USDX is called.
- // Maybe because the sound-device was not released properly?
- BASS_RecordFree;
- //Writeln('BASS_RecordFree - Done');
-
- Inc(DeviceIndex);
- end;
-
- Inc(BassDeviceID);
- end;
-
- result := true;
-end;
-
-destructor TAudioInput_Bass.Destroy;
-begin
- inherited;
-end;
-
-
-initialization
- singleton_AudioInputBass := TAudioInput_Bass.create();
- AudioManager.add( singleton_AudioInputBass );
-
-finalization
- AudioManager.Remove( singleton_AudioInputBass );
-
-end.
+unit UAudioInput_Bass; + +interface + +{$IFDEF FPC} + {$MODE Delphi} +{$ENDIF} + +{$I switches.inc} + + +uses + Classes, + SysUtils, + URecord, + UMusic; + +implementation + +uses + UMain, + UIni, + ULog, + UAudioCore_Bass, + Windows, + bass; + +type + TAudioInput_Bass = class(TAudioInputBase) + public + function GetName: String; override; + function InitializeRecord: boolean; override; + destructor Destroy; override; + end; + + TBassInputDevice = class(TAudioInputDevice) + public + DeviceIndex: integer; // index in TAudioInputProcessor.Device[] + BassDeviceID: integer; // DeviceID used by BASS + RecordStream: HSTREAM; + + function Init(): boolean; + function Start(): boolean; override; + procedure Stop(); override; + end; + +var + singleton_AudioInputBass : IAudioInput; + + +{ Global } + +{* + * Bass input capture callback. + * Params: + * stream - BASS input stream + * buffer - buffer of captured samples + * len - size of buffer in bytes + * user - players associated with left/right channels + *} +function MicrophoneCallback(stream: HSTREAM; buffer: Pointer; + len: Cardinal; Card: Cardinal): boolean; stdcall; +begin + AudioInputProcessor.HandleMicrophoneData(buffer, len, + AudioInputProcessor.Device[Card]); + Result := true; +end; + + +{ TBassInputDevice } + +function TBassInputDevice.Init(): boolean; +begin + Result := false; + + // TODO: Call once. Otherwise it's to slow + if not BASS_RecordInit(BassDeviceID) then + begin + Log.LogError('TBassInputDevice.Start: Error initializing device['+IntToStr(DeviceIndex)+']: ' + + TAudioCore_Bass.ErrorGetString()); + Exit; + end; + + Result := true; +end; + +{* + * Start input-capturing on this device. + * TODO: call BASS_RecordInit only once + *} +function TBassInputDevice.Start(): boolean; +var + flags: Word; +const + latency = 20; // 20ms callback period (= latency) +begin + Result := false; + + // recording already started -> stop first + if (RecordStream <> 0) then + Stop(); + + if not Init() then + Exit; + + case AudioFormat.Format of + asfS16: flags := 0; + asfFloat: flags := BASS_SAMPLE_FLOAT; + asfU8: flags := BASS_SAMPLE_8BITS; + else begin + Log.LogError('Unhandled sample-format', 'TBassInputDevice.Start'); + Exit; + end; + end; + + // start capturing + RecordStream := BASS_RecordStart(AudioFormat.SampleRate, AudioFormat.Channels, + MakeLong(flags, latency), + @MicrophoneCallback, DeviceIndex); + if (RecordStream = 0) then + begin + BASS_RecordFree; + Exit; + end; + + Result := true; +end; + +{* + * Stop input-capturing on this device. + *} +procedure TBassInputDevice.Stop(); +begin + if (RecordStream = 0) then + Exit; + // TODO: Don't free the device. Do this on close + if (BASS_RecordSetDevice(BassDeviceID)) then + BASS_RecordFree; + RecordStream := 0; +end; + + +{ TAudioInput_Bass } + +function TAudioInput_Bass.GetName: String; +begin + result := 'BASS_Input'; +end; + +function TAudioInput_Bass.InitializeRecord(): boolean; +var + Descr: PChar; + SourceName: PChar; + Flags: integer; + BassDeviceID: integer; + BassDevice: TBassInputDevice; + DeviceIndex: integer; + SourceIndex: integer; + RecordInfo: BASS_RECORDINFO; +begin + result := false; + + DeviceIndex := 0; + BassDeviceID := 0; + SetLength(AudioInputProcessor.Device, 0); + + // checks for recording devices and puts them into an array + while true do + begin + Descr := BASS_RecordGetDeviceDescription(BassDeviceID); + if (Descr = nil) then + break; + + // try to intialize the device + if not BASS_RecordInit(BassDeviceID) then + begin + Log.LogStatus('Failed to initialize BASS Capture-Device['+inttostr(BassDeviceID)+']', + 'TAudioInput_Bass.InitializeRecord'); + end + else + begin + SetLength(AudioInputProcessor.Device, DeviceIndex+1); + + // TODO: free object on termination + BassDevice := TBassInputDevice.Create(); + AudioInputProcessor.Device[DeviceIndex] := BassDevice; + + BassDevice.DeviceIndex := DeviceIndex; + BassDevice.BassDeviceID := BassDeviceID; + BassDevice.Description := UnifyDeviceName(Descr, DeviceIndex); + + // retrieve recording device info + BASS_RecordGetInfo(RecordInfo); + + // FIXME: does BASS use LSB/MSB or system integer values for 16bit? + + // check if BASS has capture-freq. info + if (RecordInfo.freq > 0) then + begin + // use current input sample rate (available only on Windows Vista and OSX). + // Recording at this rate will give the best quality and performance, as no resampling is required. + BassDevice.AudioFormat := TAudioFormatInfo.Create(2, RecordInfo.freq, asfS16) + end + else + begin + // BASS does not provide an explizit input channel count (except BASS_RECORDINFO.formats) + // but it doesn't fail if we use stereo input on a mono device + // -> use stereo by default + BassDevice.AudioFormat := TAudioFormatInfo.Create(2, 44100, asfS16) + end; + + SetLength(BassDevice.CaptureChannel, BassDevice.AudioFormat.Channels); + + // get input sources + SourceIndex := 0; + BassDevice.MicSource := 0; + + // process each input + while true do + begin + SourceName := BASS_RecordGetInputName(SourceIndex); + {$IFDEF DARWIN} + // Patch for SingStar USB-Microphones: + if ((SourceName = nil) and (SourceIndex = 0) and (Pos('Serial#', Descr) > 0)) then + SourceName := 'Microphone' + else + break; + {$ELSE} + if (SourceName = nil) then + break; + {$ENDIF} + + SetLength(BassDevice.Source, SourceIndex+1); + BassDevice.Source[SourceIndex].Name := + UnifyDeviceSourceName(SourceName, BassDevice.Description); + + // set mic index + Flags := BASS_RecordGetInput(SourceIndex); + if ((Flags <> -1) and ((Flags and BASS_INPUT_TYPE_MIC) <> 0)) then + begin + BassDevice.MicSource := SourceIndex; + end; + + Inc(SourceIndex); + end; + + //Writeln('BASS_RecordFree'); + // FIXME: this call hangs in FPC (windows) every 2nd time USDX is called. + // Maybe because the sound-device was not released properly? + BASS_RecordFree; + //Writeln('BASS_RecordFree - Done'); + + Inc(DeviceIndex); + end; + + Inc(BassDeviceID); + end; + + result := true; +end; + +destructor TAudioInput_Bass.Destroy; +begin + inherited; +end; + + +initialization + singleton_AudioInputBass := TAudioInput_Bass.create(); + AudioManager.add( singleton_AudioInputBass ); + +finalization + AudioManager.Remove( singleton_AudioInputBass ); + +end. diff --git a/Game/Code/Classes/UCommon.pas b/Game/Code/Classes/UCommon.pas index c5dde0c8..62d7df65 100644 --- a/Game/Code/Classes/UCommon.pas +++ b/Game/Code/Classes/UCommon.pas @@ -1,281 +1,293 @@ -unit UCommon;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-
-uses
- SysUtils,
-{$IFDEF LAZARUS}
- lResources,
-{$ENDIF}
- ULog,
-{$IFDEF DARWIN}
- messages,
-{$ENDIF}
-{$IFDEF win32}
- windows;
-{$ELSE}
- lcltype,
- messages;
-{$ENDIF}
-
-{$IFNDEF win32}
-type
- hStream = THandle;
- HGLRC = THandle;
- TLargeInteger = Int64;
- TWin32FindData = LongInt;
-{$ENDIF}
-
-{$IFDEF LAZARUS}
- function LazFindResource( const aName, aType : String ): TLResource;
-{$ENDIF}
-
-{$IFDEF FPC}
-
-function RandomRange(aMin: Integer; aMax: Integer) : Integer;
-
-function MaxValue(const Data: array of Double): Double;
-function MinValue(const Data: array of Double): Double;
-
- {$IFDEF WIN32}
- type
- TWndMethod = procedure(var Message: TMessage) of object;
- function AllocateHWnd(Method: TWndMethod): HWND;
- procedure DeallocateHWnd(Wnd: HWND);
- {$ENDIF} // Win32
-
-{$ENDIF} // FPC Only
-
-function StringReplaceW(text : WideString; search, rep: WideChar):WideString;
-function AdaptFilePaths( const aPath : widestring ): widestring;
-
-
-{$IFNDEF win32}
-(*
- function QueryPerformanceCounter(lpPerformanceCount:TLARGEINTEGER):Bool;
- function QueryPerformanceFrequency(lpFrequency:TLARGEINTEGER):Bool;
-*)
- procedure ZeroMemory( Destination: Pointer; Length: DWORD );
-{$ENDIF}
-
-// eddie: FindFirstW etc are now in UPlatformWindows.pas
-
-(*
- * Character classes
- *)
-
-function IsAlphaChar(ch: WideChar): boolean;
-function IsNumericChar(ch: WideChar): boolean;
-function IsAlphaNumericChar(ch: WideChar): boolean;
-function IsPunctuationChar(ch: WideChar): boolean;
-function IsControlChar(ch: WideChar): boolean;
-
-
-implementation
-
-function StringReplaceW(text : WideString; search, rep: WideChar):WideString;
-var
- iPos : integer;
-// sTemp : WideString;
-begin
-(*
- result := text;
- iPos := Pos(search, result);
- while (iPos > 0) do
- begin
- sTemp := copy(result, iPos + length(search), length(result));
- result := copy(result, 1, iPos - 1) + rep + sTEmp;
- iPos := Pos(search, result);
- end;
-*)
- result := text;
-
- if search = rep then
- exit;
-
- for iPos := 0 to length( result ) - 1 do
- begin
- if result[ iPos ] = search then
- result[ iPos ] := rep;
- end;
-end;
-
-function AdaptFilePaths( const aPath : widestring ): widestring;
-begin
- result := StringReplaceW( aPath, '\', PathDelim );//, [rfReplaceAll] );
-end;
-
-
-{$IFNDEF win32}
-procedure ZeroMemory( Destination: Pointer; Length: DWORD );
-begin
- FillChar( Destination^, Length, 0 );
-end; //ZeroMemory
-
-(*
-function QueryPerformanceCounter(lpPerformanceCount:TLARGEINTEGER):Bool;
-
- // From http://en.wikipedia.org/wiki/RDTSC
- function RDTSC: Int64; register;
- asm
- rdtsc
- end;
-
-begin
- // Use clock_gettime here maybe ... from libc
- lpPerformanceCount := RDTSC();
- result := true;
-end;
-
-function QueryPerformanceFrequency(lpFrequency:TLARGEINTEGER):Bool;
-begin
- lpFrequency := 0;
- result := true;
-end;
-*)
-{$ENDIF}
-
-
-{$IFDEF LAZARUS}
-
-function LazFindResource( const aName, aType : String ): TLResource;
-var
- iCount : Integer;
-begin
- result := nil;
-
- for iCount := 0 to LazarusResources.count -1 do
- begin
- if ( LazarusResources.items[ iCount ].Name = aName ) AND
- ( LazarusResources.items[ iCount ].ValueType = aType ) THEN
- begin
- result := LazarusResources.items[ iCount ];
- exit;
- end;
- end;
-end;
-{$ENDIF}
-
-{$IFDEF FPC}
-// FIXME: already exists in FPC
-function MaxValue(const Data: array of Double): Double;
-var
- I: Integer;
-begin
- Result := Data[Low(Data)];
- for I := Low(Data) + 1 to High(Data) do
- if Result < Data[I] then
- Result := Data[I];
-end;
-
-// FIXME: already exists in FPC
-function MinValue(const Data: array of Double): Double;
-var
- I: Integer;
-begin
- Result := Data[Low(Data)];
- for I := Low(Data) + 1 to High(Data) do
- if Result > Data[I] then
- Result := Data[I];
-end;
-
-function RandomRange(aMin: Integer; aMax: Integer) : Integer;
-begin
-RandomRange := Random(aMax-aMin) + aMin ;
-end;
-
-
-// NOTE !!!!!!!!!!
-// AllocateHWnd is in lclintfh.inc
-
-{$IFDEF MSWINDOWS}
-// TODO : JB this is dodgey and bad... find a REAL solution !
-function AllocateHWnd(Method: TWndMethod): HWND;
-var
- TempClass: TWndClass;
- ClassRegistered: Boolean;
-begin
- Result := CreateWindowEx(WS_EX_TOOLWINDOW, '', '', WS_POPUP , 0, 0, 0, 0, 0, 0, HInstance, nil);
-end;
-
-procedure DeallocateHWnd(Wnd: HWND);
-var
- Instance: Pointer;
-begin
- Instance := Pointer(GetWindowLong(Wnd, GWL_WNDPROC));
- DestroyWindow(Wnd);
-end;
-{$ENDIF}
-{$IFDEF DARWIN}
-// TODO : Situation for the mac isn't better !
-function AllocateHWnd(Method: TWndMethod): HWND;
-begin
-end;
-
-procedure DeallocateHWnd(Wnd: HWND);
-begin
-end;
-{$ENDIF} // IFDEF DARWIN
-
-{$ENDIF} // IFDEF FPC
-
-function IsAlphaChar(ch: WideChar): boolean;
-begin
- // TODO: add chars > 255 when unicode-fonts work?
- case ch of
- 'A'..'Z', // A-Z
- 'a'..'z', // a-z
- #170,#181,#186,
- #192..#214,
- #216..#246,
- #248..#255:
- Result := true;
- else
- Result := false;
- end;
-end;
-
-function IsNumericChar(ch: WideChar): boolean;
-begin
- case ch of
- '0'..'9':
- Result := true;
- else
- Result := false;
- end;
-end;
-
-function IsAlphaNumericChar(ch: WideChar): boolean;
-begin
- Result := (IsAlphaChar(ch) or IsNumericChar(ch));
-end;
-
-function IsPunctuationChar(ch: WideChar): boolean;
-begin
- // TODO: add chars outside of Latin1 basic (0..127)?
- case ch of
- ' '..'/',':'..'@','['..'`','{'..'~':
- Result := true;
- else
- Result := false;
- end;
-end;
-
-function IsControlChar(ch: WideChar): boolean;
-begin
- case ch of
- #0..#31,
- #127..#159:
- Result := true;
- else
- Result := false;
- end;
-end;
-
-end.
+unit UCommon; + +interface + +{$IFDEF FPC} + {$MODE Delphi} +{$ENDIF} + +{$I switches.inc} + +uses + SysUtils, +{$IFDEF LAZARUS} + lResources, +{$ENDIF} + ULog, +{$IFDEF DARWIN} + messages, +{$ENDIF} +{$IFDEF win32} + windows; +{$ELSE} + lcltype, + messages; +{$ENDIF} + +{$IFNDEF win32} +type + hStream = THandle; + HGLRC = THandle; + TLargeInteger = Int64; + TWin32FindData = LongInt; +{$ENDIF} + +{$IFDEF LAZARUS} + function LazFindResource( const aName, aType : String ): TLResource; +{$ENDIF} + +{$IFDEF DARWIN} + procedure ShowMessage( const msg : String ); +{$ENDIF} + +{$IFDEF FPC} + +function RandomRange(aMin: Integer; aMax: Integer) : Integer; + +function MaxValue(const Data: array of Double): Double; +function MinValue(const Data: array of Double): Double; + + {$IFDEF WIN32} + type + TWndMethod = procedure(var Message: TMessage) of object; + function AllocateHWnd(Method: TWndMethod): HWND; + procedure DeallocateHWnd(Wnd: HWND); + {$ENDIF} // Win32 + +{$ENDIF} // FPC Only + +function StringReplaceW(text : WideString; search, rep: WideChar):WideString; +function AdaptFilePaths( const aPath : widestring ): widestring; + + +{$IFNDEF win32} +(* + function QueryPerformanceCounter(lpPerformanceCount:TLARGEINTEGER):Bool; + function QueryPerformanceFrequency(lpFrequency:TLARGEINTEGER):Bool; +*) + procedure ZeroMemory( Destination: Pointer; Length: DWORD ); +{$ENDIF} + +// eddie: FindFirstW etc are now in UPlatformWindows.pas + +(* + * Character classes + *) + +function IsAlphaChar(ch: WideChar): boolean; +function IsNumericChar(ch: WideChar): boolean; +function IsAlphaNumericChar(ch: WideChar): boolean; +function IsPunctuationChar(ch: WideChar): boolean; +function IsControlChar(ch: WideChar): boolean; + + +implementation + +function StringReplaceW(text : WideString; search, rep: WideChar):WideString; +var + iPos : integer; +// sTemp : WideString; +begin +(* + result := text; + iPos := Pos(search, result); + while (iPos > 0) do + begin + sTemp := copy(result, iPos + length(search), length(result)); + result := copy(result, 1, iPos - 1) + rep + sTEmp; + iPos := Pos(search, result); + end; +*) + result := text; + + if search = rep then + exit; + + for iPos := 0 to length( result ) - 1 do + begin + if result[ iPos ] = search then + result[ iPos ] := rep; + end; +end; + +function AdaptFilePaths( const aPath : widestring ): widestring; +begin + result := StringReplaceW( aPath, '\', PathDelim );//, [rfReplaceAll] ); +end; + + +{$IFNDEF win32} +procedure ZeroMemory( Destination: Pointer; Length: DWORD ); +begin + FillChar( Destination^, Length, 0 ); +end; //ZeroMemory + +(* +function QueryPerformanceCounter(lpPerformanceCount:TLARGEINTEGER):Bool; + + // From http://en.wikipedia.org/wiki/RDTSC + function RDTSC: Int64; register; + asm + rdtsc + end; + +begin + // Use clock_gettime here maybe ... from libc + lpPerformanceCount := RDTSC(); + result := true; +end; + +function QueryPerformanceFrequency(lpFrequency:TLARGEINTEGER):Bool; +begin + lpFrequency := 0; + result := true; +end; +*) +{$ENDIF} + + +{$IFDEF LAZARUS} + +function LazFindResource( const aName, aType : String ): TLResource; +var + iCount : Integer; +begin + result := nil; + + for iCount := 0 to LazarusResources.count -1 do + begin + if ( LazarusResources.items[ iCount ].Name = aName ) AND + ( LazarusResources.items[ iCount ].ValueType = aType ) THEN + begin + result := LazarusResources.items[ iCount ]; + exit; + end; + end; +end; +{$ENDIF} + +{$IFDEF FPC} +// FIXME: already exists in FPC +function MaxValue(const Data: array of Double): Double; +var + I: Integer; +begin + Result := Data[Low(Data)]; + for I := Low(Data) + 1 to High(Data) do + if Result < Data[I] then + Result := Data[I]; +end; + +// FIXME: already exists in FPC +function MinValue(const Data: array of Double): Double; +var + I: Integer; +begin + Result := Data[Low(Data)]; + for I := Low(Data) + 1 to High(Data) do + if Result > Data[I] then + Result := Data[I]; +end; + +function RandomRange(aMin: Integer; aMax: Integer) : Integer; +begin +RandomRange := Random(aMax-aMin) + aMin ; +end; + + +// NOTE !!!!!!!!!! +// AllocateHWnd is in lclintfh.inc + +{$IFDEF MSWINDOWS} +// TODO : JB this is dodgey and bad... find a REAL solution ! +function AllocateHWnd(Method: TWndMethod): HWND; +var + TempClass: TWndClass; + ClassRegistered: Boolean; +begin + Result := CreateWindowEx(WS_EX_TOOLWINDOW, '', '', WS_POPUP , 0, 0, 0, 0, 0, 0, HInstance, nil); +end; + +procedure DeallocateHWnd(Wnd: HWND); +var + Instance: Pointer; +begin + Instance := Pointer(GetWindowLong(Wnd, GWL_WNDPROC)); + DestroyWindow(Wnd); +end; +{$ENDIF} +{$IFDEF DARWIN} +// TODO : Situation for the mac isn't better ! +function AllocateHWnd(Method: TWndMethod): HWND; +begin +end; + +procedure DeallocateHWnd(Wnd: HWND); +begin +end; +{$ENDIF} // IFDEF DARWIN + +{$ENDIF} // IFDEF FPC + +{$IFDEF DARWIN} +procedure ShowMessage( const msg : String ); +begin + //eddie: what to do here? +end; +{$ENDIF} + + +function IsAlphaChar(ch: WideChar): boolean; +begin + // TODO: add chars > 255 when unicode-fonts work? + case ch of + 'A'..'Z', // A-Z + 'a'..'z', // a-z + #170,#181,#186, + #192..#214, + #216..#246, + #248..#255: + Result := true; + else + Result := false; + end; +end; + +function IsNumericChar(ch: WideChar): boolean; +begin + case ch of + '0'..'9': + Result := true; + else + Result := false; + end; +end; + +function IsAlphaNumericChar(ch: WideChar): boolean; +begin + Result := (IsAlphaChar(ch) or IsNumericChar(ch)); +end; + +function IsPunctuationChar(ch: WideChar): boolean; +begin + // TODO: add chars outside of Latin1 basic (0..127)? + case ch of + ' '..'/',':'..'@','['..'`','{'..'~': + Result := true; + else + Result := false; + end; +end; + +function IsControlChar(ch: WideChar): boolean; +begin + case ch of + #0..#31, + #127..#159: + Result := true; + else + Result := false; + end; +end; + +end. diff --git a/Game/Code/Classes/UConfig.pas b/Game/Code/Classes/UConfig.pas index ee4685d3..ae9ac150 100644 --- a/Game/Code/Classes/UConfig.pas +++ b/Game/Code/Classes/UConfig.pas @@ -196,7 +196,7 @@ function USDXShortVersionStr(): string; implementation uses - StrUtils; + StrUtils, Math; function USDXShortVersionStr(): string; begin diff --git a/Game/Code/Classes/UMain.pas b/Game/Code/Classes/UMain.pas index 879c5c79..f9762c1e 100644 --- a/Game/Code/Classes/UMain.pas +++ b/Game/Code/Classes/UMain.pas @@ -1,1165 +1,1164 @@ -unit UMain;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-
-uses
- SDL,
- UGraphic,
- UMusic,
- URecord,
- UTime,
- SysUtils,
- UDisplay,
- UIni,
- ULog,
- ULyrics,
- UScreenSing,
- USong,
- OpenGL12,
- {$IFDEF UseSerialPort}
- //zlportio, //you can disable it and all PortWriteB calls
- {$ENDIF}
- //ULCD, //TODO: maybe LCD Support as Plugin?
- //ULight, //TODO: maybe Light Support as Plugin?
- UThemes;
-
-type
- TPlayer = record
- Name: string;
-
- // Index in Teaminfo record
- TeamID: Byte;
- PlayerID: Byte;
-
- // Scores
- Score: real;
- ScoreLine: real;
- ScoreGolden: real;
-
- ScoreI: integer;
- ScoreLineI: integer;
- ScoreGoldenI: integer;
- ScoreTotalI: integer;
-
- // LineBonus Mod
- ScoreLast: Real;//Last Line Score
-
- // PerfectLineTwinkle Mod (effect)
- LastSentencePerfect: Boolean;
-
- //Meter: real;
-
- HighNote: integer;
- IlNut: integer;
- Note: array of record
- Start: integer;
- Length: integer;
- Detekt: real; // accurate place, detected in the note
- Tone: real;
- Perfect: boolean; // true if the note matches the original one, lit the star
-
- // Half size Notes Patch
- Hit: boolean; // true if the note Hits the Line
- end;
- end;
-
-
-var
- // Absolute Paths
- GamePath: string;
- SoundPath: string;
- SongPath: string;
- LogPath: string;
- ThemePath: string;
- SkinsPath: string;
- ScreenshotsPath: string;
- CoversPath: string;
- LanguagesPath: string;
- PluginPath: string;
- VisualsPath: string;
- PlayListPath: string;
-
- UserSongPath: string = '';
- UserCoversPath: string = '';
- UserPlaylistPath: string = '';
-
- OGL: Boolean;
- Done: Boolean;
- Event: TSDL_event;
- FileName: string;
- Restart: boolean;
-
- // player and music info
- Player: array of TPlayer;
- PlayersPlay: integer;
-
- CurrentSong : TSong;
-
-procedure InitializePaths;
-
-Procedure Main;
-procedure MainLoop;
-procedure CheckEvents;
-procedure Sing(Sender: TScreenSing);
-procedure NewSentence(Sender: TScreenSing);
-procedure NewBeat(Sender: TScreenSing); // executed when on then new beat
-procedure NewBeatC(Sender: TScreenSing); // executed when on then new beat for click
-procedure NewBeatD(Sender: TScreenSing); // executed when on then new beat for detection
-//procedure NewHalf; // executed when in the half between beats
-procedure NewNote(Sender: TScreenSing); // detect note
-function GetMidBeat(Time: real): real;
-function GetTimeFromBeat(Beat: integer): real;
-procedure ClearScores(PlayerNum: integer);
-
-implementation
-
-uses
- USongs,
- UJoystick,
- math,
- UCommandLine,
- ULanguage,
- SDL_ttf,
- USkins,
- UCovers,
- UCatCovers,
- UDataBase,
- UPlaylist,
- UDLLManager,
- UParty,
- UConfig,
- UCore,
- UGraphicClasses,
- UPluginDefs,
- UPlatform;
-
-procedure Main;
-var
- WndTitle: string;
-begin
- try
- WndTitle := USDXVersionStr;
-
- if Platform.TerminateIfAlreadyRunning( {var} WndTitle) then
- Exit;
-
- //------------------------------
- //StartUp - Create Classes and Load Files
- //------------------------------
- USTime := TTime.Create;
-
- // Commandline Parameter Parser
- Params := TCMDParams.Create;
-
- // Log + Benchmark
- Log := TLog.Create;
- Log.Title := WndTitle;
- Log.Enabled := not Params.NoLog;
- Log.BenchmarkStart(0);
-
- // Language
- Log.BenchmarkStart(1);
- Log.LogStatus('Initialize Paths', 'Initialization');
- InitializePaths;
- Log.LogStatus('Load Language', 'Initialization');
- Language := TLanguage.Create;
-
- // Add Const Values:
- Language.AddConst('US_VERSION', USDXVersionStr);
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading Language', 1);
-
- // SDL
- Log.BenchmarkStart(1);
- Log.LogStatus('Initialize SDL', 'Initialization');
- SDL_Init(SDL_INIT_VIDEO);
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Initializing SDL', 1);
-
- // SDL_ttf
- Log.BenchmarkStart(1);
- Log.LogStatus('Initialize SDL_ttf', 'Initialization');
- TTF_Init();
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Initializing SDL_ttf', 1);
-
- // Skin
- Log.BenchmarkStart(1);
- Log.LogStatus('Loading Skin List', 'Initialization');
- Skin := TSkin.Create;
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading Skin List', 1);
-
- // Ini + Paths
- Log.BenchmarkStart(1);
- Log.LogStatus('Load Ini', 'Initialization');
- Ini := TIni.Create;
- Ini.Load;
-
- //Load Languagefile
- if (Params.Language <> -1) then
- Language.ChangeLanguage(ILanguage[Params.Language])
- else
- Language.ChangeLanguage(ILanguage[Ini.Language]);
-
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading Ini', 1);
-
- // Sound
- Log.BenchmarkStart(1);
- Log.LogStatus('Initialize Sound', 'Initialization');
- InitializeSound();
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Initializing Sound', 1);
-
- // Load Sound Settings from Ini
- Log.BenchmarkStart(1);
- Log.LogStatus('Load Sound Settings', 'Initialization');
- Ini.LoadSoundSettings;
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Load Sound Settings', 1);
-
- // LCD //TODO: maybe LCD Support as Plugin?
- //Log.BenchmarkStart(1);
- //Log.LogStatus('Load LCD', 'Initialization');
- //LCD := TLCD.Create;
- (*
- if Ini.LPT = 1 then
- begin
- //LCD.HalfInterface := true;
- LCD.Enable;
- LCD.Clear;
- LCD.WriteText(1, ' UltraStar ');
- LCD.WriteText(2, ' Loading... ');
- end;
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading LCD', 1);
- *)
- // Light //TODO: maybe Light Support as Plugin?
- (*
- Log.BenchmarkStart(1);
- Log.LogStatus('Load Light', 'Initialization');
- Light := TLight.Create;
- if Ini.LPT = 2 then
- begin
- Light.Enable;
- end;
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading Light', 1);
- *)
-
-
- // Theme
- Log.BenchmarkStart(1);
- Log.LogStatus('Load Themes', 'Initialization');
- Theme := TTheme.Create(ThemePath + ITheme[Ini.Theme] + '.ini', Ini.Color);
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading Themes', 1);
-
- // Covers Cache
- Log.BenchmarkStart(1);
- Log.LogStatus('Creating Covers Cache', 'Initialization');
- Covers := TCovers.Create;
- Log.LogBenchmark('Loading Covers Cache Array', 1);
- Log.BenchmarkStart(1);
-
- // Category Covers
- Log.BenchmarkStart(1);
- Log.LogStatus('Creating Category Covers Array', 'Initialization');
- CatCovers:= TCatCovers.Create;
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading Category Covers Array', 1);
-
- // Songs
- //Log.BenchmarkStart(1);
- Log.LogStatus('Creating Song Array', 'Initialization');
- Songs := TSongs.Create;
- //Songs.LoadSongList;
-
- Log.LogStatus('Creating 2nd Song Array', 'Initialization');
- CatSongs := TCatSongs.Create;
-
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading Songs', 1);
-
- // PluginManager
- Log.BenchmarkStart(1);
- Log.LogStatus('PluginManager', 'Initialization');
- DLLMan := TDLLMan.Create; // Load PluginList
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading PluginManager', 1);
-
- {// Party Mode Manager
- Log.BenchmarkStart(1);
- Log.LogStatus('PartySession Manager', 'Initialization');
- PartySession := TPartySession.Create; //Load PartySession
-
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading PartySession Manager', 1); }
-
- // Graphics
- Log.BenchmarkStart(1);
- Log.LogStatus('Initialize 3D', 'Initialization');
- Initialize3D(WndTitle);
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Initializing 3D', 1);
-
- // Score Saving System
- Log.BenchmarkStart(1);
- Log.LogStatus('DataBase System', 'Initialization');
- DataBase := TDataBaseSystem.Create;
-
- if (Params.ScoreFile = '') then
- DataBase.Init ('Ultrastar.db')
- else
- DataBase.Init (Params.ScoreFile);
-
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading DataBase System', 1);
-
- // Playlist Manager
- Log.BenchmarkStart(1);
- Log.LogStatus('Playlist Manager', 'Initialization');
- PlaylistMan := TPlaylistManager.Create;
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading Playlist Manager', 1);
-
- // GoldenStarsTwinkleMod
- Log.BenchmarkStart(1);
- Log.LogStatus('Effect Manager', 'Initialization');
- GoldenRec := TEffectManager.Create;
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading Particel System', 1);
-
- // Joypad
- if (Ini.Joypad = 1) OR (Params.Joypad) then
- begin
- Log.BenchmarkStart(1);
- Log.LogStatus('Initialize Joystick', 'Initialization');
- Joy := TJoy.Create;
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Initializing Joystick', 1);
- end;
-
- Log.BenchmarkEnd(0);
- Log.LogBenchmark('Loading Time', 0);
-
- Log.LogError('Creating Core');
- Core := TCore.Create(
- USDXShortVersionStr,
- MakeVersion(USDX_VERSION_MAJOR,
- USDX_VERSION_MINOR,
- USDX_VERSION_RELEASE,
- chr(0))
- );
-
- Log.LogError('Running Core');
- Core.Run;
-
- //------------------------------
- //Start- Mainloop
- //------------------------------
- Log.LogStatus('Main Loop', 'Initialization');
- MainLoop;
-
- finally
- //------------------------------
- //Finish Application
- //------------------------------
-
- // TODO:
- // call an uninitialize routine for every initialize step
- // or at least use the corresponding Free-Methods
-
- UnloadOpenGL;
- //TTF_quit();
- SDL_Quit();
-
- (*
- {$ifdef WIN32}
- if assigned(LCD) and (Ini.LPT = 1) then
- LCD.Clear;
- if assigned(Light) and (Ini.LPT = 2) then
- Light.TurnOff;
- {$endif}
- *)
-
- if assigned(Log) then
- begin
- Log.LogStatus('Main Loop', 'Finished');
- Log.Free;
- end;
- end;
-end;
-
-procedure MainLoop;
-var
- Delay: integer;
-begin
- Delay := 0;
- SDL_EnableKeyRepeat(125, 125);
-
- CountSkipTime(); // JB - for some reason this seems to be needed when we use the SDL Timer functions.
- while not Done do
- begin
- // joypad
- if (Ini.Joypad = 1) or (Params.Joypad) then
- Joy.Update;
-
- // keyboard events
- CheckEvents;
-
- // display
- done := not Display.Draw;
- SwapBuffers;
-
- // light
- //Light.Refresh;
-
- // delay
- CountMidTime;
-
- Delay := Floor(1000 / 100 - 1000 * TimeMid);
-
- if Delay >= 1 then
- SDL_Delay(Delay); // dynamic, maximum is 100 fps
-
- CountSkipTime;
-
- // reinitialization of graphics
- if Restart then
- begin
- Reinitialize3D;
- Restart := false;
- end;
-
- end;
-End;
-
-procedure CheckEvents;
-begin
- if Assigned(Display.NextScreen) then
- Exit;
-
- while SDL_PollEvent( @event ) = 1 do
- begin
- case Event.type_ of
- SDL_QUITEV:
- begin
- Display.Fade := 0;
- Display.NextScreenWithCheck := nil;
- Display.CheckOK := True;
- end;
- {
- SDL_MOUSEBUTTONDOWN:
- with Event.button Do
- begin
- if State = SDL_BUTTON_LEFT Then
- begin
- //
- end;
- end;
- }
- SDL_VIDEORESIZE:
- begin
- ScreenW := Event.resize.w;
- ScreenH := Event.resize.h;
-
- screen := SDL_SetVideoMode(ScreenW, ScreenH, (Ini.Depth+1) * 16, SDL_OPENGL or SDL_RESIZABLE);
- end;
- SDL_KEYDOWN:
- begin
- // remap the "keypad enter" key to the "standard enter" key
- if (Event.key.keysym.sym = SDLK_KP_ENTER) then
- Event.key.keysym.sym := SDLK_RETURN;
-
- if (Event.key.keysym.sym = SDLK_F11) or
- ((Event.key.keysym.sym = SDLK_RETURN) and
- ((Event.key.keysym.modifier and KMOD_ALT) <> 0)) then // toggle full screen
- begin
- Ini.FullScreen := integer( not boolean( Ini.FullScreen ) );
-
- if boolean( Ini.FullScreen ) then
- begin
- SDL_SetVideoMode(ScreenW, ScreenH, (Ini.Depth+1) * 16, SDL_OPENGL or SDL_FULLSCREEN);
- SDL_ShowCursor(0);
- end
- else
- begin
- SDL_SetVideoMode(ScreenW, ScreenH, (Ini.Depth+1) * 16, SDL_OPENGL or SDL_RESIZABLE);
- SDL_ShowCursor(1);
- end;
-
- glViewPort(0, 0, ScreenW, ScreenH);
- end
- // ScreenShot hack. If Print is pressed-> Make screenshot and Save to Screenshots Path
- else if (Event.key.keysym.sym = SDLK_SYSREQ) or (Event.key.keysym.sym = SDLK_PRINT) then
- Display.ScreenShot
- // popup hack... if there is a visible popup then let it handle input instead of underlying screen
- // shoud be done in a way to be sure the topmost popup has preference (maybe error, then check)
- else if (ScreenPopupError <> nil) and (ScreenPopupError.Visible) then
- done := not ScreenPopupError.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), True)
- else if (ScreenPopupCheck <> nil) and (ScreenPopupCheck.Visible) then
- done := not ScreenPopupCheck.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), True)
- // end of popup hack
- else
- begin
- // check for Screen want to Exit
- done := not Display.CurrentScreen^.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), True);
-
- // If Screen wants to Exit
- if done then
- begin
- // If Question Option is enabled then Show Exit Popup
- if (Ini.AskbeforeDel = 1) then
- begin
- Display.CurrentScreen^.CheckFadeTo(nil,'MSG_QUIT_USDX');
- end
- else // When asking for exit is disabled then simply exit
- begin
- Display.Fade := 0;
- Display.NextScreenWithCheck := nil;
- Display.CheckOK := True;
- end;
- end;
-
- end;
- end;
- {
- SDL_JOYAXISMOTION:
- begin
- beep
- end;
- }
- SDL_JOYBUTTONDOWN:
- begin
- beep
- end;
- end; // Case
- end; // While
-end;
-
-function GetTimeForBeats(BPM, Beats: real): real;
-begin
- Result := 60 / BPM * Beats;
-end;
-
-function GetBeats(BPM, msTime: real): real;
-begin
- Result := BPM * msTime / 60;
-end;
-
-procedure GetMidBeatSub(BPMNum: integer; var Time: real; var CurBeat: real);
-var
- NewTime: real;
-begin
- if High(CurrentSong.BPM) = BPMNum then
- begin
- // last BPM
- CurBeat := CurrentSong.BPM[BPMNum].StartBeat + GetBeats(CurrentSong.BPM[BPMNum].BPM, Time);
- Time := 0;
- end
- else
- begin
- // not last BPM
- // count how much time is it for start of the new BPM and store it in NewTime
- NewTime := GetTimeForBeats(CurrentSong.BPM[BPMNum].BPM, CurrentSong.BPM[BPMNum+1].StartBeat - CurrentSong.BPM[BPMNum].StartBeat);
-
- // compare it to remaining time
- if (Time - NewTime) > 0 then
- begin
- // there is still remaining time
- CurBeat := CurrentSong.BPM[BPMNum].StartBeat;
- Time := Time - NewTime;
- end
- else
- begin
- // there is no remaining time
- CurBeat := CurrentSong.BPM[BPMNum].StartBeat + GetBeats(CurrentSong.BPM[BPMNum].BPM, Time);
- Time := 0;
- end; // if
- end; // if
-end;
-
-function GetMidBeat(Time: real): real;
-var
- CurBeat: real;
- CurBPM: integer;
-// TopBeat: real;
-// TempBeat: real;
-// TempTime: real;
-begin
- Result := 0;
- if Length(CurrentSong.BPM) = 1 then
- Result := Time * CurrentSong.BPM[0].BPM / 60;
-
- (* 2 BPMs *)
-{ if Length(CurrentSong.BPM) > 1 then begin
- (* new system *)
- CurBeat := 0;
- TopBeat := GetBeats(CurrentSong.BPM[0].BPM, Time);
- if TopBeat > CurrentSong.BPM[1].StartBeat then begin
- // analyze second BPM
- Time := Time - GetTimeForBeats(CurrentSong.BPM[0].BPM, CurrentSong.BPM[1].StartBeat - CurBeat);
- CurBeat := CurrentSong.BPM[1].StartBeat;
- TopBeat := GetBeats(CurrentSong.BPM[1].BPM, Time);
- Result := CurBeat + TopBeat;
-
- end
- else
- begin
- (* pierwszy przedzial *)
- Result := TopBeat;
- end;
- end;}
-
- (* more BPMs *)
- if Length(CurrentSong.BPM) > 1 then
- begin
- CurBeat := 0;
- CurBPM := 0;
- while (Time > 0) do
- begin
- GetMidBeatSub(CurBPM, Time, CurBeat);
- Inc(CurBPM);
- end;
-
- Result := CurBeat;
- end;
-end;
-
-function GetTimeFromBeat(Beat: integer): real;
-var
- CurBPM: integer;
-begin
- Result := 0;
- if Length(CurrentSong.BPM) = 1 then
- Result := CurrentSong.GAP / 1000 + Beat * 60 / CurrentSong.BPM[0].BPM;
-
- (* more BPMs *)
- if Length(CurrentSong.BPM) > 1 then
- begin
- Result := CurrentSong.GAP / 1000;
- CurBPM := 0;
- while (CurBPM <= High(CurrentSong.BPM)) and
- (Beat > CurrentSong.BPM[CurBPM].StartBeat) do
- begin
- if (CurBPM < High(CurrentSong.BPM)) and
- (Beat >= CurrentSong.BPM[CurBPM+1].StartBeat) then
- begin
- // full range
- Result := Result + (60 / CurrentSong.BPM[CurBPM].BPM) *
- (CurrentSong.BPM[CurBPM+1].StartBeat - CurrentSong.BPM[CurBPM].StartBeat);
- end;
-
- if (CurBPM = High(CurrentSong.BPM)) or
- (Beat < CurrentSong.BPM[CurBPM+1].StartBeat) then
- begin
- // in the middle
- Result := Result + (60 / CurrentSong.BPM[CurBPM].BPM) *
- (Beat - CurrentSong.BPM[CurBPM].StartBeat);
- end;
- Inc(CurBPM);
- end;
-
- {
- while (Time > 0) do
- begin
- GetMidBeatSub(CurBPM, Time, CurBeat);
- Inc(CurBPM);
- end;
- }
- end; // if}
-end;
-
-procedure Sing(Sender: TScreenSing);
-var
- Count: integer;
- CountGr: integer;
- CP: integer;
- Done: real;
- N: integer;
-begin
- LineState.CurrentTime := LineState.CurrentTime + TimeSkip;
-
- LineState.OldBeat := LineState.CurrentBeat;
- LineState.MidBeat := GetMidBeat(LineState.CurrentTime - (CurrentSong.Gap{ + 90 I've forgotten for what it is}) / 1000); // new system with variable BPM in function
- LineState.CurrentBeat := Floor(LineState.MidBeat);
-
-// LineState.OldHalf := LineState.AktHalf;
-// LineState.MidHalf := LineState.MidBeat + 0.5;
-// LineState.AktHalf := Floor(LineState.MidHalf);
-
- LineState.OldBeatC := LineState.CurrentBeatC;
- LineState.MidBeatC := GetMidBeat(LineState.CurrentTime - (CurrentSong.Gap) / 1000);
- LineState.CurrentBeatC := Floor(LineState.MidBeatC);
-
- LineState.OldBeatD := LineState.CurrentBeatD;
- LineState.MidBeatD := -0.5+GetMidBeat(LineState.CurrentTime - (CurrentSong.Gap + 120 + 20) / 1000); // MidBeat with addition GAP
- LineState.CurrentBeatD := Floor(LineState.MidBeatD);
- LineState.FracBeatD := Frac(LineState.MidBeatD);
-
- // sentences routines
- for CountGr := 0 to 0 do //High(Gracz)
- begin;
- CP := CountGr;
- // ustawianie starej parts
- LineState.OldLine := Lines[CP].Current;
-
- // wybieranie aktualnej parts
- for Count := 0 to Lines[CP].High do
- begin
- if LineState.CurrentBeat >= Lines[CP].Line[Count].Start then
- Lines[CP].Current := Count;
- end;
-
- // czysczenie nut gracza, gdy to jest nowa plansza
- // (optymizacja raz na halfbeat jest zla)
- if Lines[CP].Current <> LineState.OldLine then
- NewSentence(Sender);
-
- end; // for CountGr
-
- // wykonuje operacje raz na beat
- if (LineState.CurrentBeat >= 0) and (LineState.OldBeat <> LineState.CurrentBeat) then
- NewBeat(Sender);
-
- // make some operations on clicks
- if {(LineState.CurrentBeatC >= 0) and }(LineState.OldBeatC <> LineState.CurrentBeatC) then
- NewBeatC(Sender);
-
- // make some operations when detecting new voice pitch
- if (LineState.CurrentBeatD >= 0) and (LineState.OldBeatD <> LineState.CurrentBeatD) then
- NewBeatD(Sender);
-
- // wykonuje operacje w polowie beatu
-// if (LineState.AktHalf >= 1) and (LineState.OldHalf <> LineState.AktHalf) then
-// NewHalf;
-
- // plynnie przesuwa text
- Done := 1;
- for N := 0 to Lines[0].Line[Lines[0].Current].HighNote do
- begin
- if (Lines[0].Line[Lines[0].Current].Note[N].Start <= LineState.MidBeat) and
- (Lines[0].Line[Lines[0].Current].Note[N].Start + Lines[0].Line[Lines[0].Current].Note[N].Length >= LineState.MidBeat) then
- begin
- Done := (LineState.MidBeat - Lines[0].Line[Lines[0].Current].Note[N].Start) / (Lines[0].Line[Lines[0].Current].Note[N].Length);
- end;
- end;
-
- N := Lines[0].Line[Lines[0].Current].HighNote;
-
- // wylacza ostatnia nute po przejsciu
- {// todo: Lyrics
- if (Ini.LyricsEffect = 1) and (Done = 1) and
- (LineState.MidBeat > Lines[0].Line[Lines[0].Current].Note[N].Start + Lines[0].Line[Lines[0].Current].Note[N].Length)
- then Sender.LyricMain.Selected := -1;
-
- if Done > 1 then Done := 1;
- Sender.LyricMain.Done := Done; }
-
- // use Done with LCD
-{ with ScreenSing do begin
- if LyricMain.Selected >= 0 then begin
- LCD.MoveCursor(1, LyricMain.SelectedLetter + Round((LyricMain.SelectedLength-1) * Done));
- LCD.ShowCursor;
- end;
- end;}
-
-
-end;
-
-procedure NewSentence(Sender: TScreenSing);
-var
-G: Integer;
-begin
- // czyszczenie nut graczy
- for G := 0 to High(Player) do
- begin
- Player[G].IlNut := 0;
- Player[G].HighNote := -1;
- SetLength(Player[G].Note, 0);
- end;
-
- // Add Words to Lyrics
- with Sender do
- begin
- {LyricMain.AddCzesc(Lines[0].Current);
- if Lines[0].Current < Lines[0].High then
- LyricSub.AddCzesc(Lines[0].Current+1)
- else
- LyricSub.Clear;}
- while (not Lyrics.LineinQueue) and (Lyrics.LineCounter <= High(Lines[0].Line)) do
- Lyrics.AddLine(@Lines[0].Line[Lyrics.LineCounter]);
- end;
-
- //Sender.UpdateLCD;
-
- //On Sentence Change...
- Sender.onSentenceChange(Lines[0].Current);
-end;
-
-procedure NewBeat(Sender: TScreenSing);
-var
- Count: integer;
-// TempBeat: integer;
-begin
- // ustawia zaznaczenie tekstu
-// SingScreen.LyricMain.Selected := -1;
- for Count := 0 to Lines[0].Line[Lines[0].Current].HighNote do
- if (Lines[0].Line[Lines[0].Current].Note[Count].Start = LineState.CurrentBeat) then
- begin
- // operates on currently beated note
- //Todo: Lyrics
- //Sender.LyricMain.Selected := Count;
-
-// LCD.MoveCursor(1, ScreenSing.LyricMain.SelectedLetter);
-// LCD.ShowCursor;
-
- //LCD.MoveCursorBR(Sender.LyricMain.SelectedLetter);
- //LCD.ShowCursor;
- end;
-end;
-
-procedure NewBeatC;
-var
- Count: integer;
-// LPT_1: integer;
-// LPT_2: integer;
-begin
-// LPT_1 := 1;
-// LPT_2 := 1;
-
- // beat click
- if (Ini.BeatClick = 1) and ((LineState.CurrentBeatC + Lines[0].Resolution + Lines[0].NotesGAP) mod Lines[0].Resolution = 0) then
- AudioPlayback.PlaySound(SoundLib.Click);
-
- // debug system on LPT
- if ((LineState.CurrentBeatC + Lines[0].Resolution + Lines[0].NotesGAP) mod Lines[0].Resolution = 0) then
- begin
- //LPT_1 := 0;
-// Light.LightOne(0, 150);
-
- (*
- Light.LightOne(1, 200); // beat light
- if ParamStr(1) = '-doublelights' then
- Light.LightOne(0, 200); // beat light
- *)
-
-
-{ if ((LineState.CurrentBeatC + Lines[0].Resolution + Lines[0].NotesGAP) mod (Lines[0].Resolution * 2) = 0) then
- Light.LightOne(0, 150)
- else
- Light.LightOne(1, 150)}
- end;
-
- for Count := 0 to Lines[0].Line[Lines[0].Current].HighNote do
- begin
- if (Lines[0].Line[Lines[0].Current].Note[Count].Start = LineState.CurrentBeatC) then
- begin
- // click assist
- if Ini.ClickAssist = 1 then
- AudioPlayback.PlaySound(SoundLib.Click);
-
- //LPT_2 := 0;
- (*
- if ParamStr(1) <> '-doublelights' then
- Light.LightOne(0, 150); //125
- *)
-
- // drum machine
- (*
- TempBeat := LineState.CurrentBeat;// + 2;
- if (TempBeat mod 8 = 0) then Music.PlayDrum;
- if (TempBeat mod 8 = 4) then Music.PlayClap;
-// if (TempBeat mod 4 = 2) then Music.PlayHihat;
- if (TempBeat mod 4 <> 0) then Music.PlayHihat;
- *)
- end;
- end;
-
- {$IFDEF UseSerialPort}
- // PortWriteB($378, LPT_1 + LPT_2 * 2); // 0 zapala
- {$ENDIF}
-end;
-
-procedure NewBeatD(Sender: TScreenSing);
-begin
- NewNote(Sender);
-end;
-
-//procedure NewHalf;
-//begin
-// NewNote;
-//end;
-
-procedure NewNote(Sender: TScreenSing);
-var
- CP: integer; // current player
- S: integer; // sentence
- SMin: integer;
- SMax: integer;
- SDet: integer; // temporary: sentence of detected note
- Count: integer;
- Mozna: boolean;
- New: boolean;
- Range: integer;
- NoteHit:boolean;
-begin
-// Log.LogStatus('Beat ' + IntToStr(LineState.CurrentBeat) + ' HalfBeat ' + IntToStr(LineState.AktHalf), 'NewBeat');
-// beep;
-
- // On linux we get an AV @ NEWNOTE, line 600 of Classes/UMain.pas
- if not assigned( AudioInputProcessor.Sound ) then
- exit;
-
- // analizuje dla obu graczy ten sam sygnal (Sound.OneSrcForBoth)
- // albo juz lepiej nie
- for CP := 0 to PlayersPlay-1 do
- begin
- // analyze buffer
- AudioInputProcessor.Sound[CP].AnalyzeBuffer;
-
- // adds some noise
- //LineState.Tone := LineState.Tone + Round(Random(3)) - 1;
-
- // count min and max sentence range for checking (detection is delayed to the notes we see on the screen)
- SMin := Lines[0].Current-1;
- if SMin < 0 then
- SMin := 0;
- SMax := Lines[0].Current;
-
- // check if we can add new note
- Mozna := false;
- SDet:=SMin;
- for S := SMin to SMax do
- begin
- for Count := 0 to Lines[0].Line[S].HighNote do
- begin
- if ((Lines[0].Line[S].Note[Count].Start <= LineState.CurrentBeatD)
- and (Lines[0].Line[S].Note[Count].Start + Lines[0].Line[S].Note[Count].Length - 1 >= LineState.CurrentBeatD))
- and (not Lines[0].Line[S].Note[Count].FreeStyle) // but don't allow when it's FreeStyle note
- and (Lines[0].Line[S].Note[Count].Length > 0) then // and make sure the note lengths is at least 1
- begin
- SDet := S;
- Mozna := true;
- Break;
- end;
- end;
- end;
-
- S := SDet;
-
- //Czas.SzczytJest := true;
- //Czas.Tone := 27;
-
- // gdy moze, to dodaje nute - When Mozna, it adds note (?)
- if (AudioInputProcessor.Sound[CP].ToneValid) and (Mozna) then
- begin
- // operowanie na ostatniej nucie
- for Count := 0 to Lines[0].Line[S].HighNote do
- begin
- if (Lines[0].Line[S].Note[Count].Start <= LineState.OldBeatD+1) and
- (Lines[0].Line[S].Note[Count].Start +
- Lines[0].Line[S].Note[Count].Length > LineState.OldBeatD+1) then
- begin
- // to robi, tylko dla pary nut (oryginalnej i gracza)
-
- // przesuwanie tonu w odpowiednia game
- while (AudioInputProcessor.Sound[CP].Tone - Lines[0].Line[S].Note[Count].Tone > 6) do
- AudioInputProcessor.Sound[CP].Tone := AudioInputProcessor.Sound[CP].Tone - 12;
-
- while (AudioInputProcessor.Sound[CP].Tone - Lines[0].Line[S].Note[Count].Tone < -6) do
- AudioInputProcessor.Sound[CP].Tone := AudioInputProcessor.Sound[CP].Tone + 12;
-
- // Half size Notes Patch
- NoteHit := false;
-
- //if Ini.Difficulty = 0 then Range := 2;
- //if Ini.Difficulty = 1 then Range := 1;
- //if Ini.Difficulty = 2 then Range := 0;
- Range := 2 - Ini.Difficulty;
-
- if abs(Lines[0].Line[S].Note[Count].Tone - AudioInputProcessor.Sound[CP].Tone) <= Range then
- begin
- AudioInputProcessor.Sound[CP].Tone := Lines[0].Line[S].Note[Count].Tone;
-
- // Half size Notes Patch
- NoteHit := true;
-
- if (Ini.LineBonus = 0) then
- begin
- // add points without LineBonus
- case Lines[0].Line[S].Note[Count].NoteType of
- 1: Player[CP].Score := Player[CP].Score + 10000 / Lines[0].NoteType *
- Lines[0].Line[S].Note[Count].NoteType;
- 2: Player[CP].ScoreGolden := Player[CP].ScoreGolden + 10000 / Lines[0].NoteType *
- Lines[0].Line[S].Note[Count].NoteType;
- end;
- end
- else
- begin
- // add points with Line Bonus
- case Lines[0].Line[S].Note[Count].NoteType of
- 1: Player[CP].Score := Player[CP].Score + 9000 / Lines[0].NoteType *
- Lines[0].Line[S].Note[Count].NoteType;
- 2: Player[CP].ScoreGolden := Player[CP].ScoreGolden + 9000 / Lines[0].NoteType *
- Lines[0].Line[S].Note[Count].NoteType;
- end;
- end;
-
- Player[CP].ScoreI := Floor(Player[CP].Score / 10) * 10;
- Player[CP].ScoreGoldenI := Floor(Player[CP].ScoreGolden / 10) * 10;
-
- Player[CP].ScoreTotalI := Player[CP].ScoreI + Player[CP].ScoreGoldenI + Player[CP].ScoreLineI;
- end;
-
- end; // operowanie
- end; // for
-
- // sprawdzanie czy to nowa nuta, czy przedluzenie
- if S = SMax then
- begin
- New := true;
- // if last has the same tone
- if (Player[CP].IlNut > 0 ) and
- (Player[CP].Note[Player[CP].HighNote].Tone = AudioInputProcessor.Sound[CP].Tone) and
- (Player[CP].Note[Player[CP].HighNote].Start + Player[CP].Note[Player[CP].HighNote].Length = LineState.CurrentBeatD) then
- begin
- New := false;
- end;
-
- // if is not as new note to control "beacie" (TODO: translate polish "beacie")
- for Count := 0 to Lines[0].Line[S].HighNote do
- begin
- if (Lines[0].Line[S].Note[Count].Start = LineState.CurrentBeatD) then
- New := true;
- end;
-
- // dodawanie nowej nuty
- if New then
- begin
- // New Note
- Player[CP].IlNut := Player[CP].IlNut + 1;
- Player[CP].HighNote := Player[CP].HighNote + 1;
- SetLength(Player[CP].Note, Player[CP].IlNut);
- Player[CP].Note[Player[CP].HighNote].Start := LineState.CurrentBeatD;
- Player[CP].Note[Player[CP].HighNote].Length := 1;
- Player[CP].Note[Player[CP].HighNote].Tone := AudioInputProcessor.Sound[CP].Tone; // Ton || TonDokl
- Player[CP].Note[Player[CP].HighNote].Detekt := LineState.MidBeat;
-
- // Half Note Patch
- Player[CP].Note[Player[CP].HighNote].Hit := NoteHit;
-
- //Log.LogStatus('New Note ' + IntToStr(Gracz.Note[Gracz.HighNote].Start), 'NewBeat');
- end
- else
- begin
- // przedluzenie nuty
- Player[CP].Note[Player[CP].HighNote].Length := Player[CP].Note[Player[CP].HighNote].Length + 1;
- end;
-
- // check for perfect note and then lit the star (on Draw)
- for Count := 0 to Lines[0].Line[S].HighNote do
- begin
- if (Lines[0].Line[S].Note[Count].Start = Player[CP].Note[Player[CP].HighNote].Start) and
- (Lines[0].Line[S].Note[Count].Length = Player[CP].Note[Player[CP].HighNote].Length) and
- (Lines[0].Line[S].Note[Count].Tone = Player[CP].Note[Player[CP].HighNote].Tone) then
- begin
- Player[CP].Note[Player[CP].HighNote].Perfect := true;
- end;
- end;
- end;// else beep; // if S = SMax
-
- end; // if moze
- end; // for CP
- // Log.LogStatus('EndBeat', 'NewBeat');
-
- //On Sentence End -> For LineBonus + SingBar
- if (sDet >= low(Lines[0].Line)) and (sDet <= high(Lines[0].Line)) then
- begin
- if assigned( Sender ) and
- ((Lines[0].Line[SDet].Note[Lines[0].Line[SDet].HighNote].Start + Lines[0].Line[SDet].Note[Lines[0].Line[SDet].HighNote].Length - 1) = LineState.CurrentBeatD) then
- begin
- Sender.onSentenceEnd(sDet);
- end;
- end;
-
-end;
-
-procedure ClearScores(PlayerNum: integer);
-begin
- Player[PlayerNum].Score := 0;
- Player[PlayerNum].ScoreI := 0;
- Player[PlayerNum].ScoreLine := 0;
- Player[PlayerNum].ScoreLineI := 0;
- Player[PlayerNum].ScoreGolden := 0;
- Player[PlayerNum].ScoreGoldenI := 0;
- Player[PlayerNum].ScoreTotalI := 0;
-end;
-
-
-//--------------------
-// Function sets all Absolute Paths e.g. Song Path and makes sure the Directorys exist
-//--------------------
-procedure InitializePaths;
-
- // Initialize a Path Variable
- // After Setting Paths, make sure that Paths exist
- function initialize_path( out aPathVar : string; const aLocation : string ): boolean;
- var
- lWriteable: Boolean;
- lAttrib : integer;
- begin
- lWriteable := false;
- aPathVar := aLocation;
-
- // Make sure the directory is needex
- ForceDirectories(aPathVar);
-
- if DirectoryExists(aPathVar) then
- begin
- lAttrib := fileGetAttr(aPathVar);
-
- lWriteable := (lAttrib and faDirectory <> 0) and
- not (lAttrib and faReadOnly <> 0)
- end;
-
- if not lWriteable then
- Log.LogError('Error: Dir ('+ aLocation +') is Readonly');
-
- result := lWriteable;
- end;
-
-begin
- initialize_path( LogPath , Platform.GetLogPath );
- initialize_path( SoundPath , Platform.GetGameSharedPath + 'Sounds' + PathDelim );
- initialize_path( ThemePath , Platform.GetGameSharedPath + 'Themes' + PathDelim );
- initialize_path( SkinsPath , Platform.GetGameSharedPath + 'Skins' + PathDelim );
- initialize_path( LanguagesPath , Platform.GetGameSharedPath + 'Languages' + PathDelim );
- initialize_path( PluginPath , Platform.GetGameSharedPath + 'Plugins' + PathDelim );
- initialize_path( VisualsPath , Platform.GetGameSharedPath + 'Visuals' + PathDelim );
-
- initialize_path( ScreenshotsPath , Platform.GetGameUserPath + 'Screenshots' + PathDelim );
-
- // Users Song Path ....
- initialize_path( UserSongPath , Platform.GetGameUserPath + 'Songs' + PathDelim );
- initialize_path( UserCoversPath , Platform.GetGameUserPath + 'Covers' + PathDelim );
- initialize_path( UserPlaylistPath , Platform.GetGameUserPath + 'Playlists' + PathDelim );
-
- // Shared Song Path ....
- initialize_path( SongPath , Platform.GetGameSharedPath + 'Songs' + PathDelim );
- initialize_path( CoversPath , Platform.GetGameSharedPath + 'Covers' + PathDelim );
- initialize_path( PlaylistPath , Platform.GetGameSharedPath + 'Playlists' + PathDelim );
-
- DecimalSeparator := '.';
-end;
-
-end.
-
+unit UMain; + +interface + +{$IFDEF FPC} + {$MODE Delphi} +{$ENDIF} + +{$I switches.inc} + +uses + SDL, + UGraphic, + UMusic, + URecord, + UTime, + SysUtils, + UDisplay, + UIni, + ULog, + ULyrics, + UScreenSing, + USong, + OpenGL12, + {$IFDEF UseSerialPort} + //zlportio, //you can disable it and all PortWriteB calls + {$ENDIF} + //ULCD, //TODO: maybe LCD Support as Plugin? + //ULight, //TODO: maybe Light Support as Plugin? + UThemes; + +type + TPlayer = record + Name: string; + + // Index in Teaminfo record + TeamID: Byte; + PlayerID: Byte; + + // Scores + Score: real; + ScoreLine: real; + ScoreGolden: real; + + ScoreI: integer; + ScoreLineI: integer; + ScoreGoldenI: integer; + ScoreTotalI: integer; + + // LineBonus Mod + ScoreLast: Real;//Last Line Score + + // PerfectLineTwinkle Mod (effect) + LastSentencePerfect: Boolean; + + //Meter: real; + + HighNote: integer; + IlNut: integer; + Note: array of record + Start: integer; + Length: integer; + Detekt: real; // accurate place, detected in the note + Tone: real; + Perfect: boolean; // true if the note matches the original one, lit the star + + // Half size Notes Patch + Hit: boolean; // true if the note Hits the Line + end; + end; + + +var + // Absolute Paths + GamePath: string; + SoundPath: string; + SongPath: string; + LogPath: string; + ThemePath: string; + SkinsPath: string; + ScreenshotsPath: string; + CoversPath: string; + LanguagesPath: string; + PluginPath: string; + VisualsPath: string; + PlayListPath: string; + + UserSongPath: string = ''; + UserCoversPath: string = ''; + UserPlaylistPath: string = ''; + + OGL: Boolean; + Done: Boolean; + Event: TSDL_event; + FileName: string; + Restart: boolean; + + // player and music info + Player: array of TPlayer; + PlayersPlay: integer; + + CurrentSong : TSong; + +procedure InitializePaths; + +Procedure Main; +procedure MainLoop; +procedure CheckEvents; +procedure Sing(Sender: TScreenSing); +procedure NewSentence(Sender: TScreenSing); +procedure NewBeat(Sender: TScreenSing); // executed when on then new beat +procedure NewBeatC(Sender: TScreenSing); // executed when on then new beat for click +procedure NewBeatD(Sender: TScreenSing); // executed when on then new beat for detection +//procedure NewHalf; // executed when in the half between beats +procedure NewNote(Sender: TScreenSing); // detect note +function GetMidBeat(Time: real): real; +function GetTimeFromBeat(Beat: integer): real; +procedure ClearScores(PlayerNum: integer); + +implementation + +uses + USongs, + UJoystick, + math, + UCommandLine, + ULanguage, + SDL_ttf, + USkins, + UCovers, + UCatCovers, + UDataBase, + UPlaylist, + UDLLManager, + UParty, + UConfig, + UCore, + UGraphicClasses, + UPluginDefs, + UPlatform; + +procedure Main; +var + WndTitle: string; +begin + try + WndTitle := USDXVersionStr; + + if Platform.TerminateIfAlreadyRunning( {var} WndTitle) then + Exit; + + //------------------------------ + //StartUp - Create Classes and Load Files + //------------------------------ + USTime := TTime.Create; + + // Commandline Parameter Parser + Params := TCMDParams.Create; + + // Log + Benchmark + Log := TLog.Create; + Log.Title := WndTitle; + Log.Enabled := not Params.NoLog; + Log.BenchmarkStart(0); + + // Language + Log.BenchmarkStart(1); + Log.LogStatus('Initialize Paths', 'Initialization'); + InitializePaths; + Log.LogStatus('Load Language', 'Initialization'); + Language := TLanguage.Create; + + // Add Const Values: + Language.AddConst('US_VERSION', USDXVersionStr); + Log.BenchmarkEnd(1); + Log.LogBenchmark('Loading Language', 1); + + // SDL + Log.BenchmarkStart(1); + Log.LogStatus('Initialize SDL', 'Initialization'); + SDL_Init(SDL_INIT_VIDEO); + Log.BenchmarkEnd(1); + Log.LogBenchmark('Initializing SDL', 1); + + // SDL_ttf + Log.BenchmarkStart(1); + Log.LogStatus('Initialize SDL_ttf', 'Initialization'); + TTF_Init(); + Log.BenchmarkEnd(1); + Log.LogBenchmark('Initializing SDL_ttf', 1); + + // Skin + Log.BenchmarkStart(1); + Log.LogStatus('Loading Skin List', 'Initialization'); + Skin := TSkin.Create; + Log.BenchmarkEnd(1); + Log.LogBenchmark('Loading Skin List', 1); + + // Ini + Paths + Log.BenchmarkStart(1); + Log.LogStatus('Load Ini', 'Initialization'); + Ini := TIni.Create; + Ini.Load; + + //Load Languagefile + if (Params.Language <> -1) then + Language.ChangeLanguage(ILanguage[Params.Language]) + else + Language.ChangeLanguage(ILanguage[Ini.Language]); + + Log.BenchmarkEnd(1); + Log.LogBenchmark('Loading Ini', 1); + + // Sound + Log.BenchmarkStart(1); + Log.LogStatus('Initialize Sound', 'Initialization'); + InitializeSound(); + Log.BenchmarkEnd(1); + Log.LogBenchmark('Initializing Sound', 1); + + // Load Sound Settings from Ini + Log.BenchmarkStart(1); + Log.LogStatus('Load Sound Settings', 'Initialization'); + Ini.LoadSoundSettings; + Log.BenchmarkEnd(1); + Log.LogBenchmark('Load Sound Settings', 1); + + // LCD //TODO: maybe LCD Support as Plugin? + //Log.BenchmarkStart(1); + //Log.LogStatus('Load LCD', 'Initialization'); + //LCD := TLCD.Create; + (* + if Ini.LPT = 1 then + begin + //LCD.HalfInterface := true; + LCD.Enable; + LCD.Clear; + LCD.WriteText(1, ' UltraStar '); + LCD.WriteText(2, ' Loading... '); + end; + Log.BenchmarkEnd(1); + Log.LogBenchmark('Loading LCD', 1); + *) + // Light //TODO: maybe Light Support as Plugin? + (* + Log.BenchmarkStart(1); + Log.LogStatus('Load Light', 'Initialization'); + Light := TLight.Create; + if Ini.LPT = 2 then + begin + Light.Enable; + end; + Log.BenchmarkEnd(1); + Log.LogBenchmark('Loading Light', 1); + *) + + + // Theme + Log.BenchmarkStart(1); + Log.LogStatus('Load Themes', 'Initialization'); + Theme := TTheme.Create(ThemePath + ITheme[Ini.Theme] + '.ini', Ini.Color); + Log.BenchmarkEnd(1); + Log.LogBenchmark('Loading Themes', 1); + + // Covers Cache + Log.BenchmarkStart(1); + Log.LogStatus('Creating Covers Cache', 'Initialization'); + Covers := TCovers.Create; + Log.LogBenchmark('Loading Covers Cache Array', 1); + Log.BenchmarkStart(1); + + // Category Covers + Log.BenchmarkStart(1); + Log.LogStatus('Creating Category Covers Array', 'Initialization'); + CatCovers:= TCatCovers.Create; + Log.BenchmarkEnd(1); + Log.LogBenchmark('Loading Category Covers Array', 1); + + // Songs + //Log.BenchmarkStart(1); + Log.LogStatus('Creating Song Array', 'Initialization'); + Songs := TSongs.Create; + //Songs.LoadSongList; + + Log.LogStatus('Creating 2nd Song Array', 'Initialization'); + CatSongs := TCatSongs.Create; + + Log.BenchmarkEnd(1); + Log.LogBenchmark('Loading Songs', 1); + + // PluginManager + Log.BenchmarkStart(1); + Log.LogStatus('PluginManager', 'Initialization'); + DLLMan := TDLLMan.Create; // Load PluginList + Log.BenchmarkEnd(1); + Log.LogBenchmark('Loading PluginManager', 1); + + {// Party Mode Manager + Log.BenchmarkStart(1); + Log.LogStatus('PartySession Manager', 'Initialization'); + PartySession := TPartySession.Create; //Load PartySession + + Log.BenchmarkEnd(1); + Log.LogBenchmark('Loading PartySession Manager', 1); } + + // Graphics + Log.BenchmarkStart(1); + Log.LogStatus('Initialize 3D', 'Initialization'); + Initialize3D(WndTitle); + Log.BenchmarkEnd(1); + Log.LogBenchmark('Initializing 3D', 1); + + // Score Saving System + Log.BenchmarkStart(1); + Log.LogStatus('DataBase System', 'Initialization'); + DataBase := TDataBaseSystem.Create; + + if (Params.ScoreFile = '') then + DataBase.Init ('Ultrastar.db') + else + DataBase.Init (Params.ScoreFile); + + Log.BenchmarkEnd(1); + Log.LogBenchmark('Loading DataBase System', 1); + + // Playlist Manager + Log.BenchmarkStart(1); + Log.LogStatus('Playlist Manager', 'Initialization'); + PlaylistMan := TPlaylistManager.Create; + Log.BenchmarkEnd(1); + Log.LogBenchmark('Loading Playlist Manager', 1); + + // GoldenStarsTwinkleMod + Log.BenchmarkStart(1); + Log.LogStatus('Effect Manager', 'Initialization'); + GoldenRec := TEffectManager.Create; + Log.BenchmarkEnd(1); + Log.LogBenchmark('Loading Particel System', 1); + + // Joypad + if (Ini.Joypad = 1) OR (Params.Joypad) then + begin + Log.BenchmarkStart(1); + Log.LogStatus('Initialize Joystick', 'Initialization'); + Joy := TJoy.Create; + Log.BenchmarkEnd(1); + Log.LogBenchmark('Initializing Joystick', 1); + end; + + Log.BenchmarkEnd(0); + Log.LogBenchmark('Loading Time', 0); + + Log.LogError('Creating Core'); + Core := TCore.Create( + USDXShortVersionStr, + MakeVersion(USDX_VERSION_MAJOR, + USDX_VERSION_MINOR, + USDX_VERSION_RELEASE, + chr(0)) + ); + + Log.LogError('Running Core'); + Core.Run; + + //------------------------------ + //Start- Mainloop + //------------------------------ + Log.LogStatus('Main Loop', 'Initialization'); + MainLoop; + + finally + //------------------------------ + //Finish Application + //------------------------------ + + // TODO: + // call an uninitialize routine for every initialize step + // or at least use the corresponding Free-Methods + + UnloadOpenGL; + //TTF_quit(); + SDL_Quit(); + + (* + {$ifdef WIN32} + if assigned(LCD) and (Ini.LPT = 1) then + LCD.Clear; + if assigned(Light) and (Ini.LPT = 2) then + Light.TurnOff; + {$endif} + *) + + if assigned(Log) then + begin + Log.LogStatus('Main Loop', 'Finished'); + Log.Free; + end; + end; +end; + +procedure MainLoop; +var + Delay: integer; +begin + Delay := 0; + SDL_EnableKeyRepeat(125, 125); + + CountSkipTime(); // JB - for some reason this seems to be needed when we use the SDL Timer functions. + while not Done do + begin + // joypad + if (Ini.Joypad = 1) or (Params.Joypad) then + Joy.Update; + + // keyboard events + CheckEvents; + + // display + done := not Display.Draw; + SwapBuffers; + + // light + //Light.Refresh; + + // delay + CountMidTime; + + Delay := Floor(1000 / 100 - 1000 * TimeMid); + + if Delay >= 1 then + SDL_Delay(Delay); // dynamic, maximum is 100 fps + + CountSkipTime; + + // reinitialization of graphics + if Restart then + begin + Reinitialize3D; + Restart := false; + end; + + end; +End; + +procedure CheckEvents; +begin + if Assigned(Display.NextScreen) then + Exit; + + while SDL_PollEvent( @event ) = 1 do + begin + case Event.type_ of + SDL_QUITEV: + begin + Display.Fade := 0; + Display.NextScreenWithCheck := nil; + Display.CheckOK := True; + end; + { + SDL_MOUSEBUTTONDOWN: + with Event.button Do + begin + if State = SDL_BUTTON_LEFT Then + begin + // + end; + end; + } + SDL_VIDEORESIZE: + begin + ScreenW := Event.resize.w; + ScreenH := Event.resize.h; + + screen := SDL_SetVideoMode(ScreenW, ScreenH, (Ini.Depth+1) * 16, SDL_OPENGL or SDL_RESIZABLE); + end; + SDL_KEYDOWN: + begin + // remap the "keypad enter" key to the "standard enter" key + if (Event.key.keysym.sym = SDLK_KP_ENTER) then + Event.key.keysym.sym := SDLK_RETURN; + + if (Event.key.keysym.sym = SDLK_F11) or + ((Event.key.keysym.sym = SDLK_RETURN) and + ((Event.key.keysym.modifier and KMOD_ALT) <> 0)) then // toggle full screen + begin + Ini.FullScreen := integer( not boolean( Ini.FullScreen ) ); + + if boolean( Ini.FullScreen ) then + begin + SDL_SetVideoMode(ScreenW, ScreenH, (Ini.Depth+1) * 16, SDL_OPENGL or SDL_FULLSCREEN); + SDL_ShowCursor(0); + end + else + begin + SDL_SetVideoMode(ScreenW, ScreenH, (Ini.Depth+1) * 16, SDL_OPENGL or SDL_RESIZABLE); + SDL_ShowCursor(1); + end; + + glViewPort(0, 0, ScreenW, ScreenH); + end + // ScreenShot hack. If Print is pressed-> Make screenshot and Save to Screenshots Path + else if (Event.key.keysym.sym = SDLK_SYSREQ) or (Event.key.keysym.sym = SDLK_PRINT) then + Display.ScreenShot + // popup hack... if there is a visible popup then let it handle input instead of underlying screen + // shoud be done in a way to be sure the topmost popup has preference (maybe error, then check) + else if (ScreenPopupError <> nil) and (ScreenPopupError.Visible) then + done := not ScreenPopupError.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), True) + else if (ScreenPopupCheck <> nil) and (ScreenPopupCheck.Visible) then + done := not ScreenPopupCheck.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), True) + // end of popup hack + else + begin + // check for Screen want to Exit + done := not Display.CurrentScreen^.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), True); + + // If Screen wants to Exit + if done then + begin + // If Question Option is enabled then Show Exit Popup + if (Ini.AskbeforeDel = 1) then + begin + Display.CurrentScreen^.CheckFadeTo(nil,'MSG_QUIT_USDX'); + end + else // When asking for exit is disabled then simply exit + begin + Display.Fade := 0; + Display.NextScreenWithCheck := nil; + Display.CheckOK := True; + end; + end; + + end; + end; + { + SDL_JOYAXISMOTION: + begin + beep + end; + } + SDL_JOYBUTTONDOWN: + begin + beep + end; + end; // Case + end; // While +end; + +function GetTimeForBeats(BPM, Beats: real): real; +begin + Result := 60 / BPM * Beats; +end; + +function GetBeats(BPM, msTime: real): real; +begin + Result := BPM * msTime / 60; +end; + +procedure GetMidBeatSub(BPMNum: integer; var Time: real; var CurBeat: real); +var + NewTime: real; +begin + if High(CurrentSong.BPM) = BPMNum then + begin + // last BPM + CurBeat := CurrentSong.BPM[BPMNum].StartBeat + GetBeats(CurrentSong.BPM[BPMNum].BPM, Time); + Time := 0; + end + else + begin + // not last BPM + // count how much time is it for start of the new BPM and store it in NewTime + NewTime := GetTimeForBeats(CurrentSong.BPM[BPMNum].BPM, CurrentSong.BPM[BPMNum+1].StartBeat - CurrentSong.BPM[BPMNum].StartBeat); + + // compare it to remaining time + if (Time - NewTime) > 0 then + begin + // there is still remaining time + CurBeat := CurrentSong.BPM[BPMNum].StartBeat; + Time := Time - NewTime; + end + else + begin + // there is no remaining time + CurBeat := CurrentSong.BPM[BPMNum].StartBeat + GetBeats(CurrentSong.BPM[BPMNum].BPM, Time); + Time := 0; + end; // if + end; // if +end; + +function GetMidBeat(Time: real): real; +var + CurBeat: real; + CurBPM: integer; +// TopBeat: real; +// TempBeat: real; +// TempTime: real; +begin + Result := 0; + if Length(CurrentSong.BPM) = 1 then + Result := Time * CurrentSong.BPM[0].BPM / 60; + + (* 2 BPMs *) +{ if Length(CurrentSong.BPM) > 1 then begin + (* new system *) + CurBeat := 0; + TopBeat := GetBeats(CurrentSong.BPM[0].BPM, Time); + if TopBeat > CurrentSong.BPM[1].StartBeat then begin + // analyze second BPM + Time := Time - GetTimeForBeats(CurrentSong.BPM[0].BPM, CurrentSong.BPM[1].StartBeat - CurBeat); + CurBeat := CurrentSong.BPM[1].StartBeat; + TopBeat := GetBeats(CurrentSong.BPM[1].BPM, Time); + Result := CurBeat + TopBeat; + + end + else + begin + (* pierwszy przedzial *) + Result := TopBeat; + end; + end;} + + (* more BPMs *) + if Length(CurrentSong.BPM) > 1 then + begin + CurBeat := 0; + CurBPM := 0; + while (Time > 0) do + begin + GetMidBeatSub(CurBPM, Time, CurBeat); + Inc(CurBPM); + end; + + Result := CurBeat; + end; +end; + +function GetTimeFromBeat(Beat: integer): real; +var + CurBPM: integer; +begin + Result := 0; + if Length(CurrentSong.BPM) = 1 then + Result := CurrentSong.GAP / 1000 + Beat * 60 / CurrentSong.BPM[0].BPM; + + (* more BPMs *) + if Length(CurrentSong.BPM) > 1 then + begin + Result := CurrentSong.GAP / 1000; + CurBPM := 0; + while (CurBPM <= High(CurrentSong.BPM)) and + (Beat > CurrentSong.BPM[CurBPM].StartBeat) do + begin + if (CurBPM < High(CurrentSong.BPM)) and + (Beat >= CurrentSong.BPM[CurBPM+1].StartBeat) then + begin + // full range + Result := Result + (60 / CurrentSong.BPM[CurBPM].BPM) * + (CurrentSong.BPM[CurBPM+1].StartBeat - CurrentSong.BPM[CurBPM].StartBeat); + end; + + if (CurBPM = High(CurrentSong.BPM)) or + (Beat < CurrentSong.BPM[CurBPM+1].StartBeat) then + begin + // in the middle + Result := Result + (60 / CurrentSong.BPM[CurBPM].BPM) * + (Beat - CurrentSong.BPM[CurBPM].StartBeat); + end; + Inc(CurBPM); + end; + + { + while (Time > 0) do + begin + GetMidBeatSub(CurBPM, Time, CurBeat); + Inc(CurBPM); + end; + } + end; // if} +end; + +procedure Sing(Sender: TScreenSing); +var + Count: integer; + CountGr: integer; + CP: integer; + Done: real; + N: integer; +begin + LineState.CurrentTime := LineState.CurrentTime + TimeSkip; + + LineState.OldBeat := LineState.CurrentBeat; + LineState.MidBeat := GetMidBeat(LineState.CurrentTime - (CurrentSong.Gap{ + 90 I've forgotten for what it is}) / 1000); // new system with variable BPM in function + LineState.CurrentBeat := Floor(LineState.MidBeat); + +// LineState.OldHalf := LineState.AktHalf; +// LineState.MidHalf := LineState.MidBeat + 0.5; +// LineState.AktHalf := Floor(LineState.MidHalf); + + LineState.OldBeatC := LineState.CurrentBeatC; + LineState.MidBeatC := GetMidBeat(LineState.CurrentTime - (CurrentSong.Gap) / 1000); + LineState.CurrentBeatC := Floor(LineState.MidBeatC); + + LineState.OldBeatD := LineState.CurrentBeatD; + LineState.MidBeatD := -0.5+GetMidBeat(LineState.CurrentTime - (CurrentSong.Gap + 120 + 20) / 1000); // MidBeat with addition GAP + LineState.CurrentBeatD := Floor(LineState.MidBeatD); + LineState.FracBeatD := Frac(LineState.MidBeatD); + + // sentences routines + for CountGr := 0 to 0 do //High(Gracz) + begin; + CP := CountGr; + // ustawianie starej parts + LineState.OldLine := Lines[CP].Current; + + // wybieranie aktualnej parts + for Count := 0 to Lines[CP].High do + begin + if LineState.CurrentBeat >= Lines[CP].Line[Count].Start then + Lines[CP].Current := Count; + end; + + // czysczenie nut gracza, gdy to jest nowa plansza + // (optymizacja raz na halfbeat jest zla) + if Lines[CP].Current <> LineState.OldLine then + NewSentence(Sender); + + end; // for CountGr + + // wykonuje operacje raz na beat + if (LineState.CurrentBeat >= 0) and (LineState.OldBeat <> LineState.CurrentBeat) then + NewBeat(Sender); + + // make some operations on clicks + if {(LineState.CurrentBeatC >= 0) and }(LineState.OldBeatC <> LineState.CurrentBeatC) then + NewBeatC(Sender); + + // make some operations when detecting new voice pitch + if (LineState.CurrentBeatD >= 0) and (LineState.OldBeatD <> LineState.CurrentBeatD) then + NewBeatD(Sender); + + // wykonuje operacje w polowie beatu +// if (LineState.AktHalf >= 1) and (LineState.OldHalf <> LineState.AktHalf) then +// NewHalf; + + // plynnie przesuwa text + Done := 1; + for N := 0 to Lines[0].Line[Lines[0].Current].HighNote do + begin + if (Lines[0].Line[Lines[0].Current].Note[N].Start <= LineState.MidBeat) and + (Lines[0].Line[Lines[0].Current].Note[N].Start + Lines[0].Line[Lines[0].Current].Note[N].Length >= LineState.MidBeat) then + begin + Done := (LineState.MidBeat - Lines[0].Line[Lines[0].Current].Note[N].Start) / (Lines[0].Line[Lines[0].Current].Note[N].Length); + end; + end; + + N := Lines[0].Line[Lines[0].Current].HighNote; + + // wylacza ostatnia nute po przejsciu + {// todo: Lyrics + if (Ini.LyricsEffect = 1) and (Done = 1) and + (LineState.MidBeat > Lines[0].Line[Lines[0].Current].Note[N].Start + Lines[0].Line[Lines[0].Current].Note[N].Length) + then Sender.LyricMain.Selected := -1; + + if Done > 1 then Done := 1; + Sender.LyricMain.Done := Done; } + + // use Done with LCD +{ with ScreenSing do begin + if LyricMain.Selected >= 0 then begin + LCD.MoveCursor(1, LyricMain.SelectedLetter + Round((LyricMain.SelectedLength-1) * Done)); + LCD.ShowCursor; + end; + end;} + + +end; + +procedure NewSentence(Sender: TScreenSing); +var +G: Integer; +begin + // czyszczenie nut graczy + for G := 0 to High(Player) do + begin + Player[G].IlNut := 0; + Player[G].HighNote := -1; + SetLength(Player[G].Note, 0); + end; + + // Add Words to Lyrics + with Sender do + begin + {LyricMain.AddCzesc(Lines[0].Current); + if Lines[0].Current < Lines[0].High then + LyricSub.AddCzesc(Lines[0].Current+1) + else + LyricSub.Clear;} + while (not Lyrics.LineinQueue) and (Lyrics.LineCounter <= High(Lines[0].Line)) do + Lyrics.AddLine(@Lines[0].Line[Lyrics.LineCounter]); + end; + + //Sender.UpdateLCD; + + //On Sentence Change... + Sender.onSentenceChange(Lines[0].Current); +end; + +procedure NewBeat(Sender: TScreenSing); +var + Count: integer; +// TempBeat: integer; +begin + // ustawia zaznaczenie tekstu +// SingScreen.LyricMain.Selected := -1; + for Count := 0 to Lines[0].Line[Lines[0].Current].HighNote do + if (Lines[0].Line[Lines[0].Current].Note[Count].Start = LineState.CurrentBeat) then + begin + // operates on currently beated note + //Todo: Lyrics + //Sender.LyricMain.Selected := Count; + +// LCD.MoveCursor(1, ScreenSing.LyricMain.SelectedLetter); +// LCD.ShowCursor; + + //LCD.MoveCursorBR(Sender.LyricMain.SelectedLetter); + //LCD.ShowCursor; + end; +end; + +procedure NewBeatC; +var + Count: integer; +// LPT_1: integer; +// LPT_2: integer; +begin +// LPT_1 := 1; +// LPT_2 := 1; + + // beat click + if (Ini.BeatClick = 1) and ((LineState.CurrentBeatC + Lines[0].Resolution + Lines[0].NotesGAP) mod Lines[0].Resolution = 0) then + AudioPlayback.PlaySound(SoundLib.Click); + + // debug system on LPT + if ((LineState.CurrentBeatC + Lines[0].Resolution + Lines[0].NotesGAP) mod Lines[0].Resolution = 0) then + begin + //LPT_1 := 0; +// Light.LightOne(0, 150); + + (* + Light.LightOne(1, 200); // beat light + if ParamStr(1) = '-doublelights' then + Light.LightOne(0, 200); // beat light + *) + + +{ if ((LineState.CurrentBeatC + Lines[0].Resolution + Lines[0].NotesGAP) mod (Lines[0].Resolution * 2) = 0) then + Light.LightOne(0, 150) + else + Light.LightOne(1, 150)} + end; + + for Count := 0 to Lines[0].Line[Lines[0].Current].HighNote do + begin + if (Lines[0].Line[Lines[0].Current].Note[Count].Start = LineState.CurrentBeatC) then + begin + // click assist + if Ini.ClickAssist = 1 then + AudioPlayback.PlaySound(SoundLib.Click); + + //LPT_2 := 0; + (* + if ParamStr(1) <> '-doublelights' then + Light.LightOne(0, 150); //125 + *) + + // drum machine + (* + TempBeat := LineState.CurrentBeat;// + 2; + if (TempBeat mod 8 = 0) then Music.PlayDrum; + if (TempBeat mod 8 = 4) then Music.PlayClap; +// if (TempBeat mod 4 = 2) then Music.PlayHihat; + if (TempBeat mod 4 <> 0) then Music.PlayHihat; + *) + end; + end; + + {$IFDEF UseSerialPort} + // PortWriteB($378, LPT_1 + LPT_2 * 2); // 0 zapala + {$ENDIF} +end; + +procedure NewBeatD(Sender: TScreenSing); +begin + NewNote(Sender); +end; + +//procedure NewHalf; +//begin +// NewNote; +//end; + +procedure NewNote(Sender: TScreenSing); +var + CP: integer; // current player + S: integer; // sentence + SMin: integer; + SMax: integer; + SDet: integer; // temporary: sentence of detected note + Count: integer; + Mozna: boolean; + New: boolean; + Range: integer; + NoteHit:boolean; +begin +// Log.LogStatus('Beat ' + IntToStr(LineState.CurrentBeat) + ' HalfBeat ' + IntToStr(LineState.AktHalf), 'NewBeat'); +// beep; + + // On linux we get an AV @ NEWNOTE, line 600 of Classes/UMain.pas + if not assigned( AudioInputProcessor.Sound ) then + exit; + + // analizuje dla obu graczy ten sam sygnal (Sound.OneSrcForBoth) + // albo juz lepiej nie + for CP := 0 to PlayersPlay-1 do + begin + // analyze buffer + AudioInputProcessor.Sound[CP].AnalyzeBuffer; + + // adds some noise + //LineState.Tone := LineState.Tone + Round(Random(3)) - 1; + + // count min and max sentence range for checking (detection is delayed to the notes we see on the screen) + SMin := Lines[0].Current-1; + if SMin < 0 then + SMin := 0; + SMax := Lines[0].Current; + + // check if we can add new note + Mozna := false; + SDet:=SMin; + for S := SMin to SMax do + begin + for Count := 0 to Lines[0].Line[S].HighNote do + begin + if ((Lines[0].Line[S].Note[Count].Start <= LineState.CurrentBeatD) + and (Lines[0].Line[S].Note[Count].Start + Lines[0].Line[S].Note[Count].Length - 1 >= LineState.CurrentBeatD)) + and (not Lines[0].Line[S].Note[Count].FreeStyle) // but don't allow when it's FreeStyle note + and (Lines[0].Line[S].Note[Count].Length > 0) then // and make sure the note lengths is at least 1 + begin + SDet := S; + Mozna := true; + Break; + end; + end; + end; + + S := SDet; + + //Czas.SzczytJest := true; + //Czas.Tone := 27; + + // gdy moze, to dodaje nute - When Mozna, it adds note (?) + if (AudioInputProcessor.Sound[CP].ToneValid) and (Mozna) then + begin + // operowanie na ostatniej nucie + for Count := 0 to Lines[0].Line[S].HighNote do + begin + if (Lines[0].Line[S].Note[Count].Start <= LineState.OldBeatD+1) and + (Lines[0].Line[S].Note[Count].Start + + Lines[0].Line[S].Note[Count].Length > LineState.OldBeatD+1) then + begin + // to robi, tylko dla pary nut (oryginalnej i gracza) + + // przesuwanie tonu w odpowiednia game + while (AudioInputProcessor.Sound[CP].Tone - Lines[0].Line[S].Note[Count].Tone > 6) do + AudioInputProcessor.Sound[CP].Tone := AudioInputProcessor.Sound[CP].Tone - 12; + + while (AudioInputProcessor.Sound[CP].Tone - Lines[0].Line[S].Note[Count].Tone < -6) do + AudioInputProcessor.Sound[CP].Tone := AudioInputProcessor.Sound[CP].Tone + 12; + + // Half size Notes Patch + NoteHit := false; + + //if Ini.Difficulty = 0 then Range := 2; + //if Ini.Difficulty = 1 then Range := 1; + //if Ini.Difficulty = 2 then Range := 0; + Range := 2 - Ini.Difficulty; + + if abs(Lines[0].Line[S].Note[Count].Tone - AudioInputProcessor.Sound[CP].Tone) <= Range then + begin + AudioInputProcessor.Sound[CP].Tone := Lines[0].Line[S].Note[Count].Tone; + + // Half size Notes Patch + NoteHit := true; + + if (Ini.LineBonus = 0) then + begin + // add points without LineBonus + case Lines[0].Line[S].Note[Count].NoteType of + 1: Player[CP].Score := Player[CP].Score + 10000 / Lines[0].NoteType * + Lines[0].Line[S].Note[Count].NoteType; + 2: Player[CP].ScoreGolden := Player[CP].ScoreGolden + 10000 / Lines[0].NoteType * + Lines[0].Line[S].Note[Count].NoteType; + end; + end + else + begin + // add points with Line Bonus + case Lines[0].Line[S].Note[Count].NoteType of + 1: Player[CP].Score := Player[CP].Score + 9000 / Lines[0].NoteType * + Lines[0].Line[S].Note[Count].NoteType; + 2: Player[CP].ScoreGolden := Player[CP].ScoreGolden + 9000 / Lines[0].NoteType * + Lines[0].Line[S].Note[Count].NoteType; + end; + end; + + Player[CP].ScoreI := Floor(Player[CP].Score / 10) * 10; + Player[CP].ScoreGoldenI := Floor(Player[CP].ScoreGolden / 10) * 10; + + Player[CP].ScoreTotalI := Player[CP].ScoreI + Player[CP].ScoreGoldenI + Player[CP].ScoreLineI; + end; + + end; // operowanie + end; // for + + // sprawdzanie czy to nowa nuta, czy przedluzenie + if S = SMax then + begin + New := true; + // if last has the same tone + if (Player[CP].IlNut > 0 ) and + (Player[CP].Note[Player[CP].HighNote].Tone = AudioInputProcessor.Sound[CP].Tone) and + (Player[CP].Note[Player[CP].HighNote].Start + Player[CP].Note[Player[CP].HighNote].Length = LineState.CurrentBeatD) then + begin + New := false; + end; + + // if is not as new note to control "beacie" (TODO: translate polish "beacie") + for Count := 0 to Lines[0].Line[S].HighNote do + begin + if (Lines[0].Line[S].Note[Count].Start = LineState.CurrentBeatD) then + New := true; + end; + + // dodawanie nowej nuty + if New then + begin + // New Note + Player[CP].IlNut := Player[CP].IlNut + 1; + Player[CP].HighNote := Player[CP].HighNote + 1; + SetLength(Player[CP].Note, Player[CP].IlNut); + Player[CP].Note[Player[CP].HighNote].Start := LineState.CurrentBeatD; + Player[CP].Note[Player[CP].HighNote].Length := 1; + Player[CP].Note[Player[CP].HighNote].Tone := AudioInputProcessor.Sound[CP].Tone; // Ton || TonDokl + Player[CP].Note[Player[CP].HighNote].Detekt := LineState.MidBeat; + + // Half Note Patch + Player[CP].Note[Player[CP].HighNote].Hit := NoteHit; + + //Log.LogStatus('New Note ' + IntToStr(Gracz.Note[Gracz.HighNote].Start), 'NewBeat'); + end + else + begin + // przedluzenie nuty + Player[CP].Note[Player[CP].HighNote].Length := Player[CP].Note[Player[CP].HighNote].Length + 1; + end; + + // check for perfect note and then lit the star (on Draw) + for Count := 0 to Lines[0].Line[S].HighNote do + begin + if (Lines[0].Line[S].Note[Count].Start = Player[CP].Note[Player[CP].HighNote].Start) and + (Lines[0].Line[S].Note[Count].Length = Player[CP].Note[Player[CP].HighNote].Length) and + (Lines[0].Line[S].Note[Count].Tone = Player[CP].Note[Player[CP].HighNote].Tone) then + begin + Player[CP].Note[Player[CP].HighNote].Perfect := true; + end; + end; + end;// else beep; // if S = SMax + + end; // if moze + end; // for CP + // Log.LogStatus('EndBeat', 'NewBeat'); + + //On Sentence End -> For LineBonus + SingBar + if (sDet >= low(Lines[0].Line)) and (sDet <= high(Lines[0].Line)) then + begin + if assigned( Sender ) and + ((Lines[0].Line[SDet].Note[Lines[0].Line[SDet].HighNote].Start + Lines[0].Line[SDet].Note[Lines[0].Line[SDet].HighNote].Length - 1) = LineState.CurrentBeatD) then + begin + Sender.onSentenceEnd(sDet); + end; + end; + +end; + +procedure ClearScores(PlayerNum: integer); +begin + Player[PlayerNum].Score := 0; + Player[PlayerNum].ScoreI := 0; + Player[PlayerNum].ScoreLine := 0; + Player[PlayerNum].ScoreLineI := 0; + Player[PlayerNum].ScoreGolden := 0; + Player[PlayerNum].ScoreGoldenI := 0; + Player[PlayerNum].ScoreTotalI := 0; +end; + +//-------------------- +// Function sets all Absolute Paths e.g. Song Path and makes sure the Directorys exist +//-------------------- +procedure InitializePaths; + + // Initialize a Path Variable + // After Setting Paths, make sure that Paths exist + function initialize_path( out aPathVar : string; const aLocation : string ): boolean; + var + lWriteable: Boolean; + lAttrib : integer; + begin + lWriteable := false; + aPathVar := aLocation; + + // Make sure the directory is needex + ForceDirectories(aPathVar); + + if DirectoryExists(aPathVar) then + begin + lAttrib := fileGetAttr(aPathVar); + + lWriteable := (lAttrib and faDirectory <> 0) and + not (lAttrib and faReadOnly <> 0) + end; + + if not lWriteable then + Log.LogError('Error: Dir ('+ aLocation +') is Readonly'); + + result := lWriteable; + end; + +begin + initialize_path( LogPath , Platform.GetLogPath ); + initialize_path( SoundPath , Platform.GetGameSharedPath + 'Sounds' + PathDelim ); + initialize_path( ThemePath , Platform.GetGameSharedPath + 'Themes' + PathDelim ); + initialize_path( SkinsPath , Platform.GetGameSharedPath + 'Skins' + PathDelim ); + initialize_path( LanguagesPath , Platform.GetGameSharedPath + 'Languages' + PathDelim ); + initialize_path( PluginPath , Platform.GetGameSharedPath + 'Plugins' + PathDelim ); + initialize_path( VisualsPath , Platform.GetGameSharedPath + 'Visuals' + PathDelim ); + + initialize_path( ScreenshotsPath , Platform.GetGameUserPath + 'Screenshots' + PathDelim ); + + // Users Song Path .... + initialize_path( UserSongPath , Platform.GetGameUserPath + 'Songs' + PathDelim ); + initialize_path( UserCoversPath , Platform.GetGameUserPath + 'Covers' + PathDelim ); + initialize_path( UserPlaylistPath , Platform.GetGameUserPath + 'Playlists' + PathDelim ); + + // Shared Song Path .... + initialize_path( SongPath , Platform.GetGameSharedPath + 'Songs' + PathDelim ); + initialize_path( CoversPath , Platform.GetGameSharedPath + 'Covers' + PathDelim ); + initialize_path( PlaylistPath , Platform.GetGameSharedPath + 'Playlists' + PathDelim ); + + DecimalSeparator := '.'; +end; + +end. + diff --git a/Game/Code/MacOSX/UltraStarDX.xcodeproj/eddie.mode1v3 b/Game/Code/MacOSX/UltraStarDX.xcodeproj/eddie.mode1v3 index dfe66827..3a15da1d 100644 --- a/Game/Code/MacOSX/UltraStarDX.xcodeproj/eddie.mode1v3 +++ b/Game/Code/MacOSX/UltraStarDX.xcodeproj/eddie.mode1v3 @@ -200,6 +200,286 @@ <key>Content</key> <dict> <key>PBXProjectModuleGUID</key> + <string>2CA608820D9998CC00EBC4A7</string> + <key>PBXProjectModuleLabel</key> + <string>UAudioPlayback_Bass.pas</string> + <key>PBXSplitModuleInNavigatorKey</key> + <dict> + <key>Split0</key> + <dict> + <key>PBXProjectModuleGUID</key> + <string>2CA608830D9998CC00EBC4A7</string> + <key>PBXProjectModuleLabel</key> + <string>UAudioPlayback_Bass.pas</string> + <key>_historyCapacity</key> + <integer>0</integer> + <key>bookmark</key> + <string>2CA6088F0D99999100EBC4A7</string> + <key>history</key> + <array> + <string>2CA608790D99987900EBC4A7</string> + </array> + </dict> + <key>SplitCount</key> + <string>1</string> + </dict> + <key>StatusBarVisibility</key> + <true/> + </dict> + <key>Geometry</key> + <dict> + <key>Frame</key> + <string>{{0, 20}, {993, 838}}</string> + <key>PBXModuleWindowStatusBarHidden2</key> + <false/> + <key>RubberWindowFrame</key> + <string>38 123 993 879 0 0 1680 1028 </string> + </dict> + </dict> + <dict> + <key>Content</key> + <dict> + <key>PBXProjectModuleGUID</key> + <string>2CA608850D9998CC00EBC4A7</string> + <key>PBXProjectModuleLabel</key> + <string>UAudioCore_Bass.pas</string> + <key>PBXSplitModuleInNavigatorKey</key> + <dict> + <key>Split0</key> + <dict> + <key>PBXProjectModuleGUID</key> + <string>2CA608860D9998CC00EBC4A7</string> + <key>PBXProjectModuleLabel</key> + <string>UAudioCore_Bass.pas</string> + <key>_historyCapacity</key> + <integer>0</integer> + <key>bookmark</key> + <string>2CA608900D99999100EBC4A7</string> + <key>history</key> + <array> + <string>2CA608780D99987200EBC4A7</string> + </array> + </dict> + <key>SplitCount</key> + <string>1</string> + </dict> + <key>StatusBarVisibility</key> + <true/> + </dict> + <key>Geometry</key> + <dict> + <key>Frame</key> + <string>{{0, 20}, {993, 838}}</string> + <key>PBXModuleWindowStatusBarHidden2</key> + <false/> + <key>RubberWindowFrame</key> + <string>15 144 993 879 0 0 1680 1028 </string> + </dict> + </dict> + <dict> + <key>Content</key> + <dict> + <key>PBXProjectModuleGUID</key> + <string>2C019A0B0D998D4A00974970</string> + <key>PBXProjectModuleLabel</key> + <string>UMain.pas</string> + <key>PBXSplitModuleInNavigatorKey</key> + <dict> + <key>Split0</key> + <dict> + <key>PBXProjectModuleGUID</key> + <string>2C019A0C0D998D4A00974970</string> + <key>PBXProjectModuleLabel</key> + <string>UMain.pas</string> + <key>_historyCapacity</key> + <integer>0</integer> + <key>bookmark</key> + <string>2CA608910D99999100EBC4A7</string> + <key>history</key> + <array> + <string>2CA607DD0D998F0B00EBC4A7</string> + </array> + </dict> + <key>SplitCount</key> + <string>1</string> + </dict> + <key>StatusBarVisibility</key> + <true/> + </dict> + <key>Geometry</key> + <dict> + <key>Frame</key> + <string>{{0, 20}, {1052, 646}}</string> + <key>PBXModuleWindowStatusBarHidden2</key> + <false/> + <key>RubberWindowFrame</key> + <string>30 341 1052 687 0 0 1680 1028 </string> + </dict> + </dict> + <dict> + <key>Content</key> + <dict> + <key>PBXProjectModuleGUID</key> + <string>2C0199490D9981C000974970</string> + <key>PBXProjectModuleLabel</key> + <string>UCommon.pas</string> + <key>PBXSplitModuleInNavigatorKey</key> + <dict> + <key>Split0</key> + <dict> + <key>PBXProjectModuleGUID</key> + <string>2C01994A0D9981C000974970</string> + <key>PBXProjectModuleLabel</key> + <string>UCommon.pas</string> + <key>_historyCapacity</key> + <integer>0</integer> + <key>bookmark</key> + <string>2CA608920D99999100EBC4A7</string> + <key>history</key> + <array> + <string>2CA607DF0D998F0B00EBC4A7</string> + </array> + </dict> + <key>SplitCount</key> + <string>1</string> + </dict> + <key>StatusBarVisibility</key> + <true/> + </dict> + <key>Geometry</key> + <dict> + <key>Frame</key> + <string>{{0, 20}, {754, 847}}</string> + <key>PBXModuleWindowStatusBarHidden2</key> + <false/> + <key>RubberWindowFrame</key> + <string>38 134 754 888 0 0 1680 1028 </string> + </dict> + </dict> + <dict> + <key>Content</key> + <dict> + <key>PBXProjectModuleGUID</key> + <string>2C0199430D9981C000974970</string> + <key>PBXProjectModuleLabel</key> + <string>UScreenMain.pas</string> + <key>PBXSplitModuleInNavigatorKey</key> + <dict> + <key>Split0</key> + <dict> + <key>PBXProjectModuleGUID</key> + <string>2C0199440D9981C000974970</string> + <key>PBXProjectModuleLabel</key> + <string>UScreenMain.pas</string> + <key>_historyCapacity</key> + <integer>0</integer> + <key>bookmark</key> + <string>2CA608930D99999100EBC4A7</string> + <key>history</key> + <array> + <string>2C019A190D998D4A00974970</string> + </array> + </dict> + <key>SplitCount</key> + <string>1</string> + </dict> + <key>StatusBarVisibility</key> + <true/> + </dict> + <key>Geometry</key> + <dict> + <key>Frame</key> + <string>{{0, 20}, {754, 847}}</string> + <key>PBXModuleWindowStatusBarHidden2</key> + <false/> + <key>RubberWindowFrame</key> + <string>38 135 754 888 0 0 1680 1028 </string> + </dict> + </dict> + <dict> + <key>Content</key> + <dict> + <key>PBXProjectModuleGUID</key> + <string>2C0199930D9984F900974970</string> + <key>PBXProjectModuleLabel</key> + <string>UltraStarDX.pas</string> + <key>PBXSplitModuleInNavigatorKey</key> + <dict> + <key>Split0</key> + <dict> + <key>PBXProjectModuleGUID</key> + <string>2C0199940D9984F900974970</string> + <key>PBXProjectModuleLabel</key> + <string>UltraStarDX.pas</string> + <key>_historyCapacity</key> + <integer>0</integer> + <key>bookmark</key> + <string>2CA608940D99999100EBC4A7</string> + <key>history</key> + <array> + <string>2C019A1A0D998D4A00974970</string> + </array> + </dict> + <key>SplitCount</key> + <string>1</string> + </dict> + <key>StatusBarVisibility</key> + <true/> + </dict> + <key>Geometry</key> + <dict> + <key>Frame</key> + <string>{{0, 20}, {987, 762}}</string> + <key>PBXModuleWindowStatusBarHidden2</key> + <false/> + <key>RubberWindowFrame</key> + <string>311 168 987 803 0 0 1680 1028 </string> + </dict> + </dict> + <dict> + <key>Content</key> + <dict> + <key>PBXProjectModuleGUID</key> + <string>2C01994C0D9981C000974970</string> + <key>PBXProjectModuleLabel</key> + <string>OpenGL12.pas</string> + <key>PBXSplitModuleInNavigatorKey</key> + <dict> + <key>Split0</key> + <dict> + <key>PBXProjectModuleGUID</key> + <string>2C01994D0D9981C000974970</string> + <key>PBXProjectModuleLabel</key> + <string>OpenGL12.pas</string> + <key>_historyCapacity</key> + <integer>0</integer> + <key>bookmark</key> + <string>2CA608950D99999100EBC4A7</string> + <key>history</key> + <array> + <string>2C019A1B0D998D4A00974970</string> + </array> + </dict> + <key>SplitCount</key> + <string>1</string> + </dict> + <key>StatusBarVisibility</key> + <true/> + </dict> + <key>Geometry</key> + <dict> + <key>Frame</key> + <string>{{0, 20}, {1070, 868}}</string> + <key>PBXModuleWindowStatusBarHidden2</key> + <false/> + <key>RubberWindowFrame</key> + <string>1 119 1070 909 0 0 1680 1028 </string> + </dict> + </dict> + <dict> + <key>Content</key> + <dict> + <key>PBXProjectModuleGUID</key> <string>2CE603EA0D71601400DB0D88</string> <key>PBXProjectModuleLabel</key> <string>UTexture.pas</string> @@ -214,10 +494,10 @@ <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> - <string>2CE603FF0D7160F300DB0D88</string> + <string>2CA608960D99999100EBC4A7</string> <key>history</key> <array> - <string>2CE603EC0D71601400DB0D88</string> + <string>2C019A1C0D998D4A00974970</string> </array> </dict> <key>SplitCount</key> @@ -254,10 +534,10 @@ <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> - <string>2CE604000D7160F300DB0D88</string> + <string>2CA608970D99999100EBC4A7</string> <key>history</key> <array> - <string>2CE603E50D715F9B00DB0D88</string> + <string>2C019A1D0D998D4A00974970</string> </array> </dict> <key>SplitCount</key> @@ -349,6 +629,7 @@ <string>2C4D9D980CC9EE0B0031092D</string> <string>DD7C45450A6E72DE003FA52B</string> <string>2CF5510C0CDA28F000627463</string> + <string>1C37FBAC04509CD000000102</string> <string>1C37FAAC04509CD000000102</string> </array> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> @@ -360,7 +641,7 @@ </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> - <string>{{0, 0}, {266, 694}}</string> + <string>{{0, 105}, {266, 694}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> @@ -462,9 +743,9 @@ </array> <key>TableOfContents</key> <array> - <string>2CE603E80D71601400DB0D88</string> + <string>2CA607D80D998F0B00EBC4A7</string> <string>1CE0B1FE06471DED0097A5F4</string> - <string>2CE603E90D71601400DB0D88</string> + <string>2CA607D90D998F0B00EBC4A7</string> <string>1CE0B20306471E060097A5F4</string> <string>1CE0B20506471E060097A5F4</string> </array> @@ -596,15 +877,22 @@ <integer>5</integer> <key>WindowOrderList</key> <array> - <string>2CE603F80D71601400DB0D88</string> - <string>2CE603F90D71601400DB0D88</string> - <string>2CE603FA0D71601400DB0D88</string> + <string>2CA6081C0D9991E800EBC4A7</string> + <string>2CA6081D0D9991E800EBC4A7</string> + <string>1C530D57069F1CE1000CFCEE</string> <string>1C78EAAD065D492600B07095</string> <string>1CD10A99069EF8BA00B06720</string> <string>2C65660B0CF2236C0041F7DC</string> <string>2CE603EE0D71601400DB0D88</string> <string>2CE603EA0D71601400DB0D88</string> + <string>2C01994C0D9981C000974970</string> + <string>2C0199930D9984F900974970</string> + <string>2C0199430D9981C000974970</string> + <string>2C0199490D9981C000974970</string> + <string>2C019A0B0D998D4A00974970</string> + <string>2CA608850D9998CC00EBC4A7</string> <string>/Users/eddie/Projekte/UltraStarDX/trunk/Game/Code/MacOSX/UltraStarDX.xcodeproj</string> + <string>2CA608820D9998CC00EBC4A7</string> </array> <key>WindowString</key> <string>799 242 817 753 0 0 1680 1028 </string> @@ -623,12 +911,14 @@ <key>Dock</key> <array> <dict> + <key>BecomeActive</key> + <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528F0623707200166675</string> <key>PBXProjectModuleLabel</key> - <string>UTexture.pas</string> + <string>UAudioInput_Bass.pas</string> <key>StatusBarVisibility</key> <true/> </dict> @@ -645,8 +935,6 @@ <string>546pt</string> </dict> <dict> - <key>BecomeActive</key> - <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> @@ -686,7 +974,7 @@ <key>TableOfContents</key> <array> <string>2C65660B0CF2236C0041F7DC</string> - <string>2CE603CB0D715C9200DB0D88</string> + <string>2CA607E60D998F0B00EBC4A7</string> <string>1CD0528F0623707200166675</string> <string>XCMainBuildResultsModuleGUID</string> </array> @@ -697,7 +985,7 @@ <key>WindowToolGUID</key> <string>2C65660B0CF2236C0041F7DC</string> <key>WindowToolIsVisible</key> - <true/> + <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> @@ -806,13 +1094,13 @@ <key>TableOfContents</key> <array> <string>1CD10A99069EF8BA00B06720</string> - <string>2CE603F10D71601400DB0D88</string> + <string>2CA607E70D998F0B00EBC4A7</string> <string>1C162984064C10D400B95A72</string> - <string>2CE603F20D71601400DB0D88</string> - <string>2CE603F30D71601400DB0D88</string> - <string>2CE603F40D71601400DB0D88</string> - <string>2CE603F50D71601400DB0D88</string> - <string>2CE603F60D71601400DB0D88</string> + <string>2CA607E80D998F0B00EBC4A7</string> + <string>2CA607E90D998F0B00EBC4A7</string> + <string>2CA607EA0D998F0B00EBC4A7</string> + <string>2CA607EB0D998F0B00EBC4A7</string> + <string>2CA607EC0D998F0B00EBC4A7</string> </array> <key>ToolbarConfiguration</key> <string>xcode.toolbar.config.debugV3</string> @@ -839,14 +1127,12 @@ <key>Dock</key> <array> <dict> - <key>BecomeActive</key> - <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CDD528C0622207200134675</string> <key>PBXProjectModuleLabel</key> - <string>UAudioPlayback_Bass.pas</string> + <string><No Editor></string> <key>StatusBarVisibility</key> <true/> </dict> @@ -867,6 +1153,8 @@ <string>502pt</string> </dict> <dict> + <key>BecomeActive</key> + <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> @@ -902,8 +1190,8 @@ <key>TableOfContents</key> <array> <string>1C530D57069F1CE1000CFCEE</string> - <string>2CA2E2DE0D491DDF00E7C4DF</string> - <string>2CA2E2DF0D491DDF00E7C4DF</string> + <string>2CA607ED0D998F0B00EBC4A7</string> + <string>2CA607EE0D998F0B00EBC4A7</string> <string>1CDD528C0622207200134675</string> <string>1CD0528E0623707200166675</string> </array> @@ -912,7 +1200,7 @@ <key>WindowToolGUID</key> <string>1C530D57069F1CE1000CFCEE</string> <key>WindowToolIsVisible</key> - <true/> + <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> @@ -933,6 +1221,8 @@ <key>Dock</key> <array> <dict> + <key>BecomeActive</key> + <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> @@ -968,7 +1258,7 @@ <key>TableOfContents</key> <array> <string>1C78EAAD065D492600B07095</string> - <string>2CE603F70D71601400DB0D88</string> + <string>2CA607EF0D998F0B00EBC4A7</string> <string>1C78EAAC065D492600B07095</string> </array> <key>ToolbarConfiguration</key> diff --git a/Game/Code/MacOSX/UltraStarDX.xcodeproj/eddie.pbxuser b/Game/Code/MacOSX/UltraStarDX.xcodeproj/eddie.pbxuser index 8c30a077..e054f93e 100644 --- a/Game/Code/MacOSX/UltraStarDX.xcodeproj/eddie.pbxuser +++ b/Game/Code/MacOSX/UltraStarDX.xcodeproj/eddie.pbxuser @@ -1,5 +1,63 @@ // !$*UTF8*$! { + 2C0199800D99840900974970 /* config-macosx.inc */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {934, 994}}"; + sepNavSelRange = "{540, 0}"; + sepNavVisRange = "{353, 1694}"; + sepNavWindowFrame = "{{15, 88}, {993, 935}}"; + }; + }; + 2C019A190D998D4A00974970 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 2CF54F4A0CDA1B2B00627463 /* UScreenMain.pas */; + name = "UScreenMain.pas: 76"; + rLen = 17; + rLoc = 1560; + rType = 0; + vrLen = 1274; + vrLoc = 1037; + }; + 2C019A1A0D998D4A00974970 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = DDC6851B09F57195004E4BFF /* UltraStarDX.pas */; + name = "UltraStarDX.pas: 3"; + rLen = 0; + rLoc = 72; + rType = 0; + vrLen = 152; + vrLoc = 0; + }; + 2C019A1B0D998D4A00974970 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 2C4D9E040CC9EF840031092D /* OpenGL12.pas */; + name = "OpenGL12.pas: 4683"; + rLen = 0; + rLoc = 213678; + rType = 0; + vrLen = 6646; + vrLoc = 207819; + }; + 2C019A1C0D998D4A00974970 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 2C4D9C8B0CC9EC8C0031092D /* UTexture.pas */; + name = "UTexture.pas: 344"; + rLen = 0; + rLoc = 10496; + rType = 0; + vrLen = 1662; + vrLoc = 9347; + }; + 2C019A1D0D998D4A00974970 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 2C8937310CE395CE005D8A87 /* UPlatformMacOSX.pas */; + name = "UPlatformMacOSX.pas: 13"; + rLen = 0; + rLoc = 717; + rType = 0; + vrLen = 1571; + vrLoc = 493; + }; 2C4B70220CF757A400B0F0BD /* Until5000.dpr */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {691, 1218}}"; @@ -10,9 +68,9 @@ }; 2C4D9C620CC9EC8C0031092D /* TextGL.pas */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {729, 7728}}"; - sepNavSelRange = "{4228, 11}"; - sepNavVisRange = "{3672, 1043}"; + sepNavIntBoundsRect = "{{0, 0}, {881, 7532}}"; + sepNavSelRange = "{10589, 66}"; + sepNavVisRange = "{10222, 893}"; sepNavVisRect = "{{0, 5908}, {758, 716}}"; sepNavWindowFrame = "{{38, 157}, {797, 845}}"; }; @@ -35,10 +93,11 @@ }; 2C4D9C670CC9EC8C0031092D /* UCommon.pas */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {715, 4228}}"; - sepNavSelRange = "{1581, 322}"; + sepNavIntBoundsRect = "{{0, 0}, {695, 4060}}"; + sepNavSelRange = "{584, 24}"; + sepNavVisRange = "{249, 1447}"; sepNavVisRect = "{{0, 508}, {715, 815}}"; - sepNavWindowFrame = "{{38, 58}, {754, 944}}"; + sepNavWindowFrame = "{{38, 78}, {754, 944}}"; }; }; 2C4D9C680CC9EC8C0031092D /* UCore.pas */ = { @@ -195,9 +254,9 @@ }; 2C4D9C7B0CC9EC8C0031092D /* UMain.pas */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {842, 15400}}"; - sepNavSelRange = "{9910, 0}"; - sepNavVisRange = "{9538, 599}"; + sepNavIntBoundsRect = "{{0, 0}, {1026, 16268}}"; + sepNavSelRange = "{31433, 0}"; + sepNavVisRange = "{32193, 1839}"; sepNavVisRect = "{{0, 0}, {1013, 614}}"; sepNavWindowFrame = "{{30, 285}, {1052, 743}}"; }; @@ -262,9 +321,9 @@ }; 2C4D9C840CC9EC8C0031092D /* URecord.pas */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {881, 10862}}"; - sepNavSelRange = "{4086, 14}"; - sepNavVisRange = "{3581, 928}"; + sepNavIntBoundsRect = "{{0, 0}, {738, 8372}}"; + sepNavSelRange = "{10657, 20}"; + sepNavVisRange = "{10176, 1198}"; sepNavVisRect = "{{0, 4312}, {758, 716}}"; sepNavWindowFrame = "{{130, 73}, {797, 845}}"; }; @@ -321,9 +380,9 @@ }; 2C4D9C8B0CC9EC8C0031092D /* UTexture.pas */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {854, 16562}}"; + sepNavIntBoundsRect = "{{0, 0}, {858, 16688}}"; sepNavSelRange = "{10496, 0}"; - sepNavVisRange = "{9347, 1705}"; + sepNavVisRange = "{9368, 1825}"; sepNavVisRect = "{{0, 3420}, {737, 826}}"; sepNavWindowFrame = "{{15, 68}, {776, 955}}"; }; @@ -372,9 +431,9 @@ }; 2C4D9DCC0CC9EE6F0031092D /* UDisplay.pas */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {782, 6748}}"; - sepNavSelRange = "{8084, 0}"; - sepNavVisRange = "{551, 818}"; + sepNavIntBoundsRect = "{{0, 0}, {881, 6944}}"; + sepNavSelRange = "{5028, 51}"; + sepNavVisRange = "{4044, 1359}"; sepNavVisRect = "{{0, 4834}, {758, 716}}"; sepNavWindowFrame = "{{38, 157}, {797, 845}}"; }; @@ -390,9 +449,9 @@ }; 2C4D9DCE0CC9EE6F0031092D /* UMenu.pas */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1220, 21770}}"; - sepNavSelRange = "{25533, 1}"; - sepNavVisRange = "{22476, 1170}"; + sepNavIntBoundsRect = "{{0, 0}, {1284, 22162}}"; + sepNavSelRange = "{51782, 0}"; + sepNavVisRange = "{51126, 1038}"; sepNavVisRect = "{{0, 3972}, {749, 470}}"; sepNavWindowFrame = "{{38, 82}, {898, 920}}"; }; @@ -472,9 +531,9 @@ }; 2C4D9E040CC9EF840031092D /* OpenGL12.pas */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1604, 65450}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{207947, 6380}"; + sepNavIntBoundsRect = "{{0, 0}, {1608, 64064}}"; + sepNavSelRange = "{213678, 0}"; + sepNavVisRange = "{207797, 6669}"; sepNavVisRect = "{{0, 64932}, {1031, 840}}"; sepNavWindowFrame = "{{1, 63}, {1070, 965}}"; }; @@ -489,9 +548,9 @@ }; 2C4D9E440CC9F0ED0031092D /* switches.inc */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {686, 980}}"; - sepNavSelRange = "{485, 14}"; - sepNavVisRange = "{0, 1065}"; + sepNavIntBoundsRect = "{{0, 0}, {624, 1918}}"; + sepNavSelRange = "{1326, 0}"; + sepNavVisRange = "{657, 1095}"; sepNavVisRect = "{{0, 7}, {577, 612}}"; sepNavWindowFrame = "{{15, 282}, {616, 741}}"; }; @@ -521,26 +580,145 @@ }; 2C8937310CE395CE005D8A87 /* UPlatformMacOSX.pas */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {740, 1848}}"; + sepNavIntBoundsRect = "{{0, 0}, {744, 1890}}"; sepNavSelRange = "{717, 0}"; - sepNavVisRange = "{493, 1700}"; + sepNavVisRange = "{410, 1660}"; sepNavVisRect = "{{0, 105}, {737, 827}}"; sepNavWindowFrame = "{{79, 70}, {776, 956}}"; }; }; + 2CA607DD0D998F0B00EBC4A7 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 2C4D9C7B0CC9EC8C0031092D /* UMain.pas */; + name = "UMain.pas: 120"; + rLen = 0; + rLoc = 2684; + rType = 0; + vrLen = 1123; + vrLoc = 1767; + }; + 2CA607DF0D998F0B00EBC4A7 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 2C4D9C670CC9EC8C0031092D /* UCommon.pas */; + name = "UCommon.pas: 52"; + rLen = 0; + rLoc = 807; + rType = 0; + vrLen = 1163; + vrLoc = 56; + }; + 2CA608780D99987200EBC4A7 /* PBXBookmark */ = { + isa = PBXBookmark; + fRef = 2CE603DD0D715F6700DB0D88 /* UAudioCore_Bass.pas */; + }; + 2CA608790D99987900EBC4A7 /* PBXBookmark */ = { + isa = PBXBookmark; + fRef = 2CAC2BDF0D3809F500CA518A /* UAudioPlayback_Bass.pas */; + }; + 2CA6088F0D99999100EBC4A7 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 2CAC2BDF0D3809F500CA518A /* UAudioPlayback_Bass.pas */; + name = "UAudioPlayback_Bass.pas: 219"; + rLen = 3; + rLoc = 4658; + rType = 0; + vrLen = 1277; + vrLoc = 4001; + }; + 2CA608900D99999100EBC4A7 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 2CE603DD0D715F6700DB0D88 /* UAudioCore_Bass.pas */; + name = "UAudioCore_Bass.pas: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1211; + vrLoc = 0; + }; + 2CA608910D99999100EBC4A7 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 2C4D9C7B0CC9EC8C0031092D /* UMain.pas */; + name = "UMain.pas: 1096"; + rLen = 0; + rLoc = 31433; + rType = 0; + vrLen = 1839; + vrLoc = 32193; + }; + 2CA608920D99999100EBC4A7 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 2C4D9C670CC9EC8C0031092D /* UCommon.pas */; + name = "UCommon.pas: 44"; + rLen = 24; + rLoc = 584; + rType = 0; + vrLen = 1447; + vrLoc = 249; + }; + 2CA608930D99999100EBC4A7 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 2CF54F4A0CDA1B2B00627463 /* UScreenMain.pas */; + name = "UScreenMain.pas: 76"; + rLen = 17; + rLoc = 1560; + rType = 0; + vrLen = 1336; + vrLoc = 1022; + }; + 2CA608940D99999100EBC4A7 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = DDC6851B09F57195004E4BFF /* UltraStarDX.pas */; + name = "UltraStarDX.pas: 3"; + rLen = 0; + rLoc = 72; + rType = 0; + vrLen = 152; + vrLoc = 0; + }; + 2CA608950D99999100EBC4A7 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 2C4D9E040CC9EF840031092D /* OpenGL12.pas */; + name = "OpenGL12.pas: 4683"; + rLen = 0; + rLoc = 213678; + rType = 0; + vrLen = 6669; + vrLoc = 207797; + }; + 2CA608960D99999100EBC4A7 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 2C4D9C8B0CC9EC8C0031092D /* UTexture.pas */; + name = "UTexture.pas: 344"; + rLen = 0; + rLoc = 10496; + rType = 0; + vrLen = 1825; + vrLoc = 9368; + }; + 2CA608970D99999100EBC4A7 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 2C8937310CE395CE005D8A87 /* UPlatformMacOSX.pas */; + name = "UPlatformMacOSX.pas: 13"; + rLen = 0; + rLoc = 717; + rType = 0; + vrLen = 1660; + vrLoc = 410; + }; 2CAC2BDD0D3809F500CA518A /* UAudioInput_Bass.pas */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {815, 4018}}"; - sepNavSelRange = "{2733, 0}"; - sepNavVisRange = "{5604, 1832}"; + sepNavIntBoundsRect = "{{0, 0}, {842, 3766}}"; + sepNavSelRange = "{5570, 0}"; + sepNavVisRange = "{5295, 761}"; sepNavWindowFrame = "{{15, 140}, {874, 883}}"; }; }; 2CAC2BDF0D3809F500CA518A /* UAudioPlayback_Bass.pas */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {729, 7224}}"; + sepNavIntBoundsRect = "{{0, 0}, {934, 6104}}"; sepNavSelRange = "{4658, 3}"; - sepNavVisRange = "{4075, 1054}"; + sepNavVisRange = "{4001, 1277}"; + sepNavWindowFrame = "{{38, 67}, {993, 935}}"; }; }; 2CB9E87D0D43B78400214DFA /* USong.pas */ = { @@ -614,36 +792,20 @@ isa = PBXCodeSenseManager; indexTemplatePath = ""; }; - 2CE603E50D715F9B00DB0D88 /* PBXBookmark */ = { - isa = PBXBookmark; - fRef = 2C8937310CE395CE005D8A87 /* UPlatformMacOSX.pas */; - }; - 2CE603EC0D71601400DB0D88 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 2C4D9C8B0CC9EC8C0031092D /* UTexture.pas */; - rLen = 0; - rLoc = 343; - rType = 1; - }; - 2CE603FF0D7160F300DB0D88 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 2C4D9C8B0CC9EC8C0031092D /* UTexture.pas */; - name = "UTexture.pas: 344"; - rLen = 0; - rLoc = 10496; - rType = 0; - vrLen = 1705; - vrLoc = 9347; + 2CE603DD0D715F6700DB0D88 /* UAudioCore_Bass.pas */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {934, 1764}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 1211}"; + sepNavWindowFrame = "{{15, 88}, {993, 935}}"; + }; }; - 2CE604000D7160F300DB0D88 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 2C8937310CE395CE005D8A87 /* UPlatformMacOSX.pas */; - name = "UPlatformMacOSX.pas: 13"; - rLen = 0; - rLoc = 717; - rType = 0; - vrLen = 1700; - vrLoc = 493; + 2CE603E10D715F8600DB0D88 /* UConfig.pas */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {881, 3080}}"; + sepNavSelRange = "{7279, 0}"; + sepNavVisRange = "{6847, 865}"; + }; }; 2CEA2AF00CE3868E0097A5FF /* PseudoThread.pas */ = { uiCtxt = { @@ -730,9 +892,9 @@ }; 2CF54F4A0CDA1B2B00627463 /* UScreenMain.pas */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {695, 3934}}"; - sepNavSelRange = "{5112, 0}"; - sepNavVisRange = "{4442, 1385}"; + sepNavIntBoundsRect = "{{0, 0}, {695, 4326}}"; + sepNavSelRange = "{1560, 17}"; + sepNavVisRange = "{1022, 1336}"; sepNavVisRect = "{{0, 0}, {715, 815}}"; sepNavWindowFrame = "{{38, 79}, {754, 944}}"; }; @@ -859,16 +1021,18 @@ }; 2CF54F5A0CDA1B2B00627463 /* UScreenPopup.pas */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {715, 3472}}"; - sepNavSelRange = "{56, 0}"; + sepNavIntBoundsRect = "{{0, 0}, {729, 3472}}"; + sepNavSelRange = "{1402, 0}"; + sepNavVisRange = "{987, 787}"; sepNavVisRect = "{{0, 0}, {715, 815}}"; sepNavWindowFrame = "{{38, 58}, {754, 944}}"; }; }; 2CF54F5B0CDA1B2B00627463 /* UScreenScore.pas */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1016, 9478}}"; - sepNavSelRange = "{49, 0}"; + sepNavIntBoundsRect = "{{0, 0}, {792, 14714}}"; + sepNavSelRange = "{4909, 0}"; + sepNavVisRange = "{4202, 810}"; sepNavVisRect = "{{0, 0}, {715, 815}}"; sepNavWindowFrame = "{{15, 79}, {754, 944}}"; }; @@ -893,9 +1057,9 @@ }; 2CF54F5E0CDA1B2B00627463 /* UScreenSong.pas */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {842, 31486}}"; - sepNavSelRange = "{54304, 0}"; - sepNavVisRange = "{53982, 735}"; + sepNavIntBoundsRect = "{{0, 0}, {881, 31066}}"; + sepNavSelRange = "{7241, 96}"; + sepNavVisRange = "{6687, 1426}"; sepNavVisRect = "{{0, 11219}, {1277, 312}}"; sepNavWindowFrame = "{{38, 78}, {754, 944}}"; }; @@ -910,32 +1074,36 @@ }; 2CF54F600CDA1B2B00627463 /* UScreenSongMenu.pas */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {968, 8834}}"; - sepNavSelRange = "{52, 0}"; + sepNavIntBoundsRect = "{{0, 0}, {729, 9352}}"; + sepNavSelRange = "{1910, 0}"; + sepNavVisRange = "{1505, 734}"; sepNavVisRect = "{{0, 0}, {715, 815}}"; sepNavWindowFrame = "{{38, 58}, {754, 944}}"; }; }; 2CF54F610CDA1B2B00627463 /* UScreenStatDetail.pas */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {715, 3514}}"; - sepNavSelRange = "{40, 0}"; + sepNavIntBoundsRect = "{{0, 0}, {729, 3724}}"; + sepNavSelRange = "{1078, 0}"; + sepNavVisRange = "{661, 767}"; sepNavVisRect = "{{0, 0}, {715, 815}}"; sepNavWindowFrame = "{{15, 79}, {754, 944}}"; }; }; 2CF54F620CDA1B2B00627463 /* UScreenStatMain.pas */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1277, 3976}}"; - sepNavSelRange = "{4341, 26}"; + sepNavIntBoundsRect = "{{0, 0}, {729, 4326}}"; + sepNavSelRange = "{1057, 0}"; + sepNavVisRange = "{698, 731}"; sepNavVisRect = "{{0, 2749}, {1277, 312}}"; sepNavWindowFrame = "{{38, 58}, {754, 944}}"; }; }; 2CF54F630CDA1B2B00627463 /* UScreenTop5.pas */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {715, 2324}}"; - sepNavSelRange = "{48, 0}"; + sepNavIntBoundsRect = "{{0, 0}, {729, 2492}}"; + sepNavSelRange = "{996, 0}"; + sepNavVisRange = "{458, 883}"; sepNavVisRect = "{{0, 0}, {715, 815}}"; sepNavWindowFrame = "{{15, 79}, {754, 944}}"; }; @@ -1052,8 +1220,6 @@ activeExecutable = 2CDD4B5D0CB9354800549FAC /* UltraStarDX */; activeTarget = DDC688C709F574E9004E4BFF /* UltraStarDX */; addToTargets = ( - DDC688C709F574E9004E4BFF /* UltraStarDX */, - DDC688D409F57523004E4BFF /* Put all program sources also in this target */, ); breakpoints = ( ); @@ -1184,14 +1350,28 @@ PBXFileDataSource_Warnings_ColumnID, ); }; - PBXPerProjectTemplateStateSaveDate = 225532839; - PBXWorkspaceStateSaveDate = 225532839; + PBXPerProjectTemplateStateSaveDate = 228166993; + PBXWorkspaceStateSaveDate = 228166993; }; perUserProjectItems = { - 2CE603E50D715F9B00DB0D88 /* PBXBookmark */ = 2CE603E50D715F9B00DB0D88 /* PBXBookmark */; - 2CE603EC0D71601400DB0D88 /* PBXTextBookmark */ = 2CE603EC0D71601400DB0D88 /* PBXTextBookmark */; - 2CE603FF0D7160F300DB0D88 /* PBXTextBookmark */ = 2CE603FF0D7160F300DB0D88 /* PBXTextBookmark */; - 2CE604000D7160F300DB0D88 /* PBXTextBookmark */ = 2CE604000D7160F300DB0D88 /* PBXTextBookmark */; + 2C019A190D998D4A00974970 /* PBXTextBookmark */ = 2C019A190D998D4A00974970 /* PBXTextBookmark */; + 2C019A1A0D998D4A00974970 /* PBXTextBookmark */ = 2C019A1A0D998D4A00974970 /* PBXTextBookmark */; + 2C019A1B0D998D4A00974970 /* PBXTextBookmark */ = 2C019A1B0D998D4A00974970 /* PBXTextBookmark */; + 2C019A1C0D998D4A00974970 /* PBXTextBookmark */ = 2C019A1C0D998D4A00974970 /* PBXTextBookmark */; + 2C019A1D0D998D4A00974970 /* PBXTextBookmark */ = 2C019A1D0D998D4A00974970 /* PBXTextBookmark */; + 2CA607DD0D998F0B00EBC4A7 /* PBXTextBookmark */ = 2CA607DD0D998F0B00EBC4A7 /* PBXTextBookmark */; + 2CA607DF0D998F0B00EBC4A7 /* PBXTextBookmark */ = 2CA607DF0D998F0B00EBC4A7 /* PBXTextBookmark */; + 2CA608780D99987200EBC4A7 /* PBXBookmark */ = 2CA608780D99987200EBC4A7 /* PBXBookmark */; + 2CA608790D99987900EBC4A7 /* PBXBookmark */ = 2CA608790D99987900EBC4A7 /* PBXBookmark */; + 2CA6088F0D99999100EBC4A7 /* PBXTextBookmark */ = 2CA6088F0D99999100EBC4A7 /* PBXTextBookmark */; + 2CA608900D99999100EBC4A7 /* PBXTextBookmark */ = 2CA608900D99999100EBC4A7 /* PBXTextBookmark */; + 2CA608910D99999100EBC4A7 /* PBXTextBookmark */ = 2CA608910D99999100EBC4A7 /* PBXTextBookmark */; + 2CA608920D99999100EBC4A7 /* PBXTextBookmark */ = 2CA608920D99999100EBC4A7 /* PBXTextBookmark */; + 2CA608930D99999100EBC4A7 /* PBXTextBookmark */ = 2CA608930D99999100EBC4A7 /* PBXTextBookmark */; + 2CA608940D99999100EBC4A7 /* PBXTextBookmark */ = 2CA608940D99999100EBC4A7 /* PBXTextBookmark */; + 2CA608950D99999100EBC4A7 /* PBXTextBookmark */ = 2CA608950D99999100EBC4A7 /* PBXTextBookmark */; + 2CA608960D99999100EBC4A7 /* PBXTextBookmark */ = 2CA608960D99999100EBC4A7 /* PBXTextBookmark */; + 2CA608970D99999100EBC4A7 /* PBXTextBookmark */ = 2CA608970D99999100EBC4A7 /* PBXTextBookmark */; }; sourceControlManager = 2CDD4B690CB9357000549FAC /* Source Control */; userBuildSettings = { diff --git a/Game/Code/MacOSX/UltraStarDX.xcodeproj/project.pbxproj b/Game/Code/MacOSX/UltraStarDX.xcodeproj/project.pbxproj index 8b1c3a8a..d7902145 100644 --- a/Game/Code/MacOSX/UltraStarDX.xcodeproj/project.pbxproj +++ b/Game/Code/MacOSX/UltraStarDX.xcodeproj/project.pbxproj @@ -374,6 +374,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 2C0199800D99840900974970 /* config-macosx.inc */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.pascal; name = "config-macosx.inc"; path = "../config-macosx.inc"; sourceTree = SOURCE_ROOT; }; 2C4B70220CF757A400B0F0BD /* Until5000.dpr */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = Until5000.dpr; path = ../../../Modis/5000Points/Until5000.dpr; sourceTree = SOURCE_ROOT; }; 2C4D9C620CC9EC8C0031092D /* TextGL.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = TextGL.pas; path = ../Classes/TextGL.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; }; 2C4D9C650CC9EC8C0031092D /* UCatCovers.pas */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.pascal; name = UCatCovers.pas; path = ../Classes/UCatCovers.pas; sourceTree = SOURCE_ROOT; tabWidth = 2; }; @@ -795,6 +796,7 @@ DDC6851B09F57195004E4BFF /* UltraStarDX.pas */, 2CF551A70CDA356800627463 /* UltraStar.dpr */, 2C4D9E440CC9F0ED0031092D /* switches.inc */, + 2C0199800D99840900974970 /* config-macosx.inc */, ); name = Source; sourceTree = "<group>"; @@ -1460,7 +1462,7 @@ Carbon, ); PREBINDING = NO; - PRODUCT_NAME = UltraStarDX; + PRODUCT_NAME = "UltraStar Deluxe"; WRAPPER_EXTENSION = app; ZERO_LINK = NO; }; diff --git a/Game/Code/MacOSX/Wrapper/OpenGL12.pas b/Game/Code/MacOSX/Wrapper/OpenGL12.pas index 0efff14e..6afa23ab 100755 --- a/Game/Code/MacOSX/Wrapper/OpenGL12.pas +++ b/Game/Code/MacOSX/Wrapper/OpenGL12.pas @@ -4684,6 +4684,7 @@ type // GLU functions function gluBuild2DMipmaps(target: TGLEnum; components, width, height: TGLint; format, atype: TGLEnum; Data: Pointer): TGLint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external glu32; function gluScaleImage(format: TGLEnum; widthin, heightin: TGLint; typein: TGLEnum; datain: Pointer; widthout, heightout: TGLint; typeout: TGLEnum; dataout: Pointer): TGLint; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external glu32; + function gluErrorString(errCode : GLenum) : PChar; {$IFDEF DLL_STDCALL} stdcall; {$ENDIF} {$IFDEF DLL_CDECL} cdecl; {$ENDIF} external glu32; Procedure LoadOpenGL; Procedure UnloadOpenGL; diff --git a/Game/Code/Menu/UMenu.pas b/Game/Code/Menu/UMenu.pas index dcdcf1ca..4fd9262a 100644 --- a/Game/Code/Menu/UMenu.pas +++ b/Game/Code/Menu/UMenu.pas @@ -46,6 +46,7 @@ type //constructor Create(Back: string; W, H: integer); overload; virtual; // W and H are the number of overlaps // interaction + function WideCharUpperCase(const wchar : WideChar) : WideString; procedure AddInteraction(Typ, Num: integer); procedure SetInteraction(Num: integer); property Interaction: integer read SelInteraction write SetInteraction; @@ -1543,6 +1544,16 @@ begin // beep; end; +function TMenu.WideCharUpperCase(const wchar : WideChar) : WideString; +begin + {$IFDEF DARWIN} + // eddie: WideUpperCase crashes on the mac with WideChars. + Result := UpperCase(wchar); + {$ELSE} + Result := WideUpperCase(wchar); + {$ENDIF} +end; + procedure TMenu.onHide; begin // nothing diff --git a/Game/Code/Screens/UScreenEdit.pas b/Game/Code/Screens/UScreenEdit.pas index 4d105e5f..492191ee 100644 --- a/Game/Code/Screens/UScreenEdit.pas +++ b/Game/Code/Screens/UScreenEdit.pas @@ -30,8 +30,8 @@ begin If (PressedDown) Then
begin // Key Down
// check normal keys
- case WideUpperCase(CharCode)[1] of
- 'Q': + case WideCharUpperCase(CharCode)[1] of
+ 'Q':
begin
Result := false;
Exit;
diff --git a/Game/Code/Screens/UScreenEditConvert.pas b/Game/Code/Screens/UScreenEditConvert.pas index d50d546d..a45e8458 100644 --- a/Game/Code/Screens/UScreenEditConvert.pas +++ b/Game/Code/Screens/UScreenEditConvert.pas @@ -109,13 +109,13 @@ begin If (PressedDown) Then begin // Key Down // check normal keys - case WideUpperCase(CharCode)[1] of
+ case WideCharUpperCase(CharCode)[1] of 'Q': - begin
- Result := false;
- Exit;
- end;
- end;
+ begin + Result := false; + Exit; + end; + end; // check special keys case PressedKey of diff --git a/Game/Code/Screens/UScreenEditHeader.pas b/Game/Code/Screens/UScreenEditHeader.pas index 3b29564a..f0e0a7b7 100644 --- a/Game/Code/Screens/UScreenEditHeader.pas +++ b/Game/Code/Screens/UScreenEditHeader.pas @@ -59,8 +59,8 @@ begin Result := true;
If (PressedDown) Then begin // Key Down
// check normal keys
- case WideUpperCase(CharCode)[1] of
- 'Q': + case WideCharUpperCase(CharCode)[1] of
+ 'Q':
begin
Result := false;
Exit;
diff --git a/Game/Code/Screens/UScreenEditSub.pas b/Game/Code/Screens/UScreenEditSub.pas index c75661fc..1fb7bff8 100644 --- a/Game/Code/Screens/UScreenEditSub.pas +++ b/Game/Code/Screens/UScreenEditSub.pas @@ -119,13 +119,13 @@ begin If (PressedDown) then begin // Key Down // check normal keys - case WideUpperCase(CharCode)[1] of
+ case WideCharUpperCase(CharCode)[1] of 'Q': - begin
- Result := false;
- Exit;
- end;
- 'S':
+ begin + Result := false; + Exit; + end; + 'S': begin // Save Song if SDL_ModState = KMOD_LSHIFT then @@ -181,7 +181,7 @@ begin CopySentence(CopySrc, Lines[0].Current); end; end; - 'T':
+ 'T': begin // Fixes timings between sentences FixTimings; @@ -232,7 +232,7 @@ begin end; Exit; end; - // Golden Note Patch
+ // Golden Note Patch 'G': begin case Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType of @@ -260,9 +260,9 @@ begin end; // case Exit; end; - end;
-
- // check special keys
+ end; + + // check special keys case PressedKey of SDLK_ESCAPE, SDLK_BACKSPACE : diff --git a/Game/Code/Screens/UScreenLevel.pas b/Game/Code/Screens/UScreenLevel.pas index 144ec697..1ea79e7f 100644 --- a/Game/Code/Screens/UScreenLevel.pas +++ b/Game/Code/Screens/UScreenLevel.pas @@ -30,15 +30,15 @@ begin If (PressedDown) Then begin // Key Down // check normal keys - case WideUpperCase(CharCode)[1] of
+ case WideCharUpperCase(CharCode)[1] of 'Q': - begin
- Result := false;
- Exit;
- end;
- end;
-
- // check special keys
+ begin + Result := false; + Exit; + end; + end; + + // check special keys case PressedKey of SDLK_ESCAPE, SDLK_BACKSPACE : diff --git a/Game/Code/Screens/UScreenMain.pas b/Game/Code/Screens/UScreenMain.pas index 2d13ac09..108f811c 100644 --- a/Game/Code/Screens/UScreenMain.pas +++ b/Game/Code/Screens/UScreenMain.pas @@ -56,8 +56,7 @@ uses function TScreenMain.ParseInput(PressedKey: Cardinal; CharCode: WideChar; PressedDown: Boolean): Boolean; var -I: Integer; -SDL_ModState: Word; + SDL_ModState: Word; begin Result := true; @@ -74,7 +73,7 @@ begin If (PressedDown) Then begin // Key Down // check normal keys - case WideUpperCase(CharCode)[1] of + case WideCharUpperCase(CharCode)[1] of 'Q': begin Result := false; diff --git a/Game/Code/Screens/UScreenOptions.pas b/Game/Code/Screens/UScreenOptions.pas index cfb0c977..3f936602 100644 --- a/Game/Code/Screens/UScreenOptions.pas +++ b/Game/Code/Screens/UScreenOptions.pas @@ -29,15 +29,15 @@ begin If (PressedDown) Then begin // Key Down // check normal keys - case WideUpperCase(CharCode)[1] of
+ case WideCharUpperCase(CharCode)[1] of 'Q': - begin
- Result := false;
- Exit;
- end;
- end;
-
- // check special keys
+ begin + Result := false; + Exit; + end; + end; + + // check special keys case PressedKey of SDLK_ESCAPE, SDLK_BACKSPACE : diff --git a/Game/Code/Screens/UScreenOptionsAdvanced.pas b/Game/Code/Screens/UScreenOptionsAdvanced.pas index c23f133c..adf4125d 100644 --- a/Game/Code/Screens/UScreenOptionsAdvanced.pas +++ b/Game/Code/Screens/UScreenOptionsAdvanced.pas @@ -25,15 +25,15 @@ begin If (PressedDown) Then begin // Key Down // check normal keys - case WideUpperCase(CharCode)[1] of
+ case WideCharUpperCase(CharCode)[1] of 'Q': - begin
- Result := false;
- Exit;
- end;
- end;
-
- // check special keys
+ begin + Result := false; + Exit; + end; + end; + + // check special keys case PressedKey of SDLK_ESCAPE, SDLK_BACKSPACE : diff --git a/Game/Code/Screens/UScreenOptionsGame.pas b/Game/Code/Screens/UScreenOptionsGame.pas index 40200c60..428b2ff7 100644 --- a/Game/Code/Screens/UScreenOptionsGame.pas +++ b/Game/Code/Screens/UScreenOptionsGame.pas @@ -27,15 +27,15 @@ begin If (PressedDown) Then begin // Key Down // check normal keys - case WideUpperCase(CharCode)[1] of
+ case WideCharUpperCase(CharCode)[1] of 'Q': - begin
- Result := false;
- Exit;
- end;
- end;
-
- // check special keys
+ begin + Result := false; + Exit; + end; + end; + + // check special keys case PressedKey of SDLK_ESCAPE, SDLK_BACKSPACE : diff --git a/Game/Code/Screens/UScreenOptionsGraphics.pas b/Game/Code/Screens/UScreenOptionsGraphics.pas index 04656e97..0a736a9d 100644 --- a/Game/Code/Screens/UScreenOptionsGraphics.pas +++ b/Game/Code/Screens/UScreenOptionsGraphics.pas @@ -25,8 +25,8 @@ begin If (PressedDown) Then
begin // Key Down
// check normal keys
- case WideUpperCase(CharCode)[1] of
- 'Q': + case WideCharUpperCase(CharCode)[1] of
+ 'Q':
begin
Result := false;
Exit;
diff --git a/Game/Code/Screens/UScreenOptionsLyrics.pas b/Game/Code/Screens/UScreenOptionsLyrics.pas index 50b7d53d..a314f2f3 100644 --- a/Game/Code/Screens/UScreenOptionsLyrics.pas +++ b/Game/Code/Screens/UScreenOptionsLyrics.pas @@ -25,8 +25,8 @@ begin If (PressedDown) Then
begin // Key Down
// check normal keys
- case WideUpperCase(CharCode)[1] of
- 'Q': + case WideCharUpperCase(CharCode)[1] of
+ 'Q':
begin
Result := false;
Exit;
diff --git a/Game/Code/Screens/UScreenOptionsRecord.pas b/Game/Code/Screens/UScreenOptionsRecord.pas index 0ba554c4..6ee200fa 100644 --- a/Game/Code/Screens/UScreenOptionsRecord.pas +++ b/Game/Code/Screens/UScreenOptionsRecord.pas @@ -78,8 +78,8 @@ begin If (PressedDown) Then
begin // Key Down
// check normal keys
- case WideUpperCase(CharCode)[1] of
- 'Q': + case WideCharUpperCase(CharCode)[1] of
+ 'Q':
begin
Result := false;
Exit;
diff --git a/Game/Code/Screens/UScreenOptionsSound.pas b/Game/Code/Screens/UScreenOptionsSound.pas index 70d92fa5..3cbc65a5 100644 --- a/Game/Code/Screens/UScreenOptionsSound.pas +++ b/Game/Code/Screens/UScreenOptionsSound.pas @@ -25,15 +25,15 @@ begin If (PressedDown) Then begin // Key Down // check normal keys - case WideUpperCase(CharCode)[1] of
+ case WideCharUpperCase(CharCode)[1] of 'Q': - begin
- Result := false;
- Exit;
- end;
- end;
-
- // check special keys
+ begin + Result := false; + Exit; + end; + end; + + // check special keys case PressedKey of SDLK_ESCAPE, SDLK_BACKSPACE : diff --git a/Game/Code/Screens/UScreenOptionsThemes.pas b/Game/Code/Screens/UScreenOptionsThemes.pas index c50256a2..743f5fda 100644 --- a/Game/Code/Screens/UScreenOptionsThemes.pas +++ b/Game/Code/Screens/UScreenOptionsThemes.pas @@ -39,15 +39,15 @@ begin If (PressedDown) Then begin // Key Down // check normal keys - case WideUpperCase(CharCode)[1] of
+ case WideCharUpperCase(CharCode)[1] of 'Q': - begin
- Result := false;
- Exit;
- end;
- end;
-
- // check special keys
+ begin + Result := false; + Exit; + end; + end; + + // check special keys case PressedKey of SDLK_ESCAPE, SDLK_BACKSPACE : diff --git a/Game/Code/Screens/UScreenPartyNewRound.pas b/Game/Code/Screens/UScreenPartyNewRound.pas index e7e2c682..057344dc 100644 --- a/Game/Code/Screens/UScreenPartyNewRound.pas +++ b/Game/Code/Screens/UScreenPartyNewRound.pas @@ -92,13 +92,13 @@ begin If (PressedDown) Then begin // Key Down // check normal keys - case WideUpperCase(CharCode)[1] of
+ case WideCharUpperCase(CharCode)[1] of 'Q': - begin
- Result := false;
- Exit;
- end;
- end;
+ begin + Result := false; + Exit; + end; + end; // check special keys case PressedKey of diff --git a/Game/Code/Screens/UScreenPartyOptions.pas b/Game/Code/Screens/UScreenPartyOptions.pas index c0dde4cc..bd05e653 100644 --- a/Game/Code/Screens/UScreenPartyOptions.pas +++ b/Game/Code/Screens/UScreenPartyOptions.pas @@ -57,13 +57,13 @@ begin If (PressedDown) Then begin // Key Down // check normal keys - case WideUpperCase(CharCode)[1] of
+ case WideCharUpperCase(CharCode)[1] of 'Q': - begin
- Result := false;
- Exit;
- end;
- end;
+ begin + Result := false; + Exit; + end; + end; // check special keys case PressedKey of @@ -80,13 +80,13 @@ begin If (Playlist = 2) and (Length(PlaylistMan.Playlists) = 0) then Exit; // Don't start when SinglePlayer Teams but only Multiplayer Plugins available - OnlyMultiPlayer:=true;
- for I := 0 to High(DLLMan.Plugins) do begin
- OnlyMultiPlayer := (OnlyMultiPlayer AND DLLMan.Plugins[I].TeamModeOnly);
- end;
- if (OnlyMultiPlayer) AND ((NumPlayer1 = 0) OR (NumPlayer2 = 0) OR ((NumPlayer3 = 0) AND (NumTeams = 1))) then begin
- ScreenPopupError.ShowPopup(Language.Translate('ERROR_NO_PLUGINS'));
- Exit;
+ OnlyMultiPlayer:=true; + for I := 0 to High(DLLMan.Plugins) do begin + OnlyMultiPlayer := (OnlyMultiPlayer AND DLLMan.Plugins[I].TeamModeOnly); + end; + if (OnlyMultiPlayer) AND ((NumPlayer1 = 0) OR (NumPlayer2 = 0) OR ((NumPlayer3 = 0) AND (NumTeams = 1))) then begin + ScreenPopupError.ShowPopup(Language.Translate('ERROR_NO_PLUGINS')); + Exit; end; //Save Difficulty Ini.Difficulty := SelectsS[SelectLevel].SelectedOption; diff --git a/Game/Code/Screens/UScreenPartyScore.pas b/Game/Code/Screens/UScreenPartyScore.pas index 26e53fcf..c1a84ee6 100644 --- a/Game/Code/Screens/UScreenPartyScore.pas +++ b/Game/Code/Screens/UScreenPartyScore.pas @@ -50,15 +50,15 @@ begin If (PressedDown) Then
begin // Key Down
// check normal keys
- case WideUpperCase(CharCode)[1] of
- 'Q': + case WideCharUpperCase(CharCode)[1] of
+ 'Q':
begin
Result := false;
Exit;
end;
end;
- - // check special keys +
+ // check special keys
case PressedKey of
SDLK_ESCAPE,
SDLK_BACKSPACE :
diff --git a/Game/Code/Screens/UScreenPartyWin.pas b/Game/Code/Screens/UScreenPartyWin.pas index 02079b34..002c6f75 100644 --- a/Game/Code/Screens/UScreenPartyWin.pas +++ b/Game/Code/Screens/UScreenPartyWin.pas @@ -43,13 +43,13 @@ begin If (PressedDown) Then begin // Key Down // check normal keys - case WideUpperCase(CharCode)[1] of
+ case WideCharUpperCase(CharCode)[1] of 'Q': - begin
- Result := false;
- Exit;
- end;
- end;
+ begin + Result := false; + Exit; + end; + end; // check special keys case PressedKey of diff --git a/Game/Code/Screens/UScreenPopup.pas b/Game/Code/Screens/UScreenPopup.pas index c4541050..328e9851 100644 --- a/Game/Code/Screens/UScreenPopup.pas +++ b/Game/Code/Screens/UScreenPopup.pas @@ -49,15 +49,15 @@ begin If (PressedDown) Then
begin // Key Down
// check normal keys
- case WideUpperCase(CharCode)[1] of
- 'Q': + case WideCharUpperCase(CharCode)[1] of
+ 'Q':
begin
Result := false;
Exit;
end;
end;
- - // check special keys +
+ // check special keys
case PressedKey of
SDLK_ESCAPE,
SDLK_BACKSPACE :
diff --git a/Game/Code/Screens/UScreenScore.pas b/Game/Code/Screens/UScreenScore.pas index 358c18d8..23ff86a5 100644 --- a/Game/Code/Screens/UScreenScore.pas +++ b/Game/Code/Screens/UScreenScore.pas @@ -150,15 +150,15 @@ begin Result := true;
If (PressedDown) Then begin
// check normal keys
- case WideUpperCase(CharCode)[1] of
- 'Q': + case WideCharUpperCase(CharCode)[1] of
+ 'Q':
begin
Result := false;
Exit;
end;
end;
- - // check special keys +
+ // check special keys
case PressedKey of
SDLK_ESCAPE,
SDLK_BACKSPACE :
diff --git a/Game/Code/Screens/UScreenSing.pas b/Game/Code/Screens/UScreenSing.pas index 6d05c145..bc6c0966 100644 --- a/Game/Code/Screens/UScreenSing.pas +++ b/Game/Code/Screens/UScreenSing.pas @@ -135,9 +135,9 @@ begin If (PressedDown) Then begin // Key Down // check normal keys - case WideUpperCase(CharCode)[1] of
+ case WideCharUpperCase(CharCode)[1] of 'Q': - begin
+ begin //When not ask before Exit then Finish now if (Ini.AskbeforeDel <> 1) then Finish @@ -148,7 +148,7 @@ begin Result := false; Exit; end; - 'V': //Show Visualization
+ 'V': //Show Visualization begin fShowVisualization := not fShowVisualization; @@ -162,12 +162,12 @@ begin Exit; end; - 'P':
+ 'P': begin Pause; Exit; end; - end;
+ end; // check special keys case PressedKey of diff --git a/Game/Code/Screens/UScreenSong.pas b/Game/Code/Screens/UScreenSong.pas index a1cd8748..a3467bfe 100644 --- a/Game/Code/Screens/UScreenSong.pas +++ b/Game/Code/Screens/UScreenSong.pas @@ -256,9 +256,9 @@ begin //Jump to Artist/Titel
if ((SDL_ModState and KMOD_LALT <> 0) AND (Mode = smNormal)) then
begin
- if (WideUpperCase(CharCode)[1] in ['A'..'Z']) then
+ if (WideCharUpperCase(CharCode)[1] in ['A'..'Z']) then
begin
- Letter := WideUpperCase(CharCode)[1];
+ Letter := WideCharUpperCase(CharCode)[1];
I2 := Length(CatSongs.Song);
//Jump To Titel
@@ -310,8 +310,8 @@ begin end;
// check normal keys
- case WideUpperCase(CharCode)[1] of
- 'Q': + case WideCharUpperCase(CharCode)[1] of
+ 'Q':
begin
Result := false;
Exit;
diff --git a/Game/Code/Screens/UScreenSongMenu.pas b/Game/Code/Screens/UScreenSongMenu.pas index 9cbb1be9..edd3fabb 100644 --- a/Game/Code/Screens/UScreenSongMenu.pas +++ b/Game/Code/Screens/UScreenSongMenu.pas @@ -69,10 +69,10 @@ begin Result := true; if (PressedDown) then begin // Key Down - if (CurMenu = SM_Playlist_New) AND (Interaction=0) then
+ if (CurMenu = SM_Playlist_New) AND (Interaction=0) then begin // check normal keys - case WideUpperCase(CharCode)[1] of + case WideCharUpperCase(CharCode)[1] of '0'..'9', 'A'..'Z', ' ', '-', '_', '!', ',', '<', '/', '*', '?', '''', '"': begin Button[Interaction].Text[0].Text := Button[Interaction].Text[0].Text + CharCode; @@ -91,13 +91,13 @@ begin end; // check normal keys - case WideUpperCase(CharCode)[1] of + case WideCharUpperCase(CharCode)[1] of 'Q': - begin
- Result := false;
- Exit;
- end;
- end;
+ begin + Result := false; + Exit; + end; + end; // check special keys case PressedKey of diff --git a/Game/Code/Screens/UScreenStatDetail.pas b/Game/Code/Screens/UScreenStatDetail.pas index 14f4808e..c5c8245f 100644 --- a/Game/Code/Screens/UScreenStatDetail.pas +++ b/Game/Code/Screens/UScreenStatDetail.pas @@ -45,8 +45,8 @@ begin If (PressedDown) Then
begin // Key Down
// check normal keys
- case WideUpperCase(CharCode)[1] of
- 'Q': + case WideCharUpperCase(CharCode)[1] of
+ 'Q':
begin
Result := false;
Exit;
diff --git a/Game/Code/Screens/UScreenStatMain.pas b/Game/Code/Screens/UScreenStatMain.pas index 87bd1b5f..fc0a46b8 100644 --- a/Game/Code/Screens/UScreenStatMain.pas +++ b/Game/Code/Screens/UScreenStatMain.pas @@ -53,15 +53,15 @@ begin If (PressedDown) Then begin // Key Down // check normal keys - case WideUpperCase(CharCode)[1] of
+ case WideCharUpperCase(CharCode)[1] of 'Q': - begin
- Result := false;
- Exit;
- end;
- end;
-
- // check special keys
+ begin + Result := false; + Exit; + end; + end; + + // check special keys case PressedKey of SDLK_ESCAPE, SDLK_BACKSPACE : diff --git a/Game/Code/Screens/UScreenTop5.pas b/Game/Code/Screens/UScreenTop5.pas index 8ebb056c..6893391c 100644 --- a/Game/Code/Screens/UScreenTop5.pas +++ b/Game/Code/Screens/UScreenTop5.pas @@ -38,15 +38,15 @@ begin Result := true; If (PressedDown) Then begin // check normal keys - case WideUpperCase(CharCode)[1] of
+ case WideCharUpperCase(CharCode)[1] of 'Q': - begin
- Result := false;
- Exit;
- end;
- end;
-
- // check special keys
+ begin + Result := false; + Exit; + end; + end; + + // check special keys case PressedKey of SDLK_ESCAPE, SDLK_BACKSPACE, diff --git a/Game/Code/switches.inc b/Game/Code/switches.inc index 9b31f3af..1a8f26cc 100644 --- a/Game/Code/switches.inc +++ b/Game/Code/switches.inc @@ -1,132 +1,136 @@ -// Comment by eddie:
-// The mac port currently also uses the WIN32 define.
-// Once I get the beast compiled, linked and running
-// I will change this.
-// There are some parts where the WIN32 define could not
-// be used. I changed the WIN32 to MSWINDOWS.
-// So, for Windows-only code use the MSWINDOWS define.
-
-{$IFDEF FPC}
- {$IFDEF DARWIN}
- {$H+}
- {$R-}
- {$DEFINE WIN32}
- {$DEFINE TRANSLATE}
- {$DEFINE UTF8_FILENAMES}
- {$ELSE}
- {$DEFINE LAZARUS}
- {$IFNDEF LCL}
- // LCL should be defined already
- {$MESSAGE Warn 'LCL undefined, compile with "fpc -dLCL ..."!'}
- {$DEFINE LCL}
- {$ENDIF}
- {$ENDIF}
-
- {$DEFINE DLL_CDECL}
- {$DEFINE HasInline}
- {$UNDEF UseSerialPort}
-{$ELSE}
- {$DEFINE Delphi}
-
- // Delphi version numbers (ignore versions released before Delphi 6 as they miss the $IF directive):
- // Delphi 6 (VER140), Delphi 7 (VER150), Delphi 8 (VER160)
- // Delphi 9/2005 (VER170), Delphi 10/2006 (VER180)
-
- // the inline-procedure directive was introduced with Delphi 2005
- {$IF not (Defined(VER140) or Defined(VER150) or Defined(VER160))}
- {$DEFINE HasInline}
- {$IFEND}
-
- {$DEFINE DLL_STDCALL}
- {$UNDEF UseSerialPort}
-{$ENDIF}
-
-
-{$IF Defined(win32)}
- // include defines but no constants
- {$I config-win.inc}
-
- // audio config
- {$DEFINE WinAudioLib_BASS}
- {$IFDEF WinAudioLib_BASS}
- {$DEFINE UseBASSPlayback}
- {$DEFINE UseBASSInput}
- {$ELSE}
- {$DEFINE UseFFMpegDecoder}
- //{$DEFINE UsePortaudioPlayback}
- {$DEFINE UseSDLPlayback}
- {$DEFINE UsePortaudioInput}
- {$DEFINE UsePortmixer}
- {$ENDIF}
- {$UNDEF WinAudioLib_BASS}
-
- // video config
- {$IFDEF HaveFFMpeg}
- {$DEFINE UseFFMpegVideo}
- {$IFDEF HaveSWScale}
- {$DEFINE UseSWScale}
- {$ENDIF}
- {$ENDIF}
-
- // misc defines
-
- {$IF Defined(HaveProjectM_0_9)}
- {$DEFINE UseProjectM_0_9}
- {$ELSEIF Defined(HaveProjectM_1_0_PLUS)}
- {$DEFINE UseProjectM_1_0_PLUS}
- {$IFEND}
-
- {$IFDEF DEBUG}
- {$IFNDEF DARWIN}
- {$APPTYPE CONSOLE}
- {$ENDIF}
- {$ENDIF}
-
- {$IFDEF MSWINDOWS}
- {$DEFINE UseMIDIPort}
- {$ENDIF}
-{$ELSEIF Defined(Linux)}
- // include defines but no constants
- {$I config-linux.inc}
-
- // audio config
- {$IFDEF HaveFFMpeg}
- {$DEFINE UseFFMpegDecoder}
- {$IFDEF HavePortaudio}
- //{$DEFINE UsePortaudioPlayback}
- {$DEFINE UseSDLPlayback}
- {$DEFINE UsePortaudioInput}
- {$ENDIF}
- {$ENDIF}
-
- // video config
- {$IFDEF HaveFFMpeg}
- {$DEFINE UseFFMpegVideo}
- {$IFDEF HaveSWScale}
- {$DEFINE UseSWScale}
- {$ENDIF}
- {$ENDIF}
-
- // misc defines
- {$IFDEF HaveProjectM}
- // this causes trouble at the moment
- //{$DEFINE UseProjectM_0_9}
- {$ENDIF}
-{$IFEND}
-
-{$IF Defined(UseFFMpegVideo) or Defined(UseFFMpegDecoder)}
- {$DEFINE UseFFMpeg}
-{$IFEND}
-
-{$IF Defined(UseBASSInput) or Defined(UseBASSPlayback)}
- {$DEFINE UseBASS}
-{$IFEND}
-
-{$IF Defined(UsePortaudioInput) or Defined(UsePortaudioPlayback)}
- {$DEFINE UsePortaudio}
-{$IFEND}
-
-{$IF Defined(UseProjectM_0_9) or Defined(UseProjectM_1_0_PLUS)}
- {$DEFINE UseProjectM}
-{$IFEND}
-
+// Comment by eddie: +// The mac port currently also uses the WIN32 define. +// Once I get the beast compiled, linked and running +// I will change this. +// There are some parts where the WIN32 define could not +// be used. I changed the WIN32 to MSWINDOWS. +// So, for Windows-only code use the MSWINDOWS define. + +{$IFDEF FPC} + {$IFDEF DARWIN} + {$H+} + {$R-} + {$DEFINE WIN32} + {$DEFINE TRANSLATE} + {$DEFINE UTF8_FILENAMES} + {$ELSE} + {$DEFINE LAZARUS} + {$IFNDEF LCL} + // LCL should be defined already + {$MESSAGE Warn 'LCL undefined, compile with "fpc -dLCL ..."!'} + {$DEFINE LCL} + {$ENDIF} + {$ENDIF} + + {$DEFINE DLL_CDECL} + {$DEFINE HasInline} + {$UNDEF UseSerialPort} +{$ELSE} + {$DEFINE Delphi} + + // Delphi version numbers (ignore versions released before Delphi 6 as they miss the $IF directive): + // Delphi 6 (VER140), Delphi 7 (VER150), Delphi 8 (VER160) + // Delphi 9/2005 (VER170), Delphi 10/2006 (VER180) + + // the inline-procedure directive was introduced with Delphi 2005 + {$IF not (Defined(VER140) or Defined(VER150) or Defined(VER160))} + {$DEFINE HasInline} + {$IFEND} + + {$DEFINE DLL_STDCALL} + {$UNDEF UseSerialPort} +{$ENDIF} + + +{$IF Defined(win32)} + // include defines but no constants + {$IFDEF DARWIN} + {$I config-macosx.inc} + {$ELSE} + {$I config-win.inc} + {$ENDIF} + + // audio config + {$DEFINE WinAudioLib_BASS} + {$IFDEF WinAudioLib_BASS} + {$DEFINE UseBASSPlayback} + {$DEFINE UseBASSInput} + {$ELSE} + {$DEFINE UseFFMpegDecoder} + //{$DEFINE UsePortaudioPlayback} + {$DEFINE UseSDLPlayback} + {$DEFINE UsePortaudioInput} + {$DEFINE UsePortmixer} + {$ENDIF} + {$UNDEF WinAudioLib_BASS} + + // video config + {$IFDEF HaveFFMpeg} + {$DEFINE UseFFMpegVideo} + {$IFDEF HaveSWScale} + {$DEFINE UseSWScale} + {$ENDIF} + {$ENDIF} + + // misc defines + + {$IF Defined(HaveProjectM_0_9)} + {$DEFINE UseProjectM_0_9} + {$ELSEIF Defined(HaveProjectM_1_0_PLUS)} + {$DEFINE UseProjectM_1_0_PLUS} + {$IFEND} + + {$IFDEF DEBUG} + {$IFNDEF DARWIN} + {$APPTYPE CONSOLE} + {$ENDIF} + {$ENDIF} + + {$IFDEF MSWINDOWS} + {$DEFINE UseMIDIPort} + {$ENDIF} +{$ELSEIF Defined(Linux)} + // include defines but no constants + {$I config-linux.inc} + + // audio config + {$IFDEF HaveFFMpeg} + {$DEFINE UseFFMpegDecoder} + {$IFDEF HavePortaudio} + //{$DEFINE UsePortaudioPlayback} + {$DEFINE UseSDLPlayback} + {$DEFINE UsePortaudioInput} + {$ENDIF} + {$ENDIF} + + // video config + {$IFDEF HaveFFMpeg} + {$DEFINE UseFFMpegVideo} + {$IFDEF HaveSWScale} + {$DEFINE UseSWScale} + {$ENDIF} + {$ENDIF} + + // misc defines + {$IFDEF HaveProjectM} + // this causes trouble at the moment + //{$DEFINE UseProjectM_0_9} + {$ENDIF} +{$IFEND} + +{$IF Defined(UseFFMpegVideo) or Defined(UseFFMpegDecoder)} + {$DEFINE UseFFMpeg} +{$IFEND} + +{$IF Defined(UseBASSInput) or Defined(UseBASSPlayback)} + {$DEFINE UseBASS} +{$IFEND} + +{$IF Defined(UsePortaudioInput) or Defined(UsePortaudioPlayback)} + {$DEFINE UsePortaudio} +{$IFEND} + +{$IF Defined(UseProjectM_0_9) or Defined(UseProjectM_1_0_PLUS)} + {$DEFINE UseProjectM} +{$IFEND} + |