├── .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 | ![GitHub last commit](https://img.shields.io/github/last-commit/VRPirates/rookie) 7 | ![GitHub release (latest by date)](https://img.shields.io/github/v/release/VRPirates/rookie) 8 | This repo 9 | [![Downloads (this repo)](https://img.shields.io/github/downloads/nerdunit/androidsideloader/total.svg)](https://github.com/nerdunit/androidsideloader/releases) 10 | New repo 11 | [![Downloads (new repo)](https://img.shields.io/github/downloads/VRPirates/rookie/total.svg)](https://github.com/VRPirates/rookie/releases) 12 | ![Issues](https://img.shields.io/github/issues/VRPirates/rookie) 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 --------------------------------------------------------------------------------