private int ReadPIC(ref _PIC pic, byte[] PacketData)
        {
            byte[] InData = new byte[MAX_PACKET * 2];		//Allocate for one packet
            int RetStatus;
            int DatCount;
            int DatCount2 = 0;

            switch (pic.BootCmd)
            {
                case COMMAND_READPM:
                case COMMAND_READEE:
                case COMMAND_READCFG:
                    break;
                default: return ERROR_INVALID_COMMAND;
            }

            //Limit to 1 to 3 bytes per addr
            if (pic.BytesPerAddr == 0) return ERROR_BPA_TOO_SMALL;
            if (pic.BytesPerAddr > 3) return ERROR_BPA_TOO_BIG;

            //if(pic->BytesPerBlock < pic->BytesPerAddr) return ERROR_BLOCK_TOO_SMALL;
            if (pic.BootDatLen / pic.BytesPerBlock > MAX_PACKET) return ERROR_PACKET_TOO_BIG;

            //Build header
            InData[0] = pic.BootCmd;
            InData[1] = (byte)(pic.BootDatLen / pic.BytesPerBlock);
            InData[2] = (byte)(pic.BootAddr & 0xFF);
            InData[3] = (byte)((pic.BootAddr & 0xFF00) / 0x100);
            InData[4] = (byte)((pic.BootAddr & 0xFF0000) / 0x10000);

            RetStatus = SendGetPacket(InData, 5, MAX_PACKET, pic.MaxRetrys);

            if (RetStatus < 0) return RetStatus;

            for (DatCount = 5; DatCount < RetStatus - 1; DatCount++)
            {
                PacketData[DatCount2] = InData[DatCount];
                DatCount2++;
            }

            return DatCount2;
        }
        private string ReadDeviceID(ushort maxr)
        {
            byte[] DevID;
            int RetStat;
            _PIC picb;
            string result = "";

            DevID = new byte[10];
            DevID[0] = 0;
            DevID[1] = 0;

            picb = new _PIC();
            picb.BootCmd = 1;
            picb.BootDatLen = 4;
            picb.BootAddr = 0xFF0000;
            picb.BytesPerBlock = 4;
            picb.BytesPerAddr = 2;
            picb.MaxRetrys = maxr;
            RetStat = ReadPIC(ref picb, DevID);

            if (RetStat <= 0)
            {
                result = "0";
            }
            else
            {
                result = ((DevID[1] * 256) + DevID[0]).ToString();
            }

            return result;
        }
        private int WritePIC(ref _PIC pic, byte[] PacketData)
        {
            byte[] OutData = new byte[MAX_PACKET + 7];		//Allocate for one packet
            int RetStatus;
            int DatCount;
            int DatCount2;

            switch (pic.BootCmd)
            {
                case COMMAND_WRITEPM:
                case COMMAND_WRITEEE:
                case COMMAND_WRITECFG:
                    break;
                default: return ERROR_INVALID_COMMAND;
            }

            //Limit to 1 to 3 bytes per addr
            if (pic.BytesPerAddr == 0) return ERROR_BPA_TOO_SMALL;
            if (pic.BytesPerAddr > 3) return ERROR_BPA_TOO_BIG;

            //if(pic->BytesPerBlock < pic->BytesPerAddr) return ERROR_BLOCK_TOO_SMALL;
            if (pic.BootDatLen / pic.BytesPerBlock > MAX_PACKET - 6) return ERROR_PACKET_TOO_BIG;

            if ((pic.BootAddr * pic.BytesPerAddr % pic.BytesPerBlock) > 0) return ERROR_OFF_BOUNDRY;
            if ((pic.BootDatLen % pic.BytesPerBlock) > 0) return ERROR_OFF_BOUNDRY2;

            //Build header
            OutData[0] = pic.BootCmd;
            OutData[1] = (byte)(pic.BootDatLen / pic.BytesPerBlock);
            OutData[2] = (byte)(pic.BootAddr & 0xFF);
            OutData[3] = (byte)((pic.BootAddr & 0xFF00) / 0x100);
            OutData[4] = (byte)((pic.BootAddr & 0xFF0000) / 0x10000);

            DatCount = 5;
            for (DatCount2 = 0; DatCount2 < pic.BootDatLen; DatCount2++)
            {
                OutData[DatCount] = PacketData[DatCount2];
                DatCount++;
            }

            RetStatus = SendGetPacket(OutData, (ushort)DatCount, MAX_PACKET, pic.MaxRetrys);

            if (RetStatus < 0) return RetStatus;

            return DatCount2;
        }
        private int WriteRangeDevMem(int BlockSize, byte BytsPerAddr, byte BCom, String InFile)
        {
            byte[] OutData = new byte[261 * 2];
            int RetStat;
            int ProgressInd =1;
            float progress_bar;
            String FileLine;
            _PIC picA = new _PIC();
            int i, j;

            bool VerifyFlag = true;

            // 'Setup data file creation
            StreamReader a = new StreamReader(appPath + "\\" + InFile);

            picA.BootDatLen = (ushort)BlockSize;

            i = 0;
            while (a.EndOfStream != true)
            {
                if (AbortRequest)
                {
                    RetStat = -999;
                    DoUpdateProgress("Aborting...");
                    goto AbortExit;
                }

                FileLine = a.ReadLine();

                picA.BootCmd = BCom;
                picA.BytesPerAddr = BytsPerAddr;
                picA.BytesPerBlock = (ushort)BlockSize;
                picA.MaxRetrys = PicBootS.MaxRetry;
                picA.DeviceType = PicBootS.DeviceType;

             #region  Code for EEprom and Configuration bits --
                /* 'Check command type - handle PM write as full row, dataEE by line
                If BCom = 5 Then   'Data EE
                    picA.BootAddr = (CLng(Val("&H" & Mid(FileLine, 1, 6) & "&")) And FULL_ADDRESS_MASK) \ BytsPerAddr

                    i = 0
                    j = 0
                    TmpStr = Mid(FileLine, i * 3 + 8, 2)
                    Do While TmpStr <> ""
                        If PicBootS.AESEnable Then

                            '***MODIFIED FOR AES: Must send upper unused 2 bytes because it is used during encryption/decrypt
                            OutData(j) = CByte(Val("&H" & TmpStr))
                            j = j + 1

                        Else

                            'Data EE only implements 16 bits, don't send upper 2 bytes
                            If (((i + 2) Mod 4) = 0) Or (((i + 1) Mod 4) = 0) Then
                                'Do not use upper 2 bytes of data
                            Else
                                OutData(j) = CByte(Val("&H" & TmpStr))
                                j = j + 1
                            End If

                        End If

                        i = i + 1
                        TmpStr = Mid(FileLine, i * 3 + 8, 2)
                    Loop

                    picA.BootDatLen = j

                ElseIf BCom = 7 Then   'Config fuses

                    picA.BootAddr = (CLng(Val("&H" & Mid(FileLine, 1, 7) & "&")) And FULL_ADDRESS_MASK) \ BytsPerAddr

                    i = 0
                    j = 0
                    TmpStr = Mid(FileLine, i * 3 + 9, 2)
                    Do While TmpStr <> ""

                       If PicBootS.AESEnable Then

                            '***MODIFIED FOR AES: Must send upper unused 3 bytes because it is used during encryption/decrypt
                            OutData(j) = CByte(Val("&H" & TmpStr))
                            j = j + 1

                        Else

                            'Config only implements 8 bits, don't send upper 3 bytes
                            If (((i + 3) Mod 4) = 0) Or (((i + 2) Mod 4) = 0) Or (((i + 1) Mod 4) = 0) Then
                                'Do not use upper 3 bytes of data
                            Else
                                OutData(j) = CByte(Val("&H" & TmpStr))
                                j = j + 1
                            End If
                        End If

                        i = i + 1
                        TmpStr = Mid(FileLine, i * 3 + 9, 2)
                    Loop

                    picA.BootDatLen = j
                */
             #endregion

                if ((BCom != 5) && (BCom != 7))//                'Program Memory
                {
                    if (i == 0)
                    {
                        picA.BootDatLen = (ushort)BlockSize;
                        picA.BootAddr = (uint)(CLngHex(FileLine.Substring(0, 6)) & FULL_ADDRESS_MASK) / BytsPerAddr; // 'word addressed
                    }

                    j = 0;
                    while (j < 16)
                    {
                        OutData[i] = (byte)(CLngHex(FileLine.Substring(j * 3 + 7, 2)));

                        i = i + 1;
                        j = j + 1;
                    }

                }

                if ((BCom != 2) || ((i % picA.BootDatLen) == 0))
                {

                    progress_bar = (float)(picA.BootAddr + picA.BytesPerBlock / picA.BytesPerAddr) / (float)PicBootS.ProgMemAddrH * 1000;
                    if (progress_bar < 1)      // Round up for less than 1% so that the DoUpdateProgress displasy on the progress bar and not on the list window
                        progress_bar = 1;

                    DoUpdateProgress("Writing: " + picA.BootAddr.ToString("X"), (int)progress_bar);

                    // 'Write row/line
                    RetStat = WritePIC(ref picA, OutData);
                    if (RetStat < 0)
                    {
                        DoUpdateProgress("Writing failed at:" + picA.BootAddr.ToString("X"));
                        goto AbortExit;
                    }

                    // 'Verify written row/line
                    RetStat = VerifyPIC(picA, OutData);
                    if (RetStat < 0)
                    {
                        DoUpdateProgress("Verify failed at:" + picA.BootAddr.ToString("X"));
                        if (RetStat == -12)
                        {
                            ProgressInd = -101;
                            VerifyFlag = false;
                        }
                        else
                        {
                            goto AbortExit;
                        }
                    }
                    else
                    {
                        ProgressInd = 1;
                    }

                    i = 0;

                }

            }

            if (VerifyFlag == false)
            {
                RetStat = -101;
            }
            else
            {
                RetStat = ProgressInd;
            }
            AbortExit:
            a.Close();
            return RetStat;
        }
        private int VerifyPIC(_PIC picV, byte[] outArray)
        {
            int RetStat;
            byte[] inArray = new byte[262];
            long BootAddr;
            bool VerifyFlag;
            int i;
            StreamWriter b = new StreamWriter(appPath + "\\" + PicBootS.ErrorLogFile, true);

            // 'read written data froom pic
            picV.BootCmd = (byte)(picV.BootCmd - 1);  // 'read out using read command of same memory type

            if (picV.BootCmd == 1)
            {
                picV.BytesPerBlock = (ushort)PicBootS.DeviceRdBlock;
            }

            RetStat = ReadPIC(ref picV, inArray);

            BootAddr = picV.BootAddr;

            // 'error if read fails
            if (RetStat < 0)
            {
                b.Close();
                return RetStat;
            }

            VerifyFlag = true;

            i = 0;
            // 'verify written data
            while (i < RetStat)
            {
                if (picV.BootCmd == 1)
                {
                    if ((inArray[i] != outArray[i]) ||
                        (inArray[i + 1] != outArray[i + 1]) ||
                        (inArray[i + 2] != outArray[i + 2]) ||
                        (inArray[i + 3] != outArray[i + 3]))
                    {
                        //'Device reset vector, user reset vector, and delay address are ignored because
                        // 'bootloader will intentionally write different values in these locations than what may be
                        //'specified in the .hex file causing erroneous varification errors.

                        if (BootAddr == 0)
                        {
                            //                                'ignore reset vector
                        }
                        else if (BootAddr == 2)
                        {
                            //                                'ignore reset vector
                        }
                        else if (BootAddr == PicBootS.UserResetVector)
                        {
                            //       'ignore user's reset vector
                        }
                        else if (BootAddr == PicBootS.BootDelayAddr)
                        {
                            // 'ignore boot delay address
                        }
                        else
                        {
                            //                                'otherwise, verify error
                            String line;
                            uint pa, pb;
                            pa = (((uint)outArray[i + 3]) << 24) | (((uint)outArray[i + 2]) << 16) | (((uint)outArray[i + 1]) << 8) | (((uint)outArray[i + 0]) << 0);
                            pb = (((uint)inArray[i + 3]) << 24) | (((uint)inArray[i + 2]) << 16) | (((uint)inArray[i + 1]) << 8) | (((uint)inArray[i + 0]) << 0);

                            line = "Verify Error at 0x" + BootAddr.ToString("X08") + " should be: 0x";
                            line += pa.ToString("X08") + " but read: 0x" + pb.ToString("X08");
                            b.WriteLine(line);
                            VerifyFlag = false;
                        }
                    }
                    i = i + 4;
                }
                BootAddr = BootAddr + 2;
            }

            b.Close();

            if (VerifyFlag == false)
            {
                RetStat = -12;
            }
            return RetStat;
        }