You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

92 lines
3.4 KiB

  1. using IPA.Utilities;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text;
  7. #if NET3
  8. using Net3_Proxy;
  9. using Path = Net3_Proxy.Path;
  10. using File = Net3_Proxy.File;
  11. using Directory = Net3_Proxy.Directory;
  12. #endif
  13. namespace IPA.Injector
  14. {
  15. internal static class GameVersionEarly
  16. {
  17. internal static string ResolveDataPath(string installDir) =>
  18. Directory.EnumerateDirectories(installDir, "*_Data").First();
  19. internal static string GlobalGameManagers(string installDir) =>
  20. Path.Combine(ResolveDataPath(installDir), "globalgamemanagers");
  21. internal static string GetGameVersion()
  22. {
  23. var mgr = GlobalGameManagers(UnityGame.InstallPath);
  24. using (var stream = File.OpenRead(mgr))
  25. using (var reader = new BinaryReader(stream, Encoding.UTF8))
  26. {
  27. const string key = "public.app-category.games";
  28. int pos = 0;
  29. while (stream.Position < stream.Length && pos < key.Length)
  30. {
  31. if (reader.ReadByte() == key[pos]) pos++;
  32. else pos = 0;
  33. }
  34. if (stream.Position == stream.Length) // we went through the entire stream without finding the key
  35. throw new KeyNotFoundException("Could not find key '" + key + "' in " + mgr);
  36. long startPos = 0;
  37. long length = 0;
  38. while (stream.Position < stream.Length)
  39. {
  40. char current = reader.ReadChar();
  41. if (startPos == 0 && current >= '0' && current <= '9')
  42. startPos = stream.Position - 1;
  43. else if (startPos > 0 && IllegalCharacters.Contains(current))
  44. {
  45. length = stream.Position - startPos - 1;
  46. break;
  47. }
  48. }
  49. if (startPos <= 0 || length <= 0)
  50. throw new KeyNotFoundException("Could not parse version from " + mgr);
  51. stream.Seek(startPos, SeekOrigin.Begin);
  52. var strbytes = reader.ReadBytes((int)length);
  53. return Encoding.UTF8.GetString(strbytes);
  54. }
  55. }
  56. internal static SemVer.Version SafeParseVersion() => new SemVer.Version(GetGameVersion(), true);
  57. private static void _Load()
  58. {
  59. UnityGame.SetEarlyGameVersion(SafeParseVersion());
  60. UnityGame.CheckGameVersionBoundary();
  61. }
  62. internal static void Load()
  63. {
  64. // This exists for the same reason the wierdness in Injector.Main does
  65. _ = Type.GetType("SemVer.Version, SemVer", false);
  66. _Load();
  67. }
  68. internal static readonly char[] IllegalCharacters = new char[]
  69. {
  70. '<', '>', ':', '/', '\\', '|', '?', '*', '"',
  71. '\u0000', '\u0001', '\u0002', '\u0003', '\u0004', '\u0005', '\u0006', '\u0007',
  72. '\u0008', '\u0009', '\u000a', '\u000b', '\u000c', '\u000d', '\u000e', '\u000d',
  73. '\u000f', '\u0010', '\u0011', '\u0012', '\u0013', '\u0014', '\u0015', '\u0016',
  74. '\u0017', '\u0018', '\u0019', '\u001a', '\u001b', '\u001c', '\u001d', '\u001f',
  75. };
  76. }
  77. }