--- a/hedgewars/uUtils.pas Sun Oct 28 15:18:26 2012 +0100
+++ b/hedgewars/uUtils.pas Fri Dec 06 22:20:53 2019 +0100
@@ -1,6 +1,6 @@
(*
* Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2015 Andrey Korotaev <unC0Rr@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -13,7 +13,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*)
{$INCLUDE "options.inc"}
@@ -21,29 +21,42 @@
unit uUtils;
interface
-uses uTypes, uFloat, GLunit;
+uses uTypes, uFloat;
+
+// returns s with whitespaces (chars <= #32) removed form both ends
+function Trim(s: shortstring) : shortstring;
procedure SplitBySpace(var a, b: shortstring);
procedure SplitByChar(var a, b: shortstring; c: char);
-procedure SplitByChar(var a, b: ansistring; c: char);
+procedure SplitByCharA(var a, b: ansistring; c: char);
-{$IFNDEF PAS2C}
+procedure EscapeCharA(var a: ansistring; e: char);
+procedure UnEscapeCharA(var a: ansistring; e: char);
+
+function ExtractFileDir(s: shortstring) : shortstring;
+function ExtractFileName(s: shortstring) : shortstring;
+
function EnumToStr(const en : TGearType) : shortstring; overload;
function EnumToStr(const en : TVisualGearType) : shortstring; overload;
function EnumToStr(const en : TSound) : shortstring; overload;
function EnumToStr(const en : TAmmoType) : shortstring; overload;
+function EnumToStr(const en : TStatInfoType) : shortstring; overload;
function EnumToStr(const en : THogEffect) : shortstring; overload;
function EnumToStr(const en : TCapGroup) : shortstring; overload;
-{$ENDIF}
+function EnumToStr(const en : TSprite) : shortstring; overload;
+function EnumToStr(const en : TMapGen) : shortstring; overload;
+function EnumToStr(const en : TWorldEdge) : shortstring; overload;
function Min(a, b: LongInt): LongInt; inline;
+function MinD(a, b: double) : double; inline;
function Max(a, b: LongInt): LongInt; inline;
function IntToStr(n: LongInt): shortstring;
function StrToInt(s: shortstring): LongInt;
+//function StrToInt(s: shortstring; var success: boolean): LongInt;
function FloatToStr(n: hwFloat): shortstring;
-function DxDy2Angle(const _dY, _dX: hwFloat): GLfloat; inline;
+function DxDy2Angle(const _dY, _dX: hwFloat): real; inline;
function DxDy2Angle32(const _dY, _dX: hwFloat): LongInt;
function DxDy2AttackAngle(const _dY, _dX: hwFloat): LongInt;
function DxDy2AttackAnglef(const _dY, _dX: extended): LongInt;
@@ -68,64 +81,221 @@
function GetLaunchX(at: TAmmoType; dir: LongInt; angle: LongInt): LongInt;
function GetLaunchY(at: TAmmoType; angle: LongInt): LongInt;
+function CalcWorldWrap(X, radius: LongInt): LongInt;
+
+procedure updateVolumeDelta(precise: boolean);
+procedure updateCursorMovementDelta(precise: boolean; dir: LongInt; var cursorVar: LongInt);
+
+function read1stLn(filePath: shortstring): shortstring;
+function readValueFromINI(key, filePath: shortstring): shortstring;
+
{$IFNDEF PAS2C}
procedure Write(var f: textfile; s: shortstring);
procedure WriteLn(var f: textfile; s: shortstring);
+function StrLength(s: PChar): Longword;
+procedure SetLengthA(var s: ansistring; len: Longword);
{$ENDIF}
-procedure initModule(isGame: boolean);
+function isPhone: Boolean; inline;
+
+{$IFDEF IPHONEOS}
+procedure startLoadingIndicator; cdecl; external;
+procedure stopLoadingIndicator; cdecl; external;
+procedure saveFinishedSynching; cdecl; external;
+function isApplePhone: Boolean; cdecl; external;
+procedure AudioServicesPlaySystemSound(num: LongInt); cdecl; external;
+{$ENDIF}
+
+function sanitizeForLog(s: shortstring): shortstring;
+function sanitizeCharForLog(c: char): shortstring;
+
+procedure initModule(isNotPreview: boolean);
procedure freeModule;
implementation
-uses {$IFNDEF PAS2C}typinfo, {$ENDIF}Math, uConsts, uVariables, SysUtils;
+uses {$IFNDEF PAS2C}typinfo, SDLh, {$ENDIF}Math, uConsts, uVariables, uPhysFSLayer, uDebug;
{$IFDEF DEBUGFILE}
-var f: textfile;
+var logFile: PFSFile;
{$IFDEF USE_VIDEO_RECORDING}
- logMutex: TRTLCriticalSection; // mutex for debug file
+ logMutex: PSDL_mutex; // mutex for debug file
{$ENDIF}
{$ENDIF}
-var CharArray: array[byte] of Char;
+var CharArray: array[0..255] of Char;
+
+// All leading/tailing characters with ordinal values less than or equal to 32 (a space) are stripped.
+function Trim(s: shortstring) : shortstring;
+var len, left, right: integer;
+begin
+
+len:= Length(s);
+
+if len = 0 then
+ exit(s);
+
+// find first non-whitespace
+left:= 1;
+while left <= len do
+ begin
+ if s[left] > #32 then
+ break;
+ inc(left);
+ end;
+
+// find last non-whitespace
+right:= len;
+while right >= 1 do
+ begin
+ if s[right] > #32 then
+ break;
+ dec(right);
+ end;
+
+// string is whitespace only
+if left > right then
+ exit('');
+
+// get string without surrounding whitespace
+len:= right - left + 1;
+
+Trim:= copy(s, left, len);
+
+end;
+
+function GetLastSlashPos(var s: shortString) : integer;
+var lslash: integer;
+ c: char;
+begin
+
+// find last slash
+lslash:= Length(s);
+while lslash >= 1 do
+ begin
+ c:= s[lslash];
+ if (c = #47) or (c = #92) then
+ break;
+ dec(lslash); end;
+
+GetLastSlashPos:= lslash;
+end;
+
+function ExtractFileDir(s: shortstring) : shortstring;
+var lslash: byte;
+begin
+
+if Length(s) = 0 then
+ exit(s);
+
+lslash:= GetLastSlashPos(s);
+
+if lslash <= 1 then
+ exit('');
+
+s[0]:= char(lslash - 1);
+
+ExtractFileDir:= s;
+end;
+
+function ExtractFileName(s: shortstring) : shortstring;
+var lslash, len: byte;
+begin
+
+len:= Length(s);
+
+if len = 0 then
+ exit(s);
+
+lslash:= GetLastSlashPos(s);
+
+if lslash < 1 then
+ exit(s);
+
+if lslash = len then
+ exit('');
+
+len:= len - lslash;
+ExtractFilename:= copy(s, lslash + 1, len);
+end;
procedure SplitBySpace(var a,b: shortstring);
begin
SplitByChar(a,b,' ');
end;
-// should this include "strtolower()" for the split string?
procedure SplitByChar(var a, b: shortstring; c : char);
-var i, t: LongInt;
+var i: LongInt;
begin
i:= Pos(c, a);
if i > 0 then
begin
- for t:= 1 to Pred(i) do
- if (a[t] >= 'A')and(a[t] <= 'Z') then
- Inc(a[t], 32);
b:= copy(a, i + 1, Length(a) - i);
a[0]:= char(Pred(i))
+ {$IFDEF PAS2C}
+ a[i] := 0;
+ {$ENDIF}
end
else
b:= '';
end;
-procedure SplitByChar(var a, b: ansistring; c: char);
+{$IFNDEF PAS2C}
+procedure SetLengthA(var s: ansistring; len: Longword);
+begin
+ SetLength(s, len)
+end;
+{$ENDIF}
+
+procedure SplitByCharA(var a, b: ansistring; c: char);
var i: LongInt;
begin
i:= Pos(c, a);
if i > 0 then
begin
b:= copy(a, i + 1, Length(a) - i);
- setlength(a, Pred(i));
+ SetLengthA(a, Pred(i));
end else b:= '';
-end;
+end; { SplitByCharA }
-{$IFNDEF PAS2C}
+// In the ansistring a, escapes all instances of
+// '\e' with an ASCII ESC character, where e is
+// a char chosen by you.
+procedure EscapeCharA(var a: ansistring; e: char);
+var i: LongInt;
+begin
+repeat
+ i:= Pos(e, a);
+ if (i > 1) and (a[i - 1] = '\') then
+ begin
+ a[i]:= Char($1B); // ASCII ESC
+ Delete(a, i - 1, 1);
+ end
+ else
+ break;
+until (i <= 0);
+end; { EscapeCharA }
+
+// Unescapes a previously escaped string and inserts
+// e back into the string. e is a char chosen by you.
+procedure UnEscapeCharA(var a: ansistring; e: char);
+var i: LongInt;
+begin
+repeat
+ i:= Pos(Char($1B), a); // ASCII ESC
+ if (i > 0) then
+ begin
+ a[i]:= e;
+ end
+ else
+ break;
+until (i <= 0);
+end; { UnEscapeCharA }
+
function EnumToStr(const en : TGearType) : shortstring; overload;
begin
EnumToStr:= GetEnumName(TypeInfo(TGearType), ord(en))
end;
+
function EnumToStr(const en : TVisualGearType) : shortstring; overload;
begin
EnumToStr:= GetEnumName(TypeInfo(TVisualGearType), ord(en))
@@ -141,6 +311,11 @@
EnumToStr:= GetEnumName(TypeInfo(TAmmoType), ord(en))
end;
+function EnumToStr(const en : TStatInfoType) : shortstring; overload;
+begin
+EnumToStr:= GetEnumName(TypeInfo(TStatInfoType), ord(en))
+end;
+
function EnumToStr(const en: THogEffect) : shortstring; overload;
begin
EnumToStr := GetEnumName(TypeInfo(THogEffect), ord(en))
@@ -150,7 +325,22 @@
begin
EnumToStr := GetEnumName(TypeInfo(TCapGroup), ord(en))
end;
-{$ENDIF}
+
+function EnumToStr(const en: TSprite) : shortstring; overload;
+begin
+EnumToStr := GetEnumName(TypeInfo(TSprite), ord(en))
+end;
+
+function EnumToStr(const en: TMapGen) : shortstring; overload;
+begin
+EnumToStr := GetEnumName(TypeInfo(TMapGen), ord(en))
+end;
+
+function EnumToStr(const en: TWorldEdge) : shortstring; overload;
+begin
+EnumToStr := GetEnumName(TypeInfo(TWorldEdge), ord(en))
+end;
+
function Min(a, b: LongInt): LongInt;
begin
@@ -160,6 +350,14 @@
Min:= b
end;
+function MinD(a, b: double): double;
+begin
+if a < b then
+ MinD:= a
+else
+ MinD:= b
+end;
+
function Max(a, b: LongInt): LongInt;
begin
if a > b then
@@ -174,10 +372,20 @@
str(n, IntToStr)
end;
-function StrToInt(s: shortstring): LongInt;
-var c: LongInt;
+// Convert string to longint, with error checking.
+// Success will be set to false when conversion failed.
+// See documentation on Val procedure for syntax of s
+//function StrToInt(s: shortstring; var success: boolean): LongInt;
+//var Code: Word;
+//begin
+//val(s, StrToInt, Code);
+//success:= Code = 0;
+//end;
+
+// Convert string to longint, without error checking
+function StrToInt(s: shortstring): LongInt;
begin
-val(s, StrToInt, c)
+val(s, StrToInt);
end;
function FloatToStr(n: hwFloat): shortstring;
@@ -186,7 +394,7 @@
end;
-function DxDy2Angle(const _dY, _dX: hwFloat): GLfloat; inline;
+function DxDy2Angle(const _dY, _dX: hwFloat): real; inline;
var dY, dX: Extended;
begin
dY:= hwFloat2Float(_dY);
@@ -238,7 +446,7 @@
function DecodeBase64(s: shortstring): shortstring;
const table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
-var i, t, c: Longword;
+var i, t, c: LongInt;
begin
c:= 0;
for i:= 1 to Length(s) do
@@ -271,10 +479,14 @@
function Str2PChar(const s: shortstring): PChar;
+var i :Integer ;
begin
-CharArray:= s;
-CharArray[Length(s)]:= #0;
-Str2PChar:= @CharArray
+ for i:= 1 to Length(s) do
+ begin
+ CharArray[i - 1] := s[i];
+ end;
+ CharArray[Length(s)]:= #0;
+ Str2PChar:= @(CharArray[0]);
end;
@@ -293,30 +505,51 @@
procedure AddFileLog(s: shortstring);
begin
-s:= s;
+// s:= s;
{$IFDEF DEBUGFILE}
+
{$IFDEF USE_VIDEO_RECORDING}
-EnterCriticalSection(logMutex);
+if SDL_LockMutex(logMutex) <> 0 then
+ OutError('Logging mutex could not be locked!', true);
{$ENDIF}
-writeln(f, inttostr(GameTicks) + ': ' + s);
-flush(f);
+if logFile <> nil then
+ pfsWriteLn(logFile, inttostr(GameTicks) + ': ' + s)
+else
+ WriteLn(stdout, inttostr(GameTicks) + ': ' + s);
+
{$IFDEF USE_VIDEO_RECORDING}
-LeaveCriticalSection(logMutex);
+if SDL_UnlockMutex(logMutex) <> 0 then
+ OutError('Logging mutex could not be unlocked!', true);
{$ENDIF}
+
{$ENDIF}
end;
procedure AddFileLogRaw(s: pchar); cdecl;
+var msgLine: PChar;
begin
s:= s;
+{$IFNDEF PAS2C}
{$IFDEF DEBUGFILE}
{$IFDEF USE_VIDEO_RECORDING}
-EnterCriticalSection(logMutex);
+if SDL_LockMutex(logMutex) <> 0 then
+ OutError('Logging mutex could not be locked!', true);
{$ENDIF}
-write(f, s);
-flush(f);
+msgLine:= Str2PChar(IntToStr(GameTicks) + ': ');
+if (logFile <> nil) then
+ begin
+ pfsWriteRaw(logFile, msgLine, StrLen(msgLine));
+ pfsWriteRaw(logFile, s, StrLen(s));
+ end
+else
+ begin
+ Write(stdout, msgLine);
+ Flush(stdout);
+ end;
{$IFDEF USE_VIDEO_RECORDING}
-LeaveCriticalSection(logMutex);
+if SDL_UnlockMutex(logMutex) <> 0 then
+ OutError('Logging mutex could not be unlocked!', true);
+{$ENDIF}
{$ENDIF}
{$ENDIF}
end;
@@ -334,7 +567,7 @@
{$ENDIF}
exit;
-l:= Utf8ToUnicode(@tmpstr, Str2PChar(s), length(s))-1;
+l:= Utf8ToUnicode(PWideChar(@tmpstr), PChar(s), min(length(tmpstr), length(s)))-1;
i:= 0;
while i < l do
@@ -343,15 +576,15 @@
if (#$1100 <= u) and (
(u <= #$11FF ) or // Hangul Jamo
((#$2E80 <= u) and (u <= #$2FDF)) or // CJK Radicals Supplement / Kangxi Radicals
- ((#$2FF0 <= u) and (u <= #$303F)) or // Ideographic Description Characters / CJK Radicals Supplement
- ((#$3130 <= u) and (u <= #$318F)) or // Hangul Compatibility Jamo
+ ((#$2FF0 <= u) and (u <= #$31FF)) or // Ideographic Description Characters / CJK Radicals Supplement / Hiragana / Hangul Compatibility Jamo / Katakana
((#$31C0 <= u) and (u <= #$31EF)) or // CJK Strokes
- ((#$3200 <= u) and (u <= #$4DBF)) or // Enclosed CJK Letters and Months / CJK Compatibility / CJK Unified Ideographs Extension A
+ ((#$3200 <= u) and (u <= #$4DBF)) or // Enclosed CJK Letters and Months / CJK Compatibility / CJK Unified Ideographs Extension A / Circled Katakana
((#$4E00 <= u) and (u <= #$9FFF)) or // CJK Unified Ideographs
((#$AC00 <= u) and (u <= #$D7AF)) or // Hangul Syllables
((#$F900 <= u) and (u <= #$FAFF)) or // CJK Compatibility Ideographs
- ((#$FE30 <= u) and (u <= #$FE4F))) // CJK Compatibility Forms
- then
+ ((#$FE30 <= u) and (u <= #$FE4F)) or // CJK Compatibility Forms
+ ((#$FF00 <= u) and (u <= #$FFEF))) // half- and fullwidth characters
+ then
begin
CheckCJKFont:= THWFont( ord(font) + ((ord(High(THWFont))+1) div 2) );
exit;
@@ -366,6 +599,7 @@
function GetLaunchX(at: TAmmoType; dir: LongInt; angle: LongInt): LongInt;
begin
+at:= at; dir:= dir; angle:= angle; // parameter hint suppression because code below is currently disabled
GetLaunchX:= 0
(*
if (Ammoz[at].ejectX <> 0) or (Ammoz[at].ejectY <> 0) then
@@ -376,6 +610,7 @@
function GetLaunchY(at: TAmmoType; angle: LongInt): LongInt;
begin
+at:= at; angle:= angle; // parameter hint suppression because code below is currently disabled
GetLaunchY:= 0
(*
if (Ammoz[at].ejectX <> 0) or (Ammoz[at].ejectY <> 0) then
@@ -384,6 +619,31 @@
GetLaunchY:= 0*)
end;
+// Takes an X coordinate and corrects if according to the world edge rules
+// Wrap-around: X will be wrapped
+// Bouncy: X will be kept inside the legal land (taking radius into account)
+// Other world edges: Just returns X
+// radius is a radius (gear radius) tolerance for an appropriate distance from bouncy world edges.
+// Set radius to 0 if you don't care.
+function CalcWorldWrap(X, radius: LongInt): LongInt;
+begin
+ if WorldEdge = weWrap then
+ begin
+ if X < leftX then
+ X:= X + (rightX - leftX)
+ else if X > rightX then
+ X:= X - (rightX - leftX);
+ end
+ else if WorldEdge = weBounce then
+ begin
+ if (X + radius) < leftX then
+ X:= leftX + radius
+ else if (X - radius) > rightX then
+ X:= rightX - radius;
+ end;
+ CalcWorldWrap:= X;
+end;
+
function CheckNoTeamOrHH: boolean;
begin
CheckNoTeamOrHH:= (CurrentTeam = nil) or (CurrentHedgehog^.Gear = nil);
@@ -399,65 +659,209 @@
begin
system.writeln(f, s)
end;
+
+function StrLength(s: PChar): Longword;
+begin
+ StrLength:= length(s)
+end;
{$ENDIF}
-procedure initModule(isGame: boolean);
+// this function is just to determine whether we are running on a limited screen device
+function isPhone: Boolean; inline;
+begin
+ isPhone:= false;
+{$IFDEF IPHONEOS}
+ isPhone:= isApplePhone();
+{$ENDIF}
+{$IFDEF ANDROID}
+ //nasty nasty hack. TODO: implement callback to java to have a unified way of determining if it is a tablet
+ if (cScreenWidth < 1000) and (cScreenHeight < 500) then
+ isPhone:= true;
+{$ENDIF}
+end;
+
+
+function sanitizeForLog(s: shortstring): shortstring;
+var i: byte;
+ r: shortstring;
+begin
+ r[0]:= s[0];
+ for i:= 1 to length(s) do
+ if (s[i] < #32) or (s[i] > #127) then
+ r[i]:= '?'
+ else
+ r[i]:= s[i];
+
+ sanitizeForLog:= r
+end;
+
+function sanitizeCharForLog(c: char): shortstring;
+var r: shortstring;
+begin
+ if (c < #32) or (c > #127) then
+ r:= '#' + inttostr(byte(c))
+ else
+ begin
+ // some magic for pas2c
+ r[0]:= #1;
+ r[1]:= c;
+ end;
+
+ sanitizeCharForLog:= r
+end;
+
+// helper function for volume change controls
+procedure updateVolumeDelta(precise: boolean);
+begin
+if cVolumeUpKey and (not cVolumeDownKey) then
+ if precise then
+ cVolumeDelta:= 1
+ else
+ cVolumeDelta:= 3
+else if cVolumeDownKey and (not cVolumeUpKey) then
+ if precise then
+ cVolumeDelta:= -1
+ else
+ cVolumeDelta:= -3
+else
+ cVolumeDelta:= 0;
+end;
+
+// helper function for cursor movement change controls
+procedure updateCursorMovementDelta(precise: boolean; dir: LongInt; var cursorVar: LongInt);
+begin
+if dir > 0 then
+ if precise then
+ cursorVar:= cameraKeyboardSpeedSlow
+ else
+ cursorVar:= cameraKeyboardSpeed
+else if dir < 0 then
+ if precise then
+ cursorVar:= - cameraKeyboardSpeedSlow
+ else
+ cursorVar:= - cameraKeyboardSpeed
+else
+ cursorVar:= 0;
+end;
+
+function read1stLn(filePath: shortstring): shortstring;
+var f: pfsFile;
+begin
+ read1stLn:= '';
+ if pfsExists(filePath) then
+ begin
+ f:= pfsOpenRead(filePath);
+ if (not pfsEOF(f)) and allOK then
+ pfsReadLn(f, read1stLn);
+ pfsClose(f);
+ f:= nil;
+ end;
+end;
+
+function readValueFromINI(key, filePath: shortstring): shortstring;
+var f: pfsFile;
+ s: shortstring;
+ i: LongInt;
+begin
+ s:= '';
+ readValueFromINI:= '';
+
+ if pfsExists(filePath) then
+ begin
+ f:= pfsOpenRead(filePath);
+
+ while (not pfsEOF(f)) and allOK do
+ begin pfsReadLn(f, s);
+ if Length(s) = 0 then
+ continue;
+ if s[1] = ';' then
+ continue;
+
+ i:= Pos('=', s);
+ if Trim(Copy(s, 1, Pred(i))) = key then
+ begin
+ Delete(s, 1, i);
+ readValueFromINI:= s;
+ end;
+ end;
+ pfsClose(f);
+ f:= nil;
+ end;
+end;
+
+procedure initModule(isNotPreview: boolean);
{$IFDEF DEBUGFILE}
var logfileBase: shortstring;
-{$IFNDEF MOBILE}var i: LongInt;{$ENDIF}
+ i: LongInt;
{$ENDIF}
begin
{$IFDEF DEBUGFILE}
- if isGame then
+ if isNotPreview then
begin
if GameType = gmtRecord then
logfileBase:= 'rec'
else
- logfileBase:= 'game';
+ {$IFDEF PAS2C}
+ logfileBase:= 'game_pas2c';
+ {$ELSE}
+ logfileBase:= 'game';
+ {$ENDIF}
end
else
+ {$IFDEF PAS2C}
+ logfileBase:= 'preview_pas2c';
+ {$ELSE}
logfileBase:= 'preview';
+ {$ENDIF}
{$IFDEF USE_VIDEO_RECORDING}
- InitCriticalSection(logMutex);
+ logMutex:= SDL_CreateMutex();
+ if (logMutex = nil) then
+ OutError('Could not create mutex for logging', true);
{$ENDIF}
-{$I-}
-{$IFDEF MOBILE}
- {$IFDEF IPHONEOS} Assign(f,'../Documents/hw-' + logfileBase + '.log'); {$ENDIF}
- {$IFDEF ANDROID} Assign(f,pathPrefix + '/' + logfileBase + '.log'); {$ENDIF}
- Rewrite(f);
+ if not pfsExists('/Logs') then
+ pfsMakeDir('/Logs');
+ // if log is locked, write to the next one
+ i:= 0;
+ while(i < 7) do
+ begin
+ logFile:= pfsOpenWrite('/Logs/' + logfileBase + inttostr(i) + '.log');
+ if logFile <> nil then
+ break;
+ inc(i)
+ end;
+
+ if logFile = nil then
+ WriteLn(stdout, '[WARNING] Could not open log file for writing. Log will be written to stdout!');
+{$ENDIF}
+
+ //mobile stuff
+{$IFDEF IPHONEOS}
+ mobileRecord.PerformRumble:= @AudioServicesPlaySystemSound;
+ mobileRecord.GameLoading:= @startLoadingIndicator;
+ mobileRecord.GameLoaded:= @stopLoadingIndicator;
+ mobileRecord.SaveLoadingEnded:= @saveFinishedSynching;
{$ELSE}
- if (UserPathPrefix <> '') then
- begin
- i:= 0;
- while(i < 7) do
- begin
- assign(f, UserPathPrefix + '/Logs/' + logfileBase + inttostr(i) + '.log');
- rewrite(f);
- if IOResult = 0 then
- break;
- inc(i)
- end;
- if i = 7 then
- f:= stderr; // if everything fails, write to stderr
- end
- else
- f:= stderr;
-{$ENDIF}
-{$I+}
+ mobileRecord.PerformRumble:= nil;
+ mobileRecord.GameLoading:= nil;
+ mobileRecord.GameLoaded:= nil;
+ mobileRecord.SaveLoadingEnded:= nil;
{$ENDIF}
end;
procedure freeModule;
begin
-recordFileName:= '';
-
{$IFDEF DEBUGFILE}
- writeln(f, 'halt at ' + inttostr(GameTicks) + ' ticks. TurnTimeLeft = ' + inttostr(TurnTimeLeft));
- flush(f);
- close(f);
+if logFile <> nil then
+ begin
+ pfsWriteLn(logFile, 'halt at ' + inttostr(GameTicks) + ' ticks. TurnTimeLeft = ' + inttostr(TurnTimeLeft));
+ pfsFlush(logFile);
+ pfsClose(logFile);
+ end
+else
+ WriteLn(stdout, 'halt at ' + inttostr(GameTicks) + ' ticks. TurnTimeLeft = ' + inttostr(TurnTimeLeft));
{$IFDEF USE_VIDEO_RECORDING}
- DoneCriticalSection(logMutex);
+ SDL_DestroyMutex(logMutex);
{$ENDIF}
{$ENDIF}
end;