コード例 #1
0
ファイル: InstructionsEncoder.cs プロジェクト: DINKIN/snes
        /// <summary>
        /// Ecrit une instruction. C'est un peut chiant car il faut spécifier à la fois l'instruction, l'addrMode, le type des args et les args mais bon,
        /// pour l'instant ça devrait faire l'affaire
        /// </summary>
        /// <param name="bin"></param>
        /// <param name="offset"></param>
        /// <param name="opCode"></param>
        /// <param name="addrMode"></param>
        /// <param name="param1Type"></param>
        /// <param name="param1"></param>
        /// <param name="param2"></param>
        public void Write(MemoryBin bin, ref int offset, OpCodes opCode, AddressingModes addrMode = AddressingModes.Direct, ArgumentType param1Type = ArgumentType.I1, int param1 = 0, int param2 = 0)
        {
            var originalOffset = offset;

            /* d'abord, on cherche l'instruction */
            Instruction match_instruction = null;

            var match_code = from instruction in cpu.DecodeTable.KnownInstructions where instruction.Code == opCode select instruction;
            switch(match_code.Count())
            {
                case 0: throw new InvalidOperationException(String.Format("Instruction not found : {0}", opCode));
                case 1: {
                    /* on se prend pas la tête sur le mode d'addr */
                    match_instruction = match_code.First();
                    break;
                }
                default:
                    {
                        /* on cherche le bon mode */
                        match_instruction = (from code_item in match_code where code_item.AddrMode == addrMode select code_item).FirstOrDefault();

                        if(match_instruction== null)
                            throw new InvalidOperationException(String.Format("Instruction {0} was found, but the addrMode {1} has no binding", opCode, addrMode));

                        break;
                    }
            }

            /* on écrit le code */
            bin.WriteInt1(offset, match_instruction.AssociatedHexCode);
            offset++;

            /* s'il y a des arguments, on les écrit */
            if (match_instruction.HaveArgs)
            {
                WriteParameter(bin, ref offset, param1Type, param1);

                if (addrMode == AddressingModes.BlockMove)
                {
                    /* c'est le seul mode qui a deux arguments, et il a la même
                     * taille que le premier argument
                     * */
                    WriteParameter(bin, ref offset, param1Type, param2);
                }
            }

            if (enableInstructionValidation)
            {
                /* on vérifie l'instruction écrite */
                var instructionDecode = new InstructionReference();
                var context = cpu.BuildCurrentContext();

                cpu.Platform.Decoder.DecodeOnce(bin, ref originalOffset, ref context, ref instructionDecode);

                if (instructionDecode.instruction.Code != opCode ||
                    instructionDecode.param1 != param1 ||
                    instructionDecode.param2 != param2)
                {
                    throw new InvalidProgramException(String.Format("Instruction decode mismatch.\r\nEncoded:{0}({1},{2}) [{3}]\r\nDecoded:{4}({5},{6}) [{7}]",
                        opCode,
                        param1, param2,
                        addrMode,

                        instructionDecode.instruction.Code,
                        instructionDecode.param1, instructionDecode.param2,
                        instructionDecode.instruction.AddrMode));
                }
                else if (originalOffset != offset)
                {
                    throw new InvalidProgramException(String.Format("Instruction decode mismatch, Invalid offset. Difference : {0}", offset - originalOffset));
                }
            }
        }
コード例 #2
0
ファイル: InstructionsEncoder.cs プロジェクト: DINKIN/snes
 private void WriteParameter(MemoryBin bin, ref int offset, ArgumentType paramType, int param)
 {
     switch (paramType)
     {
         default:
         case ArgumentType.None:
             break;
         case ArgumentType.I1:
             bin.WriteInt1(offset, (byte)param);
             offset++;
             break;
         case ArgumentType.I2:
             bin.WriteInt1(offset, (byte)param);
             bin.WriteInt1(offset + 1, (byte)(param >> 8));
             offset += 2;
             break;
         case ArgumentType.I3:
             bin.WriteInt1(offset, (byte)param);
             bin.WriteInt1(offset + 1, (byte)(param >> 8));
             bin.WriteInt1(offset + 2, (byte)(param >> 16));
             offset += 3;
             break;
     }
 }