Compare commits

...

6 Commits

13 changed files with 83 additions and 282 deletions

103
ADB.cs
View File

@@ -12,11 +12,7 @@ namespace AndroidSideloader
class ADB
{
static Process adb = new Process();
<<<<<<< HEAD
public static string adbFolderPath = "C:\\RSL\\2.1.1\\ADB";
=======
public static string adbFolderPath = "C:\\RSL\\2.1HF5\\ADB";
>>>>>>> + Added optional Wake on Wifi setting so Wireless ADB will still connect as long as device is not powered off or dead.
public static string adbFilePath = adbFolderPath + "\\adb.exe";
public static string DeviceID = "";
public static string package = "";
@@ -66,10 +62,6 @@ namespace AndroidSideloader
MessageBox.Show("Please check inside your headset for ADB DEBUGGING prompt, check box to \"Always allow from this computer.\" and hit OK.");
ADB.WakeDevice();
}
if (error.Contains("not enough storage space"))
{
MessageBox.Show("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.");
}
Logger.Log(output);
Logger.Log(error);
return new ProcessOutput(output, error);
@@ -127,11 +119,7 @@ namespace AndroidSideloader
return new ProcessOutput(output, error);
}
<<<<<<< HEAD
public static ProcessOutput RunCommandToString(string result, string file = "")
=======
public static ProcessOutput RunCommandToString(string result, string path = "")
>>>>>>> + Added optional Wake on Wifi setting so Wireless ADB will still connect as long as device is not powered off or dead.
{
string command = result;
Properties.Settings.Default.ADBFolder = adbFolderPath;
@@ -199,7 +187,6 @@ namespace AndroidSideloader
long usedSize = 0;
long freeSize = 0;
WakeDevice();
var output = RunAdbCommandToString("shell df").Output.Split('\n');
foreach (string currLine in output)
@@ -240,7 +227,6 @@ namespace AndroidSideloader
private static bool dialogisup = false;
public static void WakeDevice()
{
<<<<<<< HEAD
string output = RunAdbCommandToString("shell input keyevent KEYCODE_WAKEUP").Error;
RunAdbCommandToString("Devices");
if (output.Contains("found"))
@@ -332,95 +318,6 @@ namespace AndroidSideloader
}
}
}
=======
RunAdbCommandToString("shell input keyevent KEYCODE_WAKEUP");
string devicesout = RunAdbCommandToString("devices").Output;
if (!devicesout.Contains("found"))
{
if (Properties.Settings.Default.IPAddress.Contains("connect"))
{
RunAdbCommandToString(Properties.Settings.Default.IPAddress);
string response = ADB.RunAdbCommandToString(Properties.Settings.Default.IPAddress).Output;
if (response.Contains("cannot"))
{
DialogResult dialogResult = MessageBox.Show("Either your Quest is idle or you have rebooted the device.\nRSL's wireless ADB will persist on PC reboot but not on Quest reboot.\n\nNOTE: If you haven't rebooted your Quest it may be idle.\n\nTo prevent this press the HOLD button 2x prior to launching RSL. Or\nkeep your Quest plugged into power to keep it permanently \"awake\".\n\nHave you assigned your Quest a static IP in your router configuration?\n\nIf you no longer want to use Wireless ADB or your device was idle please hit CANCEL.", "DEVICE REBOOTED\\IDLE?", MessageBoxButtons.YesNoCancel);
if (dialogResult == DialogResult.Cancel)
{
DialogResult dialogResult2 = MessageBox.Show("Press OK to remove your stored IP address.\nIf your Quest went idle press the HOLD button on the device twice then press CANCEL to reconnect.", "REMOVE STORED IP?", MessageBoxButtons.OKCancel);
if (dialogResult2 == DialogResult.Cancel)
ADB.WakeDevice();
if (dialogResult2 == DialogResult.OK)
{
Properties.Settings.Default.IPAddress = "";
Properties.Settings.Default.Save();
ADB.WakeDevice();
}
}
else if (dialogResult == DialogResult.Yes)
{
MessageBox.Show("Connect your Quest to USB so we can reconnect to your saved IP address!");
ADB.RunAdbCommandToString("devices");
Thread.Sleep(250);
ADB.RunAdbCommandToString("disconnect");
Thread.Sleep(50);
ADB.RunAdbCommandToString("connect");
Thread.Sleep(50);
ADB.RunAdbCommandToString("tcpip 5555");
Thread.Sleep(500);
ADB.RunAdbCommandToString(Properties.Settings.Default.IPAddress);
MessageBox.Show($"Connected! We can now automatically enable wake on wifi. This makes it so Rookie can work wirelessly even if the device has entered \"sleep mode\". This setting is NOT permanent and resets upon Quest reboot just like wireless ADB functionality.\n\n After testing with this setting off and on the difference in battery usage seems nonexistent. We recommend this setting for the majority of users for ease of use purposes. If you click NO you must keep your Quest connected to a charger OR wake your device and then put it back on hold before using Rookie wirelessly. Do you want to enable wake on wifi?", "Enable Wake on Wifi?", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
ADB.RunAdbCommandToString("shell settings put global wifi_wakeup_available 1");
ADB.RunAdbCommandToString("shell settings put global wifi_wakeup_enabled 1");
}
if (dialogResult == DialogResult.No)
{
Program.form.ChangeTitlebarToDevice();
return;
}
}
else if (dialogResult == DialogResult.No)
{
MessageBox.Show("You must repeat the entire connection process, press OK to begin.", "Reconfigure Wireless ADB", MessageBoxButtons.OK);
ADB.RunAdbCommandToString("devices");
ADB.RunAdbCommandToString("tcpip 5555");
MessageBox.Show("Press OK to get your Quest's local IP address.", "Obtain local IP address", MessageBoxButtons.OK);
Thread.Sleep(1000);
string input = ADB.RunAdbCommandToString("shell ip route").Output;
Properties.Settings.Default.WirelessADB = true;
Properties.Settings.Default.Save();
string[] strArrayOne = new string[] { "" };
strArrayOne = input.Split(' ');
if (strArrayOne[0].Length > 7)
{
string IPaddr = strArrayOne[8];
string IPcmnd = "connect " + IPaddr + ":5555";
MessageBox.Show($"Your Quest's local IP address is: {IPaddr}\n\nPlease disconnect your Quest then wait 2 seconds.\nOnce it is disconnected hit OK", "", MessageBoxButtons.OK);
Thread.Sleep(2000);
ADB.RunAdbCommandToString(IPcmnd);
Properties.Settings.Default.IPAddress = IPcmnd;
Properties.Settings.Default.Save();
MessageBox.Show($"Connected! We can now automatically disable the Quest wifi chip from falling asleep. This makes it so Rookie can work wirelessly even if the device has entered \"sleep mode\". This setting is NOT permanent and resets upon Quest reboot, just like wireless ADB functionality.\n\nNOTE: This may cause the device battery to drain while it is in sleep mode at a very slightly increased rate. We recommend this setting for the majority of users for ease of use purposes. If you click NO you must keep your Quest connected to a charger or wake your device and then put it back on hold before using Rookie wirelessly. Do you want us to stop sleep mode from disabling wireless ADB?", "", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
ADB.RunAdbCommandToString("shell settings put global wifi_wakeup_available 1");
ADB.RunAdbCommandToString("shell settings put global wifi_wakeup_enabled 1");
}
Program.form.ChangeTitlebarToDevice();
}
}
}
>>>>>>> + Added optional Wake on Wifi setting so Wireless ADB will still connect as long as device is not powered off or dead.
}
}

View File

@@ -258,6 +258,8 @@
</ItemGroup>
<ItemGroup>
<Content Include="changelog.txt" />
<None Include="orangekey.png" />
<None Include="greenkey.png" />
<Content Include="icon.ico" />
</ItemGroup>
<ItemGroup>

View File

@@ -37,19 +37,17 @@ namespace AndroidSideloader
{
System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
<<<<<<< HEAD
=======
>>>>>>> + Added optional Wake on Wifi setting so Wireless ADB will still connect as long as device is not powered off or dead.
t.Interval = 840000; // 14 mins between wakeup commands
t.Tick += new EventHandler(timer_Tick);
t.Start();
InitializeComponent();
InitializeComponent();
lvwColumnSorter = new ListViewColumnSorter();
this.gamesListView.ListViewItemSorter = lvwColumnSorter;
}
private string oldTitle = "";
<<<<<<< HEAD
private async void Form1_Load(object sender, EventArgs e)
@@ -58,7 +56,7 @@ namespace AndroidSideloader
string adbDir = "C:\\RSL\\2.1.1\\adb";
string fileName = "";
string destFile = "";
string date_time = DateTime.Today.ToString("dddd, MMMM dd @ hh:mmtt");
string date_time = DateTime.UtcNow.ToString("dddd, MMMM dd @ hhhh:mmtt UTC");
Logger.Log($"\n\n##############\n##############\n##############\n\nAPP LAUNCH DATE/TIME: " + date_time + "\n\n##############\n##############\n##############\n\n");
Properties.Settings.Default.MainDir = Environment.CurrentDirectory;
Properties.Settings.Default.Save();
@@ -84,7 +82,7 @@ namespace AndroidSideloader
Properties.Settings.Default.Save();
if (File.Exists(Sideloader.CrashLogPath))
{
DialogResult dialogResult = FlexibleMessageBox.Show(this, $"Sideloader crashed during your last use.\nPlease report issue @ https://github.com/nerdunit/androidsideloader/issues + send the crashlog to a mod or dev.\n\n(Crashlog.txt is located here: {Path.GetFullPath(Sideloader.CrashLogPath)})\n\nIf you've already sent it press YES to delete it and prevent this message. Press NO if you'd still like to send it.", "Crash Detected", MessageBoxButtons.YesNo);
DialogResult dialogResult = FlexibleMessageBox.Show(this, $"Sideloader crashed during your last use.\nPlease report issue @ https://github.com/nerdunit/androidsideloader/issues OR send the crashlog to a mod or dev.\n\n(Crashlog.txt is located here: {Path.GetFullPath(Sideloader.CrashLogPath)})\n\nIf you've already sent it press YES to delete it and prevent this message. Press NO if you'd still like to send it.", "Crash Detected", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
File.Delete(Sideloader.CrashLogPath);
}
@@ -224,8 +222,6 @@ namespace AndroidSideloader
=======
>>>>>>> + Added optional Wake on Wifi setting so Wireless ADB will still connect as long as device is not powered off or dead.
void timer_Tick(object sender, EventArgs e)
{
@@ -233,11 +229,8 @@ namespace AndroidSideloader
}
<<<<<<< HEAD
=======
>>>>>>> + Added optional Wake on Wifi setting so Wireless ADB will still connect as long as device is not powered off or dead.
public async void ChangeTitle(string txt, bool reset = true)
{
this.Invoke(() => { oldTitle = txt; this.Text = "Rookie's Sideloader | " + txt; });
@@ -328,12 +321,8 @@ namespace AndroidSideloader
ADB.DeviceID = GetDeviceID();
Thread t1 = new Thread(() =>
{
<<<<<<< HEAD
output = ADB.RunAdbCommandToString("devices").Output;
=======
output = ADB.RunAdbCommandToString("devices").Output;
>>>>>>> + Added optional Wake on Wifi setting so Wireless ADB will still connect as long as device is not powered off or dead.
});
@@ -352,23 +341,18 @@ namespace AndroidSideloader
foreach (string currLine in line)
{
if (i > 0 && currLine.Length > 0)
{
Devices.Add(currLine.Split(' ')[0]);
devicesComboBox.Items.Add(currLine.Split(' ')[0]);
Logger.Log(currLine.Split(' ')[0] + "\n", false);
}
Debug.WriteLine(currLine);
{
Devices.Add(currLine.Split(' ')[0]);
devicesComboBox.Items.Add(currLine.Split(' ')[0]);
Logger.Log(currLine.Split(' ')[0] + "\n", false);
}
Debug.WriteLine(currLine);
i++;
}
if (devicesComboBox.Items.Count > 0)
devicesComboBox.SelectedIndex = 0;
foreach(var item in devicesComboBox.Items)
{
string result = $"{Properties.Settings.Default.ADBPath} shell -s {item} getprop ro.product.system.manufacturer";
if (ADB.RunCommandToString(result).Output.Contains("Oculus"))
devicesComboBox.SelectedItem = item;
}
return devicesComboBox.SelectedIndex;
}
@@ -517,88 +501,6 @@ namespace AndroidSideloader
catch { HasInternet = false; }
}
<<<<<<< HEAD
=======
private async void Form1_Load(object sender, EventArgs e)
{
string adbFile = "C:\\RSL\\2.1HF5\\adb\\adb.exe";
string adbDir = "C:\\RSL\\2.1HF5\\adb";
string fileName = "";
string destFile = "";
Properties.Settings.Default.MainDir = Environment.CurrentDirectory;
Properties.Settings.Default.Save();
if (!File.Exists(adbFile))
{
Directory.CreateDirectory(adbDir);
if (System.IO.Directory.Exists($"{Environment.CurrentDirectory}\\adb"))
{
string[] ADBfiles = System.IO.Directory.GetFiles($"{Properties.Settings.Default.MainDir}\\adb");
// Copy the files and overwrite destination files if they already exist.
foreach (string s in ADBfiles)
{
fileName = System.IO.Path.GetFileName(s);
destFile = System.IO.Path.Combine(adbDir, fileName);
System.IO.File.Copy(s, destFile, true);
}
}
}
Properties.Settings.Default.ADBPath = adbFile;
Properties.Settings.Default.Save();
ADB.RunAdbCommandToString("kill-server");
if (File.Exists(Sideloader.CrashLogPath))
{
DialogResult dialogResult = FlexibleMessageBox.Show(this, $@"Looks like sideloader crashed last time, please make an issue at https://github.com/nerdunit/androidsideloader/issues
Please don't forget to post the crash.log and fill in any details you can
Do you want to delete the {Sideloader.CrashLogPath} (if you press yes, this message will not appear when you start the sideloader but please first report this issue)", "Crash Detected", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
File.Delete(Sideloader.CrashLogPath);
}
CheckForInternet();
if (HasInternet == true)
Sideloader.downloadFiles();
else
FlexibleMessageBox.Show("Cannot connect to google dns, your internet may be down, won't use rclone or online features!");
await Task.Delay(100);
if (!Directory.Exists(BackupFolder))
Directory.CreateDirectory(BackupFolder);
if (Directory.Exists(Sideloader.TempFolder))
{
Directory.Delete(Sideloader.TempFolder, true);
Directory.CreateDirectory(Sideloader.TempFolder);
}
//Delete the Debug file if it is more than 5MB
if (File.Exists(Logger.logfile))
{
long length = new System.IO.FileInfo(Logger.logfile).Length;
if (length > 5000000) File.Delete(Logger.logfile);
}
RCLONE.Init();
try { Spoofer.spoofer.Init(); } catch { }
if (Properties.Settings.Default.CallUpgrade)
{
Properties.Settings.Default.Upgrade();
Properties.Settings.Default.CallUpgrade = false;
Properties.Settings.Default.Save();
}
this.CenterToScreen();
gamesListView.View = View.Details;
gamesListView.FullRowSelect = true;
gamesListView.GridLines = true;
etaLabel.Text = "";
speedLabel.Text = "";
diskLabel.Text = "";
>>>>>>> + Added optional Wake on Wifi setting so Wireless ADB will still connect as long as device is not powered off or dead.
@@ -1030,62 +932,6 @@ Do you want to delete the {Sideloader.CrashLogPath} (if you press yes, this mess
gamesListView.EndUpdate();
}
<<<<<<< HEAD
=======
private async void Form1_Shown(object sender, EventArgs e)
{
new Thread(() =>
{
Thread.Sleep(10000);
freeDisclaimer.Invoke(() => { freeDisclaimer.Dispose(); });
}).Start();
Thread t1 = new Thread(() =>
{
if (!debugMode && Properties.Settings.Default.checkForUpdates)
{
Updater.AppName = "AndroidSideloader";
Updater.Repostory = "nerdunit/androidsideloader";
Updater.Update();
}
progressBar.Invoke(() => { progressBar.Style = ProgressBarStyle.Marquee; });
ChangeTitle("Initializing Mirrors");
initMirrors(true);
ChangeTitle("Initializing Games");
SideloaderRCLONE.initGames(currentRemote);
if (!Directory.Exists(SideloaderRCLONE.ThumbnailsFolder) || !Directory.Exists(SideloaderRCLONE.NotesFolder))
{
MessageBox.Show("It seems you are missing the thumbnails and/or notes database, the first start of the sideloader takes a bit more time, so dont worry if it looks stuck!");
}
ChangeTitle("Syncing Game Photos");
SideloaderRCLONE.UpdateGamePhotos(currentRemote);
ChangeTitle("Checking for Updates on server...");
SideloaderRCLONE.UpdateGameNotes(currentRemote);
listappsbtn();
});
t1.SetApartmentState(ApartmentState.STA);
t1.IsBackground = false;
if (HasInternet)
t1.Start();
showAvailableSpace();
intToolTips();
while (t1.IsAlive)
await Task.Delay(100);
ChangeTitle("GREEN = Up to date, ORANGE = Out of date - Checking installed app versions, please wait...");
initListView();
ChangeTitle("Loaded");
downloadInstallGameButton.Enabled = true;
progressBar.Style = ProgressBarStyle.Continuous;
isLoading = false;
}
>>>>>>> + Added optional Wake on Wifi setting so Wireless ADB will still connect as long as device is not powered off or dead.
private void initMirrors(bool random)
{
int index = 0;
@@ -1197,17 +1043,9 @@ without him none of this would be possible
MessageBox.Show($"Connected! We can now automatically disable the Quest wifi chip from falling asleep. This makes it so Rookie can work wirelessly even if the device has entered \"sleep mode\". This setting is NOT permanent and resets upon Quest reboot, just like wireless ADB functionality.\n\nNOTE: This may cause the device battery to drain while it is in sleep mode at a very slightly increased rate. We recommend this setting for the majority of users for ease of use purposes. If you click NO you must keep your Quest connected to a charger or wake your device and then put it back on hold before using Rookie wirelessly. Do you want us to stop sleep mode from disabling wireless ADB?", "", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
<<<<<<< HEAD
ADB.RunAdbCommandToString("shell settings put global wifi_wakeup_available 1");
ADB.RunAdbCommandToString("shell settings put global wifi_wakeup_enabled 1");
}
=======
ADB.RunAdbCommandToString("shell settings put global wifi_wakeup_available 1");
ADB.RunAdbCommandToString("shell settings put global wifi_wakeup_enabled 1");
}
Program.form.ChangeTitlebarToDevice();
>>>>>>> + Added optional Wake on Wifi setting so Wireless ADB will still connect as long as device is not powered off or dead.
}
else
MessageBox.Show("No device connected!");
@@ -1355,7 +1193,6 @@ without him none of this would be possible
while (gamesQueueList.Count > 0)
{
gameName = gamesQueueList.ToArray()[0];
string packagename = Sideloader.gameNameToPackageName(gameName);
string dir = Path.GetDirectoryName(gameName);
string gameDirectory = Environment.CurrentDirectory + "\\" + gameName;
string path = gameDirectory;

View File

@@ -8,7 +8,10 @@ namespace AndroidSideloader
static class Program
{
/// <summary>
/// The main entry point for the application.
/// The main entry point for the appli
///
///
/// ion.
/// </summary>
[STAThread]
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]
@@ -28,7 +31,7 @@ namespace AndroidSideloader
static void MyHandler(object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception)args.ExceptionObject;
string date_time = DateTime.Today.ToString("dddd, MMMM dd @ hh:mmtt");
string date_time = DateTime.UtcNow.ToString("dddd, MMMM dd @ hh:mmtt UTC");
File.WriteAllText(Sideloader.CrashLogPath, $"\n\n################\nDate/Time of crash: {date_time}################\n\nMessage: {e.Message}\nData: {e.Data}\nSource: {e.Source}\nTargetSite: {e.TargetSite}");
}
}

View File

@@ -59,5 +59,25 @@ namespace AndroidSideloader.Properties {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
public static System.Drawing.Bitmap greenkey {
get {
object obj = ResourceManager.GetObject("greenkey", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
public static System.Drawing.Bitmap orangekey {
get {
object obj = ResourceManager.GetObject("orangekey", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
}
}

View File

@@ -117,4 +117,11 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="greenkey" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\greenkey.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="orangekey" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\orangekey.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View File

@@ -103,7 +103,7 @@ namespace AndroidSideloader
prcoutput.Output = output;
prcoutput.Error = error;
}
if (!output.Contains("Game Name;Release APK Path;"))
if (!prcoutput.Output.Contains("Game Name;Release Name;Release APK Path;Package Name;Version Code;Version Name"))
Logger.Log($"Rclone error: {error}\nRclone Output: {output}");
if (error.Contains("There is not enough space"))
MessageBox.Show("There isn't enough space on your PC to properly install this game. Please have at least 2x the size of the game you are trying to download/install available on the drive where Rookie is installed.", "NOT ENOUGH SPACE");

View File

@@ -1,4 +1,5 @@
using System.IO;
using System;
using System.IO;
namespace AndroidSideloader
{

View File

@@ -1,3 +1,37 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
RSL 2.1.1HF1
+ Prepended each line of debuglog.txt with Hour and Minute in UTC time.
+ Added DATE + TIME to Debuglog.txt each time user launches RSL.
+ Added DATE + TIME to CrashLog.txt each time program crashes.
= Simplified crashlog.txt delete message on boot.
= Fixed unhandled exception crashes (I hope).
= Fixed rare QU settings error.
= Cleaned up code order.
= Cleaned up Install.txt logic.
= Other bugfixes.
-----BEGIN PGP SIGNATURE-----
iQIzBAEBCAAdFiEEKjgtlwMyrpVu4TGfx/Rql1VoczcFAmDl8XUACgkQx/Rql1Vo
czfl3w//QQmRaVj8IGyevA3fKBB3jdKVZDCbKrRsxTS8MfvVxLeCczDwCJemmu1u
oF+8TXj0knOLA2FmgVtJAuBjTQLzlL3KGFdZjctfV+7II+LnwvNO01agxfVITAUh
nivRDsGqu7p3pDQly3dAOAjuUNl9qEy5iI3g1bVHUNK0qk+zI1DFi2AP2q3309df
O4bE14erPzDz+ELY1PA5oki7T5CyKUakcoYsA6ee4la1ClE2gYBmZym0NdlCu2ay
9iq+K47D7yHi2J5lIks/RHvmWQwAnrii9J6Ftcl+AsB3DzT8nPgDUx6empDzKgN6
8XhjF4sxGWVRbxUZe00f5QGLGS0FZjwCCXS2TjZJ3s9+mdHqQuWybYG+oO0Nk6XP
IOWXsvzMoyo8c8S7oatUuOAPaIx94BdiVS9WOJvQLEk7/HLzsT2jafJBacb/mM2y
HmLi4VFjhjxvptek+nCFgtiA+zt79/DX11luSfFNA8P2jdV7ECwRMebg0rc05SI3
DKD35f00yAsIDt/GJjP3PhiUgmlBwkmJ7GiQPNRwif6J7t3LRootA03FWTI3kHbM
MdNkI0QV6qOZFK+j6T/Xwt8J3EhJR0MNFUuzKg+9pfzeGAPiPXaCbr6BajgPiEPe
z1m2udFCNYt+bYKvbxc1ALpfkKiegwlh40IF/eAz3iPH4lLOlRs=
=dL8Y
-----END PGP SIGNATURE-----
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

BIN
glass.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
greenkey.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
orangekey.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
osquare.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB