Subversion Repositories spacemission

Rev

Rev 90 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 daniel-mar 1
unit Global;
2
 
3
interface
4
 
5
const
90 daniel-mar 6
  ProgramVersion = '1.2.2';
79 daniel-mar 7
  LevEditRasterW = 48;
8
  LevEditRasterH = 32;
81 daniel-mar 9
  LevEditRows = 15; // Attention: if you change this, you also need to change the LevEditor GUI!
10
  LevEditCols = 13; // Attention: if you change this, you also need to change the LevEditor GUI!
40 daniel-mar 11
  MaxPossibleEnemyLives = 999;
61 daniel-mar 12
  MaxPossibleLevels = 999;
79 daniel-mar 13
  RegistrySettingsKey = 'SOFTWARE\ViaThinkSoft\SpaceMission\Settings'; // do not localize
14
  MusicSettingKey = 'Music'; // do not localize
15
  SoundSettingKey = 'Sound'; // do not localize
80 daniel-mar 16
  SpeedSettingKey = 'GameSpeed'; // do not localize
51 daniel-mar 17
  DefaultLevelLength = 1200;
54 daniel-mar 18
  StartLives = 6;
81 daniel-mar 19
  SpeedEasy = 650 div 60; // 10
20
  SpeedMedium = 1000 div 60; // 16
21
  SpeedHard = 1350 div 60; // 22
22
  SpeedMaster = 2000 div 60; // 33
54 daniel-mar 23
  DEFAULT_ANIMSPEED = 15/1000;
79 daniel-mar 24
  BossWidth = 4;
25
  BossHeight = 2;
26
  SpaceMissionExe = 'SpaceMission.exe'; // do not localize
27
  LevEditExe = 'LevEdit.exe'; // do not localize
80 daniel-mar 28
  DxgFile = 'DirectX\Graphics.dxg'; // do not localize
29
  DxwFile = 'DirectX\Sound.dxw'; // do not localize
30
  DxmFile = 'DirectX\Music.dxm'; // do not localize
81 daniel-mar 31
  RandomLevelMaxEnemyLives = 10;
32
  RandomLevelMedikitEveryX = 250;
33
  RandomLevelAdditionalEnemiesPerLevel = 75; // Zufalls-Level
2 daniel-mar 34
 
89 daniel-mar 35
const
36
  // Cheat1 = 'Kmkjk'+#39+'Khyc';
37
  Cheat1 = #75+#109+#107+#106+#107+#127+#39+#75+#104+#121+#99; {Johnny Cash}
38
 
39
resourcestring
40
  Cheat1Text = 'Unendlich Leben!';
41
 
31 daniel-mar 42
type
89 daniel-mar 43
  TCheat = (ctUnknown, ctInfiniteLives);
44
  TCheatSet = set of TCheat;
45
 
31 daniel-mar 46
  // DirectX\Music.dxm
47
  TSpaceMissionMusicTrack = (
48
    smmNone,
49
    smmBoss,   // dxmusic.Midis[0]
50
    smmGame,   // dxmusic.Midis[1]
51
    smmScene,  // dxmusic.Midis[2]
52
    smmTitle   // dxmusic.Midis[3]
53
  );
54
 
55
  // DirectX\Graphics.dxg
56
  TSpaceMissionGraphicSprite = (
34 daniel-mar 57
    smgNone,
58
    smgEnemyDisk,         // ImageList.Items.Item[0]
59
    smgEnemyAttacker,     // ImageList.Items.Item[1]
60
    smgEnemyBoss,         // ImageList.Items.Item[2]
61
    smgBounce,            // ImageList.Items.Item[3]
62
    smgMachine,           // ImageList.Items.Item[4]
63
    smgEnemyAttacker2,    // ImageList.Items.Item[5]
64
    smgEnemyAttacker3,    // ImageList.Items.Item[6]
65
    smgEnemyMeteor,       // ImageList.Items.Item[7]
66
    smgBounce2,           // ImageList.Items.Item[8]
67
    smgEnemyDisk2,        // ImageList.Items.Item[9]
68
    smgLogo,              // ImageList.Items.Item[10]
69
    smgExplosion,         // ImageList.Items.Item[11]
70
    smgBackgroundPlanet1, // ImageList.Items.Item[12]
71
    smgMatrix,            // ImageList.Items.Item[13]
72
    smgStar1,             // ImageList.Items.Item[14]
73
    smgStar2,             // ImageList.Items.Item[15]
74
    smgStar3,             // ImageList.Items.Item[16]
75
    smgBackgroundBlue,    // ImageList.Items.Item[17]
76
    smgBackgroundRed,     // ImageList.Items.Item[18]
77
    smgBackgroundYellow,  // ImageList.Items.Item[19]
72 daniel-mar 78
    smgHintergrundRot,    // ImageList.Items.Item[20]
79
    smgItemMedikit        // ImageList.Items.Item[21]
31 daniel-mar 80
  );
81
 
82
  // DirectX\Sound.dxw
83
  TSpaceMissionSound = (
84
    smsNone,
85
    smsSceneMov,      // WaveList.Items.Item[0]
86
    smsExplosion,     // WaveList.Items.Item[1]
87
    smsHit,           // WaveList.Items.Item[2]
88
    smsShoot,         // WaveList.Items.Item[3]
72 daniel-mar 89
    smsItemCollected  // WaveList.Items.Item[4]
31 daniel-mar 90
  );
91
 
92
function OwnDirectory: string;
93
 
51 daniel-mar 94
const
79 daniel-mar 95
  FOLDERID_SavedGames: TGuid = '{4C5C32FF-BB9D-43b0-B5B4-2D72E54EAAA4}'; // do not localize
51 daniel-mar 96
 
54 daniel-mar 97
// Useful functions
94 daniel-mar 98
procedure SpaceMission_SwitchLanguage;
51 daniel-mar 99
function GetKnownFolderPath(const rfid: TGUID): string;
54 daniel-mar 100
function KillTask(ExeFileName: string): Integer;
74 daniel-mar 101
procedure CheckForUpdates(ViaThinkSoftProjectName: string; AVersion: string);
51 daniel-mar 102
 
2 daniel-mar 103
implementation
104
 
105
uses
79 daniel-mar 106
  Windows, SysUtils, Dialogs, ActiveX, ShlObj, TlHelp32, wininet, Forms, ShellAPI,
107
  System.UITypes;
2 daniel-mar 108
 
94 daniel-mar 109
procedure SwitchLanguage(newLang: string);
110
var
111
  bakHInst: hInst;
112
  modFileName: string;
113
begin
114
  SetLocaleOverride(newLang);
115
 
116
  // Note: SetLocaleOverride() does not work, because LibModuleList.ResInstance
117
  // is already set and won't be re-set by the FindResourceHInstance()!
118
  bakHInst := LibModuleList.ResInstance;
119
  modFileName := ChangeFileExt(ParamStr(0),'.'+GetLocaleOverride(ParamStr(0)));
120
  LibModuleList.ResInstance := LoadResourceModule(PChar(modFileName));
121
  if LibModuleList.ResInstance = 0 then
122
    LibModuleList.ResInstance := LibModuleList.Instance;
123
  FreeLibrary(bakHInst);
124
end;
125
 
126
function GetUserDefaultUILanguage: LANGID; stdcall; external 'kernel32';
127
 
128
procedure SpaceMission_SwitchLanguage;
129
begin
130
  // We need this because of a tricky problem...
131
  // Our base language is German (DE), and we have a translation for English USA (ENU)
132
  // If the system locale is not exactly ENU (even ENG is not accepted), then the base language (German) will be used.
133
  // But much more people are speaking English than German. So we need to force the system to use ENU instead of DE.
134
  // This decision if we choose DE or ENU is done by the language selected during setup.
135
  if (GetUserDefaultUILanguage and $FF) <> LANG_GERMAN then
136
    SwitchLanguage('ENU');
137
end;
138
 
51 daniel-mar 139
function GetKnownFolderPath(const rfid: TGUID): string;
140
var
141
  OutPath: PWideChar;
142
begin
143
  // https://www.delphipraxis.net/135471-unit-zur-verwendung-von-shgetknownfolderpath.html
144
  if ShGetKnownFolderPath(rfid, 0, 0, OutPath) {>= 0} = S_OK then
145
  begin
146
    Result := OutPath;
147
    // From MSDN
148
    // ppszPath [out]
149
    // Type: PWSTR*
150
    // When this method returns, contains the address of a pointer to a null-terminated Unicode string that specifies the path of the known folder
151
    // The calling process is responsible for freeing this resource once it is no longer needed by calling CoTaskMemFree.
152
    // The returned path does not include a trailing backslash. For example, "C:\Users" is returned rather than "C:\Users\".
153
    CoTaskMemFree(OutPath);
154
  end
155
  else
156
  begin
157
    Result := '';
158
  end;
159
end;
160
 
54 daniel-mar 161
// https://stackoverflow.com/questions/43774320/how-to-kill-a-process-by-name
162
function KillTask(ExeFileName: string): Integer;
163
const
164
  PROCESS_TERMINATE = $0001;
165
var
166
  ContinueLoop: BOOL;
167
  FSnapshotHandle: THandle;
168
  FProcessEntry32: TProcessEntry32;
169
begin
170
  Result := 0;
171
  FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
172
  FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
173
  ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);
174
 
175
  while Integer(ContinueLoop) <> 0 do
176
  begin
177
    if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) =
178
      UpperCase(ExeFileName)) or (UpperCase(FProcessEntry32.szExeFile) =
179
      UpperCase(ExeFileName))) then
180
      Result := Integer(TerminateProcess(
181
                        OpenProcess(PROCESS_TERMINATE,
182
                                    BOOL(0),
183
                                    FProcessEntry32.th32ProcessID),
184
                                    0));
185
     ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
186
  end;
187
  CloseHandle(FSnapshotHandle);
188
end;
189
 
31 daniel-mar 190
function OwnDirectory: string;
2 daniel-mar 191
begin
192
  result := extractfilepath(paramstr(0));
193
end;
194
 
74 daniel-mar 195
// https://www.delphipraxis.net/post43515.html , fixed , works for Delphi 12 Athens
196
function GetHTML(AUrl: string): RawByteString;
63 daniel-mar 197
var
74 daniel-mar 198
  databuffer : array[0..4095] of ansichar; // SIC! ansichar!
199
  ResStr : ansistring; // SIC! ansistring
63 daniel-mar 200
  hSession, hfile: hInternet;
201
  dwindex,dwcodelen,dwread,dwNumber: cardinal;
202
  dwcode : array[1..20] of char;
203
  res    : pchar;
74 daniel-mar 204
  Str    : pansichar; // SIC! pansichar
63 daniel-mar 205
begin
206
  ResStr:='';
79 daniel-mar 207
  if (system.pos('http://',lowercase(AUrl))=0) and // do not localize
208
     (system.pos('https://',lowercase(AUrl))=0) then // do not localize
209
     AUrl:='http://'+AUrl; // do not localize
63 daniel-mar 210
 
211
  // Hinzugefügt
212
  if Assigned(Application) then Application.ProcessMessages;
213
 
79 daniel-mar 214
  hSession:=InternetOpen('InetURL:/1.0', // do not localize
63 daniel-mar 215
                         INTERNET_OPEN_TYPE_PRECONFIG,
216
                         nil,
217
                         nil,
218
                         0);
219
  if assigned(hsession) then
220
  begin
221
    // Hinzugefügt
222
    if Assigned(Application) then application.ProcessMessages;
223
 
224
    hfile:=InternetOpenUrl(
225
           hsession,
226
           pchar(AUrl),
227
           nil,
228
           0,
229
           INTERNET_FLAG_RELOAD,
230
           0);
231
    dwIndex  := 0;
232
    dwCodeLen := 10;
233
 
234
    // Hinzugefügt
235
    if Assigned(Application) then application.ProcessMessages;
236
 
237
    HttpQueryInfo(hfile,
238
                  HTTP_QUERY_STATUS_CODE,
239
                  @dwcode,
240
                  dwcodeLen,
241
                  dwIndex);
242
    res := pchar(@dwcode);
243
    dwNumber := sizeof(databuffer)-1;
79 daniel-mar 244
    if (res ='200') or (res = '302') then // do not localize
63 daniel-mar 245
    begin
246
      while (InternetReadfile(hfile,
247
                              @databuffer,
248
                              dwNumber,
249
                              DwRead)) do
250
      begin
251
 
252
        // Hinzugefügt
253
        if Assigned(Application) then application.ProcessMessages;
254
 
255
        if dwRead =0 then
256
          break;
257
        databuffer[dwread]:=#0;
74 daniel-mar 258
        Str := pansichar(@databuffer);
63 daniel-mar 259
        resStr := resStr + Str;
260
      end;
261
    end
262
    else
79 daniel-mar 263
      ResStr := 'Status:'+AnsiString(res); // do not localize
63 daniel-mar 264
    if assigned(hfile) then
265
      InternetCloseHandle(hfile);
266
  end;
267
 
268
  // Hinzugefügt
269
  if Assigned(Application) then application.ProcessMessages;
270
 
271
  InternetCloseHandle(hsession);
272
  Result := resStr;
273
end;
274
 
74 daniel-mar 275
procedure CheckForUpdates(ViaThinkSoftProjectName: string; AVersion: string);
79 daniel-mar 276
resourcestring
277
  SDownloadError = 'Ein Fehler ist aufgetreten. Wahrscheinlich ist keine Internetverbindung aufgebaut, oder der der ViaThinkSoft-Server vorübergehend offline.';
278
  SNewProgramVersionAvailable = 'Eine neue Programmversion ist vorhanden. Möchten Sie diese jetzt herunterladen?';
279
  SNoUpdateAvailable = 'Es ist keine neue Programmversion vorhanden.';
63 daniel-mar 280
var
74 daniel-mar 281
  cont: RawByteString;
63 daniel-mar 282
begin
79 daniel-mar 283
  cont := GetHTML('https://www.viathinksoft.de/update/?id='+ViaThinkSoftProjectName); // do not localize
63 daniel-mar 284
  if copy(cont, 0, 7) = 'Status:' then
285
  begin
79 daniel-mar 286
    MessageDlg(SDownloadError, mtError, [mbOk], 0);
63 daniel-mar 287
  end
288
  else
289
  begin
74 daniel-mar 290
    if string(cont) <> AVersion then
63 daniel-mar 291
    begin
79 daniel-mar 292
      if MessageDlg(SNewProgramVersionAvailable, mtConfirmation, mbYesNoCancel, 0) = mrYes then
293
        shellexecute(application.handle, 'open', pchar('https://www.viathinksoft.de/update/?id=@'+ViaThinkSoftProjectName), '', '', sw_normal); // do not localize
63 daniel-mar 294
    end
295
    else
296
    begin
79 daniel-mar 297
      MessageDlg(SNoUpdateAvailable, mtInformation, [mbOk], 0);
63 daniel-mar 298
    end;
299
  end;
300
end;
301
 
2 daniel-mar 302
end.