├── .gitignore
├── 7z.dll
├── 7z.exe
├── ADB.cs
├── Ad.7z
├── AndroidSideloader.csproj
├── AndroidSideloader.sln
├── App.config
├── ChangelogHistory.txt
├── ColumnSort.cs
├── Donors.cs
├── DonorsListView.Designer.cs
├── DonorsListView.cs
├── DonorsListView.resx
├── FlexibleMessageBox.cs
├── LICENSE
├── MainForm.Designer.cs
├── MainForm.cs
├── MainForm.resx
├── Models
└── PublicConfig.cs
├── NewApps.Designer.cs
├── NewApps.cs
├── NewApps.resx
├── Program.cs
├── Properties
├── AssemblyInfo.cs
├── DataSources
│ ├── AndroidSideloader.Properties.Resources.datasource
│ └── AndroidSideloader.Properties.Settings.datasource
├── Resources.Designer.cs
├── Resources.resx
├── Settings.Designer.cs
└── Settings.settings
├── QuestForm.Designer.cs
├── QuestForm.cs
├── QuestForm.resx
├── RCLONE.cs
├── README.md
├── Resources
├── Pattern.png
├── SearchGlass.PNG
├── ajax-loader.gif
├── battery.png
├── battery1.png
├── battery11.png
├── nouns.txt
├── pattern_cubes-1_1_1_0-0_0_1__000000_212121.png
├── pattern_herringbone-2_1_3_0-0_90_1__000000_1c1c1c.png
├── splash.jpg
└── splashimage.png
├── Rookie Offline.cmd
├── RoundButton.cs
├── RoundedRectangleF.cs
├── SelectFolder.cs
├── SergeUtils.dll
├── SettingsForm.Designer.cs
├── SettingsForm.cs
├── SettingsForm.resx
├── Sideloader Launcher.exe
├── Sideloader.cs
├── Sideloader
├── ProcessOutput.cs
├── RCLONE.cs
└── Utilities.cs
├── Splash.Designer.cs
├── Splash.cs
├── Splash.resx
├── Transparenter.cs
├── UpdateForm.Designer.cs
├── UpdateForm.cs
├── UpdateForm.resx
├── Updater.cs
├── UsernameForm.Designer.cs
├── UsernameForm.cs
├── UsernameForm.resx
├── Utilities
├── GeneralUtilities.cs
├── Logger.cs
├── StringUtilities.cs
├── UpdateGameData.cs
├── UploadGame.cs
└── Zip.cs
├── aapt.exe
├── adb.7z
├── adb2.zip
├── androidsideloader.7z
├── changelog.txt
├── debuglog.txt
├── donators.txt
├── icon.ico
├── packages.config
├── version
└── warning.png
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pdb
2 | *.xml
3 | *.xsd
4 | AndroidSideloader.csproj.user
5 |
6 | .vs/
7 | bin/
8 | packages/
--------------------------------------------------------------------------------
/7z.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdunit/androidsideloader/f11d282c8bcb8f7b9c005a26995a6d4952d05276/7z.dll
--------------------------------------------------------------------------------
/7z.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdunit/androidsideloader/f11d282c8bcb8f7b9c005a26995a6d4952d05276/7z.exe
--------------------------------------------------------------------------------
/ADB.cs:
--------------------------------------------------------------------------------
1 | using JR.Utils.GUI.Forms;
2 | using System;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Windows.Forms;
6 |
7 | namespace AndroidSideloader
8 | {
9 | internal class ADB
10 | {
11 | private static readonly Process adb = new Process();
12 | public static string adbFolderPath = $"{Path.GetPathRoot(Environment.SystemDirectory)}RSL\\platform-tools";
13 | public static string adbFilePath = adbFolderPath + "\\adb.exe";
14 | public static string DeviceID = "";
15 | public static string package = "";
16 | public static ProcessOutput RunAdbCommandToString(string command)
17 | {
18 | Properties.Settings.Default.ADBFolder = adbFolderPath;
19 | Properties.Settings.Default.ADBPath = adbFilePath;
20 | Properties.Settings.Default.Save();
21 | if (DeviceID.Length > 1)
22 | {
23 | command = $" -s {DeviceID} {command}";
24 | }
25 | if (!command.Contains("dumpsys") && !command.Contains("shell pm list packages") && !command.Contains("KEYCODE_WAKEUP"))
26 | {
27 | string logcmd = command;
28 |
29 | if (logcmd.Contains(Environment.CurrentDirectory))
30 | {
31 | logcmd = logcmd.Replace($"{Environment.CurrentDirectory}", $"CurrentDirectory");
32 | }
33 |
34 | _ = Logger.Log($"Running command: {logcmd}");
35 | }
36 |
37 | using (Process adb = new Process())
38 | {
39 | adb.StartInfo.FileName = adbFilePath;
40 | adb.StartInfo.Arguments = command;
41 | adb.StartInfo.RedirectStandardError = true;
42 | adb.StartInfo.RedirectStandardOutput = true;
43 | adb.StartInfo.CreateNoWindow = true;
44 | adb.StartInfo.UseShellExecute = false;
45 | adb.StartInfo.WorkingDirectory = adbFolderPath;
46 | _ = adb.Start();
47 |
48 | string output = "";
49 | string error = "";
50 |
51 | try
52 | {
53 | output = adb.StandardOutput.ReadToEnd();
54 | error = adb.StandardError.ReadToEnd();
55 | }
56 | catch { }
57 |
58 | if (command.Contains("connect"))
59 | {
60 | bool graceful = adb.WaitForExit(3000);
61 | if (!graceful)
62 | {
63 | adb.Kill();
64 | adb.WaitForExit();
65 | }
66 | }
67 |
68 | if (error.Contains("ADB_VENDOR_KEYS") && !Properties.Settings.Default.adbdebugwarned)
69 | {
70 | ADBDebugWarning();
71 | }
72 | if (error.Contains("not enough storage space"))
73 | {
74 | _ = FlexibleMessageBox.Show(Program.form, "There is not enough room on your device to install this package. Please clear AT LEAST 2x the amount of the app you are trying to install.");
75 | }
76 | if (!output.Contains("version") && !output.Contains("KEYCODE_WAKEUP") && !output.Contains("Filesystem") && !output.Contains("package:") && !output.Equals(null))
77 | {
78 | _ = Logger.Log(output);
79 | }
80 |
81 | _ = Logger.Log(error, LogLevel.ERROR);
82 | return new ProcessOutput(output, error);
83 | }
84 | }
85 |
86 | public static ProcessOutput RunAdbCommandToStringWOADB(string result, string path)
87 | {
88 | string command = result;
89 | string logcmd = command;
90 | if (logcmd.Contains(Environment.CurrentDirectory))
91 | {
92 | logcmd = logcmd.Replace($"{Environment.CurrentDirectory}", $"CurrentDirectory");
93 | }
94 |
95 | _ = Logger.Log($"Running command: {logcmd}");
96 |
97 | adb.StartInfo.FileName = "cmd.exe";
98 | adb.StartInfo.RedirectStandardError = true;
99 | adb.StartInfo.RedirectStandardInput = true;
100 | adb.StartInfo.RedirectStandardOutput = true;
101 | adb.StartInfo.CreateNoWindow = true;
102 | adb.StartInfo.UseShellExecute = false;
103 | adb.StartInfo.WorkingDirectory = Path.GetDirectoryName(path);
104 | _ = adb.Start();
105 | adb.StandardInput.WriteLine(command);
106 | adb.StandardInput.Flush();
107 | adb.StandardInput.Close();
108 |
109 |
110 | string output = "";
111 | string error = "";
112 |
113 | try
114 | {
115 | output += adb.StandardOutput.ReadToEnd();
116 | error += adb.StandardError.ReadToEnd();
117 | }
118 | catch { }
119 | if (command.Contains("connect"))
120 | {
121 | bool graceful = adb.WaitForExit(3000);
122 | if (!graceful)
123 | {
124 | adb.Kill();
125 | adb.WaitForExit();
126 | }
127 | }
128 | else if (command.Contains("connect"))
129 | {
130 | bool graceful = adb.WaitForExit(3000);
131 | if (!graceful)
132 | {
133 | adb.Kill();
134 | adb.WaitForExit();
135 | }
136 | }
137 | if (error.Contains("ADB_VENDOR_KEYS") && Properties.Settings.Default.adbdebugwarned)
138 | {
139 | ADBDebugWarning();
140 | }
141 | _ = Logger.Log(output);
142 | _ = Logger.Log(error, LogLevel.ERROR);
143 | return new ProcessOutput(output, error);
144 | }
145 | public static ProcessOutput RunCommandToString(string result, string path = "")
146 | {
147 | string command = result;
148 | string logcmd = command;
149 | if (logcmd.Contains(Environment.CurrentDirectory))
150 | {
151 | logcmd = logcmd.Replace($"{Environment.CurrentDirectory}", $"CurrentDirectory");
152 | }
153 |
154 | _ = Logger.Log($"Running command: {logcmd}");
155 | adb.StartInfo.FileName = $@"{Path.GetPathRoot(Environment.SystemDirectory)}\Windows\System32\cmd.exe";
156 | adb.StartInfo.Arguments = command;
157 | adb.StartInfo.RedirectStandardError = true;
158 | adb.StartInfo.RedirectStandardInput = true;
159 | adb.StartInfo.RedirectStandardOutput = true;
160 | adb.StartInfo.CreateNoWindow = true;
161 | adb.StartInfo.UseShellExecute = false;
162 | adb.StartInfo.WorkingDirectory = Path.GetDirectoryName(path);
163 | _ = adb.Start();
164 | adb.StandardInput.WriteLine(command);
165 | adb.StandardInput.Flush();
166 | adb.StandardInput.Close();
167 |
168 |
169 | string output = "";
170 | string error = "";
171 |
172 | try
173 | {
174 | output += adb.StandardOutput.ReadToEnd();
175 | error += adb.StandardError.ReadToEnd();
176 | }
177 | catch { }
178 | if (command.Contains("connect"))
179 | {
180 | bool graceful = adb.WaitForExit(3000);
181 | if (!graceful)
182 | {
183 | adb.Kill();
184 | adb.WaitForExit();
185 | }
186 | }
187 |
188 | if (error.Contains("ADB_VENDOR_KEYS") && Properties.Settings.Default.adbdebugwarned)
189 | {
190 | ADBDebugWarning();
191 | }
192 | _ = Logger.Log(output);
193 | _ = Logger.Log(error, LogLevel.ERROR);
194 | return new ProcessOutput(output, error);
195 | }
196 |
197 | public static void ADBDebugWarning()
198 | {
199 | DialogResult dialogResult = FlexibleMessageBox.Show(Program.form, "Please check inside your headset for ADB DEBUGGING prompt, check box to \"Always allow from this computer.\" and hit OK.\nPlease note that even if you have done this\nbefore it will reset itself from time to time.\n\nPress CANCEL if you want to disable this prompt (FOR DEBUGGING ONLY, NOT RECOMMENDED).", "ADB Debugging not enabled.", MessageBoxButtons.OKCancel);
200 | if (dialogResult == DialogResult.Cancel)
201 | {
202 | Properties.Settings.Default.adbdebugwarned = true;
203 | Properties.Settings.Default.Save();
204 | }
205 | }
206 |
207 | public static ProcessOutput UninstallPackage(string package)
208 | {
209 | ProcessOutput output = new ProcessOutput("", "");
210 | output += RunAdbCommandToString($"shell pm uninstall {package}");
211 | return output;
212 | }
213 |
214 | public static string GetAvailableSpace()
215 | {
216 | long totalSize = 0;
217 | long usedSize = 0;
218 | long freeSize = 0;
219 |
220 | string[] output = RunAdbCommandToString("shell df").Output.Split('\n');
221 |
222 | foreach (string currLine in output)
223 | {
224 | if (currLine.StartsWith("/dev/fuse") || currLine.StartsWith("/data/media"))
225 | {
226 | string[] foo = currLine.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
227 | if (foo.Length >= 4)
228 | {
229 | totalSize = long.Parse(foo[1]) / 1000;
230 | usedSize = long.Parse(foo[2]) / 1000;
231 | freeSize = long.Parse(foo[3]) / 1000;
232 | break; // Assuming we only need the first matching line
233 | }
234 | }
235 | }
236 |
237 | return $"Total space: {string.Format("{0:0.00}", (double)totalSize / 1000)}GB\nUsed space: {string.Format("{0:0.00}", (double)usedSize / 1000)}GB\nFree space: {string.Format("{0:0.00}", (double)freeSize / 1000)}GB";
238 | }
239 |
240 | public static bool wirelessadbON;
241 | public static ProcessOutput Sideload(string path, string packagename = "")
242 | {
243 |
244 | ProcessOutput ret = new ProcessOutput();
245 | ret += RunAdbCommandToString($"install -g \"{path}\"");
246 | string out2 = ret.Output + ret.Error;
247 | if (out2.Contains("failed"))
248 | {
249 | _ = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), $"Rookie Backups");
250 | _ = Logger.Log(out2);
251 | if (out2.Contains("offline") && !Properties.Settings.Default.nodevicemode)
252 | {
253 | DialogResult dialogResult2 = FlexibleMessageBox.Show(Program.form, "Device is offline. Press Yes to reconnect, or if you don't wish to connect and just want to download the game (requires unchecking \"Delete games after install\" from settings menu) then press No.", "Device offline.", MessageBoxButtons.YesNoCancel);
254 | }
255 | if (out2.Contains($"signatures do not match previously") || out2.Contains("INSTALL_FAILED_VERSION_DOWNGRADE") || out2.Contains("signatures do not match") || out2.Contains("failed to install"))
256 | {
257 | ret.Error = string.Empty;
258 | ret.Output = string.Empty;
259 | if (!Properties.Settings.Default.AutoReinstall)
260 | {
261 | bool cancelClicked = false;
262 |
263 | if (!Properties.Settings.Default.AutoReinstall)
264 | {
265 | Program.form.Invoke((MethodInvoker)(() =>
266 | {
267 | DialogResult dialogResult1 = FlexibleMessageBox.Show(Program.form, "In place upgrade has failed. Rookie can attempt to backup your save data and reinstall the game automatically, however some games do not store their saves in an accessible location (less than 5%). Continue with reinstall?", "In place upgrade failed.", MessageBoxButtons.OKCancel);
268 | if (dialogResult1 == DialogResult.Cancel)
269 | cancelClicked = true;
270 | }));
271 | }
272 |
273 | if (cancelClicked)
274 | return ret;
275 | }
276 |
277 | Program.form.changeTitle("Performing reinstall, please wait...");
278 | _ = ADB.RunAdbCommandToString("kill-server");
279 | _ = ADB.RunAdbCommandToString("devices");
280 | _ = ADB.RunAdbCommandToString($"pull /sdcard/Android/data/{MainForm.CurrPCKG} \"{Environment.CurrentDirectory}\"");
281 | Program.form.changeTitle("Uninstalling game...");
282 | _ = Sideloader.UninstallGame(MainForm.CurrPCKG);
283 | Program.form.changeTitle("Reinstalling Game");
284 | ret += ADB.RunAdbCommandToString($"install -g \"{path}\"");
285 | _ = ADB.RunAdbCommandToString($"push \"{Environment.CurrentDirectory}\\{MainForm.CurrPCKG}\" /sdcard/Android/data/");
286 | if (Directory.Exists($"{Environment.CurrentDirectory}\\{MainForm.CurrPCKG}"))
287 | {
288 | Directory.Delete($"{Environment.CurrentDirectory}\\{MainForm.CurrPCKG}", true);
289 | }
290 |
291 | Program.form.changeTitle(" \n\n");
292 | return ret;
293 | }
294 | }
295 | string gamenameforQU = Sideloader.PackageNametoGameName(packagename);
296 | if (Properties.Settings.Default.QUturnedon)
297 | {
298 | if (gamenameforQU.Contains("-QU") || path.Contains("-QU"))
299 | {
300 | string gameName = packagename;
301 | packagename = Sideloader.gameNameToPackageName(gameName);
302 |
303 | Program.form.changeTitle("Pushing Custom QU S3 Config.JSON.");
304 | if (!Directory.Exists($"/sdcard/android/data/{packagename}"))
305 | {
306 | _ = RunAdbCommandToString($"shell mkdir /sdcard/android/data/{packagename}");
307 | }
308 |
309 | if (!Directory.Exists($"/sdcard/android/data/{packagename}/private"))
310 | {
311 | _ = RunAdbCommandToString($"shell mkdir /sdcard/android/data/{packagename}/private");
312 | }
313 |
314 | Random r = new Random();
315 | int x = r.Next(999999999);
316 | int y = r.Next(9999999);
317 |
318 | long sum = (y * (long)1000000000) + x;
319 |
320 | int x2 = r.Next(999999999);
321 | int y2 = r.Next(9999999);
322 |
323 | long sum2 = (y2 * (long)1000000000) + x2;
324 | Properties.Settings.Default.QUStringF = $"{{\"user_id\":{sum},\"app_id\":\"{sum2}\",";
325 | Properties.Settings.Default.Save();
326 | string boff = Properties.Settings.Default.QUStringF + Properties.Settings.Default.QUString;
327 | File.WriteAllText($"{Properties.Settings.Default.MainDir}\\config.json", boff);
328 | string blank = "";
329 | File.WriteAllText($"{Properties.Settings.Default.MainDir}\\delete_settings", blank);
330 | ret += ADB.RunAdbCommandToString($"push \"{Properties.Settings.Default.MainDir}\\delete_settings\" /sdcard/android/data/{packagename}/private/delete_settings");
331 | ret += ADB.RunAdbCommandToString($"push \"{Properties.Settings.Default.MainDir}\\config.json\" /sdcard/android/data/{packagename}/private/config.json");
332 | }
333 | }
334 |
335 |
336 | Program.form.changeTitle(string.Empty);
337 | return ret;
338 | }
339 |
340 | public static ProcessOutput CopyOBB(string path)
341 | {
342 | string folder = Path.GetFileName(path);
343 | return !folder.Contains("+") && !folder.Contains("_") && folder.Contains(".")
344 | ? RunAdbCommandToString($"push \"{path}\" \"/sdcard/Android/obb\"")
345 | : new ProcessOutput();
346 | }
347 | }
348 | }
349 |
--------------------------------------------------------------------------------
/Ad.7z:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdunit/androidsideloader/f11d282c8bcb8f7b9c005a26995a6d4952d05276/Ad.7z
--------------------------------------------------------------------------------
/AndroidSideloader.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30011.22
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AndroidSideloader", "AndroidSideloader.csproj", "{CC8BE9F0-CE07-406A-A378-81D9CFE4CC1D}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9E3C926E-5E5F-4F97-AC52-060B14DDB055}"
9 | ProjectSection(SolutionItems) = preProject
10 | .editorconfig = .editorconfig
11 | EndProjectSection
12 | EndProject
13 | Global
14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
15 | Debug|Any CPU = Debug|Any CPU
16 | Debug|x64 = Debug|x64
17 | Debug|x86 = Debug|x86
18 | Release|Any CPU = Release|Any CPU
19 | Release|x64 = Release|x64
20 | Release|x86 = Release|x86
21 | x86|Any CPU = x86|Any CPU
22 | x86|x64 = x86|x64
23 | x86|x86 = x86|x86
24 | EndGlobalSection
25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
26 | {CC8BE9F0-CE07-406A-A378-81D9CFE4CC1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {CC8BE9F0-CE07-406A-A378-81D9CFE4CC1D}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {CC8BE9F0-CE07-406A-A378-81D9CFE4CC1D}.Debug|x64.ActiveCfg = Debug|x64
29 | {CC8BE9F0-CE07-406A-A378-81D9CFE4CC1D}.Debug|x64.Build.0 = Debug|x64
30 | {CC8BE9F0-CE07-406A-A378-81D9CFE4CC1D}.Debug|x86.ActiveCfg = Debug|x86
31 | {CC8BE9F0-CE07-406A-A378-81D9CFE4CC1D}.Debug|x86.Build.0 = Debug|x86
32 | {CC8BE9F0-CE07-406A-A378-81D9CFE4CC1D}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {CC8BE9F0-CE07-406A-A378-81D9CFE4CC1D}.Release|Any CPU.Build.0 = Release|Any CPU
34 | {CC8BE9F0-CE07-406A-A378-81D9CFE4CC1D}.Release|x64.ActiveCfg = Release|x64
35 | {CC8BE9F0-CE07-406A-A378-81D9CFE4CC1D}.Release|x64.Build.0 = Release|x64
36 | {CC8BE9F0-CE07-406A-A378-81D9CFE4CC1D}.Release|x86.ActiveCfg = Release|x86
37 | {CC8BE9F0-CE07-406A-A378-81D9CFE4CC1D}.Release|x86.Build.0 = Release|x86
38 | {CC8BE9F0-CE07-406A-A378-81D9CFE4CC1D}.x86|Any CPU.ActiveCfg = x86|Any CPU
39 | {CC8BE9F0-CE07-406A-A378-81D9CFE4CC1D}.x86|Any CPU.Build.0 = x86|Any CPU
40 | {CC8BE9F0-CE07-406A-A378-81D9CFE4CC1D}.x86|x64.ActiveCfg = x86|x64
41 | {CC8BE9F0-CE07-406A-A378-81D9CFE4CC1D}.x86|x64.Build.0 = x86|x64
42 | {CC8BE9F0-CE07-406A-A378-81D9CFE4CC1D}.x86|x86.ActiveCfg = Release|x86
43 | {CC8BE9F0-CE07-406A-A378-81D9CFE4CC1D}.x86|x86.Build.0 = Release|x86
44 | EndGlobalSection
45 | GlobalSection(SolutionProperties) = preSolution
46 | HideSolutionNode = FALSE
47 | EndGlobalSection
48 | GlobalSection(ExtensibilityGlobals) = postSolution
49 | SolutionGuid = {8551213F-4001-4E03-8E46-DE0040162EBA}
50 | EndGlobalSection
51 | EndGlobal
52 |
--------------------------------------------------------------------------------
/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | True
16 |
17 |
18 | True
19 |
20 |
21 | True
22 |
23 |
24 | True
25 |
26 |
27 | True
28 |
29 |
30 | False
31 |
32 |
33 | True
34 |
35 |
36 | Microsoft Sans Serif, 11.25pt
37 |
38 |
39 |
40 |
41 |
42 | False
43 |
44 |
45 | Microsoft Sans Serif, 14pt
46 |
47 |
48 | False
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | False
61 |
62 |
63 |
64 |
65 |
66 | 0
67 |
68 |
69 | 0
70 |
71 |
72 | 0
73 |
74 |
75 | 0
76 |
77 |
78 | Change Me
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | False
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | False
100 |
101 |
102 |
103 |
104 |
105 | False
106 |
107 |
108 | False
109 |
110 |
111 | False
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 | False
127 |
128 |
129 | False
130 |
131 |
132 | False
133 |
134 |
135 | True
136 |
137 |
138 |
139 |
140 |
141 | False
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 | False
151 |
152 |
153 |
154 |
155 |
156 | 04/20/1969 16:20:00
157 |
158 |
159 |
160 |
161 |
162 | False
163 |
164 |
165 | 04/20/1969 16:20:00
166 |
167 |
168 | False
169 |
170 |
171 | White
172 |
173 |
174 | 25, 25, 25
175 |
176 |
177 | 25, 25, 25
178 |
179 |
180 | 25, 25, 25
181 |
182 |
183 | Black
184 |
185 |
186 | 1, 1, 1
187 |
188 |
189 |
190 |
191 |
192 | False
193 |
194 |
195 |
196 |
197 |
198 | False
199 |
200 |
201 | False
202 |
203 |
204 |
205 |
206 |
207 | False
208 |
209 |
210 | False
211 |
212 |
213 |
214 |
215 | True
216 |
217 |
218 | True
219 |
220 |
221 | False
222 |
223 |
224 | True
225 |
226 |
227 | True
228 |
229 |
230 | True
231 |
232 |
233 | True
234 |
235 |
236 | True
237 |
238 |
239 | 45, 45, 45
240 |
241 |
242 | ActiveCaptionText
243 |
244 |
245 | ActiveCaptionText
246 |
247 |
248 | 64, 64, 64
249 |
250 |
251 | 45, 45, 45
252 |
253 |
254 | 45, 45, 45
255 |
256 |
257 | White
258 |
259 |
260 | Microsoft Sans Serif, 11.25pt
261 |
262 |
263 |
264 |
265 |
266 | False
267 |
268 |
269 |
270 |
271 |
--------------------------------------------------------------------------------
/ColumnSort.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Windows.Forms;
3 |
4 | ///
5 | /// This class is an implementation of the 'IComparer' interface.
6 | ///
7 | public class ListViewColumnSorter : IComparer
8 | {
9 |
10 | ///
11 | /// Case insensitive comparer object
12 | ///
13 | private readonly CaseInsensitiveComparer ObjectCompare;
14 |
15 | ///
16 | /// Class constructor. Initializes various elements
17 | ///
18 | public ListViewColumnSorter()
19 | {
20 | // Initialize the column to '0'
21 | SortColumn = 0;
22 |
23 | // Initialize the sort order to 'none'
24 | Order = SortOrder.Ascending;
25 |
26 | // Initialize the CaseInsensitiveComparer object
27 | ObjectCompare = new CaseInsensitiveComparer();
28 | }
29 |
30 | ///
31 | /// This method is inherited from the IComparer interface. It compares the two objects passed using a case insensitive comparison.
32 | ///
33 | /// First object to be compared
34 | /// Second object to be compared
35 | /// The result of the comparison. "0" if equal, negative if 'x' is less than 'y' and positive if 'x' is greater than 'y'
36 | public int Compare(object x, object y)
37 | {
38 | int compareResult;
39 | ListViewItem listviewX, listviewY;
40 |
41 | // Cast the objects to be compared to ListViewItem objects
42 | listviewX = (ListViewItem)x;
43 | listviewY = (ListViewItem)y;
44 | if (SortColumn == 5)
45 | {
46 | try
47 | {
48 | int yNum = int.Parse(cleanNumber(listviewY.SubItems[SortColumn].Text));
49 | int xNum = int.Parse(cleanNumber(listviewX.SubItems[SortColumn].Text));
50 | return xNum == yNum ? 0 : xNum > yNum && Order == SortOrder.Ascending ? -1 : 1;
51 | }
52 | catch { }
53 | }
54 |
55 | // Compare the two items
56 | compareResult = ObjectCompare.Compare(listviewX.SubItems[SortColumn].Text, listviewY.SubItems[SortColumn].Text);
57 |
58 | // Calculate correct return value based on object comparison
59 | if (Order == SortOrder.Ascending)
60 | {
61 | // Ascending sort is selected, return normal result of compare operation
62 | return compareResult;
63 | }
64 | else if (Order == SortOrder.Descending)
65 | {
66 | // Descending sort is selected, return negative result of compare operation
67 | return -compareResult;
68 | }
69 | else
70 | {
71 | // Return '0' to indicate they are equal
72 | return 0;
73 | }
74 | }
75 |
76 | ///
77 | /// Gets or sets the number of the column to which to apply the sorting operation (Defaults to '0').
78 | ///
79 | public int SortColumn { set; get; }
80 |
81 | ///
82 | /// Gets or sets the order of sorting to apply (for example, 'Ascending' or 'Descending').
83 | ///
84 | public SortOrder Order { set; get; }
85 |
86 | private string cleanNumber(string number)
87 | {
88 | return number.Substring(0);
89 | }
90 |
91 | }
--------------------------------------------------------------------------------
/Donors.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace AndroidSideloader
4 | {
5 | internal class Donors
6 | {
7 | public static int GameNameIndex = 0;
8 | public static int PackageNameIndex = 1;
9 | public static int VersionCodeIndex = 2;
10 | public static int UpdateOrNew = 3;
11 | /* Game Name
12 | * Package Name
13 | * Version Code
14 | * Update or New app
15 | */
16 | public static List newAppProperties = new List();
17 | public static List donorGameProperties = new List();
18 |
19 | public static List donorGames = new List();
20 | public static List newApps = new List();
21 | public static void initDonorGames()
22 | {
23 | donorGameProperties.Clear();
24 | donorGames.Clear();
25 | if (!string.IsNullOrEmpty(MainForm.donorApps))
26 | {
27 | string[] gameListSplited = MainForm.donorApps.Split('\n');
28 | foreach (string game in gameListSplited)
29 | {
30 | if (game.Length > 1)
31 | {
32 | donorGames.Add(game.Split(';'));
33 | }
34 | }
35 | }
36 | }
37 |
38 | public static void initNewApps()
39 | {
40 | newApps.Clear();
41 | if (!string.IsNullOrEmpty(DonorsListViewForm.newAppsForList))
42 | {
43 | string[] newListSplited = DonorsListViewForm.newAppsForList.Split('\n');
44 | foreach (string game in newListSplited)
45 | {
46 | if (game.Length > 1)
47 | {
48 | newApps.Add(game.Split(';'));
49 | }
50 | }
51 | }
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/DonorsListView.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Windows.Forms;
5 |
6 | namespace AndroidSideloader
7 | {
8 | public partial class DonorsListViewForm : Form
9 | {
10 |
11 | private bool mouseDown;
12 | private Point lastLocation;
13 |
14 | public DonorsListViewForm()
15 | {
16 | InitializeComponent();
17 | Donors.initDonorGames();
18 | List DGameList = new List();
19 | foreach (string[] release in Donors.donorGames)
20 | {
21 | ListViewItem DGame = new ListViewItem(release);
22 | DGameList.Add(DGame);
23 | }
24 | ListViewItem[] arr = DGameList.ToArray();
25 | DonorsListView.BeginUpdate();
26 | DonorsListView.Items.Clear();
27 | DonorsListView.Items.AddRange(arr);
28 | DonorsListView.EndUpdate();
29 | }
30 |
31 | public static string DonorsLocal = MainForm.donorApps;
32 | public static bool ifuploads = false;
33 | public static string newAppsForList = "";
34 |
35 |
36 | private void DonorsListViewForm_Load(object sender, EventArgs e)
37 | {
38 | MainForm.updatesNotified = true;
39 | if (MainForm.updates && MainForm.newapps)
40 | {
41 | bothdet.Visible = true;
42 | }
43 | else if (MainForm.updates && !MainForm.newapps)
44 | {
45 | upddet.Visible = true;
46 | }
47 | else
48 | {
49 | newdet.Visible = true;
50 | }
51 |
52 | foreach (ListViewItem listItem in DonorsListView.Items)
53 | {
54 | if (listItem.SubItems[Donors.UpdateOrNew].Text.Contains("Update"))
55 | {
56 | listItem.BackColor = Color.FromArgb(0, 79, 97);
57 | }
58 | }
59 |
60 | }
61 |
62 | private async void DonateButton_Click(object sender, EventArgs e)
63 | {
64 | if (DonorsListView.CheckedItems.Count > 0)
65 | {
66 | bool uncheckednewapps = false;
67 | foreach (ListViewItem listItem in DonorsListView.Items)
68 | {
69 | if (!listItem.Checked)
70 | {
71 | if (listItem.SubItems[Donors.UpdateOrNew].Text.Contains("New"))
72 | {
73 | uncheckednewapps = true;
74 | newAppsForList += listItem.SubItems[Donors.GameNameIndex].Text + ";" + listItem.SubItems[Donors.PackageNameIndex].Text + "\n";
75 | }
76 | }
77 | }
78 | if (uncheckednewapps)
79 | {
80 |
81 | NewApps NewAppForm = new NewApps();
82 | _ = NewAppForm.ShowDialog();
83 | Hide();
84 | }
85 | else
86 | {
87 | Hide();
88 | }
89 | int count = DonorsListView.CheckedItems.Count;
90 | _ = new string[count];
91 | for (int i = 0; i < count; i++)
92 | {
93 | ulong vcode = Convert.ToUInt64(DonorsListView.CheckedItems[i].SubItems[Donors.VersionCodeIndex].Text);
94 | if (DonorsListView.CheckedItems[i].SubItems[Donors.UpdateOrNew].Text.Contains("Update"))
95 | {
96 | await Program.form.extractAndPrepareGameToUploadAsync(DonorsListView.CheckedItems[i].SubItems[Donors.GameNameIndex].Text, DonorsListView.CheckedItems[i].SubItems[Donors.PackageNameIndex].Text, vcode, true);
97 | }
98 | else
99 | {
100 | await Program.form.extractAndPrepareGameToUploadAsync(DonorsListView.CheckedItems[i].SubItems[Donors.GameNameIndex].Text, DonorsListView.CheckedItems[i].SubItems[Donors.PackageNameIndex].Text, vcode, false);
101 | }
102 |
103 | ifuploads = true;
104 | }
105 | }
106 |
107 | if (ifuploads)
108 | {
109 | MainForm.doUpload();
110 | }
111 | Close();
112 | }
113 |
114 | private void DonorsListView_ItemChecked(object sender, ItemCheckedEventArgs e)
115 | {
116 | SkipButton.Enabled = DonorsListView.CheckedItems.Count == 0;
117 | DonateButton.Enabled = !SkipButton.Enabled;
118 | }
119 |
120 | private void SkipButton_Click(object sender, EventArgs e)
121 | {
122 | bool uncheckednewapps = false;
123 | foreach (ListViewItem listItem in DonorsListView.Items)
124 | {
125 | if (!listItem.Checked)
126 | {
127 | if (listItem.SubItems[Donors.UpdateOrNew].Text.Contains("New"))
128 | {
129 | uncheckednewapps = true;
130 | newAppsForList += listItem.SubItems[Donors.GameNameIndex].Text + ";" + listItem.SubItems[Donors.PackageNameIndex].Text + "\n";
131 | }
132 | }
133 | }
134 | if (uncheckednewapps)
135 | {
136 | NewApps NewAppForm = new NewApps();
137 | _ = NewAppForm.ShowDialog();
138 | }
139 | Close();
140 | }
141 |
142 | private void DonorsListViewForm_MouseDown(object sender, MouseEventArgs e)
143 | {
144 | mouseDown = true;
145 | lastLocation = e.Location;
146 | }
147 |
148 | private void DonorsListViewForm_MouseMove(object sender, MouseEventArgs e)
149 | {
150 | if (mouseDown)
151 | {
152 | Location = new Point(
153 | Location.X - lastLocation.X + e.X, Location.Y - lastLocation.Y + e.Y);
154 | Update();
155 | }
156 | }
157 |
158 | private void DonorsListViewForm_MouseUp(object sender, MouseEventArgs e)
159 | {
160 | mouseDown = false;
161 | }
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/MainForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 219, 17
122 |
123 |
124 | 178, 56
125 |
126 |
127 | 514, 95
128 |
129 |
130 | 17, 17
131 |
132 |
133 | 197, 95
134 |
135 |
136 | 17, 95
137 |
138 |
139 | 1454, 56
140 |
141 |
142 | 1284, 56
143 |
144 |
145 | 1113, 56
146 |
147 |
148 | 913, 56
149 |
150 |
151 | 698, 56
152 |
153 |
154 | 493, 56
155 |
156 |
157 | 369, 95
158 |
159 |
160 | 319, 56
161 |
162 |
163 | 17, 56
164 |
165 |
166 | 1365, 17
167 |
168 |
169 | 1158, 17
170 |
171 |
172 | 954, 17
173 |
174 |
175 | 754, 17
176 |
177 |
178 | 545, 17
179 |
180 |
181 | 376, 17
182 |
183 |
--------------------------------------------------------------------------------
/Models/PublicConfig.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 | using System.Text;
4 |
5 | namespace AndroidSideloader.Models
6 | {
7 | [JsonObject(MemberSerialization.OptIn)]
8 | public class PublicConfig
9 | {
10 | [JsonProperty("baseUri")]
11 | public string BaseUri { get; set; }
12 |
13 | private string password;
14 |
15 | [JsonProperty("password")]
16 | public string Password
17 | {
18 | get => password;
19 | set => password = Encoding.UTF8.GetString(Convert.FromBase64String(value));
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/NewApps.Designer.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace AndroidSideloader
3 | {
4 | partial class NewApps
5 | {
6 | ///
7 | /// Required designer variable.
8 | ///
9 | private System.ComponentModel.IContainer components = null;
10 |
11 | ///
12 | /// Clean up any resources being used.
13 | ///
14 | /// true if managed resources should be disposed; otherwise, false.
15 | protected override void Dispose(bool disposing)
16 | {
17 | if (disposing && (components != null))
18 | {
19 | components.Dispose();
20 | }
21 | base.Dispose(disposing);
22 | }
23 |
24 | #region Windows Form Designer generated code
25 |
26 | ///
27 | /// Required method for Designer support - do not modify
28 | /// the contents of this method with the code editor.
29 | ///
30 | private void InitializeComponent()
31 | {
32 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(NewApps));
33 | this.NewAppsListView = new System.Windows.Forms.ListView();
34 | this.GameNameIndex = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
35 | this.PackageNameIndex = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
36 | this.panel2 = new System.Windows.Forms.Panel();
37 | this.label2 = new System.Windows.Forms.Label();
38 | this.NewAppsButton = new AndroidSideloader.RoundButton();
39 | this.panel2.SuspendLayout();
40 | this.SuspendLayout();
41 | //
42 | // NewAppsListView
43 | //
44 | this.NewAppsListView.AccessibleRole = System.Windows.Forms.AccessibleRole.None;
45 | this.NewAppsListView.BackColor = global::AndroidSideloader.Properties.Settings.Default.BackColor;
46 | this.NewAppsListView.BorderStyle = System.Windows.Forms.BorderStyle.None;
47 | this.NewAppsListView.CausesValidation = false;
48 | this.NewAppsListView.CheckBoxes = true;
49 | this.NewAppsListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
50 | this.GameNameIndex,
51 | this.PackageNameIndex});
52 | this.NewAppsListView.DataBindings.Add(new System.Windows.Forms.Binding("BackColor", global::AndroidSideloader.Properties.Settings.Default, "BackColor", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
53 | this.NewAppsListView.ForeColor = System.Drawing.Color.White;
54 | this.NewAppsListView.FullRowSelect = true;
55 | this.NewAppsListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
56 | this.NewAppsListView.HideSelection = false;
57 | this.NewAppsListView.Location = new System.Drawing.Point(3, 5);
58 | this.NewAppsListView.Name = "NewAppsListView";
59 | this.NewAppsListView.RightToLeftLayout = true;
60 | this.NewAppsListView.Size = new System.Drawing.Size(288, 167);
61 | this.NewAppsListView.TabIndex = 1;
62 | this.NewAppsListView.UseCompatibleStateImageBehavior = false;
63 | this.NewAppsListView.View = System.Windows.Forms.View.Details;
64 | this.NewAppsListView.MouseDown += new System.Windows.Forms.MouseEventHandler(this.label2_MouseDown);
65 | this.NewAppsListView.MouseMove += new System.Windows.Forms.MouseEventHandler(this.label2_MouseMove);
66 | this.NewAppsListView.MouseUp += new System.Windows.Forms.MouseEventHandler(this.label2_MouseUp);
67 | //
68 | // GameNameIndex
69 | //
70 | this.GameNameIndex.Text = "Game Name";
71 | this.GameNameIndex.Width = 284;
72 | //
73 | // PackageNameIndex
74 | //
75 | this.PackageNameIndex.Width = 0;
76 | //
77 | // panel2
78 | //
79 | this.panel2.BackColor = global::AndroidSideloader.Properties.Settings.Default.SubButtonColor;
80 | this.panel2.Controls.Add(this.NewAppsListView);
81 | this.panel2.DataBindings.Add(new System.Windows.Forms.Binding("BackColor", global::AndroidSideloader.Properties.Settings.Default, "SubButtonColor", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
82 | this.panel2.Location = new System.Drawing.Point(9, 31);
83 | this.panel2.Name = "panel2";
84 | this.panel2.Size = new System.Drawing.Size(295, 175);
85 | this.panel2.TabIndex = 8;
86 | //
87 | // label2
88 | //
89 | this.label2.AutoSize = true;
90 | this.label2.BackColor = System.Drawing.Color.Transparent;
91 | this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 10.25F, System.Drawing.FontStyle.Bold);
92 | this.label2.ForeColor = System.Drawing.SystemColors.ControlLightLight;
93 | this.label2.Location = new System.Drawing.Point(28, 7);
94 | this.label2.Name = "label2";
95 | this.label2.Size = new System.Drawing.Size(256, 17);
96 | this.label2.TabIndex = 9;
97 | this.label2.Text = "Check box of all free/non-VR apps";
98 | this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
99 | this.label2.MouseDown += new System.Windows.Forms.MouseEventHandler(this.label2_MouseDown);
100 | this.label2.MouseMove += new System.Windows.Forms.MouseEventHandler(this.label2_MouseMove);
101 | this.label2.MouseUp += new System.Windows.Forms.MouseEventHandler(this.label2_MouseUp);
102 | //
103 | // NewAppsButton
104 | //
105 | this.NewAppsButton.Active1 = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(40)))), ((int)(((byte)(40)))));
106 | this.NewAppsButton.Active2 = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(40)))), ((int)(((byte)(40)))));
107 | this.NewAppsButton.BackColor = System.Drawing.Color.Transparent;
108 | this.NewAppsButton.DialogResult = System.Windows.Forms.DialogResult.OK;
109 | this.NewAppsButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F);
110 | this.NewAppsButton.ForeColor = System.Drawing.Color.White;
111 | this.NewAppsButton.Inactive1 = System.Drawing.Color.FromArgb(((int)(((byte)(25)))), ((int)(((byte)(25)))), ((int)(((byte)(25)))));
112 | this.NewAppsButton.Inactive2 = System.Drawing.Color.FromArgb(((int)(((byte)(25)))), ((int)(((byte)(25)))), ((int)(((byte)(25)))));
113 | this.NewAppsButton.Location = new System.Drawing.Point(12, 212);
114 | this.NewAppsButton.Name = "NewAppsButton";
115 | this.NewAppsButton.Radius = 5;
116 | this.NewAppsButton.Size = new System.Drawing.Size(288, 29);
117 | this.NewAppsButton.Stroke = true;
118 | this.NewAppsButton.StrokeColor = System.Drawing.Color.FromArgb(((int)(((byte)(74)))), ((int)(((byte)(74)))), ((int)(((byte)(74)))));
119 | this.NewAppsButton.TabIndex = 2;
120 | this.NewAppsButton.Text = "Accept";
121 | this.NewAppsButton.Transparency = false;
122 | this.NewAppsButton.Click += new System.EventHandler(this.DonateButton_Click);
123 | //
124 | // NewApps
125 | //
126 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
127 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
128 | this.BackColor = global::AndroidSideloader.Properties.Settings.Default.BackColor;
129 | this.BackgroundImage = global::AndroidSideloader.Properties.Resources.pattern_cubes_1_1_1_0_0_0_1__000000_212121;
130 | this.ClientSize = new System.Drawing.Size(313, 248);
131 | this.ControlBox = false;
132 | this.Controls.Add(this.NewAppsButton);
133 | this.Controls.Add(this.label2);
134 | this.Controls.Add(this.panel2);
135 | this.DataBindings.Add(new System.Windows.Forms.Binding("BackColor", global::AndroidSideloader.Properties.Settings.Default, "BackColor", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
136 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
137 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
138 | this.Name = "NewApps";
139 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
140 | this.Load += new System.EventHandler(this.NewApps_Load);
141 | this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.label2_MouseDown);
142 | this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.label2_MouseMove);
143 | this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.label2_MouseUp);
144 | this.panel2.ResumeLayout(false);
145 | this.ResumeLayout(false);
146 | this.PerformLayout();
147 |
148 | }
149 |
150 | #endregion
151 |
152 | private System.Windows.Forms.ListView NewAppsListView;
153 | private System.Windows.Forms.ColumnHeader GameNameIndex;
154 | private System.Windows.Forms.Panel panel2;
155 | private System.Windows.Forms.Label label2;
156 | private System.Windows.Forms.ColumnHeader PackageNameIndex;
157 | private RoundButton NewAppsButton;
158 | }
159 | }
--------------------------------------------------------------------------------
/NewApps.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Windows.Forms;
5 |
6 | namespace AndroidSideloader
7 | {
8 | public partial class NewApps : Form
9 | {
10 | private bool mouseDown;
11 | private Point lastLocation;
12 |
13 | public NewApps()
14 | {
15 | InitializeComponent();
16 | }
17 |
18 | private void label2_MouseDown(object sender, MouseEventArgs e)
19 | {
20 | mouseDown = true;
21 | lastLocation = e.Location;
22 | }
23 |
24 | private void label2_MouseMove(object sender, MouseEventArgs e)
25 | {
26 | if (mouseDown)
27 | {
28 | Location = new Point(
29 | Location.X - lastLocation.X + e.X, Location.Y - lastLocation.Y + e.Y);
30 |
31 | Update();
32 | }
33 | }
34 |
35 | private void label2_MouseUp(object sender, MouseEventArgs e)
36 | {
37 | mouseDown = false;
38 | }
39 |
40 | private void DonateButton_Click(object sender, EventArgs e)
41 | {
42 | string HWID = SideloaderUtilities.UUID();
43 | foreach (ListViewItem listItem in NewAppsListView.Items)
44 | {
45 | if (listItem.Checked)
46 | {
47 | Properties.Settings.Default.NonAppPackages += listItem.SubItems[Donors.PackageNameIndex].Text + ";" + HWID + "\n";
48 | Properties.Settings.Default.Save();
49 | }
50 | else
51 | {
52 | Properties.Settings.Default.AppPackages += listItem.SubItems[Donors.PackageNameIndex].Text + "\n";
53 | Properties.Settings.Default.Save();
54 | }
55 | }
56 | MainForm.newPackageUpload();
57 | Close();
58 | }
59 |
60 | private void NewApps_Load(object sender, EventArgs e)
61 | {
62 | NewAppsListView.Items.Clear();
63 | Donors.initNewApps();
64 | List NewAppList = new List();
65 | foreach (string[] release in Donors.newApps)
66 | {
67 | ListViewItem NGame = new ListViewItem(release);
68 | if (!NewAppList.Contains(NGame))
69 | {
70 | NewAppList.Add(NGame);
71 | }
72 | }
73 | ListViewItem[] arr = NewAppList.ToArray();
74 | NewAppsListView.BeginUpdate();
75 | NewAppsListView.Items.Clear();
76 | NewAppsListView.Items.AddRange(arr);
77 | NewAppsListView.EndUpdate();
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Security.Permissions;
4 | using System.Windows.Forms;
5 |
6 | namespace AndroidSideloader
7 | {
8 | internal static class Program
9 | {
10 | ///
11 | /// The main entry point for the application.
12 | ///
13 | [STAThread]
14 | [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]
15 | private static void Main()
16 | {
17 |
18 | AppDomain currentDomain = AppDomain.CurrentDomain;
19 | currentDomain.UnhandledException += new UnhandledExceptionEventHandler(CrashHandler);
20 | Application.EnableVisualStyles();
21 | Application.SetCompatibleTextRenderingDefault(false);
22 |
23 | form = new MainForm();
24 | Application.Run(form);
25 | //form.Show();
26 | }
27 | public static MainForm form;
28 |
29 | private static void CrashHandler(object sender, UnhandledExceptionEventArgs args)
30 | {
31 | // Capture unhandled exceptions and write to file.
32 | Exception e = (Exception)args.ExceptionObject;
33 | string innerExceptionMessage = (e.InnerException != null)
34 | ? e.InnerException.Message
35 | : "None";
36 | string date_time = DateTime.Now.ToString("dddd, MMMM dd @ hh:mmtt (UTC)");
37 | File.WriteAllText(Sideloader.CrashLogPath, $"Date/Time of crash: {date_time}\nMessage: {e.Message}\nInner Message: {innerExceptionMessage}\nData: {e.Data}\nSource: {e.Source}\nTargetSite: {e.TargetSite}\nStack Trace: \n{e.StackTrace}\n\n\nDebuglog: \n\n\n");
38 | // If a debuglog exists we append it to the crashlog.
39 | if (File.Exists(Properties.Settings.Default.CurrentLogPath))
40 | {
41 | File.AppendAllText(Sideloader.CrashLogPath, File.ReadAllText($"{Properties.Settings.Default.CurrentLogPath}"));
42 | }
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | //[assembly: AssemblyKeyFileAttribute("keypair.snk")]
8 | [assembly: AssemblyTitle("AndroidSideloader")]
9 | [assembly: AssemblyDescription("Rookie Sideloader")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Rookie.WTF")]
12 | [assembly: AssemblyProduct("AndroidSideloader")]
13 | [assembly: AssemblyCopyright("Copyright © 2020")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("cc8be9f0-ce07-406a-a378-81d9cfe4cc1d")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("2.0.0.0")]
36 | [assembly: AssemblyFileVersion("2.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Properties/DataSources/AndroidSideloader.Properties.Resources.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | AndroidSideloader.Properties.Resources, Properties.Resources.Designer.cs.dll, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/Properties/DataSources/AndroidSideloader.Properties.Settings.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | AndroidSideloader.Properties.Settings, Properties.Resources.Designer.cs.dll, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace AndroidSideloader.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | public class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | public static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AndroidSideloader.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | public static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized resource of type System.Drawing.Bitmap.
65 | ///
66 | public static System.Drawing.Bitmap ajax_loader {
67 | get {
68 | object obj = ResourceManager.GetObject("ajax-loader", resourceCulture);
69 | return ((System.Drawing.Bitmap)(obj));
70 | }
71 | }
72 |
73 | ///
74 | /// Looks up a localized resource of type System.Drawing.Bitmap.
75 | ///
76 | public static System.Drawing.Bitmap battery {
77 | get {
78 | object obj = ResourceManager.GetObject("battery", resourceCulture);
79 | return ((System.Drawing.Bitmap)(obj));
80 | }
81 | }
82 |
83 | ///
84 | /// Looks up a localized resource of type System.Drawing.Bitmap.
85 | ///
86 | public static System.Drawing.Bitmap battery1 {
87 | get {
88 | object obj = ResourceManager.GetObject("battery1", resourceCulture);
89 | return ((System.Drawing.Bitmap)(obj));
90 | }
91 | }
92 |
93 | ///
94 | /// Looks up a localized resource of type System.Drawing.Bitmap.
95 | ///
96 | public static System.Drawing.Bitmap battery11 {
97 | get {
98 | object obj = ResourceManager.GetObject("battery11", resourceCulture);
99 | return ((System.Drawing.Bitmap)(obj));
100 | }
101 | }
102 |
103 | ///
104 | /// Looks up a localized resource of type System.Drawing.Bitmap.
105 | ///
106 | public static System.Drawing.Bitmap Pattern {
107 | get {
108 | object obj = ResourceManager.GetObject("Pattern", resourceCulture);
109 | return ((System.Drawing.Bitmap)(obj));
110 | }
111 | }
112 |
113 | ///
114 | /// Looks up a localized resource of type System.Drawing.Bitmap.
115 | ///
116 | public static System.Drawing.Bitmap pattern_cubes_1_1_1_0_0_0_1__000000_212121 {
117 | get {
118 | object obj = ResourceManager.GetObject("pattern_cubes-1_1_1_0-0_0_1__000000_212121", resourceCulture);
119 | return ((System.Drawing.Bitmap)(obj));
120 | }
121 | }
122 |
123 | ///
124 | /// Looks up a localized resource of type System.Drawing.Bitmap.
125 | ///
126 | public static System.Drawing.Bitmap pattern_herringbone_2_1_3_0_0_90_1__000000_1c1c1c {
127 | get {
128 | object obj = ResourceManager.GetObject("pattern_herringbone_2_1_3_0_0_90_1__000000_1c1c1c", resourceCulture);
129 | return ((System.Drawing.Bitmap)(obj));
130 | }
131 | }
132 |
133 | ///
134 | /// Looks up a localized resource of type System.Drawing.Bitmap.
135 | ///
136 | public static System.Drawing.Bitmap SearchGlass {
137 | get {
138 | object obj = ResourceManager.GetObject("SearchGlass", resourceCulture);
139 | return ((System.Drawing.Bitmap)(obj));
140 | }
141 | }
142 |
143 | ///
144 | /// Looks up a localized resource of type System.Drawing.Bitmap.
145 | ///
146 | public static System.Drawing.Bitmap splashimage {
147 | get {
148 | object obj = ResourceManager.GetObject("splashimage", resourceCulture);
149 | return ((System.Drawing.Bitmap)(obj));
150 | }
151 | }
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | ..\Resources\battery.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
123 |
124 |
125 | ..\Resources\battery11.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
126 |
127 |
128 | ..\resources\pattern_herringbone-2_1_3_0-0_90_1__000000_1c1c1c.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
129 |
130 |
131 | ..\Resources\splashimage.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
132 |
133 |
134 | ..\Resources\battery1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
135 |
136 |
137 | ..\Resources\ajax-loader.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
138 |
139 |
140 | ..\Resources\SearchGlass.PNG;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
141 |
142 |
143 | ..\Resources\Pattern.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
144 |
145 |
146 | ..\Resources\pattern_cubes-1_1_1_0-0_0_1__000000_212121.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
147 |
148 |
--------------------------------------------------------------------------------
/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | True
7 |
8 |
9 | True
10 |
11 |
12 | True
13 |
14 |
15 | True
16 |
17 |
18 | True
19 |
20 |
21 | False
22 |
23 |
24 | True
25 |
26 |
27 | Microsoft Sans Serif, 11.25pt
28 |
29 |
30 |
31 |
32 |
33 | False
34 |
35 |
36 | Microsoft Sans Serif, 14pt
37 |
38 |
39 | False
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | False
52 |
53 |
54 |
55 |
56 |
57 | 0
58 |
59 |
60 | 0
61 |
62 |
63 | 0
64 |
65 |
66 | 0
67 |
68 |
69 | Change Me
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | False
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | False
91 |
92 |
93 |
94 |
95 |
96 | False
97 |
98 |
99 | False
100 |
101 |
102 | False
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 | False
118 |
119 |
120 | False
121 |
122 |
123 | False
124 |
125 |
126 | True
127 |
128 |
129 |
130 |
131 |
132 | False
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 | False
142 |
143 |
144 |
145 |
146 |
147 | 04/20/1969 16:20:00
148 |
149 |
150 |
151 |
152 |
153 | False
154 |
155 |
156 | 04/20/1969 16:20:00
157 |
158 |
159 | False
160 |
161 |
162 | White
163 |
164 |
165 | 25, 25, 25
166 |
167 |
168 | 25, 25, 25
169 |
170 |
171 | 25, 25, 25
172 |
173 |
174 | Black
175 |
176 |
177 | 1, 1, 1
178 |
179 |
180 |
181 |
182 |
183 | False
184 |
185 |
186 |
187 |
188 |
189 | False
190 |
191 |
192 | False
193 |
194 |
195 |
196 |
197 |
198 | False
199 |
200 |
201 | False
202 |
203 |
204 |
--------------------------------------------------------------------------------
/QuestForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Windows.Forms;
4 |
5 | namespace AndroidSideloader
6 | {
7 | public partial class QuestForm : Form
8 | {
9 | public static int length = 0;
10 | public static string[] result;
11 | public bool settingsexist = false;
12 | public static bool QUSon = false;
13 | public bool delsh = false;
14 | public QuestForm()
15 | {
16 | InitializeComponent();
17 | }
18 |
19 |
20 | private void button1_Click(object sender, EventArgs e)
21 | {
22 | bool ChangesMade = false;
23 |
24 | //Quest 2 settings, might remove them in the future since some of them are broken
25 | if (RefreshRateComboBox.SelectedIndex != -1)
26 | {
27 | _ = ADB.RunAdbCommandToString($"shell setprop debug.oculus.refreshRate {RefreshRateComboBox.SelectedItem}");
28 | _ = ADB.RunAdbCommandToString($"shell settings put global 90hz_global {RefreshRateComboBox.SelectedIndex}");
29 | _ = ADB.RunAdbCommandToString($"shell settings put global 90hzglobal {RefreshRateComboBox.SelectedIndex}");
30 | ChangesMade = true;
31 | }
32 |
33 | if (TextureResTextBox.Text.Length > 0)
34 | {
35 | _ = int.TryParse(TextureResTextBox.Text, out _);
36 | _ = ADB.RunAdbCommandToString($"shell settings put global texture_size_Global {TextureResTextBox.Text}");
37 | _ = ADB.RunAdbCommandToString($"shell setprop debug.oculus.textureWidth {TextureResTextBox.Text}");
38 | _ = ADB.RunAdbCommandToString($"shell setprop debug.oculus.textureHeight {TextureResTextBox.Text}");
39 | ChangesMade = true;
40 | }
41 |
42 | if (CPUComboBox.SelectedIndex != -1)
43 | {
44 | _ = ADB.RunAdbCommandToString($"shell setprop debug.oculus.cpuLevel {CPUComboBox.SelectedItem}");
45 | ChangesMade = true;
46 | }
47 |
48 | if (GPUComboBox.SelectedIndex != -1)
49 | {
50 | _ = ADB.RunAdbCommandToString($"shell setprop debug.oculus.gpuLevel {GPUComboBox.SelectedItem}");
51 | ChangesMade = true;
52 | }
53 |
54 | if (ChangesMade)
55 | {
56 | _ = MessageBox.Show("Settings applied!");
57 | }
58 | }
59 |
60 |
61 | public static void setLength(int value)
62 | {
63 | result = new string[value];
64 | }
65 |
66 |
67 |
68 | public void ResetQU_click(object sender, EventArgs e)
69 | {
70 | ResBox.Text = "0";
71 | UsrBox.Text = "Change Me";
72 | FOVx.Text = "0";
73 | FOVy.Text = "0";
74 | QURfrRt.SelectedIndex = 0;
75 | }
76 |
77 | private void DeleteShots_CheckedChanged(object sender, EventArgs e)
78 | {
79 | delsh = DeleteShots.Checked;
80 | }
81 | private void QUon_CheckedChanged(object sender, EventArgs e)
82 | {
83 | if (QUon.Checked)
84 | {
85 | ResBox.Visible = true;
86 | UsrBox.Visible = true;
87 | FOVx.Visible = true;
88 | FOVy.Visible = true;
89 | QURfrRt.Visible = true;
90 | ResetQU.Visible = true;
91 | QUEnable.Visible = true;
92 | label5.Visible = true;
93 | label6.Visible = true;
94 | label7.Visible = true;
95 | label8.Visible = true;
96 | label9.Visible = true;
97 | label10.Visible = true;
98 | deleteButton.Visible = true;
99 | ResBox.Text = Properties.Settings.Default.QUres;
100 | UsrBox.Text = Properties.Settings.Default.QUname;
101 | FOVy.Text = Properties.Settings.Default.QUy;
102 | FOVx.Text = Properties.Settings.Default.QUx;
103 | QURfrRt.SelectedValue = Properties.Settings.Default.QUhz;
104 | Properties.Settings.Default.QUturnedon = true;
105 | }
106 | else if (!QUon.Checked)
107 | {
108 | ResBox.Visible = false;
109 | UsrBox.Visible = false;
110 | FOVx.Visible = false;
111 | FOVy.Visible = false;
112 | QURfrRt.Visible = false;
113 | ResetQU.Visible = false;
114 | QUEnable.Visible = false;
115 | label5.Visible = false;
116 | label6.Visible = false;
117 | label7.Visible = false;
118 | label8.Visible = false;
119 | label9.Visible = false;
120 | label10.Visible = false;
121 | deleteButton.Visible = false;
122 | Properties.Settings.Default.QUturnedon = false;
123 | _ = MessageBox.Show("Ok, Deleted your custom settings file.\nIf you would like to re-enable return here and apply settings again");
124 | File.Delete($"{Environment.CurrentDirectory}\\Config.Json");
125 | File.Delete($"{Environment.CurrentDirectory}\\delete_settings");
126 | }
127 |
128 | }
129 | private static readonly Random random = new Random();
130 | private static readonly object syncLock = new object();
131 | public static int RandomNumber(int min, int max)
132 | {
133 | lock (syncLock)
134 | { // synchronize
135 | return random.Next(min, max);
136 | }
137 | }
138 | private void QUEnable_Click(object sender, EventArgs e)
139 | {
140 |
141 | settingsexist = true;
142 | _ = MessageBox.Show("OK, any -QU packages installed will have these settings applied!\nTo delete settings: goto main app window, select a game with top menu, and click \"Remove QU Setting\"");
143 | if (QUon.Checked)
144 | {
145 | Properties.Settings.Default.QUturnedon = true;
146 | Random r = new Random();
147 |
148 | int x = r.Next(999999999);
149 | int y = r.Next(9999999);
150 |
151 | long sum = (y * (long)1000000000) + x;
152 |
153 | int x2 = r.Next(999999999);
154 | int y2 = r.Next(9999999);
155 |
156 | long sum2 = (y2 * (long)1000000000) + x2;
157 |
158 | QUSon = true;
159 |
160 | string selected = QURfrRt.GetItemText(QURfrRt.SelectedItem);
161 |
162 | Properties.Settings.Default.QUString = $"\"refresh_rate\":{selected},\"eye_texture_width\":{ResBox.Text},\"fov_x\":{FOVx.Text},\"fov_y\":{FOVy.Text},\"username\":\"{UsrBox.Text}\"}}";
163 | Properties.Settings.Default.QUStringF = $"{{\"user_id\":{sum},\"app_id\":\"{sum2}\",";
164 | Properties.Settings.Default.Save();
165 | File.WriteAllText($"{Properties.Settings.Default.MainDir}\\delete_settings", "");
166 | string boff = Properties.Settings.Default.QUStringF + Properties.Settings.Default.QUString;
167 | File.WriteAllText($"{Properties.Settings.Default.MainDir}\\config.json", boff);
168 | }
169 | else
170 | {
171 | Properties.Settings.Default.QUturnedon = false;
172 | }
173 |
174 |
175 |
176 | }
177 |
178 |
179 |
180 | private void QuestForm_FormClosed(object sender, FormClosedEventArgs e)
181 | {
182 | if (QUon.Checked)
183 | {
184 | Properties.Settings.Default.QUsett = true;
185 | Properties.Settings.Default.Save();
186 | }
187 | if (!QUon.Checked)
188 | {
189 | Properties.Settings.Default.QUsett = false;
190 | Properties.Settings.Default.Save();
191 | }
192 | if (DeleteShots.Checked)
193 | {
194 | Properties.Settings.Default.delsh = true;
195 | Properties.Settings.Default.Save();
196 | }
197 | if (!DeleteShots.Checked)
198 | {
199 | Properties.Settings.Default.delsh = false;
200 | Properties.Settings.Default.Save();
201 | }
202 | }
203 | private void QuestForm_Load(object sender, EventArgs e)
204 | {
205 | DeleteShots.Checked = Properties.Settings.Default.delsh;
206 | if (Properties.Settings.Default.QUsett)
207 | {
208 | ResBox.Text = Properties.Settings.Default.QUres;
209 | UsrBox.Text = Properties.Settings.Default.QUname;
210 | FOVy.Text = Properties.Settings.Default.QUy;
211 | FOVx.Text = Properties.Settings.Default.QUx;
212 | QURfrRt.Text = Properties.Settings.Default.QUhz;
213 | QUon.Checked = true;
214 | if (settingsexist)
215 | {
216 | QUSon = true;
217 | }
218 | }
219 | GlobalUsername.Text = Properties.Settings.Default.GlobalUsername;
220 | }
221 |
222 | private void ResBox_TextChanged(object sender, EventArgs e)
223 | {
224 | Properties.Settings.Default.QUres = ResBox.Text;
225 | Properties.Settings.Default.Save();
226 |
227 | }
228 |
229 | private void UsrBox_TextChanged(object sender, EventArgs e)
230 | {
231 | Properties.Settings.Default.QUname = UsrBox.Text;
232 | Properties.Settings.Default.Save();
233 | }
234 |
235 | private void FOVx_TextChanged(object sender, EventArgs e)
236 | {
237 | Properties.Settings.Default.QUx = FOVx.Text;
238 | Properties.Settings.Default.Save();
239 | }
240 |
241 | private void FOVy_TextChanged(object sender, EventArgs e)
242 | {
243 | Properties.Settings.Default.QUy = FOVy.Text;
244 | Properties.Settings.Default.Save();
245 | }
246 |
247 | private void QURfrRt_SelectedIndexChanged(object sender, EventArgs e)
248 | {
249 |
250 | string selected = QURfrRt.GetItemText(QURfrRt.SelectedItem);
251 | Properties.Settings.Default.QUhz = selected;
252 | Properties.Settings.Default.Save();
253 | }
254 | private void DeleteButton_Click(object sender, EventArgs e)
255 | {
256 |
257 | _ = MessageBox.Show("Ok, Deleted your custom settings file.\nIf you would like to re-enable return here and apply settings again");
258 | File.Delete($"{Properties.Settings.Default.MainDir}\\Config.Json");
259 | }
260 | private void questPics_Click(object sender, EventArgs e)
261 | {
262 | string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
263 |
264 | if (!Directory.Exists($"{path}\\Quest ScreenShots"))
265 | {
266 | _ = Directory.CreateDirectory($"{path}\\Quest ScreenShots");
267 | }
268 |
269 | _ = MessageBox.Show("Please wait until you get the message that the transfer has finished.");
270 | Program.form.changeTitle("Pulling files...");
271 | _ = ADB.RunAdbCommandToString($"pull \"/sdcard/Oculus/Screenshots\" \"{path}\\Quest ScreenShots\"");
272 | if (delsh)
273 | {
274 | DialogResult dialogResult = MessageBox.Show("You have chosen to delete files from headset after transferring, so be sure to move them from your desktop to somewhere safe!", "Warning!", MessageBoxButtons.OKCancel);
275 | if (dialogResult == DialogResult.OK)
276 | {
277 | _ = ADB.RunAdbCommandToString("shell rm -r /sdcard/Oculus/Screenshots");
278 | _ = ADB.RunAdbCommandToString("shell mkdir /sdcard/Oculus/Screenshots");
279 | }
280 | }
281 | _ = MessageBox.Show("Transfer finished! ScreenShots can be found in a folder named Quest Screenshots on your desktop!");
282 | Program.form.changeTitle("Done!");
283 | }
284 | private void questVids_Click(object sender, EventArgs e)
285 | {
286 | string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
287 | if (!Directory.Exists($"{path}\\Quest VideoShots"))
288 | {
289 | _ = Directory.CreateDirectory($"{path}\\Quest VideoShots");
290 | }
291 |
292 | _ = MessageBox.Show("Please wait until you get the message that the transfer has finished.");;
293 | Program.form.changeTitle("Pulling files...");
294 | _ = ADB.RunAdbCommandToString($"pull \"/sdcard/Oculus/Videoshots\" \"{path}\\Quest VideoShots\"");
295 | if (delsh)
296 | {
297 | DialogResult dialogResult = MessageBox.Show("You have chosen to delete files from headset after transferring, so be sure to move them from your desktop to somewhere safe!", "Warning!", MessageBoxButtons.OKCancel);
298 | if (dialogResult == DialogResult.OK)
299 | {
300 | _ = ADB.RunAdbCommandToString("shell rm -r /sdcard/Oculus/Videoshots");
301 | _ = ADB.RunAdbCommandToString("shell mkdir /sdcard/Oculus/Videoshots");
302 | }
303 | }
304 | _ = MessageBox.Show("Transfer finished! VideoShots can be found in a folder named Quest VideoShots on your desktop!");
305 | Program.form.changeTitle("Done!");
306 | }
307 | private void button3_Click(object sender, EventArgs e)
308 | {
309 | if (GlobalUsername.Text.Contains(" "))
310 | {
311 | _ = MessageBox.Show("Usernames with a space are not permitted.", "Detected a space in username!");
312 | }
313 | else
314 | {
315 | _ = ADB.RunAdbCommandToString($"shell settings put global username {GlobalUsername.Text}");
316 | _ = MessageBox.Show($"Username set as {GlobalUsername.Text}", "Success");
317 | }
318 | }
319 |
320 |
321 | private void Form_KeyDown(object sender, KeyEventArgs e)
322 | {
323 | if (e.KeyCode == Keys.Escape)
324 | {
325 | Close();
326 | }
327 | }
328 | protected override bool ProcessDialogKey(Keys keyData)
329 | {
330 | if (Form.ModifierKeys == Keys.None && keyData == Keys.Escape)
331 | {
332 | Close();
333 | return true;
334 | }
335 | return base.ProcessDialogKey(keyData);
336 | }
337 |
338 | private void WifiWake_Click(object sender, EventArgs e)
339 | {
340 | _ = ADB.RunAdbCommandToString("shell settings put global wifi_wakeup_available 1");
341 | _ = ADB.RunAdbCommandToString("shell settings put global wifi_wakeup_enabled 1");
342 | _ = MessageBox.Show("Wake on Wifi enabled!\n\nNOTE: This requires having wireless ADB enabled to work. (Obviously)");
343 | }
344 |
345 | private void GlobalUsername_TextChanged(object sender, EventArgs e)
346 | {
347 | button3.Enabled = GlobalUsername.TextLength > 0;
348 | Properties.Settings.Default.GlobalUsername = GlobalUsername.Text;
349 | Properties.Settings.Default.Save();
350 | }
351 | }
352 | }
353 |
--------------------------------------------------------------------------------
/RCLONE.cs:
--------------------------------------------------------------------------------
1 | using JR.Utils.GUI.Forms;
2 | using System;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Management;
6 | using System.Text;
7 | using System.Windows.Forms;
8 |
9 | namespace AndroidSideloader
10 | {
11 | internal class RCLONE
12 | {
13 | // Kill RCLONE Processes that were started from Rookie by looking for child processes.
14 | public static void killRclone()
15 | {
16 | var parentProcessId = Process.GetCurrentProcess().Id;
17 | var processes = Process.GetProcessesByName("rclone");
18 |
19 | foreach (var process in processes)
20 | {
21 | try
22 | {
23 | using (ManagementObject obj = new ManagementObject($"win32_process.handle='{process.Id}'"))
24 | {
25 | obj.Get();
26 | var ppid = Convert.ToInt32(obj["ParentProcessId"]);
27 |
28 | if (ppid == parentProcessId)
29 | {
30 | process.Kill();
31 | }
32 | }
33 | }
34 | catch (Exception ex)
35 | {
36 | _ = Logger.Log($"Exception occured while attempting to shut down RCLONE with exception message: {ex.Message}", LogLevel.ERROR);
37 | }
38 | }
39 | }
40 |
41 | // For custom configs that use a password
42 | public static void Init()
43 | {
44 | string PwTxtPath = Path.Combine(Environment.CurrentDirectory, "rclone\\pw.txt");
45 | if (File.Exists(PwTxtPath))
46 | {
47 | rclonepw = File.ReadAllText(PwTxtPath);
48 | }
49 | }
50 |
51 | // Change if you want to use a config
52 | public static string downloadConfigPath = "vrp.download.config";
53 | public static string uploadConfigPath = "vrp.upload.config";
54 | public static string rclonepw = "";
55 |
56 |
57 | private static readonly Process rclone = new Process();
58 |
59 | // Run an RCLONE Command that accesses the Download Config.
60 | public static ProcessOutput runRcloneCommand_DownloadConfig(string command)
61 | {
62 | if (MainForm.isOffline)
63 | {
64 | return new ProcessOutput("", "No internet");
65 | }
66 |
67 | ProcessOutput prcoutput = new ProcessOutput();
68 | // Rclone output is unicode, else it will show garbage instead of unicode characters
69 | rclone.StartInfo.StandardOutputEncoding = Encoding.UTF8;
70 | string originalCommand = command;
71 |
72 | // set configpath if there is any
73 | if (downloadConfigPath.Length > 0)
74 | {
75 | command += $" --config {downloadConfigPath}";
76 | }
77 |
78 | // set rclonepw
79 | if (rclonepw.Length > 0)
80 | {
81 | command += " --ask-password=false";
82 | }
83 |
84 | string logcmd = Utilities.StringUtilities.RemoveEverythingBeforeFirst(command, "rclone.exe");
85 | if (logcmd.Contains($"\"{Properties.Settings.Default.CurrentLogPath}\""))
86 | {
87 | logcmd = logcmd.Replace($"\"{Properties.Settings.Default.CurrentLogPath}\"", $"\"{Properties.Settings.Default.CurrentLogName}\"");
88 | }
89 |
90 | if (logcmd.Contains(Environment.CurrentDirectory))
91 | {
92 | logcmd = logcmd.Replace($"{Environment.CurrentDirectory}", $"CurrentDirectory");
93 | }
94 |
95 | _ = Logger.Log($"Running Rclone command: {logcmd}");
96 |
97 | rclone.StartInfo.FileName = Environment.CurrentDirectory + "\\rclone\\rclone.exe";
98 | rclone.StartInfo.Arguments = command;
99 | rclone.StartInfo.RedirectStandardInput = true;
100 | rclone.StartInfo.RedirectStandardError = true;
101 | rclone.StartInfo.RedirectStandardOutput = true;
102 | rclone.StartInfo.WorkingDirectory = Environment.CurrentDirectory + "\\rclone";
103 | rclone.StartInfo.CreateNoWindow = true;
104 | // Display RCLONE Window if the binary is being run in Debug Mode.
105 | if (MainForm.debugMode)
106 | {
107 | rclone.StartInfo.CreateNoWindow = false;
108 | }
109 | rclone.StartInfo.UseShellExecute = false;
110 | _ = rclone.Start();
111 | rclone.StandardInput.WriteLine(command);
112 | rclone.StandardInput.Flush();
113 | rclone.StandardInput.Close();
114 |
115 | string output = rclone.StandardOutput.ReadToEnd();
116 | string error = rclone.StandardError.ReadToEnd();
117 | rclone.WaitForExit();
118 |
119 | if (error.Contains("There is not enough space"))
120 | {
121 | _ = FlexibleMessageBox.Show(Program.form, $"There isn't enough disk space to download this game.\r\nPlease ensure you have at least 200MB more the game size available in {Environment.CurrentDirectory} and try again.",
122 | "NOT ENOUGH SPACE",
123 | MessageBoxButtons.OK,
124 | MessageBoxIcon.Error);
125 | return new ProcessOutput("Download failed.", "");
126 | }
127 |
128 | // Switch mirror upon matching error output.
129 | if (error.Contains("400 Bad Request") || error.Contains("cannot fetch token") || error.Contains("authError") || error.Contains("quota") || error.Contains("exceeded") || error.Contains("directory not found") || error.Contains("Failed to"))
130 | {
131 | string oldRemote = MainForm.currentRemote;
132 | try
133 | {
134 | Program.form.SwitchMirrors();
135 |
136 | }
137 | catch
138 | {
139 | return new ProcessOutput("All mirrors are on quota or down...", "All mirrors are on quota or down...");
140 | }
141 | prcoutput = runRcloneCommand_DownloadConfig(originalCommand.Replace(oldRemote, MainForm.currentRemote));
142 | }
143 | else
144 | {
145 | prcoutput.Output = output;
146 | prcoutput.Error = error;
147 | }
148 |
149 | if (!output.Contains("Game Name;Release Name;") && !output.Contains("package:") && !output.Contains(".meta"))
150 | {
151 | if (!string.IsNullOrWhiteSpace(error))
152 | {
153 | _ = Logger.Log($"Rclone error: {error}\n", LogLevel.ERROR);
154 | }
155 |
156 | if (!string.IsNullOrWhiteSpace(output))
157 | {
158 | _ = Logger.Log($"Rclone Output: {output}");
159 | }
160 | }
161 | return prcoutput;
162 | }
163 |
164 | public static ProcessOutput runRcloneCommand_UploadConfig(string command)
165 | {
166 | ProcessOutput prcoutput = new ProcessOutput();
167 | // Rclone output is unicode, else it will show garbage instead of unicode characters
168 | rclone.StartInfo.StandardOutputEncoding = Encoding.UTF8;
169 |
170 | // set configpath if there is any
171 | if (uploadConfigPath.Length > 0)
172 | {
173 | command += $" --config {uploadConfigPath}";
174 | }
175 |
176 | string logcmd = Utilities.StringUtilities.RemoveEverythingBeforeFirst(command, "rclone.exe");
177 | if (logcmd.Contains($"\"{Properties.Settings.Default.CurrentLogPath}\""))
178 | {
179 | logcmd = logcmd.Replace($"\"{Properties.Settings.Default.CurrentLogPath}\"", $"\"{Properties.Settings.Default.CurrentLogName}\"");
180 | }
181 |
182 | if (logcmd.Contains(Environment.CurrentDirectory))
183 | {
184 | logcmd = logcmd.Replace($"{Environment.CurrentDirectory}", $"CurrentDirectory");
185 | }
186 |
187 | _ = Logger.Log($"Running Rclone command: {logcmd}");
188 |
189 | command += " --checkers 0 --no-check-dest --retries 1";
190 |
191 | rclone.StartInfo.FileName = Environment.CurrentDirectory + "\\rclone\\rclone.exe";
192 | rclone.StartInfo.Arguments = command;
193 | rclone.StartInfo.RedirectStandardInput = true;
194 | rclone.StartInfo.RedirectStandardError = true;
195 | rclone.StartInfo.RedirectStandardOutput = true;
196 | rclone.StartInfo.WorkingDirectory = Environment.CurrentDirectory + "\\rclone";
197 | rclone.StartInfo.CreateNoWindow = true;
198 | // Display RCLONE Window if the binary is being run in Debug Mode.
199 | if (MainForm.debugMode)
200 | {
201 | rclone.StartInfo.CreateNoWindow = false;
202 | }
203 | rclone.StartInfo.UseShellExecute = false;
204 | _ = rclone.Start();
205 | rclone.StandardInput.WriteLine(command);
206 | rclone.StandardInput.Flush();
207 | rclone.StandardInput.Close();
208 |
209 | string output = rclone.StandardOutput.ReadToEnd();
210 | string error = rclone.StandardError.ReadToEnd();
211 | rclone.WaitForExit();
212 |
213 | // if there is one of these errors, we switch the mirrors
214 | if (error.Contains("400 Bad Request") || error.Contains("cannot fetch token") || error.Contains("authError") || error.Contains("quota") || error.Contains("exceeded") || error.Contains("directory not found") || error.Contains("Failed to"))
215 | {
216 | _ = Logger.Log(error, LogLevel.ERROR);
217 | return new ProcessOutput("Upload Failed.", "Upload failed.");
218 | }
219 | else
220 | {
221 | prcoutput.Output = output;
222 | prcoutput.Error = error;
223 | }
224 |
225 | if (!output.Contains("Game Name;Release Name;") && !output.Contains("package:") && !output.Contains(".meta"))
226 | {
227 | if (!string.IsNullOrWhiteSpace(error))
228 | {
229 | _ = Logger.Log($"Rclone error: {error}\n", LogLevel.ERROR);
230 | }
231 |
232 | if (!string.IsNullOrWhiteSpace(output))
233 | {
234 | _ = Logger.Log($"Rclone Output: {output}");
235 | }
236 | }
237 | return prcoutput;
238 | }
239 |
240 | public static ProcessOutput runRcloneCommand_PublicConfig(string command)
241 | {
242 | if (MainForm.isOffline)
243 | {
244 | return new ProcessOutput("", "No internet");
245 | }
246 |
247 | ProcessOutput prcoutput = new ProcessOutput();
248 | // Rclone output is unicode, else it will show garbage instead of unicode characters
249 | rclone.StartInfo.StandardOutputEncoding = Encoding.UTF8;
250 |
251 | string logcmd = Utilities.StringUtilities.RemoveEverythingBeforeFirst(command, "rclone.exe");
252 | if (logcmd.Contains($"\"{Properties.Settings.Default.CurrentLogPath}\""))
253 | {
254 | logcmd = logcmd.Replace($"\"{Properties.Settings.Default.CurrentLogPath}\"", $"\"{Properties.Settings.Default.CurrentLogName}\"");
255 | }
256 |
257 | if (logcmd.Contains(Environment.CurrentDirectory))
258 | {
259 | logcmd = logcmd.Replace($"{Environment.CurrentDirectory}", $"CurrentDirectory");
260 | }
261 |
262 | _ = Logger.Log($"Running Rclone command: {logcmd}");
263 |
264 | //set http source & args
265 | command += $" --http-url {MainForm.PublicConfigFile.BaseUri} {MainForm.PublicMirrorExtraArgs}";
266 |
267 | rclone.StartInfo.FileName = Environment.CurrentDirectory + "\\rclone\\rclone.exe";
268 | rclone.StartInfo.Arguments = command;
269 | rclone.StartInfo.RedirectStandardInput = true;
270 | rclone.StartInfo.RedirectStandardError = true;
271 | rclone.StartInfo.RedirectStandardOutput = true;
272 | rclone.StartInfo.WorkingDirectory = Environment.CurrentDirectory + "\\rclone";
273 | rclone.StartInfo.CreateNoWindow = true;
274 | // Display RCLONE Window if the binary is being run in Debug Mode.
275 | if (MainForm.debugMode)
276 | {
277 | rclone.StartInfo.CreateNoWindow = false;
278 | }
279 | rclone.StartInfo.UseShellExecute = false;
280 | _ = rclone.Start();
281 | rclone.StandardInput.WriteLine(command);
282 | rclone.StandardInput.Flush();
283 | rclone.StandardInput.Close();
284 |
285 | string output = rclone.StandardOutput.ReadToEnd();
286 | string error = rclone.StandardError.ReadToEnd();
287 | rclone.WaitForExit();
288 |
289 | if (error.Contains("There is not enough space"))
290 | {
291 | _ = FlexibleMessageBox.Show(Program.form, $"There isn't enough disk space to download this game.\r\nPlease ensure you have at least 2x the game size available in {Environment.CurrentDirectory} and try again.",
292 | "NOT ENOUGH SPACE",
293 | MessageBoxButtons.OK,
294 | MessageBoxIcon.Error);
295 | return new ProcessOutput("Download failed.", string.Empty);
296 | }
297 |
298 | if (error.Contains("Only one usage of each socket address (protocol/network address/port) is normally permitted")) {
299 | _ = Logger.Log(error, LogLevel.ERROR);
300 | return new ProcessOutput("Failed to fetch from public mirror.", "Failed to fetch from public mirror.\nYou may have a running RCLONE Task!\nCheck your Task Manager, Sort by Network Usage, and kill the process Rsync for Cloud Storage/Rclone");
301 | }
302 |
303 | else if (error.Contains("400 Bad Request")
304 | || error.Contains("cannot fetch token")
305 | || error.Contains("authError")
306 | || error.Contains("quota")
307 | || error.Contains("exceeded")
308 | || error.Contains("directory not found")
309 | || error.Contains("Failed to"))
310 | {
311 | _ = Logger.Log(error, LogLevel.ERROR);
312 | return new ProcessOutput("Failed to fetch from public mirror.", "Failed to fetch from public mirror.");
313 | }
314 | else
315 | {
316 | prcoutput.Output = output;
317 | prcoutput.Error = error;
318 | }
319 |
320 | if (!output.Contains("Game Name;Release Name;") && !output.Contains("package:") && !output.Contains(".meta"))
321 | {
322 | if (!string.IsNullOrWhiteSpace(error))
323 | {
324 | _ = Logger.Log($"Rclone error: {error}\n", LogLevel.ERROR);
325 | }
326 |
327 | if (!string.IsNullOrWhiteSpace(output))
328 | {
329 | _ = Logger.Log($"Rclone Output: {output}");
330 | }
331 | }
332 |
333 | return prcoutput;
334 | }
335 | }
336 | }
337 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # This repo is no longer maintained.
2 |
3 |
4 |
5 | # androidsideloader
6 | 
7 | 
8 | This repo
9 | [](https://github.com/nerdunit/androidsideloader/releases)
10 | New repo
11 | [](https://github.com/VRPirates/rookie/releases)
12 | 
13 |
14 | androidsideloader uses the GPL license, any forks of it must have their source code made public on the internet.
15 |
16 | ## !IMPORTANT!
17 |
18 | This app may be buggy and have problems.
19 |
20 | ### This app might get detected as malware, however both the sideloader and the sideloader launcher are open source. And obviously, it isn't.
21 | See:
22 | https://www.virustotal.com/gui/file/46b6e24a03a6670dfbbde6e6f06caac05f2f9486115ef7bd77e0b568df7e5342/detection
23 |
--------------------------------------------------------------------------------
/Resources/Pattern.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdunit/androidsideloader/f11d282c8bcb8f7b9c005a26995a6d4952d05276/Resources/Pattern.png
--------------------------------------------------------------------------------
/Resources/SearchGlass.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdunit/androidsideloader/f11d282c8bcb8f7b9c005a26995a6d4952d05276/Resources/SearchGlass.PNG
--------------------------------------------------------------------------------
/Resources/ajax-loader.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdunit/androidsideloader/f11d282c8bcb8f7b9c005a26995a6d4952d05276/Resources/ajax-loader.gif
--------------------------------------------------------------------------------
/Resources/battery.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdunit/androidsideloader/f11d282c8bcb8f7b9c005a26995a6d4952d05276/Resources/battery.png
--------------------------------------------------------------------------------
/Resources/battery1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdunit/androidsideloader/f11d282c8bcb8f7b9c005a26995a6d4952d05276/Resources/battery1.png
--------------------------------------------------------------------------------
/Resources/battery11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdunit/androidsideloader/f11d282c8bcb8f7b9c005a26995a6d4952d05276/Resources/battery11.png
--------------------------------------------------------------------------------
/Resources/pattern_cubes-1_1_1_0-0_0_1__000000_212121.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdunit/androidsideloader/f11d282c8bcb8f7b9c005a26995a6d4952d05276/Resources/pattern_cubes-1_1_1_0-0_0_1__000000_212121.png
--------------------------------------------------------------------------------
/Resources/pattern_herringbone-2_1_3_0-0_90_1__000000_1c1c1c.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdunit/androidsideloader/f11d282c8bcb8f7b9c005a26995a6d4952d05276/Resources/pattern_herringbone-2_1_3_0-0_90_1__000000_1c1c1c.png
--------------------------------------------------------------------------------
/Resources/splash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdunit/androidsideloader/f11d282c8bcb8f7b9c005a26995a6d4952d05276/Resources/splash.jpg
--------------------------------------------------------------------------------
/Resources/splashimage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdunit/androidsideloader/f11d282c8bcb8f7b9c005a26995a6d4952d05276/Resources/splashimage.png
--------------------------------------------------------------------------------
/Rookie Offline.cmd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | @echo off
5 |
6 | for /f "tokens=* usebackq" %%f in (`dir /b AndroidSideloader*.exe`) do (set "sideloader=%%f" & goto :next)
7 | :next
8 |
9 | echo %sideloader%
10 | start "" "%sideloader%" "--offline"
--------------------------------------------------------------------------------
/RoundButton.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Drawing;
4 | using System.Drawing.Drawing2D;
5 | using System.Windows.Forms;
6 |
7 | namespace AndroidSideloader
8 | {
9 | [Description("Rounded Button")]
10 | public class RoundButton : Control, IButtonControl
11 | {
12 | #region Variables
13 | private int radius;
14 | private MouseState state;
15 | private RoundedRectangleF roundedRect;
16 | private Color inactive1, inactive2, active1, active2;
17 | private Color strokeColor;
18 | private bool stroke;
19 |
20 | public bool Stroke
21 | {
22 | get => stroke;
23 | set
24 | {
25 | stroke = value;
26 | Invalidate();
27 | }
28 | }
29 |
30 | public Color StrokeColor
31 | {
32 | get => strokeColor;
33 | set
34 | {
35 | strokeColor = value;
36 | Invalidate();
37 | }
38 | }
39 | #endregion
40 | #region RoundButton
41 | public RoundButton()
42 | {
43 | Width = 65;
44 | Height = 30;
45 | stroke = false;
46 | strokeColor = Color.Gray;
47 | inactive1 = Color.FromArgb(44, 188, 210);
48 | inactive2 = Color.FromArgb(33, 167, 188);
49 | active1 = Color.FromArgb(64, 168, 183);
50 | active2 = Color.FromArgb(36, 164, 183);
51 |
52 |
53 | radius = 10;
54 | roundedRect = new RoundedRectangleF(Width, Height, radius);
55 |
56 | SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer |
57 | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor |
58 | ControlStyles.UserPaint, true);
59 | BackColor = Color.Transparent;
60 | ForeColor = Color.Black;
61 | Font = new System.Drawing.Font("Comic Sans MS", 10, FontStyle.Bold);
62 | state = MouseState.Leave;
63 | Transparency = false;
64 | }
65 | #endregion
66 | #region Events
67 | protected override void OnPaint(PaintEventArgs e)
68 | {
69 | #region Transparency
70 | if (Transparency)
71 | {
72 | Transparenter.MakeTransparent(this, e.Graphics);
73 | }
74 | #endregion
75 |
76 | #region Drawing
77 | e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
78 | roundedRect = new RoundedRectangleF(Width, Height, radius);
79 | e.Graphics.FillRectangle(Brushes.Transparent, ClientRectangle);
80 |
81 | int R1 = (active1.R + inactive1.R) / 2;
82 | int G1 = (active1.G + inactive1.G) / 2;
83 | int B1 = (active1.B + inactive1.B) / 2;
84 |
85 | int R2 = (active2.R + inactive2.R) / 2;
86 | int G2 = (active2.G + inactive2.G) / 2;
87 | int B2 = (active2.B + inactive2.B) / 2;
88 |
89 | Rectangle rect = new Rectangle(0, 0, Width, Height);
90 |
91 | if (Enabled)
92 | {
93 | if (state == MouseState.Leave)
94 | {
95 | using (LinearGradientBrush inactiveGB = new LinearGradientBrush(rect, inactive1, inactive2, 90f))
96 | {
97 | e.Graphics.FillPath(inactiveGB, roundedRect.Path);
98 | }
99 | }
100 | else if (state == MouseState.Enter)
101 | {
102 | using (LinearGradientBrush activeGB = new LinearGradientBrush(rect, active1, active2, 90f))
103 | {
104 | e.Graphics.FillPath(activeGB, roundedRect.Path);
105 | }
106 | }
107 | else if (state == MouseState.Down)
108 | {
109 | using (LinearGradientBrush downGB = new LinearGradientBrush(rect, Color.FromArgb(R1, G1, B1), Color.FromArgb(R2, G2, B2), 90f))
110 | {
111 | e.Graphics.FillPath(downGB, roundedRect.Path);
112 | }
113 | }
114 |
115 | if (stroke)
116 | {
117 | using (Pen pen = new Pen(strokeColor, 1))
118 | using (GraphicsPath path = new RoundedRectangleF(Width - (radius > 0 ? 0 : 1), Height - (radius > 0 ? 0 : 1), radius).Path)
119 | {
120 | e.Graphics.DrawPath(pen, path);
121 | }
122 | }
123 | }
124 | else
125 | {
126 | Color linear1 = Color.FromArgb(190, 190, 190);
127 | Color linear2 = Color.FromArgb(210, 210, 210);
128 | using (LinearGradientBrush inactiveGB = new LinearGradientBrush(rect, linear1, linear2, 90f))
129 | {
130 | e.Graphics.FillPath(inactiveGB, roundedRect.Path);
131 | e.Graphics.DrawPath(new Pen(inactiveGB), roundedRect.Path);
132 | }
133 | }
134 |
135 |
136 | #endregion
137 |
138 | #region Text Drawing
139 | using (StringFormat sf = new StringFormat()
140 | {
141 | LineAlignment = StringAlignment.Center,
142 | Alignment = StringAlignment.Center,
143 | })
144 | using (Brush brush = new SolidBrush(ForeColor))
145 | {
146 | e.Graphics.DrawString(Text, Font, brush, ClientRectangle, sf);
147 | }
148 | #endregion
149 | base.OnPaint(e);
150 | }
151 |
152 | protected override void OnMouseDoubleClick(MouseEventArgs e)
153 | {
154 | base.OnMouseDoubleClick(e);
155 | base.OnClick(e);
156 | }
157 | protected override void OnClick(EventArgs e)
158 | {
159 | base.OnClick(e);
160 | }
161 | protected override void OnEnabledChanged(EventArgs e)
162 | {
163 | Invalidate();
164 | base.OnEnabledChanged(e);
165 | }
166 | protected override void OnResize(EventArgs e)
167 | {
168 | Invalidate();
169 | base.OnResize(e);
170 | }
171 | protected override void OnMouseEnter(EventArgs e)
172 | {
173 | state = MouseState.Enter;
174 | base.OnMouseEnter(e);
175 | Invalidate();
176 | }
177 | protected override void OnMouseLeave(EventArgs e)
178 | {
179 | state = MouseState.Leave;
180 | base.OnMouseLeave(e);
181 | Invalidate();
182 | }
183 | protected override void OnMouseDown(MouseEventArgs e)
184 | {
185 | Capture = false;
186 | state = MouseState.Down;
187 | base.OnMouseDown(e);
188 | Invalidate();
189 | }
190 | protected override void OnMouseUp(MouseEventArgs e)
191 | {
192 | if (state != MouseState.Leave)
193 | {
194 | state = MouseState.Enter;
195 | }
196 |
197 | base.OnMouseUp(e);
198 | Invalidate();
199 | }
200 | #endregion
201 | #region Properties
202 |
203 |
204 | public int Radius
205 | {
206 | get => radius;
207 | set
208 | {
209 | radius = value;
210 | Invalidate();
211 | }
212 | }
213 | public Color Inactive1
214 | {
215 | get => inactive1;
216 | set
217 | {
218 | inactive1 = value;
219 | Invalidate();
220 | }
221 | }
222 | public Color Inactive2
223 | {
224 | get => inactive2;
225 | set
226 | {
227 | inactive2 = value;
228 | Invalidate();
229 | }
230 | }
231 | public Color Active1
232 | {
233 | get => active1;
234 | set
235 | {
236 | active1 = value;
237 | Invalidate();
238 | }
239 | }
240 | public Color Active2
241 | {
242 | get => active2;
243 | set
244 | {
245 | active2 = value;
246 | Invalidate();
247 | }
248 | }
249 | public bool Transparency { get; set; }
250 | public override string Text
251 | {
252 | get => base.Text;
253 | set
254 | {
255 | base.Text = value;
256 | Invalidate();
257 | }
258 | }
259 | public override Color ForeColor
260 | {
261 | get => base.ForeColor;
262 | set
263 | {
264 | base.ForeColor = value;
265 | Invalidate();
266 | }
267 | }
268 |
269 | public DialogResult DialogResult
270 | {
271 | get => System.Windows.Forms.DialogResult.OK;
272 | set
273 | {
274 | }
275 | }
276 |
277 | public void NotifyDefault(bool value)
278 | {
279 | }
280 |
281 | public void PerformClick()
282 | {
283 | OnClick(EventArgs.Empty);
284 | }
285 | #endregion
286 | }
287 | public enum MouseState
288 | {
289 | Enter,
290 | Leave,
291 | Down,
292 | Up,
293 | }
294 |
295 | }
--------------------------------------------------------------------------------
/RoundedRectangleF.cs:
--------------------------------------------------------------------------------
1 | using System.Drawing;
2 | using System.Drawing.Drawing2D;
3 |
4 | namespace AndroidSideloader
5 | {
6 | public class RoundedRectangleF
7 | {
8 | private Point location;
9 | private readonly float x, y;
10 | private readonly float width, height;
11 |
12 |
13 | public RoundedRectangleF(float width, float height, float radius, float x = 0, float y = 0)
14 | {
15 |
16 | location = new Point(0, 0);
17 | Radius = radius;
18 | this.x = x;
19 | this.y = y;
20 | this.width = width;
21 | this.height = height;
22 | Path = new GraphicsPath();
23 | if (radius <= 0)
24 | {
25 | Path.AddRectangle(new RectangleF(x, y, width, height));
26 | return;
27 | }
28 | RectangleF upperLeftRect = new RectangleF(x, y, 2 * radius, 2 * radius);
29 | RectangleF upperRightRect = new RectangleF(width - (2 * radius) - 1, x, 2 * radius, 2 * radius);
30 | RectangleF lowerLeftRect = new RectangleF(x, height - (2 * radius) - 1, 2 * radius, 2 * radius);
31 | RectangleF lowerRightRect = new RectangleF(width - (2 * radius) - 1, height - (2 * radius) - 1, 2 * radius, 2 * radius);
32 |
33 | Path.AddArc(upperLeftRect, 180, 90);
34 | Path.AddArc(upperRightRect, 270, 90);
35 | Path.AddArc(lowerRightRect, 0, 90);
36 | Path.AddArc(lowerLeftRect, 90, 90);
37 | Path.CloseAllFigures();
38 |
39 | }
40 | public RoundedRectangleF()
41 | {
42 | }
43 | public GraphicsPath Path { get; }
44 | public RectangleF Rect => new RectangleF(x, y, width, height);
45 | public float Radius { get; set; }
46 |
47 | }
48 | }
--------------------------------------------------------------------------------
/SelectFolder.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Reflection;
3 | using System.Windows.Forms;
4 |
5 | namespace AndroidSideloader
6 | {
7 |
8 | ///
9 | /// Present the Windows Vista-style open file dialog to select a folder. Fall back for older Windows Versions
10 | ///
11 |
12 | //Coded by Erike from stackoverflow (https://stackoverflow.com/users/57611/erike)
13 | public class FolderSelectDialog
14 | {
15 | private string _initialDirectory;
16 | private string _title;
17 |
18 | public string InitialDirectory
19 | {
20 | get => string.IsNullOrEmpty(_initialDirectory) ? Environment.CurrentDirectory : _initialDirectory;
21 | set => _initialDirectory = value;
22 | }
23 | public string Title
24 | {
25 | get => _title ?? "Select a folder";
26 | set => _title = value;
27 | }
28 | public string FileName { get; private set; } = "";
29 |
30 | public bool Show() { return Show(IntPtr.Zero); }
31 |
32 | /// Handle of the control or window to be the parent of the file dialog
33 | /// true if the user clicks OK
34 | public bool Show(IntPtr hWndOwner)
35 | {
36 | ShowDialogResult result = Environment.OSVersion.Version.Major >= 6
37 | ? VistaDialog.Show(hWndOwner, InitialDirectory, Title)
38 | : ShowXpDialog(hWndOwner, InitialDirectory, Title);
39 | FileName = result.FileName;
40 | return result.Result;
41 | }
42 |
43 | private struct ShowDialogResult
44 | {
45 | public bool Result { get; set; }
46 | public string FileName { get; set; }
47 | }
48 |
49 | private static ShowDialogResult ShowXpDialog(IntPtr ownerHandle, string initialDirectory, string title)
50 | {
51 | FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog
52 | {
53 | Description = title,
54 | SelectedPath = initialDirectory,
55 | ShowNewFolderButton = false
56 | };
57 | ShowDialogResult dialogResult = new ShowDialogResult();
58 | if (folderBrowserDialog.ShowDialog(new WindowWrapper(ownerHandle)) == DialogResult.OK)
59 | {
60 | dialogResult.Result = true;
61 | dialogResult.FileName = folderBrowserDialog.SelectedPath;
62 | }
63 | return dialogResult;
64 | }
65 |
66 | private static class VistaDialog
67 | {
68 | private const string c_foldersFilter = "Folders|\n";
69 |
70 | private const BindingFlags c_flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
71 | private static readonly Assembly s_windowsFormsAssembly = typeof(FileDialog).Assembly;
72 | private static readonly Type s_iFileDialogType = s_windowsFormsAssembly.GetType("System.Windows.Forms.FileDialogNative+IFileDialog");
73 | private static readonly MethodInfo s_createVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("CreateVistaDialog", c_flags);
74 | private static readonly MethodInfo s_onBeforeVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("OnBeforeVistaDialog", c_flags);
75 | private static readonly MethodInfo s_getOptionsMethodInfo = typeof(FileDialog).GetMethod("GetOptions", c_flags);
76 | private static readonly MethodInfo s_setOptionsMethodInfo = s_iFileDialogType.GetMethod("SetOptions", c_flags);
77 | private static readonly uint s_fosPickFoldersBitFlag = (uint)s_windowsFormsAssembly
78 | .GetType("System.Windows.Forms.FileDialogNative+FOS")
79 | .GetField("FOS_PICKFOLDERS")
80 | .GetValue(null);
81 | private static readonly ConstructorInfo s_vistaDialogEventsConstructorInfo = s_windowsFormsAssembly
82 | .GetType("System.Windows.Forms.FileDialog+VistaDialogEvents")
83 | .GetConstructor(c_flags, null, new[] { typeof(FileDialog) }, null);
84 | private static readonly MethodInfo s_adviseMethodInfo = s_iFileDialogType.GetMethod("Advise");
85 | private static readonly MethodInfo s_unAdviseMethodInfo = s_iFileDialogType.GetMethod("Unadvise");
86 | private static readonly MethodInfo s_showMethodInfo = s_iFileDialogType.GetMethod("Show");
87 |
88 | public static ShowDialogResult Show(IntPtr ownerHandle, string initialDirectory, string title)
89 | {
90 | OpenFileDialog openFileDialog = new OpenFileDialog
91 | {
92 | AddExtension = false,
93 | CheckFileExists = false,
94 | DereferenceLinks = true,
95 | Filter = c_foldersFilter,
96 | InitialDirectory = initialDirectory,
97 | Multiselect = false,
98 | Title = title
99 | };
100 |
101 | object iFileDialog = s_createVistaDialogMethodInfo.Invoke(openFileDialog, new object[] { });
102 | _ = s_onBeforeVistaDialogMethodInfo.Invoke(openFileDialog, new[] { iFileDialog });
103 | _ = s_setOptionsMethodInfo.Invoke(iFileDialog, new object[] { (uint)s_getOptionsMethodInfo.Invoke(openFileDialog, new object[] { }) | s_fosPickFoldersBitFlag });
104 | object[] adviseParametersWithOutputConnectionToken = new[] { s_vistaDialogEventsConstructorInfo.Invoke(new object[] { openFileDialog }), 0U };
105 | _ = s_adviseMethodInfo.Invoke(iFileDialog, adviseParametersWithOutputConnectionToken);
106 |
107 | try
108 | {
109 | int retVal = (int)s_showMethodInfo.Invoke(iFileDialog, new object[] { ownerHandle });
110 | return new ShowDialogResult
111 | {
112 | Result = retVal == 0,
113 | FileName = openFileDialog.FileName
114 | };
115 | }
116 | finally
117 | {
118 | _ = s_unAdviseMethodInfo.Invoke(iFileDialog, new[] { adviseParametersWithOutputConnectionToken[1] });
119 | }
120 | }
121 | }
122 |
123 | // Wrap an IWin32Window around an IntPtr
124 | private class WindowWrapper : IWin32Window
125 | {
126 | public WindowWrapper(IntPtr handle) { Handle = handle; }
127 | public IntPtr Handle { get; }
128 | }
129 | }
130 |
131 | }
132 |
--------------------------------------------------------------------------------
/SergeUtils.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdunit/androidsideloader/f11d282c8bcb8f7b9c005a26995a6d4952d05276/SergeUtils.dll
--------------------------------------------------------------------------------
/SettingsForm.cs:
--------------------------------------------------------------------------------
1 | using JR.Utils.GUI.Forms;
2 | using System;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Windows.Forms;
6 |
7 | namespace AndroidSideloader
8 | {
9 | public partial class SettingsForm : Form
10 | {
11 | public SettingsForm()
12 | {
13 | InitializeComponent();
14 | }
15 |
16 | private void SettingsForm_Load(object sender, EventArgs e)
17 | {
18 | CenterToParent();
19 | intSettings();
20 | intToolTips();
21 | }
22 |
23 | //Init form objects with values from settings
24 | private void intSettings()
25 | {
26 | checkForUpdatesCheckBox.Checked = Properties.Settings.Default.checkForUpdates;
27 | enableMessageBoxesCheckBox.Checked = Properties.Settings.Default.enableMessageBoxes;
28 | deleteAfterInstallCheckBox.Checked = Properties.Settings.Default.deleteAllAfterInstall;
29 | updateConfigCheckBox.Checked = Properties.Settings.Default.autoUpdateConfig;
30 | userJsonOnGameInstall.Checked = Properties.Settings.Default.userJsonOnGameInstall;
31 | nodevicemodeBox.Checked = Properties.Settings.Default.nodevicemode;
32 | bmbfBox.Checked = Properties.Settings.Default.BMBFchecked;
33 | AutoReinstBox.Checked = Properties.Settings.Default.AutoReinstall;
34 | trailersOn.Checked = Properties.Settings.Default.TrailersOn;
35 | singleThread.Checked = Properties.Settings.Default.singleThreadMode;
36 | virtualFilesystemCompatibilityCheckbox.Checked = Properties.Settings.Default.virtualFilesystemCompatibility;
37 | if (nodevicemodeBox.Checked)
38 | {
39 | deleteAfterInstallCheckBox.Checked = false;
40 | deleteAfterInstallCheckBox.Enabled = false;
41 | }
42 | }
43 |
44 | private void intToolTips()
45 | {
46 | ToolTip checkForUpdatesToolTip = new ToolTip();
47 | checkForUpdatesToolTip.SetToolTip(checkForUpdatesCheckBox, "If this is checked, the software will check for available updates");
48 | ToolTip enableMessageBoxesToolTip = new ToolTip();
49 | enableMessageBoxesToolTip.SetToolTip(enableMessageBoxesCheckBox, "If this is checked, the software will display message boxes after every completed task");
50 | ToolTip deleteAfterInstallToolTip = new ToolTip();
51 | deleteAfterInstallToolTip.SetToolTip(deleteAfterInstallCheckBox, "If this is checked, the software will delete all game files after downloading and installing a game from a remote server");
52 | }
53 |
54 | public void btnUploadDebug_click(object sender, EventArgs e)
55 | {
56 | if (File.Exists($"{Properties.Settings.Default.CurrentLogPath}"))
57 | {
58 | string UUID = SideloaderUtilities.UUID();
59 | string debugLogPath = $"{Environment.CurrentDirectory}\\{UUID}.log";
60 | System.IO.File.Copy("debuglog.txt", debugLogPath);
61 |
62 | Clipboard.SetText(UUID);
63 |
64 | _ = RCLONE.runRcloneCommand_UploadConfig($"copy \"{debugLogPath}\" RSL-gameuploads:DebugLogs");
65 | _ = MessageBox.Show($"Your debug log has been copied to the server. ID: {UUID}");
66 | }
67 | }
68 |
69 |
70 | public void btnResetDebug_click(object sender, EventArgs e)
71 | {
72 | if (File.Exists($"{Properties.Settings.Default.CurrentLogPath}"))
73 | {
74 | File.Delete($"{Properties.Settings.Default.CurrentLogPath}");
75 | }
76 |
77 | if (File.Exists($"{Environment.CurrentDirectory}\\debuglog.txt"))
78 | {
79 | File.Delete($"{Environment.CurrentDirectory}\\debuglog.txt");
80 | }
81 | }
82 |
83 | //Apply settings
84 | private void applyButton_Click(object sender, EventArgs e)
85 | {
86 | Properties.Settings.Default.Save();
87 | _ = FlexibleMessageBox.Show(this, "Settings applied!");
88 | }
89 |
90 | private void checkForUpdatesCheckBox_CheckedChanged(object sender, EventArgs e)
91 | {
92 | Properties.Settings.Default.checkForUpdates = checkForUpdatesCheckBox.Checked;
93 | }
94 |
95 | private void enableMessageBoxesCheckBox_CheckedChanged(object sender, EventArgs e)
96 | {
97 | Properties.Settings.Default.enableMessageBoxes = enableMessageBoxesCheckBox.Checked;
98 | }
99 |
100 | private void resetSettingsButton_Click(object sender, EventArgs e)
101 | {
102 | Properties.Settings.Default.Reset();
103 | Properties.Settings.Default.customDownloadDir = false;
104 | Properties.Settings.Default.customBackupDir = false;
105 | MainForm.backupFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), $"Rookie Backups");
106 | Properties.Settings.Default.downloadDir = Environment.CurrentDirectory.ToString();
107 | intSettings();
108 | }
109 |
110 | private void deleteAfterInstallCheckBox_CheckedChanged(object sender, EventArgs e)
111 | {
112 | Properties.Settings.Default.deleteAllAfterInstall = deleteAfterInstallCheckBox.Checked;
113 | }
114 |
115 | private void updateConfigCheckBox_CheckedChanged(object sender, EventArgs e)
116 | {
117 | Properties.Settings.Default.autoUpdateConfig = updateConfigCheckBox.Checked;
118 | }
119 |
120 | private void userJsonOnGameInstall_CheckedChanged(object sender, EventArgs e)
121 | {
122 | Properties.Settings.Default.userJsonOnGameInstall = userJsonOnGameInstall.Checked;
123 | }
124 |
125 | private void SettingsForm_KeyPress(object sender, KeyPressEventArgs e)
126 | {
127 | if (e.KeyChar == (char)Keys.Escape)
128 | {
129 | Close();
130 | }
131 | }
132 |
133 | private void SettingsForm_Leave(object sender, EventArgs e)
134 | {
135 | Close();
136 | }
137 |
138 | private void Form_KeyDown(object sender, KeyEventArgs e)
139 | {
140 | if (e.KeyCode == Keys.Escape)
141 | {
142 | Close();
143 | }
144 | }
145 | protected override bool ProcessDialogKey(Keys keyData)
146 | {
147 | if (Form.ModifierKeys == Keys.None && keyData == Keys.Escape)
148 | {
149 | Close();
150 | return true;
151 | }
152 | return base.ProcessDialogKey(keyData);
153 | }
154 |
155 | private void nodevicemodeBox_CheckedChanged(object sender, EventArgs e)
156 | {
157 | Properties.Settings.Default.nodevicemode = nodevicemodeBox.Checked;
158 | if (!nodevicemodeBox.Checked)
159 | {
160 | deleteAfterInstallCheckBox.Checked = true;
161 | Properties.Settings.Default.deleteAllAfterInstall = true;
162 | deleteAfterInstallCheckBox.Enabled = true;
163 | }
164 | else
165 | {
166 | deleteAfterInstallCheckBox.Checked = false;
167 | Properties.Settings.Default.deleteAllAfterInstall = false;
168 | deleteAfterInstallCheckBox.Enabled = false;
169 | }
170 | Properties.Settings.Default.Save();
171 | }
172 |
173 | private void bmbfBox_CheckedChanged(object sender, EventArgs e)
174 | {
175 | Properties.Settings.Default.BMBFchecked = bmbfBox.Checked;
176 | Properties.Settings.Default.Save();
177 | }
178 |
179 | private void AutoReinstBox_CheckedChanged(object sender, EventArgs e)
180 | {
181 | Properties.Settings.Default.AutoReinstall = AutoReinstBox.Checked;
182 | Properties.Settings.Default.Save();
183 | }
184 |
185 | private void trailersOn_CheckedChanged(object sender, EventArgs e)
186 | {
187 | Properties.Settings.Default.TrailersOn = trailersOn.Checked;
188 | Properties.Settings.Default.Save();
189 | }
190 |
191 | private void AutoReinstBox_Click(object sender, EventArgs e)
192 | {
193 | if (AutoReinstBox.Checked)
194 | {
195 | DialogResult dialogResult = FlexibleMessageBox.Show(this, "WARNING: This box enables automatic reinstall when installs fail,\ndue to some games not allowing " +
196 | "access to their save data (less than 5%) this\noption can lead to losing your progress." +
197 | " However with this option\nchecked when installs fail you won't have to agree to a prompt to perform\nthe reinstall. " +
198 | "(ideal when installing from a queue).\n\nNOTE: If your usb/wireless adb connection is extremely slow this option can\ncause larger" +
199 | "apk file installations to fail. Enable anyway?", "WARNING", MessageBoxButtons.OKCancel);
200 | if (dialogResult == DialogResult.Cancel)
201 | {
202 | AutoReinstBox.Checked = false;
203 | }
204 | }
205 |
206 | }
207 |
208 | private void btnOpenDebug_Click(object sender, EventArgs e)
209 | {
210 | if (File.Exists($"{Environment.CurrentDirectory}\\debuglog.txt"))
211 | {
212 | _ = Process.Start($"{Environment.CurrentDirectory}\\debuglog.txt");
213 | }
214 | }
215 |
216 | private void setDownloadDirectory_Click(object sender, EventArgs e)
217 | {
218 | if (downloadDirectorySetter.ShowDialog() == DialogResult.OK)
219 | {
220 | Properties.Settings.Default.customDownloadDir = true;
221 | Properties.Settings.Default.downloadDir = downloadDirectorySetter.SelectedPath;
222 | Properties.Settings.Default.Save();
223 | }
224 | }
225 |
226 | private void setBackupDirectory_Click(object sender, EventArgs e)
227 | {
228 | if (backupDirectorySetter.ShowDialog() == DialogResult.OK)
229 | {
230 | Properties.Settings.Default.customBackupDir = true;
231 | Properties.Settings.Default.backupDir = backupDirectorySetter.SelectedPath;
232 | MainForm.backupFolder = Properties.Settings.Default.backupDir;
233 | Properties.Settings.Default.Save();
234 | }
235 | }
236 |
237 | private void singleThread_CheckedChanged(object sender, EventArgs e)
238 | {
239 | Properties.Settings.Default.singleThreadMode = singleThread.Checked;
240 | Properties.Settings.Default.Save();
241 | }
242 |
243 | private void virtualFilesystemCompatibilityCheckbox_CheckedChanged(object sender, EventArgs e)
244 | {
245 | Properties.Settings.Default.virtualFilesystemCompatibility = virtualFilesystemCompatibilityCheckbox.Checked;
246 | Properties.Settings.Default.Save();
247 | }
248 | }
249 | }
250 |
251 |
--------------------------------------------------------------------------------
/Sideloader Launcher.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdunit/androidsideloader/f11d282c8bcb8f7b9c005a26995a6d4952d05276/Sideloader Launcher.exe
--------------------------------------------------------------------------------
/Sideloader/ProcessOutput.cs:
--------------------------------------------------------------------------------
1 | namespace AndroidSideloader
2 | {
3 | public class ProcessOutput
4 | {
5 | public string Output;
6 | public string Error;
7 |
8 | public ProcessOutput(string output = "", string error = "")
9 | {
10 | Output = output;
11 | Error = error;
12 | }
13 |
14 | public static ProcessOutput operator +(ProcessOutput a, ProcessOutput b)
15 | {
16 | return new ProcessOutput(a.Output + b.Output, a.Error + b.Error);
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Sideloader/RCLONE.cs:
--------------------------------------------------------------------------------
1 | using AndroidSideloader.Utilities;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Net;
7 | using System.Security.Cryptography;
8 |
9 | namespace AndroidSideloader
10 | {
11 | internal class rcloneFolder
12 | {
13 | public string Path { get; set; }
14 | public string Name { get; set; }
15 | public string Size { get; set; }
16 | public string ModTime { get; set; }
17 | }
18 |
19 | internal class SideloaderRCLONE
20 | {
21 | public static List RemotesList = new List();
22 |
23 | public static string RcloneGamesFolder = "Quest Games";
24 |
25 | //This shit sucks but i'll switch to programatically adding indexes from the gamelist txt sometimes maybe
26 |
27 | public static int GameNameIndex = 0;
28 | public static int ReleaseNameIndex = 1;
29 | public static int PackageNameIndex = 2;
30 | public static int VersionCodeIndex = 3;
31 | public static int ReleaseAPKPathIndex = 4;
32 | public static int VersionNameIndex = 5;
33 |
34 | public static List gameProperties = new List();
35 | /* Game Name
36 | * Release Name
37 | * Release APK Path
38 | * Package Name
39 | * Version Code
40 | * Version Name
41 | */
42 | public static List games = new List();
43 |
44 | public static string Nouns = Environment.CurrentDirectory + "\\nouns";
45 | public static string ThumbnailsFolder = Environment.CurrentDirectory + "\\thumbnails";
46 | public static string NotesFolder = Environment.CurrentDirectory + "\\notes";
47 |
48 | public static void UpdateNouns(string remote)
49 | {
50 | _ = Logger.Log($"Updating Nouns");
51 | _ = RCLONE.runRcloneCommand_DownloadConfig($"sync \"{remote}:{RcloneGamesFolder}/.meta/nouns\" \"{Nouns}\"");
52 | }
53 |
54 | public static void UpdateGamePhotos(string remote)
55 | {
56 | _ = Logger.Log($"Updating Thumbnails");
57 | _ = RCLONE.runRcloneCommand_DownloadConfig($"sync \"{remote}:{RcloneGamesFolder}/.meta/thumbnails\" \"{ThumbnailsFolder}\"");
58 | }
59 |
60 | public static void UpdateGameNotes(string remote)
61 | {
62 | _ = Logger.Log($"Updating Game Notes");
63 | _ = RCLONE.runRcloneCommand_DownloadConfig($"sync \"{remote}:{RcloneGamesFolder}/.meta/notes\" \"{NotesFolder}\"");
64 | }
65 |
66 | public static void UpdateMetadataFromPublic()
67 | {
68 | _ = Logger.Log($"Downloading Metadata");
69 | string rclonecommand =
70 | $"sync \":http:/meta.7z\" \"{Environment.CurrentDirectory}\"";
71 | _ = RCLONE.runRcloneCommand_PublicConfig(rclonecommand);
72 | }
73 |
74 | public static void ProcessMetadataFromPublic()
75 | {
76 | try
77 | {
78 | _ = Logger.Log($"Extracting Metadata");
79 | Zip.ExtractFile($"{Environment.CurrentDirectory}\\meta.7z", $"{Environment.CurrentDirectory}\\meta",
80 | MainForm.PublicConfigFile.Password);
81 |
82 | _ = Logger.Log($"Updating Metadata");
83 |
84 | if (Directory.Exists(Nouns))
85 | {
86 | Directory.Delete(Nouns, true);
87 | }
88 |
89 | if (Directory.Exists(ThumbnailsFolder))
90 | {
91 | Directory.Delete(ThumbnailsFolder, true);
92 | }
93 |
94 | if (Directory.Exists(NotesFolder))
95 | {
96 | Directory.Delete(NotesFolder, true);
97 | }
98 |
99 | Directory.Move($"{Environment.CurrentDirectory}\\meta\\.meta\\nouns", Nouns);
100 | Directory.Move($"{Environment.CurrentDirectory}\\meta\\.meta\\thumbnails", ThumbnailsFolder);
101 | Directory.Move($"{Environment.CurrentDirectory}\\meta\\.meta\\notes", NotesFolder);
102 |
103 | _ = Logger.Log($"Initializing Games List");
104 | string gameList = File.ReadAllText($"{Environment.CurrentDirectory}\\meta\\VRP-GameList.txt");
105 |
106 | string[] splitList = gameList.Split('\n');
107 | splitList = splitList.Skip(1).ToArray();
108 | foreach (string game in splitList)
109 | {
110 | if (game.Length > 1)
111 | {
112 | string[] splitGame = game.Split(';');
113 | games.Add(splitGame);
114 | }
115 | }
116 |
117 | Directory.Delete($"{Environment.CurrentDirectory}\\meta", true);
118 | }
119 | catch (Exception e)
120 | {
121 | _ = Logger.Log(e.Message);
122 | _ = Logger.Log(e.StackTrace);
123 | }
124 | }
125 |
126 | public static void RefreshRemotes()
127 | {
128 | _ = Logger.Log($"Refresh / List Remotes");
129 | RemotesList.Clear();
130 | string[] remotes = RCLONE.runRcloneCommand_DownloadConfig("listremotes").Output.Split('\n');
131 |
132 | _ = Logger.Log("Loaded following remotes: ");
133 | foreach (string r in remotes)
134 | {
135 | if (r.Length > 1)
136 | {
137 | string remote = r.Remove(r.Length - 1);
138 | if (remote.Contains("mirror"))
139 | {
140 | _ = Logger.Log(remote);
141 | RemotesList.Add(remote);
142 | }
143 | }
144 | }
145 | }
146 |
147 | public static void initGames(string remote)
148 | {
149 | _ = Logger.Log($"Initializing Games List");
150 |
151 | gameProperties.Clear();
152 | games.Clear();
153 | string tempGameList = RCLONE.runRcloneCommand_DownloadConfig($"cat \"{remote}:{RcloneGamesFolder}/VRP-GameList.txt\"").Output;
154 | if (MainForm.debugMode)
155 | {
156 | File.WriteAllText("VRP-GamesList.txt", tempGameList);
157 | }
158 | if (!tempGameList.Equals(""))
159 | {
160 | string[] gameListSplited = tempGameList.Split(new[] { '\n' });
161 | gameListSplited = gameListSplited.Skip(1).ToArray();
162 | foreach (string game in gameListSplited)
163 | {
164 | if (game.Length > 1)
165 | {
166 | string[] splitGame = game.Split(';');
167 | games.Add(splitGame);
168 | }
169 | }
170 | }
171 | }
172 |
173 | public static void updateDownloadConfig()
174 | {
175 | ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
176 | | SecurityProtocolType.Tls11
177 | | SecurityProtocolType.Tls12
178 | | SecurityProtocolType.Ssl3;
179 | _ = Logger.Log($"Attempting to Update Download Config");
180 | try
181 | {
182 | string configUrl = "https://wiki.vrpirates.club/downloads/vrp.download.config";
183 |
184 | HttpWebRequest getUrl = (HttpWebRequest)WebRequest.Create(configUrl);
185 | using (StreamReader responseReader = new StreamReader(getUrl.GetResponse().GetResponseStream()))
186 | {
187 | string resultString = responseReader.ReadToEnd();
188 |
189 | _ = Logger.Log($"Retrieved updated config from: {configUrl}");
190 |
191 | if (File.Exists(Environment.CurrentDirectory + "\\rclone\\vrp.download.config_new"))
192 | {
193 | File.Delete(Environment.CurrentDirectory + "\\rclone\\vrp.download.config_new");
194 | }
195 |
196 | File.Create(Environment.CurrentDirectory + "\\rclone\\vrp.download.config_new").Close();
197 | File.WriteAllText(Environment.CurrentDirectory + "\\rclone\\vrp.download.config_new", resultString);
198 |
199 | if (!File.Exists(Environment.CurrentDirectory + "\\rclone\\hash.txt"))
200 | {
201 | File.Create(Environment.CurrentDirectory + "\\rclone\\hash.txt").Close();
202 | }
203 |
204 | string newConfig = CalculateMD5(Environment.CurrentDirectory + "\\rclone\\vrp.download.config_new");
205 | string oldConfig = File.ReadAllText(Environment.CurrentDirectory + "\\rclone\\hash.txt");
206 |
207 | if (!File.Exists(Environment.CurrentDirectory + "\\rclone\\vrp.download.config"))
208 | {
209 | oldConfig = "Config Doesnt Exist!";
210 | }
211 |
212 | _ = Logger.Log($"Online Config Hash: {newConfig}; Local Config Hash: {oldConfig}");
213 |
214 | if (newConfig != oldConfig)
215 | {
216 | _ = Logger.Log($"Updated Config Hash is different than the current Config. Updating Configuration File.");
217 |
218 | if (File.Exists(Environment.CurrentDirectory + "\\rclone\\vrp.download.config"))
219 | {
220 | File.Delete(Environment.CurrentDirectory + "\\rclone\\vrp.download.config");
221 | }
222 |
223 | File.Move(Environment.CurrentDirectory + "\\rclone\\vrp.download.config_new", Environment.CurrentDirectory + "\\rclone\\vrp.download.config");
224 |
225 | File.WriteAllText(Environment.CurrentDirectory + "\\rclone\\hash.txt", string.Empty);
226 | File.WriteAllText(Environment.CurrentDirectory + "\\rclone\\hash.txt", newConfig);
227 | }
228 | else
229 | {
230 | _ = Logger.Log($"Updated Config Hash matches last download. Not updating.");
231 |
232 | if (File.Exists(Environment.CurrentDirectory + "\\rclone\\vrp.download.config_new"))
233 | {
234 | File.Delete(Environment.CurrentDirectory + "\\rclone\\vrp.download.config_new");
235 | }
236 | }
237 | }
238 | }
239 | catch { }
240 | }
241 |
242 | public static void updateUploadConfig()
243 | {
244 | ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
245 | | SecurityProtocolType.Tls11
246 | | SecurityProtocolType.Tls12
247 | | SecurityProtocolType.Ssl3;
248 | _ = Logger.Log($"Attempting to Update Upload Config");
249 | try
250 | {
251 | string configUrl = "https://wiki.vrpirates.club/downloads/vrp.upload.config";
252 |
253 | HttpWebRequest getUrl = (HttpWebRequest)WebRequest.Create(configUrl);
254 | using (StreamReader responseReader = new StreamReader(getUrl.GetResponse().GetResponseStream()))
255 | {
256 | string resultString = responseReader.ReadToEnd();
257 |
258 | _ = Logger.Log($"Retrieved updated config from: {configUrl}");
259 |
260 | File.WriteAllText(Environment.CurrentDirectory + "\\rclone\\vrp.upload.config", resultString);
261 |
262 | _ = Logger.Log("Upload config updated successfully.");
263 | }
264 | }
265 | catch (Exception e)
266 | {
267 | _ = Logger.Log($"Failed to update Upload config: {e.Message}", LogLevel.ERROR);
268 | }
269 | }
270 |
271 | public static void updatePublicConfig()
272 | {
273 | ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
274 | | SecurityProtocolType.Tls11
275 | | SecurityProtocolType.Tls12
276 | | SecurityProtocolType.Ssl3;
277 | _ = Logger.Log($"Attempting to Update Public Config");
278 | try
279 | {
280 | string configUrl = "https://wiki.vrpirates.club/downloads/vrp-public.json";
281 |
282 | HttpWebRequest getUrl = (HttpWebRequest)WebRequest.Create(configUrl);
283 | using (StreamReader responseReader = new StreamReader(getUrl.GetResponse().GetResponseStream()))
284 | {
285 | string resultString = responseReader.ReadToEnd();
286 |
287 | _ = Logger.Log($"Retrieved updated config from: {configUrl}");
288 |
289 | File.WriteAllText(Environment.CurrentDirectory + "\\vrp-public.json", resultString);
290 |
291 | _ = Logger.Log("Public config updated successfully.");
292 | }
293 | }
294 | catch (Exception e)
295 | {
296 | _ = Logger.Log($"Failed to update Public config: {e.Message}", LogLevel.ERROR);
297 | }
298 | }
299 |
300 | private static string CalculateMD5(string filename)
301 | {
302 | using (MD5 md5 = MD5.Create())
303 | {
304 | using (FileStream stream = File.OpenRead(filename))
305 | {
306 | byte[] hash = md5.ComputeHash(stream);
307 | return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
308 | }
309 | }
310 | }
311 | }
312 | }
--------------------------------------------------------------------------------
/Sideloader/Utilities.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Management;
4 | using System.Security.Cryptography;
5 | using System.Text;
6 |
7 | namespace AndroidSideloader
8 | {
9 | internal class SideloaderUtilities
10 | {
11 | public static bool CheckFolderIsObb(string path)
12 | {
13 | string[] files = Directory.GetFiles(path);
14 |
15 | foreach (string file in files)
16 | {
17 | if (file.EndsWith(".obb") || (Path.GetDirectoryName(file).Contains(".") && !Path.GetDirectoryName(file).Contains("_data")))
18 | {
19 | return true;
20 | }
21 | }
22 |
23 | return false;
24 | }
25 |
26 | private static string uuid = null;
27 | public static string UUID()
28 | {
29 | if (uuid != null)
30 | {
31 | return uuid;
32 | }
33 |
34 | StringBuilder sb = new StringBuilder();
35 |
36 | ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2",
37 | "SELECT * FROM Win32_Processor");
38 |
39 | foreach (ManagementObject queryObj in searcher.Get())
40 | {
41 | _ = sb.Append(queryObj["NumberOfCores"]);
42 | _ = sb.Append(queryObj["ProcessorId"]);
43 | _ = sb.Append(queryObj["Name"]);
44 | _ = sb.Append(queryObj["SocketDesignation"]);
45 | }
46 |
47 | searcher = new ManagementObjectSearcher("root\\CIMV2",
48 | "SELECT * FROM Win32_BIOS");
49 |
50 | foreach (ManagementObject queryObj in searcher.Get())
51 | {
52 | _ = sb.Append(queryObj["Manufacturer"]);
53 | _ = sb.Append(queryObj["Name"]);
54 | _ = sb.Append(queryObj["Version"]);
55 |
56 | }
57 |
58 | searcher = new ManagementObjectSearcher("root\\CIMV2",
59 | "SELECT * FROM Win32_BaseBoard");
60 |
61 | foreach (ManagementObject queryObj in searcher.Get())
62 | {
63 | _ = sb.Append(queryObj["Product"]);
64 | }
65 |
66 | byte[] bytes = Encoding.ASCII.GetBytes(sb.ToString());
67 | SHA256Managed sha = new SHA256Managed();
68 |
69 | byte[] hash = sha.ComputeHash(bytes);
70 |
71 | uuid = BitConverter.ToString(hash).Replace("-", "");
72 | return uuid;
73 | }
74 |
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/Splash.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace AndroidSideloader
2 | {
3 | partial class Splash
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Splash));
32 | this.SuspendLayout();
33 | //
34 | // Splash
35 | //
36 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
37 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
38 | this.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("$this.BackgroundImage")));
39 | this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
40 | this.CausesValidation = false;
41 | this.ClientSize = new System.Drawing.Size(427, 250);
42 | this.ControlBox = false;
43 | this.DoubleBuffered = true;
44 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
45 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
46 | this.Margin = new System.Windows.Forms.Padding(2);
47 | this.Name = "Splash";
48 | this.ShowIcon = false;
49 | this.ShowInTaskbar = false;
50 | this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
51 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
52 | this.Text = "Splash";
53 | this.ResumeLayout(false);
54 |
55 | }
56 |
57 | #endregion
58 | }
59 | }
--------------------------------------------------------------------------------
/Splash.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Forms;
2 |
3 | namespace AndroidSideloader
4 | {
5 | public partial class Splash : Form
6 | {
7 | public Splash()
8 | {
9 | InitializeComponent();
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Transparenter.cs:
--------------------------------------------------------------------------------
1 | using System.Drawing;
2 | using System.Windows.Forms;
3 |
4 | namespace AndroidSideloader
5 | {
6 | public class Transparenter
7 | {
8 | public static void MakeTransparent(Control control, Graphics g)
9 | {
10 | Control parent = control.Parent;
11 | if (parent == null)
12 | {
13 | return;
14 | }
15 |
16 | Rectangle bounds = control.Bounds;
17 | Control.ControlCollection siblings = parent.Controls;
18 | int index = siblings.IndexOf(control);
19 | Bitmap behind = null;
20 | for (int i = siblings.Count - 1; i > index; i--)
21 | {
22 | Control c = siblings[i];
23 | if (!c.Bounds.IntersectsWith(bounds))
24 | {
25 | continue;
26 | }
27 |
28 | if (behind == null)
29 | {
30 | behind = new Bitmap(control.Parent.ClientSize.Width, control.Parent.ClientSize.Height);
31 | }
32 |
33 | c.DrawToBitmap(behind, c.Bounds);
34 | }
35 | if (behind == null)
36 | {
37 | return;
38 | }
39 |
40 | g.DrawImage(behind, control.ClientRectangle, bounds, GraphicsUnit.Pixel);
41 | behind.Dispose();
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/UpdateForm.Designer.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace AndroidSideloader
3 | {
4 | partial class UpdateForm
5 | {
6 | ///
7 | /// Required designer variable.
8 | ///
9 | private System.ComponentModel.IContainer components = null;
10 |
11 | ///
12 | /// Clean up any resources being used.
13 | ///
14 | /// true if managed resources should be disposed; otherwise, false.
15 | protected override void Dispose(bool disposing)
16 | {
17 | if (disposing && (components != null))
18 | {
19 | components.Dispose();
20 | }
21 | base.Dispose(disposing);
22 | }
23 |
24 | #region Windows Form Designer generated code
25 |
26 | ///
27 | /// Required method for Designer support - do not modify
28 | /// the contents of this method with the code editor.
29 | ///
30 | private void InitializeComponent()
31 | {
32 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(UpdateForm));
33 | this.panel1 = new System.Windows.Forms.Panel();
34 | this.YesUpdate = new AndroidSideloader.RoundButton();
35 | this.panel3 = new System.Windows.Forms.Panel();
36 | this.UpdateTextBox = new System.Windows.Forms.RichTextBox();
37 | this.UpdateVerLabel = new System.Windows.Forms.Label();
38 | this.CurVerLabel = new System.Windows.Forms.Label();
39 | this.SkipUpdate = new System.Windows.Forms.Label();
40 | this.panel1.SuspendLayout();
41 | this.panel3.SuspendLayout();
42 | this.SuspendLayout();
43 | //
44 | // panel1
45 | //
46 | this.panel1.BackColor = global::AndroidSideloader.Properties.Settings.Default.BackColor;
47 | this.panel1.BackgroundImage = global::AndroidSideloader.Properties.Resources.pattern_cubes_1_1_1_0_0_0_1__000000_212121;
48 | this.panel1.Controls.Add(this.YesUpdate);
49 | this.panel1.Controls.Add(this.panel3);
50 | this.panel1.Controls.Add(this.UpdateVerLabel);
51 | this.panel1.Controls.Add(this.CurVerLabel);
52 | this.panel1.Controls.Add(this.SkipUpdate);
53 | this.panel1.DataBindings.Add(new System.Windows.Forms.Binding("BackColor", global::AndroidSideloader.Properties.Settings.Default, "BackColor", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
54 | this.panel1.Location = new System.Drawing.Point(-6, -6);
55 | this.panel1.Name = "panel1";
56 | this.panel1.Size = new System.Drawing.Size(474, 305);
57 | this.panel1.TabIndex = 5;
58 | this.panel1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.UpdateForm_MouseDown);
59 | this.panel1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.UpdateForm_MouseMove);
60 | this.panel1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.UpdateForm_MouseUp);
61 | //
62 | // YesUpdate
63 | //
64 | this.YesUpdate.Active1 = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(40)))), ((int)(((byte)(40)))));
65 | this.YesUpdate.Active2 = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(40)))), ((int)(((byte)(40)))));
66 | this.YesUpdate.BackColor = System.Drawing.Color.Transparent;
67 | this.YesUpdate.DialogResult = System.Windows.Forms.DialogResult.OK;
68 | this.YesUpdate.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F);
69 | this.YesUpdate.ForeColor = System.Drawing.Color.White;
70 | this.YesUpdate.Inactive1 = System.Drawing.Color.FromArgb(((int)(((byte)(25)))), ((int)(((byte)(25)))), ((int)(((byte)(25)))));
71 | this.YesUpdate.Inactive2 = System.Drawing.Color.FromArgb(((int)(((byte)(25)))), ((int)(((byte)(25)))), ((int)(((byte)(25)))));
72 | this.YesUpdate.Location = new System.Drawing.Point(339, 245);
73 | this.YesUpdate.Name = "YesUpdate";
74 | this.YesUpdate.Radius = 5;
75 | this.YesUpdate.Size = new System.Drawing.Size(111, 31);
76 | this.YesUpdate.Stroke = true;
77 | this.YesUpdate.StrokeColor = System.Drawing.Color.FromArgb(((int)(((byte)(74)))), ((int)(((byte)(74)))), ((int)(((byte)(74)))));
78 | this.YesUpdate.TabIndex = 2;
79 | this.YesUpdate.Text = "Update Now";
80 | this.YesUpdate.Transparency = false;
81 | this.YesUpdate.Click += new System.EventHandler(this.YesUpdate_Click);
82 | //
83 | // panel3
84 | //
85 | this.panel3.BackColor = global::AndroidSideloader.Properties.Settings.Default.SubButtonColor;
86 | this.panel3.Controls.Add(this.UpdateTextBox);
87 | this.panel3.DataBindings.Add(new System.Windows.Forms.Binding("BackColor", global::AndroidSideloader.Properties.Settings.Default, "SubButtonColor", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
88 | this.panel3.Location = new System.Drawing.Point(21, 19);
89 | this.panel3.Name = "panel3";
90 | this.panel3.Size = new System.Drawing.Size(432, 218);
91 | this.panel3.TabIndex = 0;
92 | //
93 | // UpdateTextBox
94 | //
95 | this.UpdateTextBox.BackColor = global::AndroidSideloader.Properties.Settings.Default.ComboBoxColor;
96 | this.UpdateTextBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
97 | this.UpdateTextBox.DataBindings.Add(new System.Windows.Forms.Binding("BackColor", global::AndroidSideloader.Properties.Settings.Default, "ComboBoxColor", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
98 | this.UpdateTextBox.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.25F);
99 | this.UpdateTextBox.ForeColor = System.Drawing.Color.White;
100 | this.UpdateTextBox.Location = new System.Drawing.Point(12, 8);
101 | this.UpdateTextBox.Margin = new System.Windows.Forms.Padding(6);
102 | this.UpdateTextBox.Name = "UpdateTextBox";
103 | this.UpdateTextBox.ReadOnly = true;
104 | this.UpdateTextBox.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.Vertical;
105 | this.UpdateTextBox.Size = new System.Drawing.Size(408, 200);
106 | this.UpdateTextBox.TabIndex = 1;
107 | this.UpdateTextBox.Text = "";
108 | this.UpdateTextBox.TextChanged += new System.EventHandler(this.UpdateTextBox_TextChanged);
109 | this.UpdateTextBox.MouseDown += new System.Windows.Forms.MouseEventHandler(this.UpdateForm_MouseDown);
110 | this.UpdateTextBox.MouseMove += new System.Windows.Forms.MouseEventHandler(this.UpdateForm_MouseMove);
111 | this.UpdateTextBox.MouseUp += new System.Windows.Forms.MouseEventHandler(this.UpdateForm_MouseUp);
112 | //
113 | // UpdateVerLabel
114 | //
115 | this.UpdateVerLabel.AutoSize = true;
116 | this.UpdateVerLabel.BackColor = System.Drawing.Color.Transparent;
117 | this.UpdateVerLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F);
118 | this.UpdateVerLabel.ForeColor = System.Drawing.SystemColors.Control;
119 | this.UpdateVerLabel.Location = new System.Drawing.Point(21, 261);
120 | this.UpdateVerLabel.Name = "UpdateVerLabel";
121 | this.UpdateVerLabel.Size = new System.Drawing.Size(94, 15);
122 | this.UpdateVerLabel.TabIndex = 3;
123 | this.UpdateVerLabel.Text = "Update Version:";
124 | //
125 | // CurVerLabel
126 | //
127 | this.CurVerLabel.AutoSize = true;
128 | this.CurVerLabel.BackColor = System.Drawing.Color.Transparent;
129 | this.CurVerLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F);
130 | this.CurVerLabel.ForeColor = System.Drawing.SystemColors.Control;
131 | this.CurVerLabel.Location = new System.Drawing.Point(21, 245);
132 | this.CurVerLabel.Name = "CurVerLabel";
133 | this.CurVerLabel.Size = new System.Drawing.Size(94, 15);
134 | this.CurVerLabel.TabIndex = 2;
135 | this.CurVerLabel.Text = "Current Version:";
136 | //
137 | // SkipUpdate
138 | //
139 | this.SkipUpdate.AutoSize = true;
140 | this.SkipUpdate.BackColor = System.Drawing.Color.Transparent;
141 | this.SkipUpdate.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
142 | this.SkipUpdate.Font = new System.Drawing.Font("Microsoft Sans Serif", 8F);
143 | this.SkipUpdate.ForeColor = System.Drawing.Color.Silver;
144 | this.SkipUpdate.Location = new System.Drawing.Point(374, 279);
145 | this.SkipUpdate.Name = "SkipUpdate";
146 | this.SkipUpdate.Size = new System.Drawing.Size(76, 13);
147 | this.SkipUpdate.TabIndex = 4;
148 | this.SkipUpdate.Text = "𝖲𝖪𝖨𝖯 𝖥𝖮𝖱 𝖭𝖮𝖶";
149 | this.SkipUpdate.Click += new System.EventHandler(this.SkipUpdate_Click);
150 | //
151 | // UpdateForm
152 | //
153 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
154 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
155 | this.AutoValidate = System.Windows.Forms.AutoValidate.EnablePreventFocusChange;
156 | this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(29)))), ((int)(((byte)(29)))), ((int)(((byte)(29)))));
157 | this.ClientSize = new System.Drawing.Size(462, 291);
158 | this.ControlBox = false;
159 | this.Controls.Add(this.panel1);
160 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
161 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
162 | this.Name = "UpdateForm";
163 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
164 | this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.UpdateForm_MouseDown);
165 | this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.UpdateForm_MouseMove);
166 | this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.UpdateForm_MouseUp);
167 | this.panel1.ResumeLayout(false);
168 | this.panel1.PerformLayout();
169 | this.panel3.ResumeLayout(false);
170 | this.ResumeLayout(false);
171 |
172 | }
173 |
174 | #endregion
175 |
176 | private System.Windows.Forms.Label SkipUpdate;
177 | private System.Windows.Forms.Label CurVerLabel;
178 | private System.Windows.Forms.Label UpdateVerLabel;
179 | private System.Windows.Forms.Panel panel3;
180 | private System.Windows.Forms.RichTextBox UpdateTextBox;
181 | private System.Windows.Forms.Panel panel1;
182 | private RoundButton YesUpdate;
183 | }
184 | }
--------------------------------------------------------------------------------
/UpdateForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.Windows.Forms;
4 |
5 | namespace AndroidSideloader
6 | {
7 | public partial class UpdateForm : Form
8 | {
9 | private bool mouseDown;
10 | private Point lastLocation;
11 |
12 | public UpdateForm()
13 | {
14 | InitializeComponent();
15 | CenterToScreen();
16 | CurVerLabel.Text += " " + Updater.LocalVersion;
17 | UpdateVerLabel.Text += " " + Updater.currentVersion;
18 | UpdateTextBox.Text = Updater.changelog;
19 | }
20 |
21 | private void YesUpdate_Click(object sender, EventArgs e)
22 | {
23 | Updater.doUpdate();
24 | Close();
25 | }
26 |
27 | private void SkipUpdate_Click(object sender, EventArgs e)
28 | {
29 | Close();
30 | }
31 |
32 | private void UpdateTextBox_TextChanged(object sender, EventArgs e)
33 | {
34 |
35 | }
36 |
37 | private void UpdateForm_MouseDown(object sender, MouseEventArgs e)
38 | {
39 | mouseDown = true;
40 | lastLocation = e.Location;
41 | }
42 |
43 | private void UpdateForm_MouseMove(object sender, MouseEventArgs e)
44 | {
45 | if (mouseDown)
46 | {
47 | Location = new Point(
48 | Location.X - lastLocation.X + e.X, Location.Y - lastLocation.Y + e.Y);
49 |
50 | Update();
51 | }
52 | }
53 |
54 | private void UpdateForm_MouseUp(object sender, MouseEventArgs e)
55 | {
56 | mouseDown = false;
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/Updater.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Net;
4 | using System.Net.Http;
5 | using System.Threading.Tasks;
6 |
7 | namespace AndroidSideloader
8 | {
9 | internal class Updater
10 | {
11 | public static string AppName { get; set; }
12 | public static string Repository { get; set; }
13 | private static readonly string RawGitHubUrl = "https://raw.githubusercontent.com/VRPirates/rookie";
14 | private static readonly string GitHubUrl = "https://github.com/VRPirates/rookie";
15 |
16 | public static readonly string LocalVersion = "2.22";
17 | public static string currentVersion = string.Empty;
18 | public static string changelog = string.Empty;
19 |
20 | // Check if there is a new version of the sideloader
21 | private static async Task IsUpdateAvailableAsync()
22 | {
23 | using (HttpClient client = new HttpClient())
24 | {
25 | try
26 | {
27 | currentVersion = await client.GetStringAsync($"{RawGitHubUrl}/master/version");
28 | changelog = await client.GetStringAsync($"{RawGitHubUrl}/master/changelog.txt");
29 | currentVersion = currentVersion.Trim();
30 | }
31 | catch (HttpRequestException)
32 | {
33 | return false;
34 | }
35 | }
36 |
37 | return LocalVersion.Trim() != currentVersion;
38 | }
39 |
40 | // Call this to ask the user if they want to update
41 | public static async Task Update()
42 | {
43 | if (await IsUpdateAvailableAsync())
44 | {
45 | UpdateForm upForm = new UpdateForm();
46 | _ = upForm.ShowDialog();
47 | }
48 | }
49 |
50 | // If the user wants to update
51 | public static void doUpdate()
52 | {
53 | try
54 | {
55 | ADB.RunAdbCommandToString("kill-server");
56 |
57 | using (WebClient fileClient = new WebClient())
58 | {
59 | ServicePointManager.Expect100Continue = true;
60 | ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
61 |
62 | Logger.Log($"Downloading update from {GitHubUrl}/releases/download/v{currentVersion}/{AppName}.exe to {AppName} v{currentVersion}.exe");
63 | fileClient.DownloadFile($"{GitHubUrl}/releases/download/v{currentVersion}/{AppName}.exe", $"{AppName} v{currentVersion}.exe");
64 |
65 | Logger.Log($"Starting {AppName} v{currentVersion}.exe");
66 | Process.Start($"{AppName} v{currentVersion}.exe");
67 | }
68 |
69 | // Delete current version
70 | AndroidSideloader.Utilities.GeneralUtilities.Melt();
71 | }
72 | catch (Exception ex)
73 | {
74 | // Handle specific exceptions that might occur during the update process
75 | Logger.Log($"Update failed: {ex.Message}");
76 | }
77 | }
78 | }
79 | }
--------------------------------------------------------------------------------
/UsernameForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace AndroidSideloader
2 | {
3 | partial class UsernameForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(UsernameForm));
32 | this.textBox1 = new System.Windows.Forms.TextBox();
33 | this.button1 = new AndroidSideloader.RoundButton();
34 | this.SuspendLayout();
35 | //
36 | // textBox1
37 | //
38 | this.textBox1.BackColor = global::AndroidSideloader.Properties.Settings.Default.TextBoxColor;
39 | this.textBox1.DataBindings.Add(new System.Windows.Forms.Binding("BackColor", global::AndroidSideloader.Properties.Settings.Default, "TextBoxColor", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
40 | this.textBox1.DataBindings.Add(new System.Windows.Forms.Binding("Font", global::AndroidSideloader.Properties.Settings.Default, "FontStyle", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
41 | this.textBox1.Font = global::AndroidSideloader.Properties.Settings.Default.FontStyle;
42 | this.textBox1.ForeColor = System.Drawing.Color.White;
43 | this.textBox1.Location = new System.Drawing.Point(13, 13);
44 | this.textBox1.Name = "textBox1";
45 | this.textBox1.Size = new System.Drawing.Size(418, 24);
46 | this.textBox1.TabIndex = 0;
47 | this.textBox1.Text = "Enter your username here";
48 | //
49 | // button1
50 | //
51 | this.button1.Active1 = System.Drawing.Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(45)))));
52 | this.button1.Active2 = System.Drawing.Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(45)))));
53 | this.button1.BackColor = System.Drawing.Color.Transparent;
54 | this.button1.DialogResult = System.Windows.Forms.DialogResult.OK;
55 | this.button1.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F);
56 | this.button1.ForeColor = System.Drawing.Color.White;
57 | this.button1.Inactive1 = System.Drawing.Color.FromArgb(((int)(((byte)(25)))), ((int)(((byte)(25)))), ((int)(((byte)(25)))));
58 | this.button1.Inactive2 = System.Drawing.Color.FromArgb(((int)(((byte)(25)))), ((int)(((byte)(25)))), ((int)(((byte)(25)))));
59 | this.button1.Location = new System.Drawing.Point(13, 51);
60 | this.button1.Name = "button1";
61 | this.button1.Radius = 5;
62 | this.button1.Size = new System.Drawing.Size(418, 34);
63 | this.button1.Stroke = true;
64 | this.button1.StrokeColor = System.Drawing.Color.FromArgb(((int)(((byte)(74)))), ((int)(((byte)(74)))), ((int)(((byte)(74)))));
65 | this.button1.TabIndex = 2;
66 | this.button1.Text = "Create User.Json";
67 | this.button1.Transparency = false;
68 | this.button1.Click += new System.EventHandler(this.button1_Click);
69 | //
70 | // UsernameForm
71 | //
72 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
73 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
74 | this.BackColor = global::AndroidSideloader.Properties.Settings.Default.BackColor;
75 | this.BackgroundImage = global::AndroidSideloader.Properties.Resources.pattern_cubes_1_1_1_0_0_0_1__000000_212121;
76 | this.ClientSize = new System.Drawing.Size(443, 100);
77 | this.Controls.Add(this.button1);
78 | this.Controls.Add(this.textBox1);
79 | this.DataBindings.Add(new System.Windows.Forms.Binding("BackColor", global::AndroidSideloader.Properties.Settings.Default, "BackColor", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
80 | this.ForeColor = System.Drawing.Color.White;
81 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
82 | this.MaximumSize = new System.Drawing.Size(459, 139);
83 | this.MinimumSize = new System.Drawing.Size(459, 139);
84 | this.Name = "UsernameForm";
85 | this.ShowIcon = false;
86 | this.Text = "USER.JSON";
87 | this.Load += new System.EventHandler(this.usernameForm_Load);
88 | this.ResumeLayout(false);
89 | this.PerformLayout();
90 |
91 | }
92 |
93 | #endregion
94 |
95 | private System.Windows.Forms.TextBox textBox1;
96 | private RoundButton button1;
97 | }
98 | }
--------------------------------------------------------------------------------
/UsernameForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using System.Windows.Forms;
7 |
8 | namespace AndroidSideloader
9 | {
10 | public partial class UsernameForm : Form
11 | {
12 | public UsernameForm()
13 | {
14 | InitializeComponent();
15 | }
16 |
17 | private string defaultText;
18 |
19 | private void usernameForm_Load(object sender, EventArgs e)
20 | {
21 | defaultText = textBox1.Text;
22 | }
23 |
24 |
25 | private async void button1_Click(object sender, EventArgs e)
26 | {
27 | if (textBox1.Text == defaultText || textBox1.Text.Length == 0)
28 | {
29 | _ = MessageBox.Show("Please enter your username first");
30 | return;
31 | }
32 |
33 | Thread t1 = new Thread(() =>
34 | {
35 | createUserJson(textBox1.Text);
36 |
37 | })
38 | {
39 | IsBackground = true
40 | };
41 | t1.Start();
42 |
43 | while (t1.IsAlive)
44 | {
45 | await Task.Delay(100);
46 | }
47 |
48 | MainForm.notify("Done");
49 |
50 | }
51 |
52 | public static List userJsons = new List(new string[] { "user.json", "vrmoo.cn.json", "qq1091481055.json", "dollarvr.com.json" });
53 |
54 | public static void createUserJson(string username)
55 | {
56 | _ = ADB.RunAdbCommandToString($"shell settings put global username {username}");
57 | foreach (string jsonFileName in userJsons)
58 | {
59 | createUserJsonByName(username, jsonFileName);
60 | _ = ADB.RunAdbCommandToString("push \"" + Environment.CurrentDirectory + $"\\{jsonFileName}\" " + " /sdcard/");
61 | File.Delete(jsonFileName);
62 | }
63 |
64 | }
65 | public static void createUserJsonByName(string username, string jsonName)
66 | {
67 | switch (jsonName)
68 | {
69 | case "user.json":
70 | File.WriteAllText("user.json", "{\"username\":\"" + username + "\"}");
71 | break;
72 | case "vrmoo.cn.json":
73 | File.WriteAllText("vrmoo.cn.json", "{\"username\":\"" + username + "\"}");
74 | break;
75 | case "qq1091481055.json":
76 | File.WriteAllText("qq1091481055.json", "{\n \"username\":\"" + username + "\"\n }");
77 | break;
78 | case "dollarvr.com.json":
79 | File.WriteAllText("dollarvr.com.json", "{\n \"username\":\"" + username + "\"\n }");
80 | break;
81 | }
82 |
83 |
84 | }
85 |
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/Utilities/GeneralUtilities.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Windows.Forms;
7 |
8 | namespace AndroidSideloader.Utilities
9 | {
10 | internal class GeneralUtilities
11 | {
12 | public static long GetDirectorySize(string folderPath)
13 | {
14 | DirectoryInfo di = new DirectoryInfo(folderPath);
15 | return di.EnumerateFiles("*", SearchOption.AllDirectories).Sum(fi => fi.Length);
16 | }
17 |
18 | public static string RandomPackageName()
19 | {
20 | return $"com.{GeneralUtilities.randomString(rand.Next(3, 8))}.{GeneralUtilities.randomString(rand.Next(3, 8))}";
21 | }
22 | public static string CommandOutput = "";
23 | public static string CommandError = "";
24 |
25 | public static void ExecuteCommand(string command)
26 | {
27 | ProcessStartInfo processInfo = new ProcessStartInfo("cmd.exe", "/c " + command)
28 | {
29 | CreateNoWindow = true,
30 | UseShellExecute = false,
31 | RedirectStandardError = true,
32 | RedirectStandardOutput = true
33 | };
34 |
35 | Process process = Process.Start(processInfo);
36 |
37 | process.OutputDataReceived += (object sender, DataReceivedEventArgs e) =>
38 | CommandOutput += e.Data;
39 | process.BeginOutputReadLine();
40 |
41 | process.ErrorDataReceived += (object sender, DataReceivedEventArgs e) =>
42 | CommandError += e.Data;
43 | process.BeginErrorReadLine();
44 |
45 | process.WaitForExit();
46 |
47 | process.Close();
48 | }
49 |
50 | public static void Melt()
51 | {
52 | _ = Process.Start(new ProcessStartInfo()
53 | {
54 | Arguments = "/C choice /C Y /N /D Y /T 5 & Del \"" + Application.ExecutablePath + "\"",
55 | WindowStyle = ProcessWindowStyle.Hidden,
56 | CreateNoWindow = true,
57 | FileName = "cmd.exe"
58 | });
59 | Environment.Exit(0);
60 | }
61 |
62 | private static readonly Random rand = new Random();
63 | public static string randomString(int length)
64 | {
65 | string valid = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
66 | StringBuilder res = new StringBuilder();
67 |
68 | int randomInteger = rand.Next(0, valid.Length);
69 | while (0 < length--)
70 | {
71 | _ = res.Append(valid[randomInteger]);
72 | randomInteger = rand.Next(0, valid.Length);
73 | }
74 | return res.ToString();
75 | }
76 |
77 | public static ProcessOutput startProcess(string process, string path, string command)
78 | {
79 | _ = Logger.Log($"Ran process {process} with command {command} in path {path}");
80 | Process cmd = new Process();
81 | cmd.StartInfo.FileName = "cmd.exe";
82 | cmd.StartInfo.RedirectStandardInput = true;
83 | cmd.StartInfo.RedirectStandardOutput = true;
84 | cmd.StartInfo.RedirectStandardError = true;
85 | cmd.StartInfo.WorkingDirectory = path;
86 | cmd.StartInfo.CreateNoWindow = true;
87 | cmd.StartInfo.UseShellExecute = false;
88 | _ = cmd.Start();
89 | cmd.StandardInput.WriteLine(command);
90 | cmd.StandardInput.Flush();
91 | cmd.StandardInput.Close();
92 | cmd.WaitForExit();
93 | string error = cmd.StandardError.ReadToEnd();
94 | string output = cmd.StandardOutput.ReadToEnd();
95 | _ = Logger.Log($"Output: {output}");
96 | _ = Logger.Log($"Error: {error}", LogLevel.ERROR);
97 | return new ProcessOutput(output, error);
98 | }
99 |
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/Utilities/Logger.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Text;
4 |
5 | namespace AndroidSideloader
6 | {
7 | public enum LogLevel
8 | {
9 | DEBUG,
10 | INFO,
11 | WARNING,
12 | ERROR,
13 | TRACE,
14 | FATAL
15 | }
16 |
17 | public static class Logger
18 | {
19 | private static readonly object lockObject = new object();
20 | private static string logFilePath = Properties.Settings.Default.CurrentLogPath;
21 |
22 | public static bool Log(string text, LogLevel logLevel = LogLevel.INFO, bool ret = true)
23 | {
24 | if (string.IsNullOrWhiteSpace(text) || text.Length <= 5)
25 | return ret;
26 |
27 | string time = DateTime.UtcNow.ToString("hh:mm:ss.fff tt (UTC): ");
28 | string newline = text.Length > 40 && text.Contains("\n") ? "\n\n" : "\n";
29 | string logEntry = time + "[" + logLevel.ToString().ToUpper() + "] [" + GetCallerInfo() + "] " + text + newline;
30 |
31 | try
32 | {
33 | lock (lockObject)
34 | {
35 | File.AppendAllText(logFilePath, logEntry);
36 | }
37 | }
38 | catch
39 | {
40 | // Handle the exception if necessary
41 | }
42 |
43 | return ret;
44 | }
45 |
46 | private static string GetCallerInfo()
47 | {
48 | System.Diagnostics.StackTrace stackTrace = new System.Diagnostics.StackTrace(true);
49 | if (stackTrace.FrameCount >= 3)
50 | {
51 | var frame = stackTrace.GetFrame(2);
52 | var method = frame.GetMethod();
53 | string className = method.DeclaringType?.Name;
54 | string methodName = method.Name;
55 | string callerInfo = $"{className}.{methodName}";
56 | return callerInfo;
57 | }
58 |
59 | return string.Empty;
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Utilities/StringUtilities.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 |
3 | namespace AndroidSideloader.Utilities
4 | {
5 | internal class StringUtilities
6 | {
7 | public static string RemoveEverythingAfterFirst(string s, string removeMe)
8 | {
9 | int index = s.IndexOf(removeMe);
10 | if (index > 0)
11 | {
12 | s = s.Substring(0, index);
13 | }
14 |
15 | return s;
16 | }
17 |
18 | public static string RemoveEverythingAfterLast(string s, string removeMe)
19 | {
20 | int index = s.LastIndexOf(removeMe);
21 | if (index > 0)
22 | {
23 | s = s.Substring(0, index);
24 | }
25 |
26 | return s;
27 | }
28 |
29 | public static string RemoveEverythingBeforeFirst(string s, string removeMe)
30 | {
31 | int index = s.IndexOf(removeMe);
32 | if (index > 0)
33 | {
34 | s = s.Substring(index);
35 | }
36 |
37 | return s;
38 | }
39 |
40 | public static string KeepOnlyNumbers(string s)
41 | {
42 | string numbers = "0123456789";
43 | string a = "";
44 | foreach (char ch in s)
45 | {
46 | if (numbers.Contains(ch))
47 | {
48 | a += ch;
49 | }
50 | }
51 | return a;
52 | }
53 |
54 | public static string RemoveEverythingBeforeLast(string s, string removeMe)
55 | {
56 | int index = s.LastIndexOf(removeMe);
57 | if (index > 0)
58 | {
59 | s = s.Substring(index);
60 | }
61 |
62 | return s;
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Utilities/UpdateGameData.cs:
--------------------------------------------------------------------------------
1 | namespace AndroidSideloader.Utilities
2 | {
3 | internal class UpdateGameData
4 | {
5 | public UpdateGameData(string gameName, string packageName, ulong installedVersionInt)
6 | {
7 | GameName = gameName;
8 | Packagename = packageName;
9 | InstalledVersionInt = installedVersionInt;
10 | }
11 | public string GameName { get; set; }
12 | public string Packagename { get; set; }
13 |
14 | public ulong InstalledVersionInt { get; set; }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Utilities/UploadGame.cs:
--------------------------------------------------------------------------------
1 | namespace AndroidSideloader.Utilities
2 | {
3 | internal class UploadGame
4 | {
5 | public UploadGame(string Uploadcommand, string Pckgcommand, string Uploadgamename, ulong Uploadversion, bool isUpdate)
6 | {
7 | this.Pckgcommand = Pckgcommand;
8 | this.Uploadgamename = Uploadgamename;
9 | this.Uploadversion = Uploadversion;
10 | this.isUpdate = isUpdate;
11 | }
12 | public UploadGame()
13 | {
14 |
15 | }
16 | public bool isUpdate { get; set; }
17 |
18 | public string Pckgcommand { get; set; }
19 |
20 | public string Uploadgamename { get; set; }
21 |
22 | public ulong Uploadversion { get; set; }
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Utilities/Zip.cs:
--------------------------------------------------------------------------------
1 | using JR.Utils.GUI.Forms;
2 | using System;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Net;
7 | using System.Windows.Forms;
8 |
9 | namespace AndroidSideloader.Utilities
10 | {
11 | internal class Zip
12 | {
13 | public static void ExtractFile(string sourceArchive, string destination)
14 | {
15 | string args = $"x \"{sourceArchive}\" -y -o\"{destination}\"";
16 | DoExtract(args);
17 | }
18 |
19 | public static void ExtractFile(string sourceArchive, string destination, string password)
20 | {
21 | string args = $"x \"{sourceArchive}\" -y -o\"{destination}\" -p\"{password}\"";
22 | DoExtract(args);
23 | }
24 |
25 | private static void DoExtract(string args)
26 | {
27 | if (!File.Exists(Environment.CurrentDirectory + "\\7z.exe") || !File.Exists(Environment.CurrentDirectory + "\\7z.dll"))
28 | {
29 | _ = Logger.Log("Begin download 7-zip");
30 | WebClient client = new WebClient();
31 | client.DownloadFile("https://github.com/VRPirates/rookie/raw/master/7z.exe", "7z.exe");
32 | client.DownloadFile("https://github.com/VRPirates/rookie/raw/master/7z.dll", "7z.dll");
33 | _ = Logger.Log("Complete download 7-zip");
34 | }
35 | ProcessStartInfo pro = new ProcessStartInfo
36 | {
37 | WindowStyle = ProcessWindowStyle.Hidden,
38 | FileName = "7z.exe",
39 | Arguments = args,
40 | CreateNoWindow = true,
41 | UseShellExecute = false,
42 | RedirectStandardInput = true,
43 | RedirectStandardError = true,
44 | RedirectStandardOutput = true
45 | };
46 |
47 | _ = Logger.Log($"Extract: 7z {string.Join(" ", args.Split(' ').Where(a => !a.StartsWith("-p")))}");
48 |
49 | Process x = Process.Start(pro);
50 | x.WaitForExit();
51 | if (x.ExitCode != 0)
52 | {
53 | string error = x.StandardError.ReadToEnd();
54 |
55 | if (error.Contains("There is not enough space on the disk"))
56 | {
57 | _ = FlexibleMessageBox.Show(Program.form, $"Not enough space to extract archive.\r\nCheck free space in {Environment.CurrentDirectory} and try again.",
58 | "NOT ENOUGH SPACE",
59 | MessageBoxButtons.OK,
60 | MessageBoxIcon.Error);
61 | }
62 | _ = Logger.Log(x.StandardOutput.ReadToEnd());
63 | _ = Logger.Log(error, LogLevel.ERROR);
64 | throw new ApplicationException($"Extracting failed, status code {x.ExitCode}");
65 | }
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/aapt.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdunit/androidsideloader/f11d282c8bcb8f7b9c005a26995a6d4952d05276/aapt.exe
--------------------------------------------------------------------------------
/adb.7z:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdunit/androidsideloader/f11d282c8bcb8f7b9c005a26995a6d4952d05276/adb.7z
--------------------------------------------------------------------------------
/adb2.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdunit/androidsideloader/f11d282c8bcb8f7b9c005a26995a6d4952d05276/adb2.zip
--------------------------------------------------------------------------------
/androidsideloader.7z:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdunit/androidsideloader/f11d282c8bcb8f7b9c005a26995a6d4952d05276/androidsideloader.7z
--------------------------------------------------------------------------------
/changelog.txt:
--------------------------------------------------------------------------------
1 | RSL 2.22
2 |
3 | - Fix: Crash on failed extractions.
4 | - Fix: Trailers controls not functioning properly.
5 | - Fix: No Device Mode having the wrong output message.
6 | - Chore: Remove ADB.WakeDevice() due to being non-functional.
7 | - Chore: Make changeTitlebarToDevice less prone to crashes and more robust.
--------------------------------------------------------------------------------
/donators.txt:
--------------------------------------------------------------------------------
1 | CC0E0834BFEBFBFF000906E9;5000;ROOKIE.WTF
2 | 184204E0178BFBFF00870F10;0;Flow
3 | E5148390BFEBFBFF000906EA;250;Gotard
4 | 5ECC5497178BFBFF00870F10;1024;Saidis21
5 | B0374BE2BFEBFBFF00040651;0;ecirbaf
6 | 926C60A8178BFBFF00800F82;250;ThePhantomPickaxe
7 | 2A8C5999BFEBFBFF0001067A;0;karl
8 | 80ACB80FBFEBFBFF000206C2;4096;JJ-4
9 | 9AA172C9BFEBFBFF000906ED;1024;Clayton Bigsby
10 | 645C9EADBFEBFBFF000906EA;5000;Heracide
11 | 1C51D0CD178BFBFF00870F10;0;Mr.Tibby
12 | 287B5C6CBFEBFBFF000906EA;0;videobeer
--------------------------------------------------------------------------------
/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdunit/androidsideloader/f11d282c8bcb8f7b9c005a26995a6d4952d05276/icon.ico
--------------------------------------------------------------------------------
/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/version:
--------------------------------------------------------------------------------
1 | 2.22
--------------------------------------------------------------------------------
/warning.png:
--------------------------------------------------------------------------------
1 | ignore this, it is for backward compatibility
--------------------------------------------------------------------------------