Subversion Repositories spacemission

Rev

Rev 94 | 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
96 daniel-mar 111
  oldHInst: hInst;
112
  newHInst: hInst;
113
  bakOverride: string;
114
  FileName: array [0..MAX_PATH] of Char;
115
  Module: PLibModule;
94 daniel-mar 116
begin
96 daniel-mar 117
  Module := LibModuleList;
118
  GetModuleFileName(Module.Instance, FileName, Length(FileName));
94 daniel-mar 119
 
96 daniel-mar 120
  bakOverride := GetLocaleOverride('');
121
  try
122
    SetLocaleOverride(newLang);
123
 
124
    // Note: SetLocaleOverride() alone does not work, because LibModuleList.ResInstance
125
    // is already set and won't be re-set by the FindResourceHInstance()!
126
    newHInst := LoadResourceModule(FileName);
127
    if newHInst = 0 then newHInst := Module.Instance;
128
 
129
    oldHInst := Module.ResInstance;
130
    Module.ResInstance := newHInst;
131
    FreeLibrary(oldHInst);
132
  except
133
    SetLocaleOverride(bakOverride);
134
  end;
94 daniel-mar 135
end;
136
 
137
function GetUserDefaultUILanguage: LANGID; stdcall; external 'kernel32';
138
 
139
procedure SpaceMission_SwitchLanguage;
96 daniel-mar 140
const
141
  BaseLanguage = LANG_GERMAN;
142
  DesiredFallbackLanguage = 'ENU'; // English USA
94 daniel-mar 143
begin
144
  // We need this because of a tricky problem...
145
  // Our base language is German (DE), and we have a translation for English USA (ENU)
146
  // If the system locale is not exactly ENU (even ENG is not accepted), then the base language (German) will be used.
147
  // But much more people are speaking English than German. So we need to force the system to use ENU instead of DE.
148
  // This decision if we choose DE or ENU is done by the language selected during setup.
96 daniel-mar 149
  if (GetLocaleOverride('') = '') and
150
     ((GetUserDefaultUILanguage and $FF) <> BaseLanguage) then
151
  begin
152
    SwitchLanguage(DesiredFallbackLanguage);
153
  end;
94 daniel-mar 154
end;
155
 
51 daniel-mar 156
function GetKnownFolderPath(const rfid: TGUID): string;
157
var
158
  OutPath: PWideChar;
159
begin
160
  // https://www.delphipraxis.net/135471-unit-zur-verwendung-von-shgetknownfolderpath.html
161
  if ShGetKnownFolderPath(rfid, 0, 0, OutPath) {>= 0} = S_OK then
162
  begin
163
    Result := OutPath;
164
    // From MSDN
165
    // ppszPath [out]
166
    // Type: PWSTR*
167
    // When this method returns, contains the address of a pointer to a null-terminated Unicode string that specifies the path of the known folder
168
    // The calling process is responsible for freeing this resource once it is no longer needed by calling CoTaskMemFree.
169
    // The returned path does not include a trailing backslash. For example, "C:\Users" is returned rather than "C:\Users\".
170
    CoTaskMemFree(OutPath);
171
  end
172
  else
173
  begin
174
    Result := '';
175
  end;
176
end;
177
 
54 daniel-mar 178
// https://stackoverflow.com/questions/43774320/how-to-kill-a-process-by-name
179
function KillTask(ExeFileName: string): Integer;
180
const
181
  PROCESS_TERMINATE = $0001;
182
var
183
  ContinueLoop: BOOL;
184
  FSnapshotHandle: THandle;
185
  FProcessEntry32: TProcessEntry32;
186
begin
187
  Result := 0;
188
  FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
189
  FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
190
  ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);
191
 
192
  while Integer(ContinueLoop) <> 0 do
193
  begin
194
    if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) =
195
      UpperCase(ExeFileName)) or (UpperCase(FProcessEntry32.szExeFile) =
196
      UpperCase(ExeFileName))) then
197
      Result := Integer(TerminateProcess(
198
                        OpenProcess(PROCESS_TERMINATE,
199
                                    BOOL(0),
200
                                    FProcessEntry32.th32ProcessID),
201
                                    0));
202
     ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
203
  end;
204
  CloseHandle(FSnapshotHandle);
205
end;
206
 
31 daniel-mar 207
function OwnDirectory: string;
2 daniel-mar 208
begin
209
  result := extractfilepath(paramstr(0));
210
end;
211
 
74 daniel-mar 212
// https://www.delphipraxis.net/post43515.html , fixed , works for Delphi 12 Athens
213
function GetHTML(AUrl: string): RawByteString;
63 daniel-mar 214
var
74 daniel-mar 215
  databuffer : array[0..4095] of ansichar; // SIC! ansichar!
216
  ResStr : ansistring; // SIC! ansistring
63 daniel-mar 217
  hSession, hfile: hInternet;
218
  dwindex,dwcodelen,dwread,dwNumber: cardinal;
219
  dwcode : array[1..20] of char;
220
  res    : pchar;
74 daniel-mar 221
  Str    : pansichar; // SIC! pansichar
63 daniel-mar 222
begin
223
  ResStr:='';
79 daniel-mar 224
  if (system.pos('http://',lowercase(AUrl))=0) and // do not localize
225
     (system.pos('https://',lowercase(AUrl))=0) then // do not localize
226
     AUrl:='http://'+AUrl; // do not localize
63 daniel-mar 227
 
228
  // Hinzugefügt
229
  if Assigned(Application) then Application.ProcessMessages;
230
 
79 daniel-mar 231
  hSession:=InternetOpen('InetURL:/1.0', // do not localize
63 daniel-mar 232
                         INTERNET_OPEN_TYPE_PRECONFIG,
233
                         nil,
234
                         nil,
235
                         0);
236
  if assigned(hsession) then
237
  begin
238
    // Hinzugefügt
239
    if Assigned(Application) then application.ProcessMessages;
240
 
241
    hfile:=InternetOpenUrl(
242
           hsession,
243
           pchar(AUrl),
244
           nil,
245
           0,
246
           INTERNET_FLAG_RELOAD,
247
           0);
248
    dwIndex  := 0;
249
    dwCodeLen := 10;
250
 
251
    // Hinzugefügt
252
    if Assigned(Application) then application.ProcessMessages;
253
 
254
    HttpQueryInfo(hfile,
255
                  HTTP_QUERY_STATUS_CODE,
256
                  @dwcode,
257
                  dwcodeLen,
258
                  dwIndex);
259
    res := pchar(@dwcode);
260
    dwNumber := sizeof(databuffer)-1;
79 daniel-mar 261
    if (res ='200') or (res = '302') then // do not localize
63 daniel-mar 262
    begin
263
      while (InternetReadfile(hfile,
264
                              @databuffer,
265
                              dwNumber,
266
                              DwRead)) do
267
      begin
268
 
269
        // Hinzugefügt
270
        if Assigned(Application) then application.ProcessMessages;
271
 
272
        if dwRead =0 then
273
          break;
274
        databuffer[dwread]:=#0;
74 daniel-mar 275
        Str := pansichar(@databuffer);
63 daniel-mar 276
        resStr := resStr + Str;
277
      end;
278
    end
279
    else
79 daniel-mar 280
      ResStr := 'Status:'+AnsiString(res); // do not localize
63 daniel-mar 281
    if assigned(hfile) then
282
      InternetCloseHandle(hfile);
283
  end;
284
 
285
  // Hinzugefügt
286
  if Assigned(Application) then application.ProcessMessages;
287
 
288
  InternetCloseHandle(hsession);
289
  Result := resStr;
290
end;
291
 
74 daniel-mar 292
procedure CheckForUpdates(ViaThinkSoftProjectName: string; AVersion: string);
79 daniel-mar 293
resourcestring
294
  SDownloadError = 'Ein Fehler ist aufgetreten. Wahrscheinlich ist keine Internetverbindung aufgebaut, oder der der ViaThinkSoft-Server vorübergehend offline.';
295
  SNewProgramVersionAvailable = 'Eine neue Programmversion ist vorhanden. Möchten Sie diese jetzt herunterladen?';
296
  SNoUpdateAvailable = 'Es ist keine neue Programmversion vorhanden.';
63 daniel-mar 297
var
74 daniel-mar 298
  cont: RawByteString;
63 daniel-mar 299
begin
79 daniel-mar 300
  cont := GetHTML('https://www.viathinksoft.de/update/?id='+ViaThinkSoftProjectName); // do not localize
63 daniel-mar 301
  if copy(cont, 0, 7) = 'Status:' then
302
  begin
79 daniel-mar 303
    MessageDlg(SDownloadError, mtError, [mbOk], 0);
63 daniel-mar 304
  end
305
  else
306
  begin
74 daniel-mar 307
    if string(cont) <> AVersion then
63 daniel-mar 308
    begin
79 daniel-mar 309
      if MessageDlg(SNewProgramVersionAvailable, mtConfirmation, mbYesNoCancel, 0) = mrYes then
310
        shellexecute(application.handle, 'open', pchar('https://www.viathinksoft.de/update/?id=@'+ViaThinkSoftProjectName), '', '', sw_normal); // do not localize
63 daniel-mar 311
    end
312
    else
313
    begin
79 daniel-mar 314
      MessageDlg(SNoUpdateAvailable, mtInformation, [mbOk], 0);
63 daniel-mar 315
    end;
316
  end;
317
end;
318
 
2 daniel-mar 319
end.