Skip to content

Commit 18ab41b

Browse files
authored
Merge pull request #31 from maximilianmaihoefner/feature/os-detection
Feature/os detection
2 parents d9ff367 + e42afe0 commit 18ab41b

8 files changed

Lines changed: 509 additions & 177 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,3 +260,6 @@ paket-files/
260260
__pycache__/
261261
*.pyc
262262
/Patcher/Properties/launchSettings.json
263+
264+
# macOS
265+
.DS_Store

Patcher/BinarySearcher.cs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace Patcher
5+
{
6+
/// <summary>
7+
/// Original by Matthew Watson from https://stackoverflow.com/questions/37500629/find-byte-sequence-within-a-byte-array
8+
/// </summary>
9+
public sealed class BinarySearcher
10+
{
11+
readonly byte[] needle;
12+
readonly int[] charTable;
13+
readonly int[] offsetTable;
14+
15+
public BinarySearcher(byte[] needle)
16+
{
17+
this.needle = needle;
18+
this.charTable = makeByteTable(needle);
19+
this.offsetTable = makeOffsetTable(needle);
20+
}
21+
22+
public IEnumerable<int> Search(byte[] haystack)
23+
{
24+
if (needle.Length == 0)
25+
yield break;
26+
27+
for (int i = needle.Length - 1; i < haystack.Length;)
28+
{
29+
int j;
30+
31+
for (j = needle.Length - 1; needle[j] == haystack[i]; --i, --j)
32+
{
33+
if (j != 0)
34+
continue;
35+
36+
yield return i;
37+
i += needle.Length - 1;
38+
break;
39+
}
40+
41+
i += Math.Max(offsetTable[needle.Length - 1 - j], charTable[haystack[i]]);
42+
}
43+
}
44+
45+
static int[] makeByteTable(byte[] needle)
46+
{
47+
int[] table = new int[256];
48+
49+
for (int i = 0; i < table.Length; ++i)
50+
table[i] = needle.Length;
51+
52+
for (int i = 0; i < needle.Length - 1; ++i)
53+
table[needle[i]] = needle.Length - 1 - i;
54+
55+
return table;
56+
}
57+
58+
static int[] makeOffsetTable(byte[] needle)
59+
{
60+
int[] table = new int[needle.Length];
61+
int lastPrefixPosition = needle.Length;
62+
63+
for (int i = needle.Length - 1; i >= 0; --i)
64+
{
65+
if (isPrefix(needle, i + 1))
66+
lastPrefixPosition = i + 1;
67+
68+
table[needle.Length - 1 - i] = lastPrefixPosition - i + needle.Length - 1;
69+
}
70+
71+
for (int i = 0; i < needle.Length - 1; ++i)
72+
{
73+
int slen = suffixLength(needle, i);
74+
table[slen] = needle.Length - 1 - i + slen;
75+
}
76+
77+
return table;
78+
}
79+
80+
static bool isPrefix(byte[] needle, int p)
81+
{
82+
for (int i = p, j = 0; i < needle.Length; ++i, ++j)
83+
if (needle[i] != needle[j])
84+
return false;
85+
86+
return true;
87+
}
88+
89+
static int suffixLength(byte[] needle, int p)
90+
{
91+
int len = 0;
92+
93+
for (int i = p, j = needle.Length - 1; i >= 0 && needle[i] == needle[j]; --i, --j)
94+
++len;
95+
96+
return len;
97+
}
98+
}
99+
}

Patcher/ConsoleUtility.cs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace Patcher
5+
{
6+
/// <summary>
7+
/// Utility methods for interacting with the console.
8+
/// </summary>
9+
public static class ConsoleUtility
10+
{
11+
/// <summary>
12+
/// Displays a selection menu in the console to the user which can be navigated using the arrow keys and enter
13+
/// to select the desired option from the list.
14+
/// </summary>
15+
/// <param name="options">The list of options from which the user can choose</param>
16+
/// <param name="optionLine">
17+
/// A function taking one of the options an returning a string representation of how it should be displayed to the user
18+
/// </param>
19+
/// <typeparam name="T">The type of a single option</typeparam>
20+
/// <returns>The selected option from the list</returns>
21+
public static T ShowSelectionMenu<T>(List<T> options, Func<T, string> optionLine)
22+
{
23+
int selected = 0;
24+
bool done = false;
25+
26+
while (!done)
27+
{
28+
for (int i = 0; i < options.Count; i++)
29+
{
30+
if (i == selected)
31+
{
32+
Console.ForegroundColor = ConsoleColor.Cyan;
33+
Console.Write("> ");
34+
}
35+
else
36+
{
37+
Console.Write(" ");
38+
}
39+
Console.WriteLine(optionLine(options[i]));
40+
Console.ResetColor();
41+
}
42+
43+
switch (Console.ReadKey(true).Key)
44+
{
45+
case ConsoleKey.UpArrow:
46+
selected = Math.Max(0, selected - 1);
47+
break;
48+
case ConsoleKey.DownArrow:
49+
selected = Math.Min(options.Count - 1, selected + 1);
50+
break;
51+
case ConsoleKey.Spacebar:
52+
case ConsoleKey.Enter:
53+
done = true;
54+
break;
55+
}
56+
57+
if (!done)
58+
Console.CursorTop -= options.Count;
59+
}
60+
61+
return options[selected];
62+
}
63+
}
64+
}

Patcher/OperatingSystem.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace Patcher
2+
{
3+
public enum OperatingSystem
4+
{
5+
Unknown,
6+
Windows,
7+
MacOS,
8+
Linux
9+
}
10+
}

Patcher/PatchInfo.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace Patcher
2+
{
3+
public class PatchInfo
4+
{
5+
public string Version { get; set; }
6+
7+
public byte[] DarkPattern { get; set; }
8+
9+
public byte[] LightPattern { get; set; }
10+
}
11+
}

Patcher/Patches.cs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
5+
namespace Patcher
6+
{
7+
public static class Patches
8+
{
9+
private static readonly List<PatchInfo> WindowsPatches = new List<PatchInfo>
10+
{
11+
new PatchInfo
12+
{
13+
Version = "2018.2",
14+
LightPattern = new byte[] {0x75, 0x08, 0x33, 0xC0, 0x48, 0x83, 0xC4, 0x30},
15+
DarkPattern = new byte[] {0x74, 0x08, 0x33, 0xC0, 0x48, 0x83, 0xC4, 0x30}
16+
},
17+
new PatchInfo
18+
{
19+
Version = "2018.3",
20+
LightPattern = new byte[] {0x75, 0x08, 0x33, 0xC0, 0x48, 0x83, 0xC4, 0x30},
21+
DarkPattern = new byte[] {0x74, 0x08, 0x33, 0xC0, 0x48, 0x83, 0xC4, 0x30}
22+
},
23+
new PatchInfo
24+
{
25+
Version = "2018.4",
26+
LightPattern = new byte[] {0x75, 0x08, 0x33, 0xC0, 0x48, 0x83, 0xC4, 0x30},
27+
DarkPattern = new byte[] {0x74, 0x08, 0x33, 0xC0, 0x48, 0x83, 0xC4, 0x30}
28+
},
29+
new PatchInfo
30+
{
31+
Version = "2019.2",
32+
LightPattern = new byte[] {0x75, 0x15, 0x33, 0xC0, 0xEB, 0x13, 0x90, 0x49},
33+
DarkPattern = new byte[] {0x74, 0x15, 0x33, 0xC0, 0xEB, 0x13, 0x90, 0x49}
34+
},
35+
new PatchInfo
36+
{
37+
Version = "2019.3",
38+
LightPattern = new byte[] {0x75, 0x15, 0x33, 0xC0, 0xEB, 0x13, 0x90, 0x49},
39+
DarkPattern = new byte[] {0x74, 0x15, 0x33, 0xC0, 0xEB, 0x13, 0x90, 0x49}
40+
},
41+
new PatchInfo
42+
{
43+
Version = "2020.1",
44+
LightPattern = new byte[] {0x75, 0x15, 0x33, 0xC0, 0xEB, 0x13, 0x90, 0x49},
45+
DarkPattern = new byte[] {0x74, 0x15, 0x33, 0xC0, 0xEB, 0x13, 0x90, 0x49}
46+
}
47+
};
48+
49+
private static readonly List<PatchInfo> MacPatches = new List<PatchInfo>
50+
{
51+
new PatchInfo
52+
{
53+
Version = "2018.4",
54+
DarkPattern = new byte[] {0x75, 0x03, 0x41, 0x8B, 0x06, 0x4C, 0x3B},
55+
LightPattern = new byte[] {0x74, 0x03, 0x41, 0x8B, 0x06, 0x4C, 0x3B}
56+
},
57+
new PatchInfo
58+
{
59+
Version = "2019.1.0f2",
60+
DarkPattern = new byte[] {0x75, 0x03, 0x41, 0x8b, 0x06, 0x48},
61+
LightPattern = new byte[] {0x74, 0x03, 0x41, 0x8b, 0x06, 0x48}
62+
},
63+
new PatchInfo
64+
{
65+
Version = "2019.3",
66+
DarkPattern = new byte[] {0x85, 0xD5, 0x00, 0x00, 0x00, 0x8B, 0x03},
67+
LightPattern = new byte[] {0x84, 0xD5, 0x00, 0x00, 0x00, 0x8B, 0x03}
68+
},
69+
new PatchInfo
70+
{
71+
Version = "2020.1",
72+
DarkPattern = new byte[] {0x75, 0x5E, 0x8B, 0x03, 0xEB},
73+
LightPattern = new byte[] {0x74, 0x5E, 0x8B, 0x03, 0xEB}
74+
},
75+
new PatchInfo
76+
{
77+
Version = "2020.2",
78+
DarkPattern = new byte[] {0x75, 0x5E, 0x8B, 0x03, 0xEB},
79+
LightPattern = new byte[] {0x74, 0x5E, 0x8B, 0x03, 0xEB}
80+
}
81+
};
82+
83+
private static readonly List<PatchInfo> LinuxPatches = new List<PatchInfo>
84+
{
85+
new PatchInfo
86+
{
87+
Version = "2019.2.3f",
88+
DarkPattern = new byte[] {0x75, 0x02, 0x8b, 0x03, 0x48, 0x83},
89+
LightPattern = new byte[] {0x74, 0x02, 0x8b, 0x03, 0x48, 0x83}
90+
}
91+
};
92+
93+
public static List<PatchInfo> GetPatches(OperatingSystem os)
94+
{
95+
var patches = os switch
96+
{
97+
OperatingSystem.Windows => WindowsPatches,
98+
OperatingSystem.MacOS => MacPatches,
99+
OperatingSystem.Linux => LinuxPatches,
100+
_ => throw new ArgumentOutOfRangeException(nameof(os))
101+
};
102+
103+
return patches.OrderByDescending(info => info.Version).ToList();
104+
}
105+
}
106+
}

0 commit comments

Comments
 (0)