Commits

Kareem Callender committed 4af2b86 Draft

Added handling of the data ops (db/dw/dd/dq).
Fixed error relating to number recognition. Numbers that are too long are now
handled.
Using long variables for arithmetic instead of int.

  • Participants
  • Parent commits 78ec7e8

Comments (0)

Files changed (4)

gbread/Base/Assembler.cs

 
     public class Assembler
     {
-        private Dictionary<string, int> variableDict = new Dictionary<string, int>();
-        private Dictionary<string, int> callDict = new Dictionary<string, int>();
+        private Dictionary<string, long> variableDict = new Dictionary<string, long>();
+        private Dictionary<string, long> callDict = new Dictionary<string, long>();
         private List<SymEntry> symFillTable = new List<SymEntry>();
 
         private CodeGenerator codeGen = new CodeGenerator();
                             error.extraInfo1 = idName;
                             return new byte[1];
                         }
-                        int result = 0;
+                        var result = 0L;
                         ErrorMessage emt = Evaluate(idValue, out result);
                         if (emt == ErrorMessage.NO_ERROR)
                         {
                                 }
                                 else
                                 {
-                                    callDict.Add(labelName, (int)(codeGen.Position + baseOffset));
+                                    callDict.Add(labelName, codeGen.Position + baseOffset);
                                 }
                             }
                         }
 
                             case "call":
                                 {
-                                    int memLoc = 0;
+                                    var memLoc = 0L;
                                     if (instField.ChildCount == 1)
                                     {
                                         if (callDict.ContainsKey(instField.GetChild(0).Text))
                                 codeGen.EmitDAA();
                                 break;
 
+                            case "db":
+                                {
+                                    if (!EvalDataFunc(codeGen.EmitByte, instField, ref error))
+                                    {
+                                        return new byte[1];
+                                    }
+                                }
+                                break;
+
+                            case "dw":
+                                {
+                                    if (!EvalDataFunc(codeGen.EmitWord, instField, ref error))
+                                    {
+                                        return new byte[1];
+                                    }
+                                }
+                                break;
+
+                            case "dd":
+                                {
+                                    if (!EvalDataFunc(codeGen.EmitDWord, instField, ref error))
+                                    {
+                                        return new byte[1];
+                                    }
+                                }
+                                break;
+
+                            case "dq":
+                                {
+                                    if (!EvalDataFunc(codeGen.EmitQWord, instField, ref error))
+                                    {
+                                        return new byte[1];
+                                    }
+                                }
+                                break;
+
                             case "dec":
                                 {
                                     switch (instField.GetChild(0).Text)
                             case "jp":
                                 if (instField.ChildCount == 1)
                                 {
-                                    int memLoc = 0;
+                                    var memLoc = 0L;
                                     if (callDict.ContainsKey(instField.GetChild(0).Text))
                                     {
                                         memLoc = callDict[instField.GetChild(0).Text];
                                 }
                                 else
                                 {
-                                    int memLoc = 0;
+                                    var memLoc = 0L;
                                     if (callDict.ContainsKey(instField.GetChild(1).Text))
                                     {
                                         memLoc = callDict[instField.GetChild(1).Text];
                                     long diff = 0;
                                     if (callDict.ContainsKey(arg.Text))
                                     {
-                                        int memLoc = callDict[arg.Text];
+                                        var memLoc = callDict[arg.Text];
                                         diff = memLoc - (codeGen.Position + 2);
                                         if (diff < -128 || diff > 127)
                                         {
 
                                     if (sel == 0)
                                     {
-                                        codeGen.EmitJr((int)diff);
+                                        codeGen.EmitJr(diff);
                                     }
                                     else
                                     {
-                                        codeGen.EmitJrCCN(instField.GetChild(0).Text, (int)diff);
-                                    } 
+                                        codeGen.EmitJrCCN(instField.GetChild(0).Text, diff);
+                                    }
                                 }
-                                
+
                                 break;
 
                             case "ldhl":
                                             {
                                                 if (arg2.Text == ExpressionToken)
                                                 {
-                                                    int result = 0;
+                                                    var result = 0L;
                                                     ErrorMessage emt = Evaluate(arg2, out result);
                                                     if (emt == ErrorMessage.NO_ERROR)
                                                     {
                                                 }
                                                 else if (arg2.Text == MemRefToken)
                                                 {
-                                                    int result = 0;
+                                                    var result = 0L;
                                                     ErrorMessage emt = Evaluate(arg2.GetChild(0), out result);
                                                     if (emt == ErrorMessage.NO_ERROR)
                                                     {
                                             {
                                                 if (arg2.Text == ExpressionToken)
                                                 {
-                                                    int result = 0;
+                                                    var result = 0L;
                                                     ErrorMessage emt = Evaluate(arg2, out result);
                                                     if (emt == ErrorMessage.NO_ERROR)
                                                     {
                                         case "de":
                                         case "hl":
                                             {
-                                                int result = 0;
+                                                var result = 0L;
                                                 ErrorMessage emt = Evaluate(arg2, out result);
                                                 if (emt == ErrorMessage.NO_ERROR)
                                                 {
                                             {
                                                 if (arg2.Text == ExpressionToken)
                                                 {
-                                                    int result = 0;
+                                                    var result = 0L;
                                                     ErrorMessage emt = Evaluate(arg2, out result);
                                                     if (emt == ErrorMessage.NO_ERROR)
                                                     {
 
                                         case "MEM_REF":
                                             {
-                                                int result = 0;
+                                                var result = 0L;
                                                 ErrorMessage emt = Evaluate(arg1.GetChild(0), out result);
                                                 if (emt == ErrorMessage.NO_ERROR)
                                                 {
                                             {
                                                 if (arg2.Text == ExpressionToken)
                                                 {
-                                                    int result = 0;
+                                                    var result = 0L;
                                                     ErrorMessage emt = Evaluate(arg2, out result);
                                                     if (emt == ErrorMessage.NO_ERROR)
                                                     {
                     if (callDict.ContainsKey(se.label))
                     {
                         codeGen.Seek(se.offsetToFill);
-                        int memLoc = callDict[se.label];
+                        var memLoc = callDict[se.label];
                         if (se.isJR)
                         {
                             long diff = memLoc - (se.instructionPosition + 2);
                                 MakeErrorMessage(se, ErrorMessage.JR_OUT_OF_RANGE, ref error);
                                 return new byte[1];
                             }
-                            codeGen.EmitByte((int)diff);
+                            codeGen.EmitByte(diff);
                         }
                         else
                         {
             error.extraInfo1 = arg.Text;
         }
 
+        private bool EvalDataFunc(CodeGenerator.DataFuncDelegate dataFunc, ITree instField, ref CompError error)
+        {
+            if (instField.ChildCount == 0)
+            {
+                codeGen.EmitByte(0);
+            }
+            else
+            {
+                bool good = true;
+                for (int i = 0; i < instField.ChildCount; i++)
+                {
+                    var arg = instField.GetChild(i);
+                    var result = 0L;
+                    ErrorMessage emt = Evaluate(arg, out result);
+                    if (emt == ErrorMessage.NO_ERROR)
+                    {
+                        dataFunc(result);
+                    }
+                    else
+                    {
+                        MakeErrorMessage(arg, emt, ref error);
+                        good = false;
+                    }
+                    if (!good)
+                    {
+                        break;
+                    }
+                }
+                return good;
+            }
+            return true;
+        }
+
         private bool EvalArithArgFunc(CodeGenerator.ArithmeticFuncDelegate arithFunc, ITree arg, ref CompError error)
         {
-            int result = 0;
+            var result = 0L;
             ErrorMessage emt = Evaluate(arg, out result);
             if (emt == ErrorMessage.NO_ERROR)
             {
 
         private bool EvalBitFunc(CodeGenerator.BitFunctionDelegate arithFunc, ITree arg, string reg, ref CompError error)
         {
-            int result = 0;
+            var result = 0L;
             ErrorMessage emt = Evaluate(arg, out result);
             if (emt == ErrorMessage.NO_ERROR)
             {
             }
         }
 
-        private ErrorMessage Evaluate(ITree eval, out int result)
+        private ErrorMessage Evaluate(ITree eval, out long result)
         {
             result = 0;
             if (eval.Text == "EXPRESSION")
             else
             {
                 // It's either an operator, or a number.
-                var res1 = 0;
-                var res2 = 0;
-                var res3 = 0;
+                var res1 = 0L;
+                var res2 = 0L;
+                var res3 = 0L;
                 switch (eval.ChildCount)
                 {
                     case 0:
                         {
-                            result = Utility.NumStringToInt(eval.Text);
+                            if (!Utility.NumStringToInt(eval.Text, out result))
+                            {
+                                return ErrorMessage.NumberOverflow;
+                            }
                             return ErrorMessage.NO_ERROR;
                         }
                     case 1:
                                     result = res1 % res2;
                                     return ErrorMessage.NO_ERROR;
                                 case "<<":
-                                    result = res1 << res2;
+                                    result = res1 << (int)res2;
                                     return ErrorMessage.NO_ERROR;
                                 case ">>":
-                                    result = res1 >> res2;
+                                    result = res1 >> (int)res2;
                                     return ErrorMessage.NO_ERROR;
                                 case "<":
                                     result = res1 < res2 ? 1 : 0;

gbread/Base/CodeGenerator.cs

     /// </summary>
     public class CodeGenerator
     {
-        public delegate void ArithmeticFuncDelegate(int arg);
+        public delegate void DataFuncDelegate(long arg);
 
-        public delegate void BitFunctionDelegate(int bit, string arg);
+        public delegate void ArithmeticFuncDelegate(long arg);
+
+        public delegate void BitFunctionDelegate(long bit, string arg);
 
         private MemoryStream ms;
 
             return ms.ToArray();
         }
 
-        public void EmitByte(int num)
+        public void EmitByte(long num)
         {
             ms.WriteByte((byte)num);
         }
 
-        public void EmitWord(int num)
+        public void EmitWord(long num)
         {
             ms.WriteByte((byte)num);
             ms.WriteByte((byte)(num >> 8));
         }
 
-        public void EmitDWord(int num)
+        public void EmitDWord(long num)
         {
             ms.WriteByte((byte)num);
             ms.WriteByte((byte)(num >> 8));
 
         #region ADC
 
-        public void EmitAdcN(int arg)
+        public void EmitAdcN(long arg)
         {
             EmitByte(0xCE);
             EmitByte(arg);
 
         #region ADD
 
-        public void EmitAddN(int arg)
+        public void EmitAddN(long arg)
         {
             EmitByte(0xC6);
             EmitByte(arg);
             EmitByte(0x09 + regDoubleBytes[reg]);
         }
 
-        public void EmitAddSPN(int arg)
+        public void EmitAddSPN(long arg)
         {
             EmitByte(0xE8);
             EmitByte(arg);
 
         #region AND
 
-        public void EmitAndN(int arg)
+        public void EmitAndN(long arg)
         {
             EmitByte(0xE6);
             EmitByte(arg);
 
         #region BIT
 
-        public void EmitBitXR(int bit, string reg)
+        public void EmitBitXR(long bit, string reg)
         {
             bit &= 7;
             EmitByte(0xCB);
 
         #region CALL
 
-        public void EmitCallN(int arg)
+        public void EmitCallN(long arg)
         {
             EmitByte(0xCD);
             EmitWord(arg);
         }
 
-        public void EmitCallCCN(string cond, int arg)
+        public void EmitCallCCN(string cond, long arg)
         {
             EmitByte(0xC4 + conditionBytes[cond]);
             EmitWord(arg);
 
         #region CP
 
-        public void EmitCpN(int arg)
+        public void EmitCpN(long arg)
         {
             EmitByte(0xFE);
             EmitByte(arg);
             EmitByte(0xE9);
         }
 
-        public void EmitJpN(int arg)
+        public void EmitJpN(long arg)
         {
             EmitByte(0xC3);
             EmitWord(arg);
         }
 
-        public void EmitJpCCN(string cond, int arg)
+        public void EmitJpCCN(string cond, long arg)
         {
             EmitByte(0xC2 + conditionBytes[cond]);
             EmitWord(arg);
 
         #region JR
 
-        public void EmitJr(int arg)
+        public void EmitJr(long arg)
         {
             EmitByte(0x18);
             EmitByte(arg);
         }
 
-        public void EmitJrCCN(string cond, int arg)
+        public void EmitJrCCN(string cond, long arg)
         {
             EmitByte(0x20 + conditionBytes[cond]);
             EmitByte(arg);
 
         #region LDHL
 
-        public void EmitLdHLSP(int arg)
+        public void EmitLdHLSP(long arg)
         {
             EmitByte(0xF8);
             EmitByte(arg);
 
         #region LDIO
 
-        public void EmitLdioAN(int arg)
+        public void EmitLdioAN(long arg)
         {
             EmitByte(0xF0);
             EmitByte(arg);
         }
 
-        public void EmitLdioNA(int arg)
+        public void EmitLdioNA(long arg)
         {
             EmitByte(0xE0);
             EmitByte(arg);
             EmitByte(0x1A);
         }
 
-        public void EmitLdANRef(int arg)
+        public void EmitLdANRef(long arg)
         {
             ushort pre = (byte)(arg >> 8);
             pre <<= 8;
             }
         }
 
-        public void EmitLdRN(string reg, int arg)
+        public void EmitLdRN(string reg, long arg)
         {
             EmitByte(0x06 + (8 * regSingleBytes[reg]));
             EmitByte(arg);
         }
 
-        public void EmitLdRRN(string reg, int arg)
+        public void EmitLdRRN(string reg, long arg)
         {
             EmitByte(0x01 + regDoubleBytes[reg]);
         }
             EmitByte(0x12);
         }
 
-        public void EmitLdNRefA(int arg)
+        public void EmitLdNRefA(long arg)
         {
             ushort pre = (byte)(arg >> 8);
             pre <<= 8;
             }
         }
 
-        public void EmitLdNRefSP(int arg)
+        public void EmitLdNRefSP(long arg)
         {
             EmitByte(0x08);
             EmitWord(arg);
 
         #region OR
 
-        public void EmitOrN(int arg)
+        public void EmitOrN(long arg)
         {
             EmitByte(0xF6);
             EmitByte(arg);
 
         #region RES
 
-        public void EmitResXR(int bit, string reg)
+        public void EmitResXR(long bit, string reg)
         {
             bit &= 7;
             EmitByte(0xCB);
 
         #region RST
 
-        public void EmitRst(int arg)
+        public void EmitRst(long arg)
         {
             arg &= 0x38;
             EmitByte(0xC7 + arg);
 
         #region SBC
 
-        public void EmitSbcN(int arg)
+        public void EmitSbcN(long arg)
         {
             EmitByte(0xDE);
             EmitByte(arg);
 
         #region SET
 
-        public void EmitSetXR(int bit, string reg)
+        public void EmitSetXR(long bit, string reg)
         {
             bit &= 7;
             EmitByte(0xC0 + (bit * 8) + regSingleBytes[reg]);
 
         #region SUB
 
-        public void EmitSubN(int arg)
+        public void EmitSubN(long arg)
         {
             EmitByte(0xD6);
             EmitByte(arg);
 
         #region XOR
 
-        public void EmitXorN(int arg)
+        public void EmitXorN(long arg)
         {
             EmitByte(0xEE);
             EmitByte(arg);

gbread/Base/Utility.cs

             }
         }
 
-        public static int NumStringToInt(string check)
+        public static bool NumStringToInt(string check, out long result)
         {
             check = check.ToLower();
+            result = 0;
             if (check.StartsWith("0x"))
             {
-                return Convert.ToInt32(check, 16);
+                try
+                {
+                    result = Convert.ToInt64(check, 16);
+                }
+                catch (OverflowException)
+                {
+                    return false;
+                }
             }
             else if (check.StartsWith("$"))
             {
                 check = check.Substring(1);
-                return Convert.ToInt32(check, 16);
+                try
+                {
+                    result = Convert.ToInt64(check, 16);
+                }
+                catch (OverflowException)
+                {
+                    return false;
+                }
             }
             else if (check.StartsWith("0o"))
             {
                 check = check.Substring(2);
-                return Convert.ToInt32(check, 8);
+                try
+                {
+                    result = Convert.ToInt64(check, 8);
+                }
+                catch (OverflowException)
+                {
+                    return false;
+                }
             }
             else if (check.StartsWith("&"))
             {
                 check = check.Substring(1);
-                return Convert.ToInt32(check, 8);
+                try
+                {
+                    result = Convert.ToInt64(check, 8);
+                }
+                catch (OverflowException)
+                {
+                    return false;
+                }
             }
             else if (check.StartsWith("0b"))
             {
                 check = check.Substring(2);
-                return Convert.ToInt32(check, 2);
+                try
+                {
+                    result = Convert.ToInt64(check, 2);
+                }
+                catch (OverflowException)
+                {
+                    return false;
+                }
             }
             else if (check.StartsWith("%"))
             {
                 check = check.Substring(1);
-                return Convert.ToInt32(check, 2);
+                try
+                {
+                    result = Convert.ToInt64(check, 2);
+                }
+                catch (OverflowException)
+                {
+                    return false;
+                }
             }
             else
             {
-                return Convert.ToInt32(check);
+                try
+                {
+                    result = Convert.ToInt64(check);
+                }
+                catch (OverflowException)
+                {
+                    return false;
+                }
             }
+            return true;
         }
     }
 }
         LENGTH_IS_INVALID, 
         ROW_LENGTH_IS_INVALID,
         VARIABLE_IS_INVALID,
+        NumberOverflow,
         CUSTOM,
     }
 
     {
         public static Dictionary<ErrorMessage, string> ErrorMessages = new Dictionary<ErrorMessage, string>()
         {
+            {ErrorMessage.NO_ERROR,                     "No error."},
             {ErrorMessage.END_INVALID,                  "Please make sure that your end position is a place in the file."}, 
             {ErrorMessage.FILE_TOO_LARGE,               "The file is too large for a GameBoy file."}, 
             {ErrorMessage.NO_FILE,                      "Please load a file."}, 
             {ErrorMessage.OFFSET_IS_INVALID,            "The offset is invalid."}, 
             {ErrorMessage.LENGTH_IS_INVALID,            "The length is invalid."}, 
             {ErrorMessage.VARIABLE_IS_INVALID,          "The value is invalid."},
+            {ErrorMessage.NumberOverflow,               "The number on this line is too long."},
             {ErrorMessage.CUSTOM,                       "{0}"},
         };
         public static void ShowErrorMessage(ErrorMessage errorOptions)