public UnaryExpression(byte[] bytes, Prg prg, ref int offset,
                        FileVersion version = FileVersion.Current)
     : base(version)
 {
     Expression = new VariableExpression(bytes, prg, ref offset, FileVersion);
     Type       = (TYPE_TOKEN)bytes.ToByte(ref offset);
 }
        private void FromIF(byte[] bytes, Prg prg, ref int offset,
                            FileVersion version = FileVersion.Current)
        {
            var ifPart = GetLinePart(bytes, ref offset, FileVersion);

            Expressions.Add(ToExpression(ifPart, prg, 0, FileVersion));
            var check = bytes.ToByte(ref offset);

            if (check != 0xFF)
            {
                throw new OffsetException(offset, ifPart.Length);
            }
            var nextOffset = bytes.ToUInt16(ref offset);

            var thenPart = GetLinePart(bytes, ref offset, FileVersion, nextOffset);

            Expressions.Add(ToExpression(thenPart, prg, 0, FileVersion));
            if (bytes[offset] == 0xFF)
            {
                offset += 1; //0xFF byte
            }
            if (offset != nextOffset)
            {
                throw new OffsetException(offset, nextOffset);
            }

            return;
        }
Пример #3
0
        /// <summary>
        /// Read all bytes from a .PRG File to build an object.
        /// Now it supports Class messaging with its parent.
        /// Allows to show LOAD progress in a control of a parent FORM
        /// </summary>
        /// <param name="path">Path to .PRG File</param>
        /// <param name="parent">Parent object</param>
        /// <!--Modified by LRUIZ : 2018-06-05-->
        /// <returns>Prg Object</returns>
        public static Prg Load(string path, object parent)
        {
            Prg _prg = new Prg();

            _prg = PrgReader.Read(path, parent);
            _prg.SetParentClass(parent);
            return(_prg);
        }
        private void FromIFM(byte[] bytes, Prg prg, ref int offset,
                             FileVersion version = FileVersion.Current)
        {
            var ifPart = GetLinePart(bytes, ref offset, FileVersion);

            Expressions.Add(ToExpression(ifPart, prg, 0, FileVersion));
            offset += 4;
            var thenPart = GetLinePart(bytes, ref offset, FileVersion);

            Expressions.Add(ToExpression(thenPart, prg, 0, FileVersion));
            offset += 1;
        }
        public VariableExpression(byte[] bytes, Prg prg, ref int offset,
                                  FileVersion version = FileVersion.Current)
            : base(version)
        {
            Prg   = prg;
            Token = (FUNCTION_TOKEN)bytes.ToByte(ref offset);

            switch (Token)
            {
            case FUNCTION_TOKEN.TIME_ON:
                Number = bytes.ToByte(ref offset);
                Type   = (TYPE_TOKEN)bytes.ToByte(ref offset);
                break;

            case FUNCTION_TOKEN.LOCAL_POINT_PRG:
                Number = bytes.ToByte(ref offset);
                Type   = (TYPE_TOKEN)bytes.ToByte(ref offset);
                break;

            case FUNCTION_TOKEN.REMOTE_POINT_PRG:
                Number  = bytes.ToByte(ref offset);
                Number2 = bytes.ToByte(ref offset);
                Number3 = bytes.ToByte(ref offset);
                Number4 = bytes.ToByte(ref offset);
                Number5 = bytes.ToByte(ref offset);
                break;

            case FUNCTION_TOKEN.CONST_VALUE_PRG:
                var value = bytes.ToInt32(ref offset);
                var unit  = Unit.Unused;
                if (offset < bytes.Length)
                {
                    var valueType = (FUNCTION_TOKEN)bytes.ToByte(ref offset);
                    if (valueType == FUNCTION_TOKEN.TIME_FORMAT)
                    {
                        unit = Unit.Time;
                    }
                    else
                    {
                        offset -= 1;
                    }
                }
                Value = new VariableValue(value, unit);
                break;

            default:
                //Number = bytes.ToByte(ref offset);
                //Type = (ExpressionType)bytes.ToByte(ref offset);
                break;
                //throw new NotImplementedException(
                //    $"Function token: {Token} not implemented.");
            }
        }
Пример #6
0
        public static void Write(Prg prg, string path)
        {
            if (prg == null)
            {
                throw new ArgumentNullException(nameof(prg));
            }
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            File.WriteAllBytes(path, prg.ToBytes());
        }
        public FunctionExpression(byte[] bytes, Prg prg, ref int offset,
                                  FileVersion version = FileVersion.Current)
            : base(version)
        {
            Arguments.Add(new VariableExpression(bytes, prg, ref offset, FileVersion));
            var token = bytes.ToByte(ref offset);

            while (!ProgramCodeUtilities.IsFunction(token))
            {
                --offset;
                Arguments.Add(new VariableExpression(bytes, prg, ref offset, FileVersion));
                token = bytes.ToByte(ref offset);
            }
            Token = (FUNCTION_TOKEN)token;
        }
Пример #8
0
        /// <summary>
        /// FileVersion.Current - need 2000 bytes
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="offset"></param>
        /// <param name="version"></param>
        public ProgramCode(byte[] bytes, Prg prg, int offset = 0,
                           FileVersion version = FileVersion.Current)
            : base(bytes, 2000, offset, version)
        {
            var maxSize = GetSize(FileVersion);

            Version = bytes.ToInt16(ref offset);
            while (offset < maxSize)
            {
                //Console.WriteLine($"{offset}: Line {Lines.Count}");
                var line = new Line(bytes, prg, ref offset, FileVersion);

                Lines.Add(line);
            }

            offset = 2000;
            CheckOffset(offset, GetSize(FileVersion));
        }
        /// <summary>
        /// FileVersion.Current - need 2000 bytes
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="offset"></param>
        /// <param name="version"></param>
        public ProgramCode(byte[] bytes, Prg prg, int offset = 0,
                           FileVersion version = FileVersion.Current)
            : base(bytes, 2000, offset, version)
        {
            var maxSize = GetSize(FileVersion);

            Version = bytes.ToInt16(ref offset);

            //DEPRECATED: Line objects are incomplete to decode Program.
            //Leaving this task to the REAL DECODER

            ////////while (offset < maxSize)
            ////////{
            ////////    //Console.WriteLine($"{offset}: Line {Lines.Count}");
            ////////    var line = new Line(bytes, prg, ref offset, FileVersion);

            ////////    Lines.Add(line);
            ////////}

            offset = 2000;
            CheckOffset(offset, GetSize(FileVersion));
        }
        private Expression ToExpression(byte[] bytes, Prg prg, int offset = 0,
                                        FileVersion version = FileVersion.Current, bool isTrace = false)
        {
            var expressions = GetExpressions(bytes, prg, ref offset, FileVersion, isTrace: isTrace);

            if (offset != bytes.Length || expressions.Count != 1)
            {
                Debug.WriteLine($@"Bad part:
    bytes: {DebugUtilities.CompareBytes(bytes, bytes, onlyDif: false, toText: false)}
    offset: {offset}
    bytes.Length: {bytes.Length}
    expressions: {expressions.Count}
    ");
            }

            //One expression
            if (expressions.Count == 1)
            {
                return(expressions[0]);
            }

            return(null);
        }
        private void FromASSIGN(byte[] bytes, Prg prg, ref int offset,
                                FileVersion version = FileVersion.Current)
        {
            Expressions.Add(new VariableExpression(bytes, prg, ref offset, FileVersion));

            var        first      = new VariableExpression(bytes, prg, ref offset, FileVersion);
            var        second     = new VariableExpression(bytes, prg, ref offset, FileVersion);
            var        type       = (TYPE_TOKEN)bytes.ToByte(ref offset);
            Expression expression = new BinaryExpression(first, second, type, FileVersion);

            //var temp = offset;
            var check = bytes.ToByte(ref offset);

            --offset;
            //Console.WriteLine($"{Number} {check} before");
            if (check != (byte)TYPE_TOKEN.NUMBER)
            {
                if (ProgramCodeUtilities.IsVariable(check))
                {
                    var third = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    var type2 = (TYPE_TOKEN)bytes.ToByte(ref offset);
                    expression = new BinaryExpression(expression, third, type2, FileVersion);
                }
                else if (ProgramCodeUtilities.IsFunction(check))
                {
                    var token = (FUNCTION_TOKEN)bytes.ToByte(ref offset);
                    expression = new FunctionExpression(token, FileVersion, expression);
                }

                //++offset;
                //check = (ExpressionType)bytes.ToByte(ref offset);
                //--offset;
                //Console.WriteLine($"{Number} {check} after");
            }

            Expressions.Add(expression);
        }
        //DEPRECATED: Not used, because it's a obsolte method too, just like LINE
        /////// <summary>
        /////// Raw Lines Constructor
        /////// </summary>
        /////// <remarks>Author: LRUIZ</remarks>

        ////static public byte[] RawLine(string line)
        ////{

        ////    List<byte> returnvalue = new List<byte>();
        ////    List<byte> Data = new List<byte>();
        ////    byte Type, Token;
        ////    short Number;

        ////    Type = (byte)TYPE_TOKEN.NUMBER; //1 Byte
        ////    returnvalue.Add((byte)Type);


        ////    string[] separators = { " " };
        ////    string[] LineParts = line.Split(separators, StringSplitOptions.RemoveEmptyEntries);

        ////    if (!LineParts.Any())
        ////    {
        ////        throw new Exception($"Not enough tokens in line: {line}");
        ////    }

        ////    if (String.IsNullOrEmpty(LineParts[0]))
        ////    {
        ////        Number = 0;
        ////    }
        ////    else
        ////    {
        ////        Number = Convert.ToInt16(LineParts[0]);
        ////    }



        ////    byte[] intBytes = BitConverter.GetBytes(Number);
        ////    //if (BitConverter.IsLittleEndian)
        ////    //    Array.Reverse(intBytes);
        ////    if (intBytes.Count() < 2)
        ////    {
        ////        throw new Exception("Line Number less than 2 bytes");
        ////    }
        ////    byte[] result = intBytes;


        ////    Debug.WriteLine($"Converting {Number} to bytes[] : {result}");
        ////    returnvalue.AddRange(result);


        ////    switch (LineParts[1] ?? "RAW")
        ////    {
        ////        case "REM":
        ////            Token = (byte)LINE_TOKEN.REM;
        ////            break;
        ////        //case "IF+":
        ////        //    Token = (byte)LineToken.IFP;
        ////        //    break;

        ////        //case "IF-":
        ////        //    Token = (byte)LineToken.IFM;
        ////        //    break;
        ////        //case "IF":
        ////        //    Token = (byte)LineToken.IF;
        ////        //    break;
        ////        default:
        ////            Token = (byte)LINE_TOKEN.RAWLINE;
        ////            break;


        ////    }
        ////    returnvalue.Add(Token);


        ////    //Number = bytes.ToInt16(ref offset); //2 Bytes
        ////    int OffSet = (Token == (byte)LINE_TOKEN.RAWLINE ? 1 : 2);

        ////    line = string.Join(" ", LineParts, OffSet, LineParts.Count() - OffSet);

        ////    Data.AddRange(line.ToBytes());

        ////    //Data = PRGReaderLibrary.BytesExtensions.ToBytes(line.ToBytes());
        ////    byte size = (byte)Data.Count();

        ////    returnvalue.Add(size);
        ////    returnvalue.AddRange(Data);

        ////    return returnvalue.ToArray();
        ////}


        //DEPRECATED: Incomplete and obsolete version to decode line by line a Program.

        public Line(byte[] bytes, Prg prg, ref int offset,
                    FileVersion version = FileVersion.Current)
            : base(version)
        {
            Type   = (TYPE_TOKEN)bytes.ToByte(ref offset); //1 Byte
            Number = bytes.ToInt16(ref offset);            //2 Bytes
            Token  = (LINE_TOKEN)bytes.ToByte(ref offset); //1 Byte


            //Offset is 4

            try
            {
                if (Number == 140) //8C 00
                {
                    var ifPart = GetLinePart(bytes, ref offset, FileVersion);
                    Expressions.Add(ToExpression(ifPart, prg, 0, FileVersion));
                    var check = bytes.ToByte(ref offset);
                    if (check != 0xFF)
                    {
                        throw new OffsetException(offset, ifPart.Length);
                    }
                    var nextOffset = bytes.ToUInt16(ref offset);

                    //Expressions.Add(new FunctionExpression(bytes, prg, ref offset, FileVersion));
                    //offset += 4;
                    //offset += 3;
                    //var type = (ExpressionType)bytes.ToByte(ref offset);
                    //var first = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    //var second = new FunctionExpression(bytes, prg, ref offset, FileVersion);
                    //Expressions.Add(new BinaryExpression(first, second, type, FileVersion));
                    //offset += 2;

                    var thenPart = GetLinePart(bytes, ref offset, FileVersion, nextOffset);
                    Expressions.Add(ToExpression(thenPart, prg, 0, FileVersion, isTrace: true));
                    if (bytes[offset] == 0xFF)
                    {
                        offset += 1; //0xFF byte
                    }
                    if (offset != nextOffset)
                    {
                        throw new OffsetException(offset, nextOffset);
                    }

                    return;
                }

                if (Number == 300) //2C 01
                {
                    Expressions.Add(new UnaryExpression(bytes, prg, ref offset, FileVersion));
                    offset += 3;
                    var type       = (TYPE_TOKEN)bytes.ToByte(ref offset);
                    var first      = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    var expression = new VariableExpression(bytes, prg, ref offset, FileVersion) +
                                     new VariableExpression(bytes, prg, ref offset, FileVersion);
                    expression.Type = (TYPE_TOKEN)bytes.ToByte(ref offset);
                    expression      = new FunctionExpression(
                        (FUNCTION_TOKEN)bytes.ToByte(ref offset), FileVersion,
                        expression);
                    expression      = first + expression;
                    expression.Type = type;
                    Expressions.Add(expression);
                    offset += 1;
                    return;
                }

                if (Number == 350) //5E 01
                {
                    var ifPart = GetLinePart(bytes, ref offset, FileVersion);
                    Expressions.Add(ToExpression(ifPart, prg, 0, FileVersion));
                    offset += 3;
                    var type   = (TYPE_TOKEN)bytes.ToByte(ref offset);
                    var first  = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    var second = new UnaryExpression(bytes, prg, ref offset, FileVersion);
                    var third  = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    var four   = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    var type2  = (FUNCTION_TOKEN)bytes.ToByte(ref offset);
                    offset += 1;
                    var type3 = (FUNCTION_TOKEN)bytes.ToByte(ref offset);
                    offset += 1;
                    Expression expression = new FunctionExpression(type2, FileVersion, third, four);
                    expression = new FunctionExpression(type3, FileVersion, second, expression);
                    expression = new BinaryExpression(first, expression, type, FileVersion);
                    Expressions.Add(expression);
                    offset += 1;
                    return;
                }

                if (Number == 360) //68 01
                {
                    var ifPart = GetLinePart(bytes, ref offset, FileVersion);
                    Expressions.Add(ToExpression(ifPart, prg, 0, FileVersion));
                    offset += 3;
                    var        type       = (TYPE_TOKEN)bytes.ToByte(ref offset);
                    var        first      = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    var        second     = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    var        third      = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    var        type2      = (TYPE_TOKEN)bytes.ToByte(ref offset);
                    var        four       = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    var        type3      = (TYPE_TOKEN)bytes.ToByte(ref offset);
                    Expression expression = new BinaryExpression(second, third, type2, FileVersion);
                    expression = new BinaryExpression(expression, four, type3, FileVersion);
                    expression = new BinaryExpression(first, expression, type, FileVersion);
                    Expressions.Add(expression);
                    offset    += 5;
                    type       = (TYPE_TOKEN)bytes.ToByte(ref offset);
                    first      = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    second     = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    expression = new BinaryExpression(first, second, type, FileVersion);
                    Expressions.Add(expression);
                    offset += 1;
                    return;
                }

                switch (Token)
                {
                case LINE_TOKEN.IF:
                    FromIF(bytes, prg, ref offset, FileVersion);
                    break;

                case LINE_TOKEN.IFM:
                    FromIFM(bytes, prg, ref offset, FileVersion);
                    break;

                case LINE_TOKEN.ASSIGN:
                    FromASSIGN(bytes, prg, ref offset, FileVersion);
                    break;

                case LINE_TOKEN.REM:
                case LINE_TOKEN.RAWLINE:
                default:
                    var size = bytes.ToByte(ref offset);
                    Data = bytes.ToBytes(ref offset, size);
                    break;
                }

                if (Number == 380) //7C 01
                {
                    offset += 115;
                }
            }
            catch (Exception exception)
            {
                Debug.WriteLine($@"Exception on line: 
        Type: {Type}
        Number: {Number}
        Token: {Token}
        {exception.Message}");
                throw;
            }
        }
        private List <Expression> GetExpressions(byte[] bytes, Prg prg, ref int offset,
                                                 FileVersion version = FileVersion.Current, LINE_TOKEN lineToken = 0,
                                                 bool isTrace        = false)
        {
            if (isTrace)
            {
                Debug.WriteLine("----------------------------");
                Debug.WriteLine(DebugUtilities.CompareBytes(bytes, bytes,
                                                            onlyDif: false, toText: false, offset: offset));
            }

            var expressions = new List <Expression>();

            while (offset < bytes.Length)
            {
                var byteType = ProgramCodeUtilities.GetByteType(bytes, offset);

                if (byteType == ProgramCodeUtilities.ByteType.Variable)
                {
                    if (isTrace)
                    {
                        Debug.WriteLine($"IsVariable {offset}");
                    }
                    var expression = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    expressions.Add(expression);
                }
                else if (byteType == ProgramCodeUtilities.ByteType.Line)
                {
                    if (isTrace)
                    {
                        Debug.WriteLine($"IsLine {offset}");
                    }
                    var token           = (LINE_TOKEN)bytes.ToByte(ref offset);
                    var lineExpressions = GetExpressions(bytes, prg, ref offset, version, token, isTrace);
                    var expression      = lineExpressions.Count > 1 ? new BinaryExpression(
                        lineExpressions[0],
                        lineExpressions[1],
                        (TYPE_TOKEN)token, FileVersion) :
                                          lineExpressions[0];
                    expressions.Add(expression);
                }
                else if (byteType == ProgramCodeUtilities.ByteType.Function)
                {
                    if (isTrace)
                    {
                        Debug.WriteLine($"IsFunction {offset}");
                    }
                    var token = (FUNCTION_TOKEN)bytes.ToByte(ref offset);
                    if ((byte)token == (byte)LINE_TOKEN.STOP)
                    {
                        var variable   = new VariableExpression(bytes, prg, ref offset, FileVersion);
                        var expression = new UnaryExpression(variable, (TYPE_TOKEN)LINE_TOKEN.STOP, version);

                        expressions.Add(expression);
                    }
                    else if (expressions.Count == 0)
                    {
                        Debug.WriteLine("expressions.Count = 0");
                        var temp = 0;
                        offset -= 1;
                        expressions.Add(new VariableExpression(bytes, prg, ref offset, FileVersion));
                        expressions.AddRange(
                            GetExpressions(bytes.ToBytes(ref offset, 3), prg, ref temp, FileVersion, lineToken));

                        var prevLastExpression = expressions[expressions.Count - 2];
                        var lastExpression     = expressions[expressions.Count - 1];
                        expressions.RemoveAt(expressions.Count - 1);
                        expressions.RemoveAt(expressions.Count - 1);
                        var expression = new BinaryExpression(prevLastExpression, lastExpression, TYPE_TOKEN.DELIMITER, FileVersion);
                        expressions.Add(expression);
                    }
                    else
                    {
                        var expression = new FunctionExpression(token, FileVersion, expressions.ToArray());
                        expressions.Clear();
                        expressions.Add(expression);
                    }
                }
                else if (byteType == ProgramCodeUtilities.ByteType.Expression)
                {
                    if (isTrace)
                    {
                        Debug.WriteLine($"IsExpression {offset}");
                    }
                    var type = (TYPE_TOKEN)bytes.ToByte(ref offset);
                    if (ProgramCodeUtilities.IsBinaryExpression(type))
                    {
                        var prevLastExpression = expressions[expressions.Count - 2];
                        var lastExpression     = expressions[expressions.Count - 1];
                        expressions.RemoveAt(expressions.Count - 1);
                        expressions.RemoveAt(expressions.Count - 1);
                        var expression = new BinaryExpression(prevLastExpression, lastExpression, type, FileVersion);
                        expressions.Add(expression);
                    }
                    else
                    {
                        var lastExpression = expressions[expressions.Count - 1];
                        expressions.RemoveAt(expressions.Count - 1);
                        var expression = new UnaryExpression(lastExpression, type, FileVersion);
                        expressions.Add(expression);
                    }
                }
                else
                {
                    break;
                }
            }

            if (isTrace)
            {
                Debug.WriteLine($"Result: {expressions.Count} expressions. Line token: {lineToken}");
                for (var i = 0; i < expressions.Count; ++i)
                {
                    Debug.WriteLine($"Expression {i + 1}: {expressions[i].ToString()}");
                }
                Debug.WriteLine("----------------------------");
                Debug.WriteLine("");
            }

            return(expressions);
        }