Option Strict Off
Imports System.Collections
Imports Microsoft.Win32
Imports System.Text.RegularExpressions
Imports System.IO
Imports System.IO.MemoryMappedFiles
Imports System.Runtime.InteropServices
Imports System.Threading
Imports System.Security
Imports System.ComponentModel
Imports Microsoft.Win32.SafeHandles
Imports System.Runtime.ConstrainedExecution
Imports System.Security.Permissions

Public Class Class1
    Implements GOverlayPlugin.Interfaces.IPlugin
    Public testvar As Integer = 1

    Private objHost As GOverlayPlugin.Interfaces.IHost
    Public PluginName As String = "SimBin Car Stats"

    Public CM_Registry As RegistryKey = Nothing
    Public CM_DisksAvailable As New Hashtable
    Public Cache As String

    Public Const MapPrefix As String = "Local\"
    Public Const MapName As String = "$Race$"
    Public Const FullMapName As String = MapPrefix & MapName

    Public PosSlot As Integer
    Public LastCache As New System.Collections.Hashtable

    Dim hMapFile As SafeFileMappingHandle = Nothing
    Public pView As IntPtr = IntPtr.Zero
    Public rdata As rdataStructure

    ' File offset where the view is to begin.
    Public Const ViewOffset As UInt32 = 0

    ' The number of bytes of a file mapping to map to the view. All bytes of the
    ' view must be within the maximum size of the file mapping object (MAP_SIZE). 
    ' If VIEW_SIZE is 0, the mapping extends from the offset (VIEW_OFFSET) to 
    ' the end of the file mapping.
    'Friend Const ViewSize As UInt32 = &H400
    Public Const ViewSize As UInt32 = 259
    Public Sub Initialize(ByVal Host As GOverlayPlugin.Interfaces.IHost) Implements GOverlayPlugin.Interfaces.IPlugin.Initialize
        objHost = Host
    End Sub

    Public ReadOnly Property Description() As String Implements GOverlayPlugin.Interfaces.IPlugin.Description
        'Return your plugin name
        Get
            Return "This plugin allows to read the Car Information from SimBin Games such as Race07." & vbNewLine & vbNewLine & _
                "Make sure the MMF is enabled on the game, to do so, go to ""c:\Users\<WindowsUsername>\Documents\SimBin\RACE 07\UserData\<GameProfile>\<GameProfile>.PLR"" and change the line " & vbNewLine & "Write Shared Memory=""0"" " & vbNewLine & " to " & vbNewLine & "Write Shared Memory=""1"". " & vbNewLine & vbNewLine & _
                "Remember to UPLOAD the LCDSysInfo files with GOverlay (destinations 310, 340, 341, 342, 343, 345)" & vbNewLine & vbNewLine & _
                "Developed by TheLaGmAn"
        End Get
    End Property

    Public ReadOnly Property Name() As String Implements GOverlayPlugin.Interfaces.IPlugin.Name
        'Return your plugin name
        Get
            Return PluginName
        End Get
    End Property

    Public ReadOnly Property Display() As String Implements GOverlayPlugin.Interfaces.IPlugin.Display
        'Return the display this plugin belongs to
        Get
            Return "lcdsys"
        End Get
    End Property

    Function CallBack(method As String) As Hashtable Implements GOverlayPlugin.Interfaces.IPlugin.CallBacks
        Try
            If method = "reqimagesbutton" Then
                objHost.AccessHost("plugin_upload_files", PluginName, "reqimages", "")
            End If
        Catch ex As Exception
            objHost.DebugMessage("Error on callback:" & ex.Message & ": " & ex.StackTrace)
        End Try

    End Function

    Function LCDSys2_AvailableSensors(pluginOptions As Hashtable) As System.Collections.Generic.Dictionary(Of String, String) Implements GOverlayPlugin.Interfaces.IPlugin.LCDSys2_AvailableSensors
        Dim sensors As New System.Collections.Generic.Dictionary(Of String, String)
        Return sensors
    End Function

    Public Function LCDSys2_DisplayOnLCD(sensorId As String, elementData As Hashtable, pluginOptions As Hashtable, cacheRuns As Integer) As ArrayList Implements GOverlayPlugin.Interfaces.IPlugin.LCDSys2_DisplayOnLCD
        'GOverlay draws instead of us
        Return New ArrayList
    End Function
    Function SensorHasCustomDraw(sensor_name As String) As Boolean Implements GOverlayPlugin.Interfaces.IPlugin.SensorHasCustomDraw
        'All sensors are drawn with GOverlay default drawing
        Return False
    End Function

    Public Function LCDSys2_CreateOptions(sensorId As String, elementData As Hashtable) As Hashtable Implements GOverlayPlugin.Interfaces.IPlugin.LCDSys2_CreateOptions
        'Set the options the user will have when clicking on the element
        'The available option_types are:
        'Text: Input text
        'Combo3: Combo with options (Enabled=0, Disabled=1)
        'Sensors: Combo with available sensors
        'ColorRGB: Combo with common RGB colors = 16bitinteger
        'ComboOnOff: Combo with options (Disabled=0, Enabled=1)
        'ComboYesNo: Combo with options (Yes=Yes, No=No)
        'FontStyle: Combo with options of the fonts the user has installed
        'Orientation: Combo with options (Horizontal=0, Vertical=1)
        'Alignment: Left=-1,Center=0,Right=1
        'Here you can also load your custom comboboxes

        'No options because GOverlay draws instead of us
        Return New Hashtable
    End Function

    Function AvailableSensors(pluginOptions As Hashtable) As System.Collections.Generic.Dictionary(Of String, String) Implements GOverlayPlugin.Interfaces.IPlugin.AvailableSensors
        'Create the list of the sensors/elements this plugin has
        'You can access your pluginOptions here as pluginOptions(your_option)        
        Try

            Dim sensors As New System.Collections.Generic.Dictionary(Of String, String)
            sensors.Add("SimBin.Gauge", "Box: Full Gauge")
            sensors.Add("SimBin.Tires", "Box: Tires Information")
            sensors.Add("SimBin.Speed", "Car Speed")
            sensors.Add("SimBin.Gear", "Current Gear")
            sensors.Add("SimBin.EngineRPM", "Engine RPM")
            sensors.Add("SimBin.OilTemp", "Engine Oil Temp")
            sensors.Add("SimBin.OilPress", "Engine Oil Pressure")
            sensors.Add("SimBin.WaterTemp", "Engine Water Temp")
            sensors.Add("SimBin.FuelPressure", "Fuel Pressure")
            sensors.Add("SimBin.FuelLiters", "Fuel Liters")
            sensors.Add("SimBin.Lap", "Current Lap")
            sensors.Add("SimBin.TimeBestLap", "Time of Best Lap")
            sensors.Add("SimBin.TimeLastLap", "Time of Last Lap")
            sensors.Add("SimBin.TimeCurrentLap", "Time of Current Lap")
            sensors.Add("SimBin.Position", "Position")

            Return sensors
        Catch ex As Exception
            objHost.DebugMessage("Error loading sensors:" & ex.Message & ": " & ex.StackTrace)
            'MsgBox(ex.Message & ":: " & ex.StackTrace)
        End Try
    End Function


    Function ComboBoxes() As Hashtable Implements GOverlayPlugin.Interfaces.IPlugin.ComboBoxes
        'Create custom ComboBox for your configuration to use
        Dim boxes As New Hashtable
        Dim myboxOptions As New Hashtable
        'Set each one of the Combobox options as value, Display Name
        'myboxOptions.Add("DiskSize", "Disk Size")
        'myboxOptions.Add("DriveLetter", "Drive Letter")
        'myboxOptions.Add("Model", "Model")
        'myboxOptions.Add("Temperature", "Temperature")
        'myboxOptions.Add("TemperatureClass", "Temperature Class")

        'Add the combobox options as the combobox "PLUG.optioncustom1"
        'boxes.Add("CM.DiskData", myboxOptions)
        Return boxes
    End Function

    Public Function SetDefaultOptions(sensorId As String, elementData As Hashtable) As Hashtable Implements GOverlayPlugin.Interfaces.IPlugin.SetDefaultOptions
        'Set the default values you want to have on your sensor when its created, if the user doesnt change any option, he will have this settings

        If sensorId = "SimBin.Gauge" Then
            elementData("width") = 320
            elementData("height") = 168
            elementData("maxfuel") = 60
            elementData("maxspeed") = 200
            elementData("maxtemp") = 120
        ElseIf sensorId = "SimBin.Tires" Then
            elementData("width") = 80
            elementData("height") = 70
        Else
            elementData("width") = 50
            elementData("height") = 20
            elementData("font_style") = 0
            elementData("basic_color") = 0
            elementData("font_size") = 1
            elementData("font_color") = 0
            elementData("font_transform") = 0
        End If
        'elementData("CM.DiskData") = "DiskSize"

        'elementData("font_style") = 0
        'elementData("font_size") = 10
        'elementData("max_digits") = 2

        Return elementData
    End Function

    Public Function CreateOptions(sensorId As String, elementData As Hashtable) As Hashtable Implements GOverlayPlugin.Interfaces.IPlugin.CreateOptions
        'Set the options the user will have when clicking on the element
        'The available option_types are:
        'Text: Input text
        'Combo3: Combo with options (Enabled=0, Disabled=1)
        'Sensors: Combo with available sensors
        'ColorBasic: Combo with basic colors for the regular text font
        'ColorRGB: Combo with common RGB colors = 16bitinteger
        'ComboOnOff: Combo with options (Disabled=0, Enabled=1)
        'ComboYesNo: Combo with options (Yes=Yes, No=No)
        'TextSize: Combo with options (Extra Small=4, Very Small=5, Small=10, Normal=15, Big=20, Very Big=30, Extreme=40)
        'FontStyle2: Combo with options (Regular Font=0, Square Font=1, Numbers Font 1=2
        'Orientation: Combo with options (Horizontal=0, Vertical=1)
        'Here you can also load your custom comboboxes

        Dim options As New Hashtable
        Dim x = 0


        If sensorId = "SimBin.Gauge" Then
            options.Add(x, New ArrayList({"Text", "Max Speed", "maxspeed", "Write the max speed to calculate the gauge colors"})) : x = x + 1
            options.Add(x, New ArrayList({"Text", "Fuel Tank", "maxfuel", "Write the fuel tank size to calculate the fuel gauge"})) : x = x + 1
            options.Add(x, New ArrayList({"Text", "Max Oil Pressure", "maxtemp", "Write the maximum pressure to calculate the gauge"})) : x = x + 1
            Return options
        ElseIf sensorId = "SimBin.Tires" Then
        Else
            options.Add(x, New ArrayList({"FontStyle2", "Font Style", "font_style", "Font style"})) : x = x + 1

            If elementData("font_style") = 0 Then
                'Regular font
                options.Add(x, New ArrayList({"ColorBasic", "Text Color", "basic_color", "Select the basic color"})) : x = x + 1
            ElseIf elementData("font_style") = 1 Then
                'Square Font
                options.Add(x, New ArrayList({"FontSize", "Font Size", "font_size", "Select the font size"})) : x = x + 1
                options.Add(x, New ArrayList({"ColorRGB", "Font Color", "font_color", "Select the font color"})) : x = x + 1
                options.Add(x, New ArrayList({"FontTransform", "Font Transform", "font_transform", "Select font-transform"})) : x = x + 1
            Else
                'Image-font
                options.Add(x, New ArrayList({"Text", "Maximum Digits", "maxdigits", "Write the maximum digits to show"})) : x = x + 1
            End If

            options.Add(x, New ArrayList({"Text", "Width", "width", "Write a width in pixels"})) : x = x + 1
            options.Add(x, New ArrayList({"Text", "Height", "height", "Write a height in pixels"})) : x = x + 1

            Return options
        End If


        Dim options2 As New Hashtable
        Return options2

    End Function

    Public Function PluginOptionsDefault() As Hashtable Implements GOverlayPlugin.Interfaces.IPlugin.PluginOptionsDefault
        'Set the default values you want to have on plugin, if the user doesnt change any option, he will have this settings
        Dim options As New Hashtable
        options("reqimages") = "*.*.plugin_car_*"
        Return options
    End Function
    Public Function PluginOptions(pluginCurrentOptions As Hashtable) As Hashtable Implements GOverlayPlugin.Interfaces.IPlugin.PluginOptions
        'Set the options the user will have when going to the plugins tab and clicking on your plugin
        'The availalbe option_type are teh same as CreateOptions function
        Dim options As New Hashtable
        'Option: option_index as integer, option_data as ArrayList
        'Option_Data: option_type as string, option_label as string, option_name as string (no spaces, no _)
        'options.Add(0, New ArrayList({"Text", "Registry Path", "regkey"}))
        options.Add(0, New ArrayList({"TextMulti", "Images Match finder", "reqimages"}))
        options.Add(1, New ArrayList({"Button", "Upload Images", "reqimagesbutton"}))
        Return options
    End Function

    Structure rdataStructure
        Dim speed As Integer '56-4
        Dim ActualEngineRPM As Integer '24
        Dim EngineMaxRPM As Integer '28
        Dim ActualFuelPressure As Integer '32
        Dim ActualFuelLiters As Integer '36
        Dim ActualEngineWaterTemp As Integer '44
        Dim ActualEngineOilTemp As Integer '48
        Dim ActualEngineOilPressure As Integer '52
        Dim ActualGear As Integer '88

        Dim CurrentLap As Integer '64
        Dim TimeBestLap As Integer '68
        Dim TimeLastLap As Integer '72
        Dim TimecurrentLap As Integer '76
        Dim Position As Integer '80
        Dim TimeCurrentLap_Text As String
        Dim TimeBestLap_Text As String
        Dim TimeLastLap_Text As String

        Dim Temp_Tire_Front_Left As Integer '92+96+100
        Dim Temp_Tire_Front_Right As Integer '104+108+112
        Dim Temp_Tire_Rear_Left As Integer '116+120+124
        Dim Temp_Tire_Rear_Right As Integer '128+132+136      
    End Structure

    Public Function GrabData()
        Try
            ' Try to open the named file mapping.
            If hMapFile Is Nothing OrElse hMapFile.IsInvalid Then
                hMapFile = NativeMethod.OpenFileMapping(FileMapAccess.FILE_MAP_READ, False, FullMapName)
                objHost.DebugMessage("SimBin - Connected to MapFile")
            End If

            If pView = IntPtr.Zero Then
                pView = NativeMethod.MapViewOfFile(hMapFile, FileMapAccess.FILE_MAP_READ, 0, ViewOffset, ViewSize)
                objHost.DebugMessage("SimBin - pView Inited")
            End If

            If hMapFile Is Nothing Then Return False

            If (hMapFile.IsInvalid) Then Return False

            If (pView = IntPtr.Zero) Then Throw New Win32Exception


            Dim value = 0
            Dim arrSize As Integer = 259
            Dim data(arrSize - 1) As Byte
            Dim i As Integer
            For i = 0 To arrSize - 1
                data(i) = Marshal.ReadByte(New IntPtr(pView.ToInt32() + i))
            Next

            rdata.speed = BitConverter.ToSingle({data(56), data(57), data(58), data(59)}, 0) * 3.6
            rdata.ActualEngineRPM = BitConverter.ToSingle({data(24), data(25), data(26), data(27)}, 0)
            If rdata.ActualEngineRPM < 0 Then rdata.ActualEngineRPM = 0
            rdata.EngineMaxRPM = BitConverter.ToSingle({data(28), data(29), data(30), data(31)}, 0)
            rdata.ActualFuelPressure = BitConverter.ToSingle({data(32), data(33), data(34), data(35)}, 0)
            rdata.ActualFuelLiters = BitConverter.ToSingle({data(36), data(37), data(38), data(39)}, 0)
            rdata.ActualEngineWaterTemp = BitConverter.ToSingle({data(44), data(45), data(46), data(47)}, 0)
            rdata.ActualEngineOilTemp = BitConverter.ToSingle({data(48), data(49), data(50), data(51)}, 0)
            rdata.ActualEngineOilPressure = BitConverter.ToSingle({data(52), data(53), data(54), data(55)}, 0)
            rdata.ActualGear = data(88)
            rdata.CurrentLap = data(64)
            If rdata.CurrentLap >= 255 Then rdata.CurrentLap = 0
            rdata.Temp_Tire_Front_Left = Math.Round((BitConverter.ToSingle({data(92), data(93), data(94), data(95)}, 0) + _
                                                     BitConverter.ToSingle({data(96), data(97), data(98), data(99)}, 0) + _
                                                     BitConverter.ToSingle({data(100), data(101), data(102), data(103)}, 0)) / 3, 2)
            rdata.Temp_Tire_Front_Right = Math.Round((BitConverter.ToSingle({data(104), data(105), data(106), data(107)}, 0) + _
                                                     BitConverter.ToSingle({data(108), data(109), data(110), data(111)}, 0) + _
                                                     BitConverter.ToSingle({data(112), data(113), data(114), data(115)}, 0)) / 3, 2)
            rdata.Temp_Tire_Rear_Left = Math.Round((BitConverter.ToSingle({data(116), data(117), data(118), data(119)}, 0) + _
                                                     BitConverter.ToSingle({data(120), data(121), data(122), data(123)}, 0) + _
                                                     BitConverter.ToSingle({data(124), data(125), data(126), data(127)}, 0)) / 3, 2)
            rdata.Temp_Tire_Rear_Right = Math.Round((BitConverter.ToSingle({data(128), data(129), data(130), data(131)}, 0) + _
                                                     BitConverter.ToSingle({data(132), data(133), data(134), data(135)}, 0) + _
                                                     BitConverter.ToSingle({data(136), data(137), data(138), data(139)}, 0)) / 3, 2)

            If rdata.Temp_Tire_Front_Left < 0 Then rdata.Temp_Tire_Front_Left = 0
            If rdata.Temp_Tire_Front_Right < 0 Then rdata.Temp_Tire_Front_Right = 0
            If rdata.Temp_Tire_Rear_Left < 0 Then rdata.Temp_Tire_Rear_Left = 0
            If rdata.Temp_Tire_Rear_Right < 0 Then rdata.Temp_Tire_Rear_Right = 0

            rdata.Position = data(80)
            If rdata.Position >= 255 Then rdata.Position = 0
            value = rdata.speed
            rdata.TimecurrentLap = BitConverter.ToSingle({data(76), data(77), data(78), data(79)}, 0)
            Dim m = rdata.TimecurrentLap \ 60
            Dim s = rdata.TimecurrentLap Mod 60
            If s < 0 Then s = 0
            If m < 10 Then m = "0" & m.ToString
            If s < 10 Then s = "0" & s.ToString
            rdata.TimeCurrentLap_Text = m.ToString & "m" & s.ToString & "s"


            rdata.TimeBestLap = BitConverter.ToSingle({data(68), data(69), data(70), data(71)}, 0)
            m = rdata.TimeBestLap \ 60
            s = rdata.TimeBestLap Mod 60
            If s < 0 Then s = 0
            If m < 10 Then m = "0" & m.ToString
            If s < 10 Then s = "0" & s.ToString
            rdata.TimeBestLap_Text = m & "m" & s & "s"

            rdata.TimeLastLap = BitConverter.ToSingle({data(72), data(73), data(74), data(75)}, 0)
            m = rdata.TimeLastLap \ 60
            s = rdata.TimeLastLap Mod 60
            If s < 0 Then s = 0
            If m < 10 Then m = "0" & m.ToString
            If s < 10 Then s = "0" & s.ToString
            rdata.TimeLastLap_Text = m & "m" & s & "s"

            Return True
        Catch ex As Exception
            Return False
        End Try
    End Function
    Public Function DisplayOnLCD(sensorId As String, elementData As Hashtable, pluginOptions As Hashtable, cacheRuns As Integer) As ArrayList Implements GOverlayPlugin.Interfaces.IPlugin.DisplayOnLCD

        Dim x = CInt(elementData("x"))    'grab X position of the element
        Dim y = CInt(elementData("y"))    'grab Y position of the element

        Dim commandList2 As New ArrayList()

        Try
            Dim value = 0

            'If it fails, dont output anything
            If GrabData() = False Then
                'Return commandList2
            End If

            Try

                If sensorId = "SimBin.Gauge" Then
                    Dim inited = objHost.AccessHost("retrieve", "GLOBAL_GeneralVars", "lcdsys_windows_inited", "")
                    If inited <> 1 Then
                        objHost.DebugMessage("SimBin - init Full Gauge")
                        commandList2.Add(New ArrayList({"image", x, y, 310}))
                        commandList2.Add(New ArrayList({"wait", 1500}))
                        commandList2.Add(New ArrayList({"text_square", "LAP", 142, 4, 4, 4 * 2, 3, 65535}))
                        'Reset our internal cache
                        LastCache = New System.Collections.Hashtable
                    End If


                    Dim images = 19
                    Dim maxspeed = elementData("maxspeed")
                    Dim steps = maxspeed / images
                    Dim color_grey = 340
                    Dim color_green = 341
                    Dim color_red = 342
                    Dim color_yellow = 343
                    Dim use_color = color_grey

                    Dim needleEnabled = False

                    Dim centerX, centerY, leftX, leftY, rightX, rightY, thetaRad, topX, topY, val, needleLen, needleRadius, percent
                    needleLen = 30
                    needleRadius = 1.5

                    If needleEnabled = True Then
                        val = ((rdata.speed * 145 / maxspeed) * 0.01) - 0.25
                        percent = val

                        thetaRad = percToRad(percent / 2)

                        centerX = x + 93
                        centerY = y + 88

                        topX = centerX - needleLen * Math.Cos(thetaRad)
                        topY = centerY - needleLen * Math.Sin(thetaRad)

                        leftX = centerX - needleRadius * Math.Cos(thetaRad - Math.PI / 2)
                        leftY = centerY - needleRadius * Math.Sin(thetaRad - Math.PI / 2)

                        rightX = centerX - needleRadius * Math.Cos(thetaRad + Math.PI / 2)
                        rightY = centerY - needleRadius * Math.Sin(thetaRad + Math.PI / 2)

                        If (Not LastCache.ContainsKey("prev_speed_value")) OrElse (LastCache.ContainsKey("prev_speed_value") AndAlso LastCache("prev_speed_value") <> rdata.speed) Then
                            If LastCache.ContainsKey("prev_speed_lines") Then
                                commandList2.Add(New ArrayList({"draw_lines", LastCache("prev_speed_lines"), convertcolorto16bit(0, 0, 0)}))
                            End If

                            Dim mid = x + 60
                            Dim lines As New ArrayList
                            lines.Add(New ArrayList({leftX, leftY}))
                            lines.Add(New ArrayList({topX, topY}))
                            lines.Add(New ArrayList({rightX, rightY}))
                            lines.Add(New ArrayList({leftX, leftY}))
                            'objHost.DebugMessage(val & " > " & centerX & ":" & centerY & " > " & topX & ":" & topY)
                            commandList2.Add(New ArrayList({"draw_lines", lines, convertcolorto16bit(27, 160, 232)}))
                            LastCache("prev_speed_lines") = lines
                        End If
                        LastCache("prev_speed_value") = rdata.speed
                    End If

                    If steps * 1 < rdata.speed Then use_color = color_green Else use_color = color_grey
                    If Not LastCache.ContainsKey("s1") OrElse LastCache("s1") <> use_color Then commandList2.Add(New ArrayList({"image", x + 63, y + 112, use_color}))
                    LastCache("s1") = use_color
                    If steps * 2 < rdata.speed Then use_color = color_green Else use_color = color_grey
                    If Not LastCache.ContainsKey("s2") OrElse LastCache("s2") <> use_color Then commandList2.Add(New ArrayList({"image", x + 57, y + 104, use_color}))
                    LastCache("s2") = use_color
                    If steps * 3 < rdata.speed Then use_color = color_green Else use_color = color_grey
                    If Not LastCache.ContainsKey("s3") OrElse LastCache("s3") <> use_color Then commandList2.Add(New ArrayList({"image", x + 52, y + 94, use_color}))
                    LastCache("s3") = use_color
                    If steps * 4 < rdata.speed Then use_color = color_green Else use_color = color_grey
                    If Not LastCache.ContainsKey("s4") OrElse LastCache("s4") <> use_color Then commandList2.Add(New ArrayList({"image", x + 50, y + 84, use_color}))
                    LastCache("s4") = use_color
                    If steps * 5 < rdata.speed Then use_color = color_green Else use_color = color_grey
                    If Not LastCache.ContainsKey("s5") OrElse LastCache("s5") <> use_color Then commandList2.Add(New ArrayList({"image", x + 53, y + 73, use_color}))
                    LastCache("s5") = use_color
                    If steps * 6 < rdata.speed Then use_color = color_green Else use_color = color_grey
                    If Not LastCache.ContainsKey("s6") OrElse LastCache("s6") <> use_color Then commandList2.Add(New ArrayList({"image", x + 58, y + 64, use_color}))
                    LastCache("s6") = use_color
                    If steps * 7 < rdata.speed Then use_color = color_green Else use_color = color_grey
                    If Not LastCache.ContainsKey("s7") OrElse LastCache("s7") <> use_color Then commandList2.Add(New ArrayList({"image", x + 64, y + 56, use_color}))
                    LastCache("s7") = use_color
                    If steps * 8 < rdata.speed Then use_color = color_green Else use_color = color_grey
                    If Not LastCache.ContainsKey("s8") OrElse LastCache("s8") <> use_color Then commandList2.Add(New ArrayList({"image", x + 73, y + 50, use_color}))
                    LastCache("s8") = use_color
                    If steps * 9 < rdata.speed Then use_color = color_green Else use_color = color_grey
                    If Not LastCache.ContainsKey("s9") OrElse LastCache("s9") <> use_color Then commandList2.Add(New ArrayList({"image", x + 83, y + 46, use_color}))
                    LastCache("s9") = use_color
                    If steps * 10 < rdata.speed Then use_color = color_green Else use_color = color_grey
                    If Not LastCache.ContainsKey("s10") OrElse LastCache("s10") <> use_color Then commandList2.Add(New ArrayList({"image", x + 93, y + 46, use_color}))
                    LastCache("s10") = use_color

                    If steps * 11 < rdata.speed Then use_color = color_yellow Else use_color = color_grey
                    If Not LastCache.ContainsKey("s11") OrElse LastCache("s11") <> use_color Then commandList2.Add(New ArrayList({"image", x + 104, y + 50, use_color}))
                    LastCache("s11") = use_color
                    If steps * 12 < rdata.speed Then use_color = color_yellow Else use_color = color_grey
                    If Not LastCache.ContainsKey("s12") OrElse LastCache("s12") <> use_color Then commandList2.Add(New ArrayList({"image", x + 113, y + 56, use_color}))
                    LastCache("s12") = use_color
                    If steps * 13 < rdata.speed Then use_color = color_yellow Else use_color = color_grey
                    If Not LastCache.ContainsKey("s13") OrElse LastCache("s13") <> use_color Then commandList2.Add(New ArrayList({"image", x + 113, y + 56, use_color}))
                    LastCache("s13") = use_color
                    If steps * 14 < rdata.speed Then use_color = color_yellow Else use_color = color_grey
                    If Not LastCache.ContainsKey("s14") OrElse LastCache("s14") <> use_color Then commandList2.Add(New ArrayList({"image", x + 120, y + 64, use_color}))
                    LastCache("s14") = use_color
                    If steps * 15 < rdata.speed Then use_color = color_yellow Else use_color = color_grey
                    If Not LastCache.ContainsKey("s15") OrElse LastCache("s15") <> use_color Then commandList2.Add(New ArrayList({"image", x + 125, y + 73, use_color}))
                    LastCache("s15") = use_color
                    If steps * 16 < rdata.speed Then use_color = color_red Else use_color = color_grey
                    If Not LastCache.ContainsKey("s16") OrElse LastCache("s16") <> use_color Then commandList2.Add(New ArrayList({"image", x + 128, y + 84, use_color}))
                    LastCache("s16") = use_color
                    If steps * 17 < rdata.speed Then use_color = color_red Else use_color = color_grey
                    If Not LastCache.ContainsKey("s17") OrElse LastCache("s17") <> use_color Then commandList2.Add(New ArrayList({"image", x + 126, y + 94, use_color}))
                    LastCache("s17") = use_color
                    If steps * 18 < rdata.speed Then use_color = color_red Else use_color = color_grey
                    If Not LastCache.ContainsKey("s18") OrElse LastCache("s18") <> use_color Then commandList2.Add(New ArrayList({"image", x + 122, y + 104, use_color}))
                    LastCache("s18") = use_color
                    If steps * 19 < rdata.speed Then use_color = color_red Else use_color = color_grey
                    If Not LastCache.ContainsKey("s19") OrElse LastCache("s19") <> use_color Then commandList2.Add(New ArrayList({"image", x + 116, y + 112, use_color}))
                    LastCache("s19") = use_color

                    steps = rdata.EngineMaxRPM / images
                    Dim offsetx = 128

                    If needleEnabled = True Then
                        Dim rpm_max = rdata.EngineMaxRPM
                        steps = rpm_max / images

                        Dim rpm_current = rdata.ActualEngineRPM
                        If rdata.ActualEngineRPM > rpm_max Then rpm_current = rpm_max Else rpm_current = rdata.ActualEngineRPM
                        val = ((rpm_current * 145 / rpm_max) * 0.01) - 0.25
                        percent = val

                        thetaRad = percToRad(percent / 2)

                        centerX = x + 128 + 93
                        centerY = y + 88

                        topX = centerX - needleLen * Math.Cos(thetaRad)
                        topY = centerY - needleLen * Math.Sin(thetaRad)

                        leftX = centerX - needleRadius * Math.Cos(thetaRad - Math.PI / 2)
                        leftY = centerY - needleRadius * Math.Sin(thetaRad - Math.PI / 2)

                        rightX = centerX - needleRadius * Math.Cos(thetaRad + Math.PI / 2)
                        rightY = centerY - needleRadius * Math.Sin(thetaRad + Math.PI / 2)

                        If (Not LastCache.ContainsKey("prev_rpm_value")) OrElse (LastCache.ContainsKey("prev_rpm_value") AndAlso LastCache("prev_rpm_value") <> rpm_current) Then
                            If LastCache.ContainsKey("prev_rpm_lines") Then
                                commandList2.Add(New ArrayList({"draw_lines", LastCache("prev_rpm_lines"), convertcolorto16bit(0, 0, 0)}))
                            End If

                            Dim mid = x + 60
                            Dim lines As New ArrayList
                            lines.Add(New ArrayList({leftX, leftY}))
                            lines.Add(New ArrayList({topX, topY}))
                            lines.Add(New ArrayList({rightX, rightY}))
                            lines.Add(New ArrayList({leftX, leftY}))
                            'objHost.DebugMessage(val & " > " & centerX & ":" & centerY & " > " & topX & ":" & topY)
                            commandList2.Add(New ArrayList({"draw_lines", lines, convertcolorto16bit(27, 160, 232)}))
                            LastCache("prev_rpm_lines") = lines
                        End If
                        LastCache("prev_rpm_value") = rpm_current

                    End If


                    If steps * 1 < rdata.ActualEngineRPM Then use_color = color_green Else use_color = color_grey
                    If Not LastCache.ContainsKey("r1") OrElse LastCache("r1") <> use_color Then commandList2.Add(New ArrayList({"image", offsetx + x + 63, y + 112, use_color}))
                    LastCache("r1") = use_color
                    If steps * 2 < rdata.ActualEngineRPM Then use_color = color_green Else use_color = color_grey
                    If Not LastCache.ContainsKey("r2") OrElse LastCache("r2") <> use_color Then commandList2.Add(New ArrayList({"image", offsetx + x + 57, y + 104, use_color}))
                    LastCache("r2") = use_color
                    If steps * 3 < rdata.ActualEngineRPM Then use_color = color_green Else use_color = color_grey
                    If Not LastCache.ContainsKey("r3") OrElse LastCache("r3") <> use_color Then commandList2.Add(New ArrayList({"image", offsetx + x + 52, y + 94, use_color}))
                    LastCache("r3") = use_color
                    If steps * 4 < rdata.ActualEngineRPM Then use_color = color_green Else use_color = color_grey
                    If Not LastCache.ContainsKey("r4") OrElse LastCache("r4") <> use_color Then commandList2.Add(New ArrayList({"image", offsetx + x + 50, y + 84, use_color}))
                    LastCache("r4") = use_color
                    If steps * 5 < rdata.ActualEngineRPM Then use_color = color_green Else use_color = color_grey
                    If Not LastCache.ContainsKey("r5") OrElse LastCache("r5") <> use_color Then commandList2.Add(New ArrayList({"image", offsetx + x + 53, y + 73, use_color}))
                    LastCache("r5") = use_color
                    If steps * 6 < rdata.ActualEngineRPM Then use_color = color_green Else use_color = color_grey
                    If Not LastCache.ContainsKey("r6") OrElse LastCache("r6") <> use_color Then commandList2.Add(New ArrayList({"image", offsetx + x + 58, y + 64, use_color}))
                    LastCache("r6") = use_color
                    If steps * 7 < rdata.ActualEngineRPM Then use_color = color_green Else use_color = color_grey
                    If Not LastCache.ContainsKey("r7") OrElse LastCache("r7") <> use_color Then commandList2.Add(New ArrayList({"image", offsetx + x + 64, y + 56, use_color}))
                    LastCache("r7") = use_color
                    If steps * 8 < rdata.ActualEngineRPM Then use_color = color_green Else use_color = color_grey
                    If Not LastCache.ContainsKey("r8") OrElse LastCache("r8") <> use_color Then commandList2.Add(New ArrayList({"image", offsetx + x + 73, y + 50, use_color}))
                    LastCache("r8") = use_color
                    If steps * 9 < rdata.ActualEngineRPM Then use_color = color_green Else use_color = color_grey
                    If Not LastCache.ContainsKey("r9") OrElse LastCache("r9") <> use_color Then commandList2.Add(New ArrayList({"image", offsetx + x + 83, y + 46, use_color}))
                    LastCache("r9") = use_color
                    If steps * 10 < rdata.ActualEngineRPM Then use_color = color_green Else use_color = color_grey
                    If Not LastCache.ContainsKey("r10") OrElse LastCache("r10") <> use_color Then commandList2.Add(New ArrayList({"image", offsetx + x + 93, y + 46, use_color}))
                    LastCache("r10") = use_color

                    If steps * 11 < rdata.ActualEngineRPM Then use_color = color_yellow Else use_color = color_grey
                    If Not LastCache.ContainsKey("r11") OrElse LastCache("r11") <> use_color Then commandList2.Add(New ArrayList({"image", offsetx + x + 104, y + 50, use_color}))
                    LastCache("r1") = use_color
                    If steps * 12 < rdata.ActualEngineRPM Then use_color = color_yellow Else use_color = color_grey
                    If Not LastCache.ContainsKey("r12") OrElse LastCache("r12") <> use_color Then commandList2.Add(New ArrayList({"image", offsetx + x + 113, y + 56, use_color}))
                    LastCache("r12") = use_color
                    If steps * 13 < rdata.ActualEngineRPM Then use_color = color_yellow Else use_color = color_grey
                    If Not LastCache.ContainsKey("r13") OrElse LastCache("r13") <> use_color Then commandList2.Add(New ArrayList({"image", offsetx + x + 113, y + 56, use_color}))
                    LastCache("r13") = use_color
                    If steps * 14 < rdata.ActualEngineRPM Then use_color = color_yellow Else use_color = color_grey
                    If Not LastCache.ContainsKey("r14") OrElse LastCache("r14") <> use_color Then commandList2.Add(New ArrayList({"image", offsetx + x + 120, y + 64, use_color}))
                    LastCache("r14") = use_color
                    If steps * 15 < rdata.ActualEngineRPM Then use_color = color_yellow Else use_color = color_grey
                    If Not LastCache.ContainsKey("r15") OrElse LastCache("r15") <> use_color Then commandList2.Add(New ArrayList({"image", offsetx + x + 125, y + 73, use_color}))
                    LastCache("r15") = use_color
                    If steps * 16 < rdata.ActualEngineRPM Then use_color = color_red Else use_color = color_grey
                    If Not LastCache.ContainsKey("r16") OrElse LastCache("r16") <> use_color Then commandList2.Add(New ArrayList({"image", offsetx + x + 128, y + 84, use_color}))
                    LastCache("r16") = use_color
                    If steps * 17 < rdata.ActualEngineRPM Then use_color = color_red Else use_color = color_grey
                    If Not LastCache.ContainsKey("r17") OrElse LastCache("r17") <> use_color Then commandList2.Add(New ArrayList({"image", offsetx + x + 126, y + 94, use_color}))
                    LastCache("r17") = use_color
                    If steps * 18 < rdata.ActualEngineRPM Then use_color = color_red Else use_color = color_grey
                    If Not LastCache.ContainsKey("r18") OrElse LastCache("r18") <> use_color Then commandList2.Add(New ArrayList({"image", offsetx + x + 122, y + 104, use_color}))
                    LastCache("r18") = use_color
                    If steps * 19 < rdata.ActualEngineRPM Then use_color = color_red Else use_color = color_grey
                    If Not LastCache.ContainsKey("r19") OrElse LastCache("r19") <> use_color Then commandList2.Add(New ArrayList({"image", offsetx + x + 116, y + 112, use_color}))
                    LastCache("r19") = use_color

                    Dim rect_x = 204
                    Dim rect_y = 105
                    Dim rect_y2 = rect_y + 37
                    Dim rect_x2 = rect_x + 35
                    Dim text_y = rect_y - 1
                    Dim text_x = rect_x + 9

                    If rdata.ActualGear < 1 Then
                        commandList2.Add(New ArrayList({"draw_rectangle", rect_x, rect_y, rect_x2, rect_y2, 1, convertcolorto16bit(0, 0, 0)}))
                        commandList2.Add(New ArrayList({"text", text_x, text_y, "N", 0, False, False, 0, 0}))
                    Else
                        If rdata.ActualGear.ToString.Length = 1 Then
                            If steps * 16 < rdata.ActualEngineRPM Then
                                commandList2.Add(New ArrayList({"draw_rectangle", rect_x, rect_y, rect_x2, rect_y2, 1, convertcolorto16bit(253, 23, 36)}))
                                commandList2.Add(New ArrayList({"text", text_x, text_y, rdata.ActualGear.ToString, 0, False, False, 0, 3}))
                            Else
                                commandList2.Add(New ArrayList({"draw_rectangle", rect_x, rect_y, rect_x2, rect_y2, 1, convertcolorto16bit(0, 0, 0)}))
                                commandList2.Add(New ArrayList({"text", text_x, text_y, rdata.ActualGear.ToString, 0, False, False, 0, 0}))
                            End If
                        Else
                            commandList2.Add(New ArrayList({"draw_rectangle", rect_x, rect_y, rect_x2, rect_y2, 1, convertcolorto16bit(0, 0, 0)}))
                            commandList2.Add(New ArrayList({"text", text_x, text_y, "R", 0, False, False, 0, 0}))
                        End If
                    End If

                    commandList2.Add(New ArrayList({"text", 150, 10, rdata.CurrentLap.ToString, 0, False, False, 0, 0}))

                    Dim max_temp = elementData("maxtemp")
                    'Dim fuel_color_in = convertcolorto16bit(78, 141, 163)
                    'Dim fuel_color_out = convertcolorto16bit(254, 254, 254)
                    Dim fuel_color_out = convertcolorto16bit(254, 254, 254)
                    Dim fuel_color_in = convertcolorto16bit(253, 23, 36)
                    Dim rect_xstep = 7
                    Dim rect_ystep = 8
                    steps = max_temp / 8
                    rect_x = 286
                    rect_y = 138
                    rect_x2 = rect_x + rect_xstep
                    rect_y2 = rect_y + rect_ystep

                    ' objHost.DebugMessage("Fuel: " & rdata.ActualFuelLiters)
                    ' objHost.DebugMessage("temp: " & rdata.ActualEngineOilTemp)

                    'TEMP
                    Dim xbox = 0
                    Dim xbox_Step = 1
                    For xbox = 0 To 7
                        If steps * xbox < rdata.ActualEngineOilTemp Then use_color = fuel_color_in Else use_color = fuel_color_out
                        commandList2.Add(New ArrayList({"fill_rectangle", rect_x, rect_y, rect_x2, rect_y2, use_color}))

                        rect_y = rect_y - rect_ystep - xbox_Step
                        rect_y2 = rect_y + rect_ystep
                        rect_x2 = rect_x + rect_xstep

                        If xbox = 0 Or xbox = 2 Then
                            xbox_Step = 3
                        ElseIf xbox = 4 Then
                            xbox_Step = 4
                        Else
                            xbox_Step = 1
                        End If
                    Next


                    value = rdata.ActualEngineOilTemp
                    If Not LastCache.ContainsKey("temp_num") OrElse LastCache("temp_num") <> value Then
                        commandList2.Add(New ArrayList({"text_square", value.ToString, 276, 152, 4, 4 * 2, 3, 65535}))
                    End If
                    LastCache("temp_num") = rdata.ActualFuelLiters


                    'FUEL
                    Dim max_fuel = elementData("maxfuel")
                    steps = max_fuel / 8
                    rect_x = 16
                    rect_y = 67
                    rect_y = 137
                    rect_x2 = rect_x + rect_xstep
                    rect_y2 = rect_y + rect_ystep
                    xbox = 0
                    xbox_Step = 1
                    For xbox = 0 To 7
                        If steps * xbox < rdata.ActualFuelLiters Then use_color = fuel_color_in Else use_color = fuel_color_out
                        commandList2.Add(New ArrayList({"fill_rectangle", rect_x, rect_y, rect_x2, rect_y2, use_color}))

                        rect_y = rect_y - rect_ystep - xbox_Step
                        rect_y2 = rect_y + rect_ystep
                        rect_x2 = rect_x + rect_xstep

                        If xbox = 0 Or xbox = 2 Then
                            xbox_Step = 3
                        ElseIf xbox = 4 Then
                            xbox_Step = 4
                        Else
                            xbox_Step = 1
                        End If
                    Next

                    value = rdata.ActualFuelLiters
                    If Not LastCache.ContainsKey("fuel_num") OrElse LastCache("fuel_num") <> value Then
                        commandList2.Add(New ArrayList({"text_square", value.ToString, 6, 152, 4, 4 * 2, 3, 65535}))
                    End If
                    LastCache("fuel_num") = rdata.ActualFuelLiters


                    Dim rpm As String = rdata.ActualEngineRPM.ToString
                    If rpm.Length <= 0 Then
                        rpm = "0000"
                    ElseIf rpm.Length <= 1 Then
                        rpm = "000" & rpm
                    ElseIf rpm.Length <= 2 Then
                        rpm = "00" & rpm
                    ElseIf rpm.Length <= 3 Then
                        rpm = "0" & rpm
                    ElseIf rpm.Length > 4 Then
                        rpm = "9999"
                    End If

                    Dim speed2 As String = rdata.speed
                    If speed2.Length <= 0 Then
                        speed2 = "000"
                    ElseIf speed2.Length <= 1 Then
                        speed2 = "00" & speed2
                    ElseIf speed2.Length <= 2 Then
                        speed2 = "0" & speed2
                    ElseIf speed2.Length <= 3 Then
                        speed2 = speed2
                    ElseIf speed2.Length >= 4 Then
                        speed2 = "999"
                    End If

                    commandList2.Add(New ArrayList({"text_image", x + 60, y + 77, speed2, 4}))
                    commandList2.Add(New ArrayList({"text_image", x + 195, y + 77, rpm, 3}))

                    Dim pos = rdata.Position
                    Dim xoffset As Integer = 0
                    If pos.ToString.Length = 0 Then
                        pos = "00"
                    ElseIf pos.ToString.Length = 1 Then
                        xoffset = 6
                    End If

                    If Not LastCache.ContainsKey("pos") OrElse LastCache("pos") <> pos Then
                        If PosSlot > 1 And pos.ToString.Length < 2 Then
                            'Clear the previous two slows
                            commandList2.Add(New ArrayList({"text_image", x + 269, y + 14, "  ", 3}))
                        End If
                        commandList2.Add(New ArrayList({"text_image", x + 269 + xoffset, y + 14, pos, 3}))
                        PosSlot = pos.ToString.Length

                        LastCache("pos") = pos
                    End If

                    Return commandList2

                ElseIf sensorId = "SimBin.Tires" Then
                    Dim inited = objHost.AccessHost("retrieve", "GLOBAL_GeneralVars", "lcdsys_windows_inited", "")
                    If inited <> 1 Then
                        objHost.DebugMessage("SimBin - init Tires")
                        commandList2.Add(New ArrayList({"image", x + 20, y, 345}))
                        commandList2.Add(New ArrayList({"wait", 100}))
                    End If

                    Dim f_left = rdata.Temp_Tire_Front_Left.ToString
                    Dim f_right = rdata.Temp_Tire_Front_Right.ToString
                    Dim r_left = rdata.Temp_Tire_Rear_Left.ToString
                    Dim r_right = rdata.Temp_Tire_Rear_Right.ToString

                    If f_left.Length = 1 Then f_left = "  " & f_left
                    If f_right.Length = 1 Then f_right = f_right & "  "
                    If r_left.length = 1 Then r_left = "  " & r_left
                    If r_right.length = 1 Then r_right = r_right & "  "

                    If f_left.Length = 2 Then f_left = " " & f_left
                    If f_right.Length = 2 Then f_right = f_right & " "
                    If r_left.length = 2 Then r_left = " " & r_left
                    If r_right.length = 2 Then r_right = r_right & " "


                    If Not LastCache.ContainsKey("t1") OrElse LastCache("t1") <> f_left Then commandList2.Add(New ArrayList({"text_image", x - 10, y + 10, f_left, 5}))
                    LastCache("t1") = f_left
                    If Not LastCache.ContainsKey("t2") OrElse LastCache("t2") <> f_right Then commandList2.Add(New ArrayList({"text_image", x + 60, y + 10, f_right, 5}))
                    LastCache("t2") = f_right

                    If Not LastCache.ContainsKey("t3") OrElse LastCache("t3") <> r_left Then commandList2.Add(New ArrayList({"text_image", x - 10, y + 48, r_left, 5}))
                    LastCache("t3") = r_left
                    If Not LastCache.ContainsKey("t4") OrElse LastCache("t4") <> r_right Then commandList2.Add(New ArrayList({"text_image", x + 60, y + 48, r_right, 5}))
                    LastCache("t4") = r_right

                    Return commandList2
                Else

                    If sensorId = "SimBin.Speed" Then
                        value = rdata.speed
                    ElseIf sensorId = "SimBin.EngineRPM" Then
                        value = rdata.ActualEngineRPM
                    ElseIf sensorId = "SimBin.FuelPressure" Then
                        value = rdata.ActualFuelPressure
                    ElseIf sensorId = "SimBin.FuelLiters" Then
                        value = rdata.ActualFuelLiters
                    ElseIf sensorId = "SimBin.WaterTemp" Then
                        value = rdata.ActualEngineWaterTemp
                    ElseIf sensorId = "SimBin.OilTemp" Then
                        value = rdata.ActualEngineOilTemp
                    ElseIf sensorId = "SimBin.OilPress" Then
                        value = rdata.ActualEngineOilPressure
                    ElseIf sensorId = "SimBin.Gear" Then
                        value = rdata.ActualGear
                    ElseIf sensorId = "SimBin.Lap" Then
                        value = rdata.CurrentLap
                    ElseIf sensorId = "SimBin.TimeBestLap" Then
                        value = rdata.TimeBestLap
                        value = rdata.TimeBestLap_Text
                    ElseIf sensorId = "SimBin.TimeLastLap" Then
                        value = rdata.TimeLastLap
                        value = rdata.TimeLastLap_Text
                    ElseIf sensorId = "SimBin.TimeCurrentLap" Then
                        value = rdata.TimecurrentLap
                        value = rdata.TimeCurrentLap_Text
                    ElseIf sensorId = "SimBin.Position" Then
                        value = rdata.Position
                    Else
                        value = 0
                    End If

                    If Not LastCache.ContainsKey(sensorId) OrElse value.ToString.ToLower <> LastCache(sensorId).ToString.ToLower Then

                        If elementData("font_style") = 0 Then
                            commandList2.Add(New ArrayList({"text", x, y, value.ToString, 0, False, False, 0, elementData("basic_color")}))
                        ElseIf elementData("font_style") = 1 Then
                            If elementData("font_transform") = 1 Then value = value.ToString.ToUpper
                            If elementData("font_transform") = 2 Then value = value.ToString.ToLower
                            'clear previous value
                            If LastCache.ContainsKey(sensorId) Then
                                commandList2.Add(New ArrayList({"text_square", LastCache(sensorId).ToString, x, y, elementData("font_size"), CInt(elementData("font_size")) * 2, 3, 0}))
                                'objHost.DebugMessage("clear: " & LastCache(sensorId).ToString)
                            End If
                            'write value
                            commandList2.Add(New ArrayList({"text_square", value.ToString, x, y, elementData("font_size"), CInt(elementData("font_size")) * 2, 3, elementData("font_color")}))
                        Else
                            commandList2.Add(New ArrayList({"text_image", x, y, value.ToString, elementData("font_style")}))
                        End If

                        LastCache(sensorId) = value
                    Else

                    End If

                    Return commandList2
                End If


                'objHost.DebugMessage("v: " & data(55).ToString)


            Catch ex As Exception
                objHost.DebugMessage(ex.Message & ": " & ex.StackTrace)
            End Try

        Catch ex As Exception
            objHost.DebugMessage("The process throws the error:" & ex.Message & " : " & ex.StackTrace)
            'Console.ReadLine()
        Finally
            If (Not hMapFile Is Nothing) Then
                If (pView <> IntPtr.Zero) Then
                    ' Unmap the file view.
                    'NativeMethod.UnmapViewOfFile(pView)
                    'pView = IntPtr.Zero
                End If
                ' Close the file mapping object.
                'hMapFile.Close()
                'hMapFile = Nothing
            End If
        End Try


        Return commandList2
        'When the cache is refreshed, lets redraw even if the value stays the same, we could avoid this if we want, this is done just in case there were some errors and the value wasnt draw for some reason before.
        If cacheRuns = 0 Then
            Cache = Nothing
        End If

        Return New ArrayList()
    End Function

    Public Function percToDeg(perc)
        Return perc * 360
    End Function

    Public Function percToRad(perc)
        Return degToRad(percToDeg(perc))
    End Function

    Public Function degToRad(deg)
        Return deg * Math.PI / 180
    End Function

    Public Function convertcolorto16bit(cr, cg, cb)

        Dim R As Double
        Dim G As Double
        Dim B As Double

        R = cr / 256 * 32
        G = cg / 256 * 64
        B = cb / 256 * 32

        R = Math.Floor(R)
        G = Math.Floor(G)
        B = Math.Floor(B)

        Dim final As Int32 = (CInt(R) << 11)
        final = final + Int(G << 5)
        final = final + Int(B)

        Return final

    End Function



#Region "Native API Signatures and Types"

    ''' <summary>
    ''' Access rights for file mapping objects
    ''' http://msdn.microsoft.com/en-us/library/aa366559.aspx
    ''' </summary>
    ''' <remarks></remarks>
    Public Enum FileMapAccess
        FILE_MAP_COPY = 1
        FILE_MAP_WRITE = 2
        FILE_MAP_READ = 4
        FILE_MAP_ALL_ACCESS = &HF001F
    End Enum


    ''' <summary>
    ''' Represents a wrapper class for a file mapping handle. 
    ''' </summary>
    ''' <remarks></remarks>
    <SuppressUnmanagedCodeSecurity(), _
    HostProtection(SecurityAction.LinkDemand, MayLeakOnAbort:=True)> _
    Friend NotInheritable Class SafeFileMappingHandle
        Inherits SafeHandleZeroOrMinusOneIsInvalid

        <SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode:=True)> _
        Private Sub New()
            MyBase.New(True)
        End Sub

        <SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode:=True)> _
        Public Sub New(ByVal handle As IntPtr, ByVal ownsHandle As Boolean)
            MyBase.New(ownsHandle)
            MyBase.SetHandle(handle)
        End Sub

        <ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), _
        DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
        Private Shared Function CloseHandle(ByVal handle As IntPtr) _
        As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function

        Protected Overrides Function ReleaseHandle() As Boolean
            Return SafeFileMappingHandle.CloseHandle(MyBase.handle)
        End Function

    End Class


    Friend ReadOnly INVALID_HANDLE_VALUE As New IntPtr(-1)


    ''' <summary>
    ''' The class exposes Windows APIs used in this code sample.
    ''' </summary>
    ''' <remarks></remarks>
    <SuppressUnmanagedCodeSecurity()> _
    Friend Class NativeMethod

        ''' <summary>
        ''' Opens a named file mapping object.
        ''' </summary>
        ''' <param name="dwDesiredAccess">
        ''' The access to the file mapping object. This access is checked against 
        ''' any security descriptor on the target file mapping object.
        ''' </param>
        ''' <param name="bInheritHandle">
        ''' If this parameter is TRUE, a process created by the CreateProcess 
        ''' function can inherit the handle; otherwise, the handle cannot be 
        ''' inherited.
        ''' </param>
        ''' <param name="lpName">
        ''' The name of the file mapping object to be opened.
        ''' </param>
        ''' <returns>
        ''' If the function succeeds, the return value is an open handle to the 
        ''' specified file mapping object.
        ''' </returns>
        <DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
        Public Shared Function OpenFileMapping( _
            ByVal dwDesiredAccess As FileMapAccess, _
            ByVal bInheritHandle As Boolean, _
            ByVal lpName As String) _
            As SafeFileMappingHandle
        End Function


        ''' <summary>
        ''' Maps a view of a file mapping into the address space of a calling 
        ''' process.
        ''' </summary>
        ''' <param name="hFileMappingObject">
        ''' A handle to a file mapping object. The CreateFileMapping and 
        ''' OpenFileMapping functions return this handle.
        ''' </param>
        ''' <param name="dwDesiredAccess">
        ''' The type of access to a file mapping object, which determines the 
        ''' protection of the pages.
        ''' </param>
        ''' <param name="dwFileOffsetHigh">
        ''' A high-order DWORD of the file offset where the view begins.
        ''' </param>
        ''' <param name="dwFileOffsetLow">
        ''' A low-order DWORD of the file offset where the view is to begin.
        ''' </param>
        ''' <param name="dwNumberOfBytesToMap">
        ''' The number of bytes of a file mapping to map to the view. All bytes 
        ''' must be within the maximum size specified by CreateFileMapping.
        ''' </param>
        ''' <returns>
        ''' If the function succeeds, the return value is the starting address of
        ''' the mapped view.
        ''' </returns>
        <DllImport("Kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
        Public Shared Function MapViewOfFile( _
            ByVal hFileMappingObject As SafeFileMappingHandle, _
            ByVal dwDesiredAccess As FileMapAccess, _
            ByVal dwFileOffsetHigh As UInt32, _
            ByVal dwFileOffsetLow As UInt32, _
            ByVal dwNumberOfBytesToMap As UInt32) _
            As IntPtr
        End Function


        ''' <summary>
        ''' Unmaps a mapped view of a file from the calling process's address 
        ''' space.
        ''' </summary>
        ''' <param name="lpBaseAddress">
        ''' A pointer to the base address of the mapped view of a file that is to 
        ''' be unmapped.
        ''' </param>
        ''' <returns></returns>
        <DllImport("Kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
        Public Shared Function UnmapViewOfFile( _
            ByVal lpBaseAddress As IntPtr) _
            As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function

    End Class

#End Region
End Class