1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
unit UPlatform;
// Comment by Eddie:
// This unit defines an interface for platform specific utility functions.
// The Interface is implemented in separate files for each platform:
// UPlatformWindows, UPlatformLinux and UPlatformMacOSX.
interface
{$IFDEF FPC}
{$MODE Delphi}
{$ENDIF}
{$I switches.inc}
uses Classes;
type
TDirectoryEntry = record
Name : WideString;
IsDirectory : boolean;
IsFile : boolean;
end;
TDirectoryEntryArray = array of TDirectoryEntry;
TPlatform = class
function GetExecutionDir(): string;
procedure Init; virtual;
function DirectoryFindFiles(Dir, Filter: WideString; ReturnAllSubDirs: boolean): TDirectoryEntryArray; virtual; abstract;
function TerminateIfAlreadyRunning(var WndTitle : string): boolean; virtual;
function FindSongFile(Dir, Mask: WideString): WideString; virtual;
procedure Halt; virtual;
function GetLogPath : WideString; virtual; abstract;
function GetGameSharedPath : WideString; virtual; abstract;
function GetGameUserPath : WideString; virtual; abstract;
function CopyFile(const Source, Target: WideString; FailIfExists: boolean): boolean; virtual;
end;
function Platform(): TPlatform;
implementation
uses
SysUtils,
{$IFDEF MSWINDOWS}
UPlatformWindows,
{$ENDIF}
{$IFDEF LINUX}
UPlatformLinux,
{$ENDIF}
{$IFDEF DARWIN}
UPlatformMacOSX,
{$ENDIF}
ULog;
// I have modified it to use the Platform_singleton in this location ( in the implementaiton )
// so that this variable can NOT be overwritten from anywhere else in the application.
// the accessor function platform, emulates all previous calls to work the same way.
var
Platform_singleton : TPlatform;
function Platform : TPlatform;
begin
Result := Platform_singleton;
end;
(**
* Default Init() implementation
*)
procedure TPlatform.Init;
begin
end;
(**
* Default Halt() implementation
*)
procedure TPlatform.Halt;
begin
// Note: Application.terminate is NOT the same
System.Halt;
end;
{**
* Returns the directory of the executable
*}
function TPlatform.GetExecutionDir(): string;
begin
Result := ExtractFilePath(ParamStr(0));
end;
(**
* Default TerminateIfAlreadyRunning() implementation
*)
function TPlatform.TerminateIfAlreadyRunning(var WndTitle : string): Boolean;
begin
Result := false;
end;
(**
* Default FindSongFile() implementation
*)
function TPlatform.FindSongFile(Dir, Mask: WideString): WideString;
var
SR: TSearchRec; // for parsing song directory
begin
Result := '';
if SysUtils.FindFirst(Dir + Mask, faDirectory, SR) = 0 then
begin
Result := SR.Name;
end;
SysUtils.FindClose(SR);
end;
function TPlatform.CopyFile(const Source, Target: WideString; FailIfExists: boolean): boolean;
const
COPY_BUFFER_SIZE = 4096; // a good tradeoff between speed and memory consumption
var
SourceFile, TargetFile: TFileStream;
FileCopyBuffer: array [0..COPY_BUFFER_SIZE-1] of byte; // temporary copy-buffer.
NumberOfBytes: integer; // number of bytes read from SourceFile
begin
Result := false;
SourceFile := nil;
TargetFile := nil;
// if overwrite is disabled return if the target file already exists
if (FailIfExists and FileExists(Target)) then
Exit;
try
try
// open source and target file (might throw an exception on error)
SourceFile := TFileStream.Create(Source, fmOpenRead);
TargetFile := TFileStream.Create(Target, fmCreate or fmOpenWrite);
while true do
begin
// read a block from the source file and check for errors or EOF
NumberOfBytes := SourceFile.Read(FileCopyBuffer, SizeOf(FileCopyBuffer));
if (NumberOfBytes <= 0) then
Break;
// write block to target file and check if everything was written
if (TargetFile.Write(FileCopyBuffer, NumberOfBytes) <> NumberOfBytes) then
Exit;
end;
except
Exit;
end;
finally
SourceFile.Free;
TargetFile.Free;
end;
Result := true;
end;
initialization
{$IFDEF MSWINDOWS}
Platform_singleton := TPlatformWindows.Create;
{$ENDIF}
{$IFDEF LINUX}
Platform_singleton := TPlatformLinux.Create;
{$ENDIF}
{$IFDEF DARWIN}
Platform_singleton := TPlatformMacOSX.Create;
{$ENDIF}
finalization
Platform_singleton.Free;
end.
|