Subversion Repositories spacemission

Rev

Rev 80 | Rev 89 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

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