Subversion Repositories spacemission

Rev

Rev 90 | 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.2';
  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. 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.  
  42. type
  43.   TCheat = (ctUnknown, ctInfiniteLives);
  44.   TCheatSet = set of TCheat;
  45.  
  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 = (
  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]
  78.     smgHintergrundRot,    // ImageList.Items.Item[20]
  79.     smgItemMedikit        // ImageList.Items.Item[21]
  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]
  89.     smsItemCollected  // WaveList.Items.Item[4]
  90.   );
  91.  
  92. function OwnDirectory: string;
  93.  
  94. const
  95.   FOLDERID_SavedGames: TGuid = '{4C5C32FF-BB9D-43b0-B5B4-2D72E54EAAA4}'; // do not localize
  96.  
  97. // Useful functions
  98. procedure SpaceMission_SwitchLanguage;
  99. function GetKnownFolderPath(const rfid: TGUID): string;
  100. function KillTask(ExeFileName: string): Integer;
  101. procedure CheckForUpdates(ViaThinkSoftProjectName: string; AVersion: string);
  102.  
  103. implementation
  104.  
  105. uses
  106.   Windows, SysUtils, Dialogs, ActiveX, ShlObj, TlHelp32, wininet, Forms, ShellAPI,
  107.   System.UITypes;
  108.  
  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.  
  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.  
  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.  
  190. function OwnDirectory: string;
  191. begin
  192.   result := extractfilepath(paramstr(0));
  193. end;
  194.  
  195. // https://www.delphipraxis.net/post43515.html , fixed , works for Delphi 12 Athens
  196. function GetHTML(AUrl: string): RawByteString;
  197. var
  198.   databuffer : array[0..4095] of ansichar; // SIC! ansichar!
  199.   ResStr : ansistring; // SIC! ansistring
  200.   hSession, hfile: hInternet;
  201.   dwindex,dwcodelen,dwread,dwNumber: cardinal;
  202.   dwcode : array[1..20] of char;
  203.   res    : pchar;
  204.   Str    : pansichar; // SIC! pansichar
  205. begin
  206.   ResStr:='';
  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
  210.  
  211.   // Hinzugefügt
  212.   if Assigned(Application) then Application.ProcessMessages;
  213.  
  214.   hSession:=InternetOpen('InetURL:/1.0', // do not localize
  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;
  244.     if (res ='200') or (res = '302') then // do not localize
  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;
  258.         Str := pansichar(@databuffer);
  259.         resStr := resStr + Str;
  260.       end;
  261.     end
  262.     else
  263.       ResStr := 'Status:'+AnsiString(res); // do not localize
  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.  
  275. procedure CheckForUpdates(ViaThinkSoftProjectName: string; AVersion: string);
  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.';
  280. var
  281.   cont: RawByteString;
  282. begin
  283.   cont := GetHTML('https://www.viathinksoft.de/update/?id='+ViaThinkSoftProjectName); // do not localize
  284.   if copy(cont, 0, 7) = 'Status:' then
  285.   begin
  286.     MessageDlg(SDownloadError, mtError, [mbOk], 0);
  287.   end
  288.   else
  289.   begin
  290.     if string(cont) <> AVersion then
  291.     begin
  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
  294.     end
  295.     else
  296.     begin
  297.       MessageDlg(SNoUpdateAvailable, mtInformation, [mbOk], 0);
  298.     end;
  299.   end;
  300. end;
  301.  
  302. end.
  303.