Example #1
0
            public static string BytecodeToInfix(EzSembleContext context, byte[] Bytes)
            {
                //string MEOWDEBUG_OLD_DISSEMBLE = MEOWDEBUG_OldDissemble(Bytes);

                var bigEndianReverseBytes = Bytes.Reverse().ToArray();

                Stack <string> stack = new Stack <string>();

                Queue <string> garbage = new Queue <string>();

                string popLastNonGarbageAndStoreGarbage(bool wantNumber = false)
                {
                    var popped = stack.Pop();

                    //while (popped == "~" || popped == ".")
                    //{
                    //    garbage.Enqueue(popped);
                    //    popped = stack.Pop();
                    //}

                    if (wantNumber)
                    {
                        return(popped.Trim('(', ')'));
                    }
                    else
                    {
                        return(popped);
                    }
                }

                void restoreGarbage()
                {
                    while (garbage.Count > 0)
                    {
                        stack.Push(garbage.Dequeue());
                    }
                }

                for (int i = 0; i < Bytes.Length; i++)
                {
                    var b = Bytes[i];
                    if (b >= 0 && b <= 0x7F)
                    {
                        stack.Push($"{b - 64}");
                    }
                    else if (b == 0xA5)
                    {
                        int j = 0;
                        while (Bytes[i + j + 1] != 0 || Bytes[i + j + 2] != 0)
                        {
                            j += 2;
                        }
                        string text = context.IsBigEndian ?
                                      Encoding.BigEndianUnicode.GetString(Bytes, i + 1, j)
                            : Encoding.Unicode.GetString(Bytes, i + 1, j);

                        if (text.Contains('"') || text.Contains('\r') || text.Contains('\n'))
                        {
                            throw new Exception("Illegal character in string literal");
                        }
                        stack.Push($"\"{text}\"");
                        i += j + 2;
                    }
                    else if (b == 0x80)
                    {
                        if (!context.IsBigEndian)
                        {
                            stack.Push($"{BitConverter.ToSingle(Bytes, i + 1)}");
                        }
                        else
                        {
                            stack.Push($"{BitConverter.ToSingle(bigEndianReverseBytes, (bigEndianReverseBytes.Length - 1) - (i + 1) - 4)}");
                        }

                        i += 4;
                    }
                    else if (b == 0x81)
                    {
                        if (!context.IsBigEndian)
                        {
                            stack.Push($"{BitConverter.ToDouble(Bytes, i + 1)}");
                        }
                        else
                        {
                            stack.Push($"{BitConverter.ToDouble(bigEndianReverseBytes, (bigEndianReverseBytes.Length - 1) - (i + 1) - 8)}");
                        }

                        i += 8;
                    }
                    else if (b == 0x82)
                    {
                        if (!context.IsBigEndian)
                        {
                            stack.Push($"{BitConverter.ToInt32(Bytes, i + 1)}");
                        }
                        else
                        {
                            stack.Push($"{BitConverter.ToInt32(bigEndianReverseBytes, (bigEndianReverseBytes.Length - 1) - (i + 1) - 4)}");
                        }


                        i += 4;
                    }
                    else if (b == 0x84)
                    {
                        var id = popLastNonGarbageAndStoreGarbage(true);
                        restoreGarbage();
                        stack.Push($"{context.GetFunctionInfo(int.Parse(id)).Name}()");
                    }
                    else if (b == 0x85)
                    {
                        var arg1 = popLastNonGarbageAndStoreGarbage();
                        var id   = popLastNonGarbageAndStoreGarbage(true);
                        restoreGarbage();
                        stack.Push($"{context.GetFunctionInfo(int.Parse(id)).Name}({arg1})");
                    }
                    else if (b == 0x86)
                    {
                        var arg2 = popLastNonGarbageAndStoreGarbage();
                        var arg1 = popLastNonGarbageAndStoreGarbage();
                        var id   = popLastNonGarbageAndStoreGarbage(true);
                        restoreGarbage();
                        stack.Push($"{context.GetFunctionInfo(int.Parse(id)).Name}({arg1}, {arg2})");
                    }
                    else if (b == 0x87)
                    {
                        var arg3 = popLastNonGarbageAndStoreGarbage();
                        var arg2 = popLastNonGarbageAndStoreGarbage();
                        var arg1 = popLastNonGarbageAndStoreGarbage();
                        var id   = popLastNonGarbageAndStoreGarbage(true);
                        restoreGarbage();
                        stack.Push($"{context.GetFunctionInfo(int.Parse(id)).Name}({arg1}, {arg2}, {arg3})");
                    }
                    else if (b == 0x88)
                    {
                        var arg4 = popLastNonGarbageAndStoreGarbage();
                        var arg3 = popLastNonGarbageAndStoreGarbage();
                        var arg2 = popLastNonGarbageAndStoreGarbage();
                        var arg1 = popLastNonGarbageAndStoreGarbage();
                        var id   = popLastNonGarbageAndStoreGarbage(true);
                        restoreGarbage();
                        stack.Push($"{context.GetFunctionInfo(int.Parse(id)).Name}({arg1}, {arg2}, {arg3}, {arg4})");
                    }
                    else if (b == 0x89)
                    {
                        var arg5 = popLastNonGarbageAndStoreGarbage();
                        var arg4 = popLastNonGarbageAndStoreGarbage();
                        var arg3 = popLastNonGarbageAndStoreGarbage();
                        var arg2 = popLastNonGarbageAndStoreGarbage();
                        var arg1 = popLastNonGarbageAndStoreGarbage();
                        var id   = popLastNonGarbageAndStoreGarbage(true);
                        restoreGarbage();
                        stack.Push($"{context.GetFunctionInfo(int.Parse(id)).Name}({arg1}, {arg2}, {arg3}, {arg4}, {arg5})");
                    }
                    else if (b == 0x8A)
                    {
                        var arg6 = popLastNonGarbageAndStoreGarbage();
                        var arg5 = popLastNonGarbageAndStoreGarbage();
                        var arg4 = popLastNonGarbageAndStoreGarbage();
                        var arg3 = popLastNonGarbageAndStoreGarbage();
                        var arg2 = popLastNonGarbageAndStoreGarbage();
                        var arg1 = popLastNonGarbageAndStoreGarbage();
                        var id   = popLastNonGarbageAndStoreGarbage(true);
                        restoreGarbage();
                        stack.Push($"{context.GetFunctionInfo(int.Parse(id)).Name}({arg1}, {arg2}, {arg3}, {arg4}, {arg5}, {arg6})");
                    }
                    else if (OperatorsByByte.ContainsKey(b))
                    {
                        var item2 = popLastNonGarbageAndStoreGarbage();
                        var item1 = popLastNonGarbageAndStoreGarbage();

                        restoreGarbage();

                        stack.Push($"{GetExpressionWithParenthesesIfContainsOperator(item1, OperatorsByByte[b])} " +
                                   $"{OperatorsByByte[b]} {GetExpressionWithParenthesesIfContainsOperator(item2, OperatorsByByte[b])}");
                    }
                    else if (b == 0xA6)
                    {
                        //if (stack.Count > 2)
                        //{
                        //    var stackContents = new string[stack.Count];
                        //    int j = stack.Count - 1;
                        //    while (stack.Count > 0)
                        //    {
                        //        var latest = stack.Pop();
                        //        stackContents[j] = latest;
                        //        j--;
                        //    }

                        //    stack.Push($"({string.Join(" ", stackContents)})");

                        //    Console.WriteLine("TEST");
                        //}
                        //else
                        //{
                        //    stack.Push($"({stack.Pop()})");
                        //}
                        stack.Push($"({stack.Pop()})");
                    }
                    else if (b >= 0xA7 && b <= 0xAE)
                    {
                        byte regIndex = (byte)(b - 0xA7);
                        var  item     = popLastNonGarbageAndStoreGarbage();
                        restoreGarbage();
                        stack.Push($"SetREG{regIndex}({item})");
                    }
                    else if (b >= 0xAF && b <= 0xB6)
                    {
                        byte regIndex = (byte)(b - 0xAF);
                        stack.Push($"GetREG{regIndex}()");
                    }
                    else if (b == 0xB7)
                    {
                        var item = stack.Pop();
                        stack.Push($"AbortIfFalse({item})");
                    }
                    else if (b == 0xA1)
                    {
                        //break;
                    }
                    else
                    {
                        stack.Push($"#{b:X2}");
                    }
                }

                return(string.Join(" ", stack));
            }
Example #2
0
            public static Expr BytecodeToInfix(EzSembleContext context, byte[] Bytes)
            {
                var bigEndianReverseBytes = Bytes.Reverse().ToArray();

                Stack <Expr> exprs = new Stack <Expr>();

                List <Expr> popArgs(int amount)
                {
                    List <Expr> args = new List <Expr>();

                    for (int i = 0; i < amount; i++)
                    {
                        args.Add(exprs.Pop());
                    }
                    args.Reverse();
                    return(args);
                }

                for (int i = 0; i < Bytes.Length; i++)
                {
                    var b = Bytes[i];
                    if (b >= 0 && b <= 0x7F)
                    {
                        exprs.Push(new ConstExpr {
                            Value = (sbyte)(b - 64)
                        });
                    }
                    else if (b == 0xA5)
                    {
                        int j = 0;
                        while (Bytes[i + j + 1] != 0 || Bytes[i + j + 2] != 0)
                        {
                            j += 2;
                        }
                        string text = context.IsBigEndian ?
                                      Encoding.BigEndianUnicode.GetString(Bytes, i + 1, j)
                            : Encoding.Unicode.GetString(Bytes, i + 1, j);

                        if (text.Contains('"') || text.Contains('\r') || text.Contains('\n'))
                        {
                            throw new Exception("Illegal character in string literal");
                        }
                        exprs.Push(new ConstExpr {
                            Value = text
                        });
                        i += j + 2;
                    }
                    else if (b == 0x80)
                    {
                        float val;
                        if (!context.IsBigEndian)
                        {
                            val = BitConverter.ToSingle(Bytes, i + 1);
                        }
                        else
                        {
                            val = BitConverter.ToSingle(bigEndianReverseBytes, (bigEndianReverseBytes.Length - 1) - (i + 1) - 4);
                        }
                        exprs.Push(new ConstExpr {
                            Value = val
                        });

                        i += 4;
                    }
                    else if (b == 0x81)
                    {
                        double val;
                        if (!context.IsBigEndian)
                        {
                            val = BitConverter.ToDouble(Bytes, i + 1);
                        }
                        else
                        {
                            val = BitConverter.ToDouble(bigEndianReverseBytes, (bigEndianReverseBytes.Length - 1) - (i + 1) - 8);
                        }
                        exprs.Push(new ConstExpr {
                            Value = val
                        });

                        i += 8;
                    }
                    else if (b == 0x82)
                    {
                        int val;
                        if (!context.IsBigEndian)
                        {
                            val = BitConverter.ToInt32(Bytes, i + 1);
                        }
                        else
                        {
                            val = BitConverter.ToInt32(bigEndianReverseBytes, (bigEndianReverseBytes.Length - 1) - (i + 1) - 4);
                        }
                        exprs.Push(new ConstExpr {
                            Value = val
                        });

                        i += 4;
                    }
                    else if (b == 0x84)
                    {
                        exprs.Push(new FunctionCall {
                            Args = popArgs(0), Name = context.GetFunctionInfo(exprs.Pop().AsInt()).Name
                        });
                    }
                    else if (b == 0x85)
                    {
                        exprs.Push(new FunctionCall {
                            Args = popArgs(1), Name = context.GetFunctionInfo(exprs.Pop().AsInt()).Name
                        });
                    }
                    else if (b == 0x86)
                    {
                        exprs.Push(new FunctionCall {
                            Args = popArgs(2), Name = context.GetFunctionInfo(exprs.Pop().AsInt()).Name
                        });
                    }
                    else if (b == 0x87)
                    {
                        exprs.Push(new FunctionCall {
                            Args = popArgs(3), Name = context.GetFunctionInfo(exprs.Pop().AsInt()).Name
                        });
                    }
                    else if (b == 0x88)
                    {
                        exprs.Push(new FunctionCall {
                            Args = popArgs(4), Name = context.GetFunctionInfo(exprs.Pop().AsInt()).Name
                        });
                    }
                    else if (b == 0x89)
                    {
                        exprs.Push(new FunctionCall {
                            Args = popArgs(5), Name = context.GetFunctionInfo(exprs.Pop().AsInt()).Name
                        });
                    }
                    else if (b == 0x8A)
                    {
                        exprs.Push(new FunctionCall {
                            Args = popArgs(6), Name = context.GetFunctionInfo(exprs.Pop().AsInt()).Name
                        });
                    }
                    else if (OperatorsByByte.ContainsKey(b))
                    {
                        if (OperatorsByByte[b] == "N")
                        {
                            exprs.Push(new UnaryExpr {
                                Op = "N", Arg = exprs.Pop()
                            });
                        }
                        else
                        {
                            exprs.Push(new BinaryExpr {
                                Op = OperatorsByByte[b], Rhs = exprs.Pop(), Lhs = exprs.Pop()
                            });
                        }
                    }
                    else if (b == 0xA6)
                    {
                        Expr top = exprs.Peek();
                        top.IfFalse = FalseCond.CONTINUE;
                    }
                    else if (b >= 0xA7 && b <= 0xAE)
                    {
                        byte regIndex = (byte)(b - 0xA7);
                        exprs.Push(new FunctionCall {
                            Args = popArgs(1), Name = $"SetREG{regIndex}"
                        });
                    }
                    else if (b >= 0xAF && b <= 0xB6)
                    {
                        byte regIndex = (byte)(b - 0xAF);
                        exprs.Push(new FunctionCall {
                            Args = popArgs(0), Name = $"GetREG{regIndex}"
                        });
                    }
                    else if (b == 0xB7)
                    {
                        Expr top = exprs.Peek();
                        top.IfFalse = FalseCond.ABORT;
                    }
                    else if (b == 0xB8)
                    {
                        // exprs.Push(new FunctionCall { Args = popArgs(1), Name = "StateGroupArg" });
                        FunctionCall func = new FunctionCall {
                            Args = popArgs(1), Name = "StateGroupArg"
                        };
                        ConstExpr ce = func.Args[0] as ConstExpr;
                        // Console.WriteLine($"{ce} {ce.Value.GetType()}");
                        exprs.Push(func);
                    }
                    else if (b == 0xB9)
                    {
                        exprs.Push(new CallResult());
                    }
                    else if (b == 0xBA)
                    {
                        // This opcode just returns a constant value 0x7FFFFFFF
                        // But use higher-level representation of it
                        exprs.Push(new CallOngoing());
                    }
                    else if (b == 0xA1)
                    {
                        //break;
                    }
                    else
                    {
                        exprs.Push(new Unknown {
                            Opcode = b
                        });
                    }
                }
                if (exprs.Count != 1)
                {
                    throw new Exception("Could not parse expr. Remaining stack: " + string.Join("; ", exprs) + $"; = {string.Join(" ", Bytes.Select(x => x.ToString("X2")))}");
                }
                return(exprs.Pop());
            }