diff --git a/App.xaml b/App.xaml
new file mode 100644
index 0000000..940e78c
--- /dev/null
+++ b/App.xaml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/App.xaml.cs b/App.xaml.cs
new file mode 100644
index 0000000..de2eeb3
--- /dev/null
+++ b/App.xaml.cs
@@ -0,0 +1,12 @@
+using System.Configuration;
+using System.Data;
+using System.Windows;
+
+namespace WpfMaiTouchEmulator;
+///
+/// Interaction logic for App.xaml
+///
+public partial class App : Application
+{
+}
+
diff --git a/AssemblyInfo.cs b/AssemblyInfo.cs
new file mode 100644
index 0000000..b0ec827
--- /dev/null
+++ b/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+using System.Windows;
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
diff --git a/MaiTouchComConnector.cs b/MaiTouchComConnector.cs
new file mode 100644
index 0000000..1045f46
--- /dev/null
+++ b/MaiTouchComConnector.cs
@@ -0,0 +1,147 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO.Ports;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace WpfMaiTouchEmulator;
+internal class MaiTouchComConnector
+{
+ private static SerialPort? serialPort;
+ private bool isActiveMode;
+ private readonly MaiTouchSensorButtonStateManager _buttonState;
+
+ public Action OnConnectStatusChange
+ {
+ get;
+ internal set;
+ }
+ public Action OnDataSent
+ {
+ get;
+ internal set;
+ }
+ public Action OnDataRecieved
+ {
+ get;
+ internal set;
+ }
+
+ public MaiTouchComConnector(MaiTouchSensorButtonStateManager buttonState)
+ {
+ _buttonState = buttonState;
+ }
+
+ public async Task startLoopAsync()
+ {
+ string virtualPort = "COM23"; // Adjust as needed
+
+
+ try
+ {
+
+ // Use setupc.exe to create a virtual COM port pair
+ //StartProcessWithAdminRights("C:\\Program Files (x86)\\com0com\\setupc.exe", $"PortName=COM3 PortName=COM23");
+
+ serialPort = new SerialPort(virtualPort, 9600, Parity.None, 8, StopBits.One);
+ serialPort.DataReceived += SerialPort_DataReceived;
+ serialPort.Open();
+ Console.WriteLine("Serial port opened successfully.");
+ OnConnectStatusChange("Connected");
+
+
+
+ // Simulate receiving a STAT packet
+ // Keep the program running to simulate active mode
+ while (true)
+ {
+ if (isActiveMode)
+ {
+ SendTouchscreenState();
+ await Task.Delay(1);
+ }
+ else
+ {
+ await Task.Delay(100);
+ }
+ }
+
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Error opening serial port: {ex.Message}");
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ MessageBox.Show(ex.Message, "Error connecting to COM port", MessageBoxButton.OK, MessageBoxImage.Error);
+ });
+
+ }
+ finally
+ {
+ OnConnectStatusChange("Not Connected");
+ // Close the serial port when done
+ if (serialPort.IsOpen)
+ {
+ serialPort.Close();
+ }
+
+ // Use setupc.exe to remove the virtual COM port pair with administrator privileges
+ //StartProcessWithAdminRights("C:\\Program Files (x86)\\com0com\\setupc.exe", $"remove 0");
+ }
+ }
+
+ void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
+ {
+ string recievedData = serialPort.ReadExisting();
+ var commands = recievedData.Split(new[] { '}' }, StringSplitOptions.RemoveEmptyEntries);
+ foreach (string command in commands)
+ {
+ string cleanedCommand = command.TrimStart('{');
+ // Implement your logic to process the received data here
+ Console.WriteLine($"Received data: {cleanedCommand}");
+ OnDataRecieved(cleanedCommand);
+
+
+ // Check if the received packet is a STAT packet
+ if (cleanedCommand == "STAT")
+ {
+ // Simulate entering active mode
+ isActiveMode = true;
+ Console.WriteLine("Entered Active Mode");
+ }
+ else if (cleanedCommand == "RSET")
+ {
+
+ }
+ else if (cleanedCommand == "HALT")
+ {
+ isActiveMode = false;
+ }
+ else if (cleanedCommand[2] == 'r' || cleanedCommand[2] == 'k')
+ {
+ char leftOrRight = cleanedCommand[0];
+ char sensor = cleanedCommand[1];
+ char ratio = cleanedCommand[3];
+
+ // Create the new string in the specified format
+ string newString = $"({leftOrRight}{sensor}{cleanedCommand[2]}{ratio})";
+ serialPort.Write(newString);
+ OnDataSent(newString);
+ }
+ else
+ {
+ Console.WriteLine(cleanedCommand);
+ }
+ }
+ }
+
+ void SendTouchscreenState()
+ {
+ var currentState = _buttonState.GetCurrentState();
+ serialPort?.Write(currentState, 0, currentState.Length);
+ //Console.WriteLine($"Sent Touchscreen State: {report}");*/
+ }
+}
diff --git a/MaiTouchSensorButtonStateManager.cs b/MaiTouchSensorButtonStateManager.cs
new file mode 100644
index 0000000..66e427e
--- /dev/null
+++ b/MaiTouchSensorButtonStateManager.cs
@@ -0,0 +1,109 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace WpfMaiTouchEmulator;
+
+enum TouchValue: long
+{
+ A1 = 1 << 0, // 2^0
+ A2 = 1 << 1, // 2^1
+ A3 = 1 << 2, // 2^2
+ A4 = 1 << 3, // 2^3
+ A5 = 1 << 4, // 2^4
+ A6 = 1 << 5, // 2^5
+ A7 = 1 << 6, // 2^6
+ A8 = 1 << 7, // 2^7
+ B1 = 1 << 8, // 2^8
+ B2 = 1 << 9, // 2^9
+ B3 = 1 << 10, // 2^10
+ B4 = 1 << 11, // 2^11
+ B5 = 1 << 12, // 2^12
+ B6 = 1 << 13, // 2^13
+ B7 = 1 << 14, // 2^14
+ B8 = 1 << 15, // 2^15
+ C1 = 1 << 16, // 2^16
+ C2 = 1 << 17, // 2^17
+ D1 = 1 << 18, // 2^18
+ D2 = 1 << 19, // 2^19
+ D3 = 1 << 20, // 2^20
+ D4 = 1 << 21, // 2^21
+ D5 = 1 << 22, // 2^22
+ D6 = 1 << 23, // 2^23
+ D7 = 1 << 24, // 2^24
+ D8 = 1 << 25, // 2^25
+ E1 = 1 << 26, // 2^26
+ E2 = 1 << 27, // 2^27
+ E3 = 1 << 28, // 2^28
+ E4 = 1 << 29, // 2^29
+ E5 = 1 << 30, // 2^30
+ E6 = 1L << 31, // Note: Use 1L for long literals, as this and subsequent values exceed Int32.MaxValue
+ E7 = 1L << 32,
+ E8 = 1L << 33,
+}
+
+internal class MaiTouchSensorButtonStateManager
+{
+ static long buttonState = 0L;
+ private readonly Label buttonStateValue;
+
+ public MaiTouchSensorButtonStateManager(Label buttonStateValue)
+ {
+ this.buttonStateValue = buttonStateValue;
+ SetupUpdateLoop();
+
+ }
+
+ private async void SetupUpdateLoop()
+ {
+ while (true)
+ {
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ buttonStateValue.Content = buttonState.ToString();
+ });
+ await Task.Delay(1);
+ }
+ }
+
+ public void Reset()
+ {
+ buttonState = 0L;
+ }
+
+ public void PressButton(TouchValue button)
+ {
+ buttonState |= ((long)button);
+ }
+
+ public void ReleaseButton(TouchValue button)
+ {
+ buttonState &= ~((long)button);
+ }
+
+ public byte[] GetCurrentState()
+ {
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ buttonStateValue.Content = buttonState.ToString();
+ });
+
+
+ return
+ [
+ 0x28,
+ (byte)(buttonState & 0b11111),
+ (byte)(buttonState >> 5 & 0b11111),
+ (byte)(buttonState >> 10 & 0b11111),
+ (byte)(buttonState >> 15 & 0b11111),
+ (byte)(buttonState >> 20 & 0b11111),
+ (byte)(buttonState >> 25 & 0b11111),
+ (byte)(buttonState >> 30 & 0b11111),
+ 0x29
+ ];
+ }
+}
diff --git a/MainWindow.xaml b/MainWindow.xaml
new file mode 100644
index 0000000..bdb101f
--- /dev/null
+++ b/MainWindow.xaml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs
new file mode 100644
index 0000000..5ff51ca
--- /dev/null
+++ b/MainWindow.xaml.cs
@@ -0,0 +1,79 @@
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace WpfMaiTouchEmulator;
+///
+/// Interaction logic for MainWindow.xaml
+///
+public partial class MainWindow : Window
+{
+ private MaiTouchSensorButtonStateManager buttonState;
+ private MaiTouchComConnector connector;
+
+ public MainWindow()
+ {
+ InitializeComponent();
+ Title = "Mai Touch Emulator";
+ buttonState = new MaiTouchSensorButtonStateManager(buttonStateValue);
+ connector = new MaiTouchComConnector(buttonState);
+ connector.OnConnectStatusChange = (status) => Title = $"Mai Touch Emulator - {status}";
+ connector.OnDataSent = (data) =>
+ {
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ SentLogBox.AppendText(data + Environment.NewLine);
+ SentLogBox.ScrollToEnd();
+ });
+ };
+ connector.OnDataRecieved = (data) =>
+ {
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ RecievedLogBox.AppendText(data + Environment.NewLine);
+ RecievedLogBox.ScrollToEnd();
+ });
+ };
+
+ var touchPanel = new TouchPanel();
+ touchPanel.onTouch = (value) => { buttonState.PressButton(value); };
+ touchPanel.onRelease = (value) => { buttonState.ReleaseButton(value); };
+ touchPanel.Show();
+ touchPanel.SetDebugMode(true);
+ }
+
+ private async void ConnectToPortButton_Click(object sender, RoutedEventArgs e)
+ {
+ await connector.startLoopAsync();
+ }
+
+ private void Touch_A1_PreviewMouseDown(object sender, MouseButtonEventArgs e)
+ {
+ buttonState.PressButton(TouchValue.A1);
+ }
+
+ private void Touch_A1_PreviewMouseUp(object sender, MouseButtonEventArgs e)
+ {
+ buttonState.ReleaseButton(TouchValue.A1);
+ }
+
+ private void Touch_A2_C1_PreviewMouseDown(object sender, MouseButtonEventArgs e)
+ {
+ buttonState.PressButton(TouchValue.A2);
+ buttonState.PressButton(TouchValue.C1);
+
+ }
+
+ private void Touch_A2_C1_PreviewMouseUp(object sender, MouseButtonEventArgs e)
+ {
+ buttonState.ReleaseButton(TouchValue.A2);
+ buttonState.ReleaseButton(TouchValue.C1);
+ }
+}
\ No newline at end of file
diff --git a/TouchPanel.xaml b/TouchPanel.xaml
new file mode 100644
index 0000000..707cd23
--- /dev/null
+++ b/TouchPanel.xaml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TouchPanel.xaml.cs b/TouchPanel.xaml.cs
new file mode 100644
index 0000000..e14a245
--- /dev/null
+++ b/TouchPanel.xaml.cs
@@ -0,0 +1,201 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+using System.Windows.Media.Imaging; // For BitmapImage
+using System.IO;
+using System.Windows.Interop; // For Imaging.CreateBitmapSourceFromHBitmap
+using System.Runtime.InteropServices;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Windows.Controls.Primitives; // For Marshal
+
+namespace WpfMaiTouchEmulator;
+///
+/// Interaction logic for TouchPanel.xaml
+///
+public partial class TouchPanel : Window
+{
+ internal Action onTouch;
+ internal Action onRelease;
+ private bool isResizing = false;
+ private System.Windows.Point clickPosition;
+
+ [DllImport("user32.dll")]
+ public static extern int SetWindowLong(IntPtr window, int index, int value);
+
+ [DllImport("user32.dll")]
+ public static extern int GetWindowLong(IntPtr window, int index);
+
+ public const int GWL_EXSTYLE = -20;
+ public const int WS_EX_TRANSPARENT = 0x00000020;
+ public const int WS_EX_LAYERED = 0x00080000;
+
+ public TouchPanel()
+ {
+ InitializeComponent();
+ this.Topmost = true;
+ var positionManager = new TouchPanelPositionManager();
+ var position = positionManager.GetTouchPanelPosition();
+ if (position != null )
+ {
+ Top = position.Value.Top;
+ Left = position.Value.Left;
+ Width = position.Value.Width;
+ Height = position.Value.Height;
+ }
+
+ this.Loaded += new RoutedEventHandler(Window_Loaded);
+ }
+
+ private void Window_Loaded(object sender, RoutedEventArgs e)
+ {
+ // Make the window transparent to input
+ var hwnd = new WindowInteropHelper(this).Handle;
+ //SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_TRANSPARENT | WS_EX_LAYERED);
+ }
+
+ private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+ {
+ // This allows the entire window to be draggable
+ DragMove();
+ }
+
+ private void DragBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+ {
+ // This event is for the draggable bar, it calls DragMove to move the window
+ DragMove();
+ }
+
+ private void ResizeGrip_MouseDown(object sender, MouseButtonEventArgs e)
+ {
+ if (e.LeftButton == MouseButtonState.Pressed)
+ {
+ ResizeWindow(ResizeDirection.BottomRight);
+ }
+ }
+
+ private enum ResizeDirection
+ {
+ BottomRight = 8,
+ }
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto)]
+ private static extern bool ReleaseCapture();
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto)]
+ private static extern int SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
+
+ private void ResizeWindow(ResizeDirection direction)
+ {
+ ReleaseCapture();
+ SendMessage(new System.Windows.Interop.WindowInteropHelper(this).Handle,
+ 0x112, // WM_SYSCOMMAND message
+ (IntPtr)(0xF000 + direction),
+ IntPtr.Zero);
+ }
+
+ private Dictionary activeTouches = new Dictionary();
+
+
+ private void Element_TouchDown(object sender, TouchEventArgs e)
+ {
+ // Cast the sender to a Border to ensure it's the correct element type.
+ var element = sender as System.Windows.Controls.Image;
+ if (element != null)
+ {
+ // Highlight the element and add it to the active touches tracking.
+ HighlightElement(element, true);
+ onTouch((TouchValue)element.Tag);
+ activeTouches[e.TouchDevice.Id] = element;
+ }
+ e.Handled = true;
+ }
+
+ private void Element_TouchMove(object sender, TouchEventArgs e)
+ {
+ // Attempt to find the element under the current touch point.
+ var touchPoint = e.GetTouchPoint(this).Position;
+ var hitTestResult = VisualTreeHelper.HitTest(this, touchPoint);
+ if (hitTestResult != null && hitTestResult.VisualHit is System.Windows.Controls.Image newElement)
+ {
+ // If this touch point is already tracking another element, unhighlight the previous one.
+ if (activeTouches.TryGetValue(e.TouchDevice.Id, out System.Windows.Controls.Image previousElement) && previousElement != newElement)
+ {
+ HighlightElement(previousElement, false);
+ onRelease((TouchValue)previousElement.Tag);
+ }
+
+ // Highlight the new element and update the tracking.
+ HighlightElement(newElement, true);
+ onTouch((TouchValue)newElement.Tag);
+ activeTouches[e.TouchDevice.Id] = newElement;
+ }
+
+ if (!IsTouchInsideWindow(touchPoint))
+ {
+ // Touch is outside the window, act accordingly
+ DeselectAllItems();
+ }
+
+ e.Handled = true;
+ }
+
+ private void Element_TouchUp(object sender, TouchEventArgs e)
+ {
+ // When touch is lifted, unhighlight the associated element and remove it from tracking.
+ if (activeTouches.TryGetValue(e.TouchDevice.Id, out System.Windows.Controls.Image element))
+ {
+ HighlightElement(element, false);
+ onRelease((TouchValue)element.Tag);
+ activeTouches.Remove(e.TouchDevice.Id);
+ }
+
+ e.Handled = true;
+ }
+
+ private bool IsTouchInsideWindow(System.Windows.Point touchPoint)
+ {
+ // Define the window's bounds
+ var windowBounds = new Rect(0, 0, this.ActualWidth, this.ActualHeight);
+
+ // Check if the touch point is within the window's bounds
+ return windowBounds.Contains(touchPoint);
+ }
+
+ private void DeselectAllItems()
+ {
+ // Logic to deselect all items or the last touched item
+ foreach (var element in activeTouches.Values)
+ {
+ HighlightElement(element, false);
+ }
+ activeTouches.Clear();
+ }
+
+ public void SetDebugMode(bool enabled)
+ {
+ var buttons = VisualTreeHelperExtensions.FindVisualChildren(this);
+ buttons.ForEach(button =>
+ {
+ button.Opacity = enabled ? 0.3 : 0;
+ });
+ }
+
+ private void HighlightElement(System.Windows.Controls.Image element, bool highlight)
+ {
+ element.Opacity = highlight ? 0.8 : 0.3;
+ }
+
+}
diff --git a/TouchPanelPositionManager.cs b/TouchPanelPositionManager.cs
new file mode 100644
index 0000000..89ed805
--- /dev/null
+++ b/TouchPanelPositionManager.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace WpfMaiTouchEmulator
+{
+ class TouchPanelPositionManager
+ {
+ [DllImport("user32.dll", SetLastError = true)]
+ static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct RECT
+ {
+ public int Left;
+ public int Top;
+ public int Right;
+ public int Bottom;
+ }
+
+ public Rect? GetTouchPanelPosition()
+ {
+ // Replace "OtherAppWindowName" with the window name (title) of the other application
+ IntPtr hWnd = FindWindow(null, "Sinmai");
+ if (hWnd != IntPtr.Zero)
+ {
+ RECT rect;
+ if (GetWindowRect(hWnd, out rect))
+ {
+ // Calculate the desired size and position based on the other application's window
+ int width = Convert.ToInt32((rect.Right - rect.Left));
+ int height = width + 20;
+ int left = rect.Left + ((rect.Right - rect.Left) - width) / 2; // Center horizontally
+ int top = rect.Bottom - height;
+ return new Rect(left, top, width, height);
+ }
+ else
+ {
+ MessageBox.Show("Failed to get window rect.");
+ }
+ }
+ else
+ {
+ MessageBox.Show("Other application window not found.");
+ }
+ return null;
+ }
+ }
+}
diff --git a/VisualTreeHelperExtensions.cs b/VisualTreeHelperExtensions.cs
new file mode 100644
index 0000000..ab34933
--- /dev/null
+++ b/VisualTreeHelperExtensions.cs
@@ -0,0 +1,27 @@
+using System.Collections.Generic;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+public static class VisualTreeHelperExtensions
+{
+ // Method to get all Image controls in the visual tree of a parent element
+ public static List FindVisualChildren(DependencyObject parent) where Image : DependencyObject
+ {
+ var images = new List();
+
+ // Recursive search of the visual tree to find all Image controls
+ for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
+ {
+ var child = VisualTreeHelper.GetChild(parent, i);
+ if (child != null && child is Image)
+ {
+ images.Add((Image)child);
+ }
+
+ images.AddRange(FindVisualChildren(child));
+ }
+
+ return images;
+ }
+}
diff --git a/WpfMaiTouchEmulator.csproj b/WpfMaiTouchEmulator.csproj
new file mode 100644
index 0000000..3e11290
--- /dev/null
+++ b/WpfMaiTouchEmulator.csproj
@@ -0,0 +1,16 @@
+
+
+
+ WinExe
+ net8.0-windows
+ enable
+ enable
+ true
+
+
+
+
+
+
+
+
diff --git a/WpfMaiTouchEmulator.sln b/WpfMaiTouchEmulator.sln
new file mode 100644
index 0000000..fa27fac
--- /dev/null
+++ b/WpfMaiTouchEmulator.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.8.34525.116
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfMaiTouchEmulator", "WpfMaiTouchEmulator.csproj", "{12065588-9C14-41F6-B866-76CAEBDF9E89}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {12065588-9C14-41F6-B866-76CAEBDF9E89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {12065588-9C14-41F6-B866-76CAEBDF9E89}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {12065588-9C14-41F6-B866-76CAEBDF9E89}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {12065588-9C14-41F6-B866-76CAEBDF9E89}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {54F9B40B-528A-4EBE-BE07-6DCB97467469}
+ EndGlobalSection
+EndGlobal
diff --git a/assets/A1.png b/assets/A1.png
new file mode 100644
index 0000000..6a1bdf5
Binary files /dev/null and b/assets/A1.png differ
diff --git a/assets/A2.png b/assets/A2.png
new file mode 100644
index 0000000..fc6b101
Binary files /dev/null and b/assets/A2.png differ
diff --git a/assets/A3.png b/assets/A3.png
new file mode 100644
index 0000000..53f53f3
Binary files /dev/null and b/assets/A3.png differ
diff --git a/assets/A4.png b/assets/A4.png
new file mode 100644
index 0000000..710cd5e
Binary files /dev/null and b/assets/A4.png differ
diff --git a/assets/A5.png b/assets/A5.png
new file mode 100644
index 0000000..68a506b
Binary files /dev/null and b/assets/A5.png differ
diff --git a/assets/A6.png b/assets/A6.png
new file mode 100644
index 0000000..02a3bce
Binary files /dev/null and b/assets/A6.png differ
diff --git a/assets/A7.png b/assets/A7.png
new file mode 100644
index 0000000..c8e497f
Binary files /dev/null and b/assets/A7.png differ
diff --git a/assets/A8.png b/assets/A8.png
new file mode 100644
index 0000000..e33bc59
Binary files /dev/null and b/assets/A8.png differ
diff --git a/assets/B1.png b/assets/B1.png
new file mode 100644
index 0000000..88710b3
Binary files /dev/null and b/assets/B1.png differ
diff --git a/assets/B2.png b/assets/B2.png
new file mode 100644
index 0000000..c3946a5
Binary files /dev/null and b/assets/B2.png differ
diff --git a/assets/B3.png b/assets/B3.png
new file mode 100644
index 0000000..876316c
Binary files /dev/null and b/assets/B3.png differ
diff --git a/assets/B4.png b/assets/B4.png
new file mode 100644
index 0000000..c7517da
Binary files /dev/null and b/assets/B4.png differ
diff --git a/assets/B5.png b/assets/B5.png
new file mode 100644
index 0000000..0b57000
Binary files /dev/null and b/assets/B5.png differ
diff --git a/assets/B6.png b/assets/B6.png
new file mode 100644
index 0000000..bb1be52
Binary files /dev/null and b/assets/B6.png differ
diff --git a/assets/B7.png b/assets/B7.png
new file mode 100644
index 0000000..0198f51
Binary files /dev/null and b/assets/B7.png differ
diff --git a/assets/B8.png b/assets/B8.png
new file mode 100644
index 0000000..a58ddca
Binary files /dev/null and b/assets/B8.png differ
diff --git a/assets/C1.png b/assets/C1.png
new file mode 100644
index 0000000..344f981
Binary files /dev/null and b/assets/C1.png differ
diff --git a/assets/C2.png b/assets/C2.png
new file mode 100644
index 0000000..9042b49
Binary files /dev/null and b/assets/C2.png differ
diff --git a/assets/D1.png b/assets/D1.png
new file mode 100644
index 0000000..3bcfc41
Binary files /dev/null and b/assets/D1.png differ
diff --git a/assets/D2.png b/assets/D2.png
new file mode 100644
index 0000000..7c863b7
Binary files /dev/null and b/assets/D2.png differ
diff --git a/assets/D3.png b/assets/D3.png
new file mode 100644
index 0000000..e4bcadc
Binary files /dev/null and b/assets/D3.png differ
diff --git a/assets/D4.png b/assets/D4.png
new file mode 100644
index 0000000..9579c59
Binary files /dev/null and b/assets/D4.png differ
diff --git a/assets/D5.png b/assets/D5.png
new file mode 100644
index 0000000..804715a
Binary files /dev/null and b/assets/D5.png differ
diff --git a/assets/D6.png b/assets/D6.png
new file mode 100644
index 0000000..b56a7d7
Binary files /dev/null and b/assets/D6.png differ
diff --git a/assets/D7.png b/assets/D7.png
new file mode 100644
index 0000000..fddaeaa
Binary files /dev/null and b/assets/D7.png differ
diff --git a/assets/D8.png b/assets/D8.png
new file mode 100644
index 0000000..57d746b
Binary files /dev/null and b/assets/D8.png differ
diff --git a/assets/E1.png b/assets/E1.png
new file mode 100644
index 0000000..b392f40
Binary files /dev/null and b/assets/E1.png differ
diff --git a/assets/E2.png b/assets/E2.png
new file mode 100644
index 0000000..35ef82f
Binary files /dev/null and b/assets/E2.png differ
diff --git a/assets/E3.png b/assets/E3.png
new file mode 100644
index 0000000..b392f40
Binary files /dev/null and b/assets/E3.png differ
diff --git a/assets/E4.png b/assets/E4.png
new file mode 100644
index 0000000..35ef82f
Binary files /dev/null and b/assets/E4.png differ
diff --git a/assets/E5.png b/assets/E5.png
new file mode 100644
index 0000000..b392f40
Binary files /dev/null and b/assets/E5.png differ
diff --git a/assets/E6.png b/assets/E6.png
new file mode 100644
index 0000000..35ef82f
Binary files /dev/null and b/assets/E6.png differ
diff --git a/assets/E7.png b/assets/E7.png
new file mode 100644
index 0000000..b392f40
Binary files /dev/null and b/assets/E7.png differ
diff --git a/assets/E8.png b/assets/E8.png
new file mode 100644
index 0000000..35ef82f
Binary files /dev/null and b/assets/E8.png differ
diff --git a/assets/Source Image.png b/assets/Source Image.png
new file mode 100644
index 0000000..0e9cd69
Binary files /dev/null and b/assets/Source Image.png differ