Ejemplo n.º 1
0
        public string Format(Z80Instruction instruction)
        {
            string textInst;

            switch (instruction.Opcode)
            {
            case Z80Opcode.PrefixCB:
                textInst = instruction.OpcodeCB.ToString();
                break;

            case Z80Opcode.PrefixDD:
                switch (instruction.OpcodeDD)
                {
                case Z80OpcodeDD.PrefixDDCB:
                    textInst = instruction.OpcodeDDCB.ToString();
                    break;

                default:
                    textInst = instruction.OpcodeDD.ToString();
                    break;
                }
                break;

            case Z80Opcode.PrefixED:
                textInst = instruction.OpcodeED.ToString();
                break;

            case Z80Opcode.PrefixFD:
                switch (instruction.OpcodeFD)
                {
                case Z80OpcodeFD.PrefixFDCB:
                    textInst = instruction.OpcodeFDCB.ToString();
                    break;

                default:
                    textInst = instruction.OpcodeFD.ToString();
                    break;
                }
                break;

            default:
                textInst = instruction.Opcode.ToString();
                break;
            }

            //if (!textInst.Contains('_'))
            //{
            //    return textInst;
            //}

            textInst = textInst
                       .Replace("_Plus_", "+")
                       .Replace("Ptr_", "(");

            var leftParen = textInst.IndexOf('(');

            if (leftParen != -1)
            {
                var rightParen = textInst.IndexOf('_', leftParen);

                if (rightParen == -1)
                {
                    textInst += ")";
                }
                else
                {
                    textInst = textInst.Insert(rightParen, ")");
                }
            }

            var indexUnderscore = textInst.IndexOf('_');

            if (indexUnderscore != -1)
            {
                textInst = textInst
                           .Remove(indexUnderscore, 1)
                           .Insert(indexUnderscore, " ");
            }

            indexUnderscore = textInst.IndexOf('_');

            if (indexUnderscore != -1)
            {
                textInst = textInst
                           .Remove(indexUnderscore, 1)
                           .Insert(indexUnderscore, ", ");
            }

            textInst = textInst
                       .Replace("NZ", "$Z");

            if (textInst.Contains("NN"))
            {
                textInst = textInst.Replace(
                    "NN",
                    string.Format("0x{0:X4}", instruction.Immediate));
            }
            else
            {
                if (textInst.Contains("+N"))
                {
                    var bytes = BitConverter.GetBytes(instruction.Immediate);

                    textInst = textInst.Replace(
                        "+N",
                        string.Format("+0x{0:X2}", bytes[0]));

                    if (textInst.Contains(", N"))
                    {
                        textInst = textInst.Replace(
                            ", N",
                            string.Format(", 0x{0:X2}", bytes[1]));
                    }
                }

                if (textInst.StartsWith("JR"))
                {
                    var offset = (int)unchecked ((sbyte)(byte)instruction.Immediate) + 2;

                    bool negative = false;

                    if (offset < 0)
                    {
                        offset  *= -1;
                        negative = true;
                    }

                    var offsetStr = string.Format(
                        "{0}0x{1:X2}",
                        negative ? "-" : "", offset);

                    if (textInst.Contains(", N"))
                    {
                        textInst = textInst.Replace(", N", ", " + offsetStr);
                    }
                    else
                    {
                        textInst = textInst.Replace(" N", " " + offsetStr);
                    }
                }
                else if (textInst.Contains(", N"))
                {
                    if (textInst.Contains(", N"))
                    {
                        textInst = textInst.Replace(
                            ", N",
                            string.Format(", 0x{0:X2}", instruction.Immediate));
                    }
                }
                //else
                //{
                //}
            }

            textInst = textInst.Replace("$Z", "NZ");

            var objectCode = instruction.ObjectCode
                             .Select(x => string.Format("{0:X2}", x))
                             .Aggregate((x, y) => x + " " + y);

            textInst = textInst.PadRight(17) + "; " + objectCode;



            return(textInst);
        }
Ejemplo n.º 2
0
        public Dictionary <ushort, Z80Instruction> Disassemble()
        {
            var instructions        = new Dictionary <ushort, Z80Instruction>();
            var unconditionalBranch = false;
            var branches            = new List <ushort>();

            branches.AddRange(_symbols.Select(x => (ushort)x.Key));
            ushort lastAddress = 0;

            while (true)
            {
                var address = (ushort)_reader.BaseStream.Position;

                if (address != 0)
                {
                    var size = address - lastAddress;
                    _reader.BaseStream.Position -= size;
                    instructions.Last().Value.ObjectCode = _reader.ReadBytes(size);
                }

                var lastInst = instructions.LastOrDefault();

                var isRet = instructions.Any() &&
                            (lastInst.Value.Opcode == Z80Opcode.RET ||
                             lastInst.Value.OpcodeED == Z80OpcodeED.RETI ||
                             lastInst.Value.OpcodeED == Z80OpcodeED.RETN);

                if (unconditionalBranch ||
                    instructions.ContainsKey(address) ||
                    _reader.BaseStream.Length <= address ||
                    isRet)
                {
                    unconditionalBranch = false;
                    branches            = branches
                                          .Distinct()
                                          .Where(x =>
                                                 !instructions.ContainsKey(x) &&
                                                 x < _reader.BaseStream.Length)
                                          .ToList();

                    if (branches.Any())
                    {
                        _reader.BaseStream.Position = (int)branches[0];
                        address = branches[0];
                        branches.RemoveAt(0);
                    }
                    else
                    {
                        break;
                    }
                }

                lastAddress = address;

                var opcode = _reader.ReadEnum <Z80Opcode>();

                switch (opcode)
                {
                    ////////////////////////////////////////////////////////////////
                    #region [Opcode]
                case Z80Opcode.NOP:
                case Z80Opcode.LD_Ptr_BC_A:
                case Z80Opcode.INC_BC:
                case Z80Opcode.INC_B:
                case Z80Opcode.DEC_B:
                case Z80Opcode.RLCA:
                case Z80Opcode.EX_AF_AF:
                case Z80Opcode.ADD_HL_BC:
                case Z80Opcode.LD_A_Ptr_BC:
                case Z80Opcode.DEC_BC:
                case Z80Opcode.INC_C:
                case Z80Opcode.DEC_C:
                case Z80Opcode.RRCA:
                case Z80Opcode.LD_Ptr_DE_A:
                case Z80Opcode.INC_DE:
                case Z80Opcode.INC_D:
                case Z80Opcode.DEC_D:
                case Z80Opcode.RLA:
                case Z80Opcode.ADD_HL_DE:
                case Z80Opcode.LD_A_Ptr_DE:
                case Z80Opcode.DEC_DE:
                case Z80Opcode.INC_E:
                case Z80Opcode.DEC_E:
                case Z80Opcode.RRA:
                case Z80Opcode.INC_HL:
                case Z80Opcode.INC_H:
                case Z80Opcode.DEC_H:
                case Z80Opcode.DAA:
                case Z80Opcode.ADD_HL_HL:
                case Z80Opcode.DEC_HL:
                case Z80Opcode.INC_L:
                case Z80Opcode.DEC_L:
                case Z80Opcode.CPL:
                case Z80Opcode.INC_SP:
                case Z80Opcode.INC_Ptr_HL:
                case Z80Opcode.DEC_Ptr_HL:
                case Z80Opcode.SCF:
                case Z80Opcode.ADD_HL_SP:
                case Z80Opcode.DEC_SP:
                case Z80Opcode.INC_A:
                case Z80Opcode.DEC_A:
                case Z80Opcode.CCF:
                case Z80Opcode.LD_B_B:
                case Z80Opcode.LD_B_C:
                case Z80Opcode.LD_B_D:
                case Z80Opcode.LD_B_E:
                case Z80Opcode.LD_B_H:
                case Z80Opcode.LD_B_L:
                case Z80Opcode.LD_B_Ptr_HL:
                case Z80Opcode.LD_B_A:
                case Z80Opcode.LD_C_B:
                case Z80Opcode.LD_C_C:
                case Z80Opcode.LD_C_D:
                case Z80Opcode.LD_C_E:
                case Z80Opcode.LD_C_H:
                case Z80Opcode.LD_C_L:
                case Z80Opcode.LD_C_Ptr_HL:
                case Z80Opcode.LD_C_A:
                case Z80Opcode.LD_D_B:
                case Z80Opcode.LD_D_C:
                case Z80Opcode.LD_D_D:
                case Z80Opcode.LD_D_E:
                case Z80Opcode.LD_D_H:
                case Z80Opcode.LD_D_L:
                case Z80Opcode.LD_D_Ptr_HL:
                case Z80Opcode.LD_D_A:
                case Z80Opcode.LD_E_B:
                case Z80Opcode.LD_E_C:
                case Z80Opcode.LD_E_D:
                case Z80Opcode.LD_E_E:
                case Z80Opcode.LD_E_H:
                case Z80Opcode.LD_E_L:
                case Z80Opcode.LD_E_Ptr_HL:
                case Z80Opcode.LD_E_A:
                case Z80Opcode.LD_H_B:
                case Z80Opcode.LD_H_C:
                case Z80Opcode.LD_H_D:
                case Z80Opcode.LD_H_E:
                case Z80Opcode.LD_H_H:
                case Z80Opcode.LD_H_L:
                case Z80Opcode.LD_H_Ptr_HL:
                case Z80Opcode.LD_H_A:
                case Z80Opcode.LD_L_B:
                case Z80Opcode.LD_L_C:
                case Z80Opcode.LD_L_D:
                case Z80Opcode.LD_L_E:
                case Z80Opcode.LD_L_H:
                case Z80Opcode.LD_L_L:
                case Z80Opcode.LD_L_Ptr_HL:
                case Z80Opcode.LD_L_A:
                case Z80Opcode.LD_Ptr_HL_B:
                case Z80Opcode.LD_Ptr_HL_C:
                case Z80Opcode.LD_Ptr_HL_D:
                case Z80Opcode.LD_Ptr_HL_E:
                case Z80Opcode.LD_Ptr_HL_H:
                case Z80Opcode.LD_Ptr_HL_L:
                case Z80Opcode.HALT:
                case Z80Opcode.LD_Ptr_HL_A:
                case Z80Opcode.LD_A_B:
                case Z80Opcode.LD_A_C:
                case Z80Opcode.LD_A_D:
                case Z80Opcode.LD_A_E:
                case Z80Opcode.LD_A_H:
                case Z80Opcode.LD_A_L:
                case Z80Opcode.LD_A_Ptr_HL:
                case Z80Opcode.LD_A_A:
                case Z80Opcode.ADD_A_B:
                case Z80Opcode.ADD_A_C:
                case Z80Opcode.ADD_A_D:
                case Z80Opcode.ADD_A_E:
                case Z80Opcode.ADD_A_H:
                case Z80Opcode.ADD_A_L:
                case Z80Opcode.ADD_A_Ptr_HL:
                case Z80Opcode.ADD_A_A:
                case Z80Opcode.ADC_A_B:
                case Z80Opcode.ADC_A_C:
                case Z80Opcode.ADC_A_D:
                case Z80Opcode.ADC_A_E:
                case Z80Opcode.ADC_A_H:
                case Z80Opcode.ADC_A_L:
                case Z80Opcode.ADC_A_Ptr_HL:
                case Z80Opcode.ADC_A_A:
                case Z80Opcode.SUB_B:
                case Z80Opcode.SUB_C:
                case Z80Opcode.SUB_D:
                case Z80Opcode.SUB_E:
                case Z80Opcode.SUB_H:
                case Z80Opcode.SUB_L:
                case Z80Opcode.SUB_Ptr_HL:
                case Z80Opcode.SUB_A:
                case Z80Opcode.SBC_B:
                case Z80Opcode.SBC_C:
                case Z80Opcode.SBC_D:
                case Z80Opcode.SBC_E:
                case Z80Opcode.SBC_H:
                case Z80Opcode.SBC_L:
                case Z80Opcode.SBC_Ptr_HL:
                case Z80Opcode.SBC_A:
                case Z80Opcode.AND_B:
                case Z80Opcode.AND_C:
                case Z80Opcode.AND_D:
                case Z80Opcode.AND_E:
                case Z80Opcode.AND_H:
                case Z80Opcode.AND_L:
                case Z80Opcode.AND_Ptr_HL:
                case Z80Opcode.AND_A:
                case Z80Opcode.XOR_B:
                case Z80Opcode.XOR_C:
                case Z80Opcode.XOR_D:
                case Z80Opcode.XOR_E:
                case Z80Opcode.XOR_H:
                case Z80Opcode.XOR_L:
                case Z80Opcode.XOR_Ptr_HL:
                case Z80Opcode.XOR_A:
                case Z80Opcode.OR_B:
                case Z80Opcode.OR_C:
                case Z80Opcode.OR_D:
                case Z80Opcode.OR_E:
                case Z80Opcode.OR_H:
                case Z80Opcode.OR_L:
                case Z80Opcode.OR_Ptr_HL:
                case Z80Opcode.OR_A:
                case Z80Opcode.CP_B:
                case Z80Opcode.CP_C:
                case Z80Opcode.CP_D:
                case Z80Opcode.CP_E:
                case Z80Opcode.CP_H:
                case Z80Opcode.CP_L:
                case Z80Opcode.CP_Ptr_HL:
                case Z80Opcode.CP_A:
                case Z80Opcode.RET_NZ:
                case Z80Opcode.POP_BC:
                case Z80Opcode.PUSH_BC:
                case Z80Opcode.RST_0:
                case Z80Opcode.RET_Z:
                case Z80Opcode.RET:
                case Z80Opcode.RST_8H:
                case Z80Opcode.RET_NC:
                case Z80Opcode.POP_DE:
                case Z80Opcode.PUSH_DE:
                case Z80Opcode.RST_10H:
                case Z80Opcode.RET_C:
                case Z80Opcode.EXX:
                case Z80Opcode.RST_18H:
                case Z80Opcode.RET_PO:
                case Z80Opcode.POP_HL:
                case Z80Opcode.EX_Ptr_SP_HL:
                case Z80Opcode.PUSH_HL:
                case Z80Opcode.RST_20H:
                case Z80Opcode.RET_PE:
                case Z80Opcode.JP_Ptr_HL:
                case Z80Opcode.EX_DE_HL:
                case Z80Opcode.RST_28H:
                case Z80Opcode.RET_P:
                case Z80Opcode.POP_AF:
                case Z80Opcode.DI:
                case Z80Opcode.PUSH_AF:
                case Z80Opcode.RST_30H:
                case Z80Opcode.RET_M:
                case Z80Opcode.LD_SP_HL:
                case Z80Opcode.EI:
                case Z80Opcode.RST_38H:
                    instructions.Add(address, opcode);
                    break;
                    #endregion

                    ////////////////////////////////////////////////////////////////
                    #region [Opcode] [Imm 8]
                case Z80Opcode.LD_B_N:
                case Z80Opcode.LD_C_N:
                case Z80Opcode.DJNZ_N:
                case Z80Opcode.LD_D_N:
                case Z80Opcode.JR_N:
                case Z80Opcode.LD_E_N:
                case Z80Opcode.JR_NZ_N:
                case Z80Opcode.LD_H_N:
                case Z80Opcode.JR_Z_N:
                case Z80Opcode.LD_L_N:
                case Z80Opcode.JR_NC_N:
                case Z80Opcode.LD_Ptr_HL_N:
                case Z80Opcode.JR_C_N:
                case Z80Opcode.LD_A_N:
                case Z80Opcode.ADD_A_N:
                case Z80Opcode.ADC_A_N:
                case Z80Opcode.OUT_Ptr_N_A:
                case Z80Opcode.SUB_N:
                case Z80Opcode.IN_A_Ptr_N:
                case Z80Opcode.SBC_A_N:
                case Z80Opcode.AND_N:
                case Z80Opcode.XOR_N:
                case Z80Opcode.OR_N:
                case Z80Opcode.CP_N:
                    var instruction = new Z80Instruction(
                        opcode,
                        OperandType.Byte,
                        _reader.ReadByte());

                    instructions.Add(address, instruction);

                    if (opcode.ToString().StartsWith("JR"))
                    {
                        var offset = unchecked ((sbyte)(byte)instruction.Immediate);
                        var branch = (ushort)(_reader.BaseStream.Position + offset);
                        branches.Add(branch);

                        if (opcode == Z80Opcode.JR_N)
                        {
                            unconditionalBranch = true;
                        }
                    }
                    break;
                    #endregion

                    ////////////////////////////////////////////////////////////////
                    #region [Opcode] [Imm 16]
                case Z80Opcode.LD_BC_NN:
                case Z80Opcode.LD_DE_NN:
                case Z80Opcode.LD_HL_NN:
                case Z80Opcode.LD_Ptr_NN_HL:
                case Z80Opcode.LD_HL_Ptr_NN:
                case Z80Opcode.LD_SP_NN:
                case Z80Opcode.LD_Ptr_NN_A:
                case Z80Opcode.LD_A_Ptr_NN:
                case Z80Opcode.JP_NZ_NN:
                case Z80Opcode.JP_NN:
                case Z80Opcode.CALL_NZ_NN:
                case Z80Opcode.JP_Z_NN:
                case Z80Opcode.CALL_Z_NN:
                case Z80Opcode.CALL_NN:
                case Z80Opcode.JP_NC_NN:
                case Z80Opcode.CALL_NC_NN:
                case Z80Opcode.JP_C_NN:
                case Z80Opcode.CALL_C_NN:
                case Z80Opcode.JP_PO_NN:
                case Z80Opcode.CALL_PO_NN:
                case Z80Opcode.JP_PE_NN:
                case Z80Opcode.CALL_PE_NN:
                case Z80Opcode.JP_P_NN:
                case Z80Opcode.CALL_P_NN:
                case Z80Opcode.JP_M_NN:
                case Z80Opcode.CALL_M_NN:
                    var inst = new Z80Instruction(
                        opcode,
                        OperandType.Word,
                        _reader.ReadUInt16());

                    instructions.Add(address, inst);

                    if (inst.Opcode.ToString().StartsWith("JP_"))
                    {
                        branches.Add(inst.Immediate);

                        if (opcode == Z80Opcode.JP_NN)
                        {
                            unconditionalBranch = true;
                        }
                    }
                    else if (inst.Opcode.ToString().StartsWith("CALL_"))
                    {
                        branches.Add(inst.Immediate);
                    }

                    break;
                    #endregion

                    #region ED Opcodes
                case Z80Opcode.PrefixED:
                    var opcodeED = _reader.ReadEnum <Z80OpcodeED>();

                    switch (opcodeED)
                    {
                        ////////////////////////////////////////////////////////////////
                        #region [ED] [Opcode]
                    case Z80OpcodeED.IN_B_Ptr_C:
                    case Z80OpcodeED.OUT_Ptr_C_B:
                    case Z80OpcodeED.SBC_HL_BC:
                    case Z80OpcodeED.NEG:
                    case Z80OpcodeED.RETN:
                    case Z80OpcodeED.IM_0:
                    case Z80OpcodeED.LD_I_A:
                    case Z80OpcodeED.IN_C_Ptr_C:
                    case Z80OpcodeED.OUT_Ptr_C_C:
                    case Z80OpcodeED.ADC_HL_BC:
                    case Z80OpcodeED.RETI:
                    case Z80OpcodeED.IN_D_Ptr_C:
                    case Z80OpcodeED.OUT_Ptr_C_D:
                    case Z80OpcodeED.SBC_HL_DE:
                    case Z80OpcodeED.IM_1:
                    case Z80OpcodeED.LD_A_I:
                    case Z80OpcodeED.IN_E_Ptr_C:
                    case Z80OpcodeED.OUT_Ptr_C_E:
                    case Z80OpcodeED.ADC_HL_DE:
                    case Z80OpcodeED.IM_2:
                    case Z80OpcodeED.LD_A_R:
                    case Z80OpcodeED.IN_H_Ptr_C:
                    case Z80OpcodeED.OUT_Ptr_C_H:
                    case Z80OpcodeED.SBC_HL_HL:
                    case Z80OpcodeED.RRD:
                    case Z80OpcodeED.IN_L_Ptr_C:
                    case Z80OpcodeED.OUT_Ptr_C_L:
                    case Z80OpcodeED.ADC_HL_HL:
                    case Z80OpcodeED.RLD:
                    case Z80OpcodeED.SBC_HL_SP:
                    case Z80OpcodeED.IN_A_Ptr_C:
                    case Z80OpcodeED.OUT_Ptr_C_A:
                    case Z80OpcodeED.ADC_HL_SP:
                    case Z80OpcodeED.LDI:
                    case Z80OpcodeED.CPI:
                    case Z80OpcodeED.INI:
                    case Z80OpcodeED.OUTI:
                    case Z80OpcodeED.LDD:
                    case Z80OpcodeED.CPD:
                    case Z80OpcodeED.IND:
                    case Z80OpcodeED.OUTD:
                    case Z80OpcodeED.LDIR:
                    case Z80OpcodeED.CPIR:
                    case Z80OpcodeED.INIR:
                    case Z80OpcodeED.OTIR:
                    case Z80OpcodeED.LDDR:
                    case Z80OpcodeED.CPDR:
                    case Z80OpcodeED.INDR:
                    case Z80OpcodeED.OTDR:
                        instructions.Add(address, opcodeED);
                        break;
                        #endregion

                        ////////////////////////////////////////////////////////////////
                        #region [ED] [Opcode] [Imm16]
                    case Z80OpcodeED.LD_Ptr_NN_BC:
                    case Z80OpcodeED.LD_BC_Ptr_NN:
                    case Z80OpcodeED.LD_Ptr_NN_DE:
                    case Z80OpcodeED.LD_DE_Ptr_NN:
                    case Z80OpcodeED.LD_Ptr_NN_SP:
                    case Z80OpcodeED.LD_SP_Ptr_NN:
                        instructions.Add(
                            address,
                            new Z80Instruction(opcodeED, _reader.ReadUInt16()));
                        break;
                        #endregion

                    default:
                        throw new NotImplementedException();
                    }
                    break;
                    #endregion

                    #region DD Opcodes
                case Z80Opcode.PrefixDD:
                    var opcodeDD = _reader.ReadEnum <Z80OpcodeDD>();

                    switch (opcodeDD)
                    {
                        ////////////////////////////////////////////////////////////////
                        #region [DD] [Opcode]
                    case Z80OpcodeDD.ADD_IX_BC:
                    case Z80OpcodeDD.ADD_IX_DE:
                    case Z80OpcodeDD.INC_IX:
                    case Z80OpcodeDD.ADD_IX_IX:
                    case Z80OpcodeDD.DEC_IX:
                    case Z80OpcodeDD.ADD_IX_SP:
                    case Z80OpcodeDD.POP_IX:
                    case Z80OpcodeDD.EX_Ptr_SP_IX:
                    case Z80OpcodeDD.PUSH_IX:
                    case Z80OpcodeDD.JP_Ptr_IX:
                    case Z80OpcodeDD.LD_SP_IX:
                        instructions.Add(address, opcodeDD);
                        break;
                        #endregion

                        ////////////////////////////////////////////////////////////////
                        #region [DD] [Opcode] [Imm8]
                    case Z80OpcodeDD.INC_Ptr_IX_Plus_N:
                    case Z80OpcodeDD.DEC_Ptr_IX_Plus_N:
                    case Z80OpcodeDD.LD_B_Ptr_IX_Plus_N:
                    case Z80OpcodeDD.LD_C_Ptr_IX_Plus_N:
                    case Z80OpcodeDD.LD_D_Ptr_IX_Plus_N:
                    case Z80OpcodeDD.LD_E_Ptr_IX_Plus_N:
                    case Z80OpcodeDD.LD_H_Ptr_IX_Plus_N:
                    case Z80OpcodeDD.LD_L_Ptr_IX_Plus_N:
                    case Z80OpcodeDD.LD_Ptr_IX_Plus_N_B:
                    case Z80OpcodeDD.LD_Ptr_IX_Plus_N_C:
                    case Z80OpcodeDD.LD_Ptr_IX_Plus_N_D:
                    case Z80OpcodeDD.LD_Ptr_IX_Plus_N_E:
                    case Z80OpcodeDD.LD_Ptr_IX_Plus_N_H:
                    case Z80OpcodeDD.LD_Ptr_IX_Plus_N_L:
                    case Z80OpcodeDD.LD_Ptr_IX_Plus_N_A:
                    case Z80OpcodeDD.LD_A_Ptr_IX_Plus_N:
                    case Z80OpcodeDD.ADD_A_Ptr_IX_Plus_N:
                    case Z80OpcodeDD.ADC_A_Ptr_IX_Plus_N:
                    case Z80OpcodeDD.SUB_Ptr_IX_Plus_N:
                    case Z80OpcodeDD.SBC_A_Ptr_IX_Plus_N:
                    case Z80OpcodeDD.AND_Ptr_IX_Plus_N:
                    case Z80OpcodeDD.XOR_Ptr_IX_Plus_N:
                    case Z80OpcodeDD.OR_Ptr_IX_Plus_N:
                    case Z80OpcodeDD.CP_Ptr_IX_Plus_N:
                        instructions.Add(
                            address,
                            new Z80Instruction(
                                opcodeDD,
                                OperandType.Byte,
                                _reader.ReadByte()));
                        break;
                        #endregion

                        ////////////////////////////////////////////////////////////////
                        #region [DD] [Opcode] [Imm16]
                    case Z80OpcodeDD.LD_IX_NN:
                    case Z80OpcodeDD.LD_Ptr_NN_IX:
                    case Z80OpcodeDD.LD_IX_Ptr_NN:
                    case Z80OpcodeDD.LD_Ptr_IX_Plus_N_N:
                        instructions.Add(
                            address,
                            new Z80Instruction(
                                opcodeDD,
                                OperandType.Word,
                                _reader.ReadUInt16()));
                        break;
                        #endregion

                    case Z80OpcodeDD.PrefixDDCB:
                        ////////////////////////////////////////////////////////////////
                        #region [DD] [CB] [Imm8] [Opcode]
                        var operand    = _reader.ReadByte();
                        var opcodeDDCB = _reader.ReadEnum <Z80OpcodeDDCB>();

                        switch (opcodeDDCB)
                        {
                        case Z80OpcodeDDCB.RLC_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.RRC_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.RL_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.RR_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.SLA_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.SRA_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.BIT_0_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.BIT_1_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.BIT_2_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.BIT_3_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.BIT_4_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.BIT_5_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.BIT_6_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.BIT_7_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.RES_0_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.RES_1_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.RES_2_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.RES_3_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.RES_4_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.RES_5_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.RES_6_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.RES_7_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.SET_0_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.SET_1_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.SET_2_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.SET_3_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.SET_4_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.SET_5_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.SET_6_Ptr_IX_Plus_N:
                        case Z80OpcodeDDCB.SET_7_Ptr_IX_Plus_N:
                            instructions.Add(
                                address,
                                new Z80Instruction(opcodeDDCB, operand));
                            break;
                        }
                        break;
                        #endregion

                    default:
                        throw new NotImplementedException();
                    }
                    break;
                    #endregion

                    #region CB Opcodes
                case Z80Opcode.PrefixCB:
                    var opcodeCB = _reader.ReadEnum <Z80OpcodeCB>();

                    switch (opcodeCB)
                    {
                        ////////////////////////////////////////////////////////////////
                        #region [CB] [Opcode]
                    case Z80OpcodeCB.RLC_B:
                    case Z80OpcodeCB.RLC_C:
                    case Z80OpcodeCB.RLC_D:
                    case Z80OpcodeCB.RLC_E:
                    case Z80OpcodeCB.RLC_H:
                    case Z80OpcodeCB.RLC_L:
                    case Z80OpcodeCB.RLC_Ptr_HL:
                    case Z80OpcodeCB.RLC_A:
                    case Z80OpcodeCB.RRC_B:
                    case Z80OpcodeCB.RRC_C:
                    case Z80OpcodeCB.RRC_D:
                    case Z80OpcodeCB.RRC_E:
                    case Z80OpcodeCB.RRC_H:
                    case Z80OpcodeCB.RRC_L:
                    case Z80OpcodeCB.RRC_Ptr_HL:
                    case Z80OpcodeCB.RRC_A:
                    case Z80OpcodeCB.RL_B:
                    case Z80OpcodeCB.RL_C:
                    case Z80OpcodeCB.RL_D:
                    case Z80OpcodeCB.RL_E:
                    case Z80OpcodeCB.RL_H:
                    case Z80OpcodeCB.RL_L:
                    case Z80OpcodeCB.RL_Ptr_HL:
                    case Z80OpcodeCB.RL_A:
                    case Z80OpcodeCB.RR_B:
                    case Z80OpcodeCB.RR_C:
                    case Z80OpcodeCB.RR_D:
                    case Z80OpcodeCB.RR_E:
                    case Z80OpcodeCB.RR_H:
                    case Z80OpcodeCB.RR_L:
                    case Z80OpcodeCB.RR_Ptr_HL:
                    case Z80OpcodeCB.RR_A:
                    case Z80OpcodeCB.SLA_B:
                    case Z80OpcodeCB.SLA_C:
                    case Z80OpcodeCB.SLA_D:
                    case Z80OpcodeCB.SLA_E:
                    case Z80OpcodeCB.SLA_H:
                    case Z80OpcodeCB.SLA_L:
                    case Z80OpcodeCB.SLA_Ptr_HL:
                    case Z80OpcodeCB.SLA_A:
                    case Z80OpcodeCB.SRA_B:
                    case Z80OpcodeCB.SRA_C:
                    case Z80OpcodeCB.SRA_D:
                    case Z80OpcodeCB.SRA_E:
                    case Z80OpcodeCB.SRA_H:
                    case Z80OpcodeCB.SRA_L:
                    case Z80OpcodeCB.SRA_Ptr_HL:
                    case Z80OpcodeCB.SRA_A:
                    case Z80OpcodeCB.SRL_B:
                    case Z80OpcodeCB.SRL_C:
                    case Z80OpcodeCB.SRL_D:
                    case Z80OpcodeCB.SRL_E:
                    case Z80OpcodeCB.SRL_H:
                    case Z80OpcodeCB.SRL_L:
                    case Z80OpcodeCB.SRL_Ptr_HL:
                    case Z80OpcodeCB.SRL_A:
                    case Z80OpcodeCB.BIT_0_B:
                    case Z80OpcodeCB.BIT_0_C:
                    case Z80OpcodeCB.BIT_0_D:
                    case Z80OpcodeCB.BIT_0_E:
                    case Z80OpcodeCB.BIT_0_H:
                    case Z80OpcodeCB.BIT_0_L:
                    case Z80OpcodeCB.BIT_0_Ptr_HL:
                    case Z80OpcodeCB.BIT_0_A:
                    case Z80OpcodeCB.BIT_1_B:
                    case Z80OpcodeCB.BIT_1_C:
                    case Z80OpcodeCB.BIT_1_D:
                    case Z80OpcodeCB.BIT_1_E:
                    case Z80OpcodeCB.BIT_1_H:
                    case Z80OpcodeCB.BIT_1_L:
                    case Z80OpcodeCB.BIT_1_Ptr_HL:
                    case Z80OpcodeCB.BIT_1_A:
                    case Z80OpcodeCB.BIT_2_B:
                    case Z80OpcodeCB.BIT_2_C:
                    case Z80OpcodeCB.BIT_2_D:
                    case Z80OpcodeCB.BIT_2_E:
                    case Z80OpcodeCB.BIT_2_H:
                    case Z80OpcodeCB.BIT_2_L:
                    case Z80OpcodeCB.BIT_2_Ptr_HL:
                    case Z80OpcodeCB.BIT_2_A:
                    case Z80OpcodeCB.BIT_3_B:
                    case Z80OpcodeCB.BIT_3_C:
                    case Z80OpcodeCB.BIT_3_D:
                    case Z80OpcodeCB.BIT_3_E:
                    case Z80OpcodeCB.BIT_3_H:
                    case Z80OpcodeCB.BIT_3_L:
                    case Z80OpcodeCB.BIT_3_Ptr_HL:
                    case Z80OpcodeCB.BIT_3_A:
                    case Z80OpcodeCB.BIT_4_B:
                    case Z80OpcodeCB.BIT_4_C:
                    case Z80OpcodeCB.BIT_4_D:
                    case Z80OpcodeCB.BIT_4_E:
                    case Z80OpcodeCB.BIT_4_H:
                    case Z80OpcodeCB.BIT_4_L:
                    case Z80OpcodeCB.BIT_4_Ptr_HL:
                    case Z80OpcodeCB.BIT_4_A:
                    case Z80OpcodeCB.BIT_5_B:
                    case Z80OpcodeCB.BIT_5_C:
                    case Z80OpcodeCB.BIT_5_D:
                    case Z80OpcodeCB.BIT_5_E:
                    case Z80OpcodeCB.BIT_5_H:
                    case Z80OpcodeCB.BIT_5_L:
                    case Z80OpcodeCB.BIT_5_Ptr_HL:
                    case Z80OpcodeCB.BIT_5_A:
                    case Z80OpcodeCB.BIT_6_B:
                    case Z80OpcodeCB.BIT_6_C:
                    case Z80OpcodeCB.BIT_6_D:
                    case Z80OpcodeCB.BIT_6_E:
                    case Z80OpcodeCB.BIT_6_H:
                    case Z80OpcodeCB.BIT_6_L:
                    case Z80OpcodeCB.BIT_6_Ptr_HL:
                    case Z80OpcodeCB.BIT_6_A:
                    case Z80OpcodeCB.BIT_7_B:
                    case Z80OpcodeCB.BIT_7_C:
                    case Z80OpcodeCB.BIT_7_D:
                    case Z80OpcodeCB.BIT_7_E:
                    case Z80OpcodeCB.BIT_7_H:
                    case Z80OpcodeCB.BIT_7_L:
                    case Z80OpcodeCB.BIT_7_Ptr_HL:
                    case Z80OpcodeCB.BIT_7_A:
                    case Z80OpcodeCB.RES_0_B:
                    case Z80OpcodeCB.RES_0_C:
                    case Z80OpcodeCB.RES_0_D:
                    case Z80OpcodeCB.RES_0_E:
                    case Z80OpcodeCB.RES_0_H:
                    case Z80OpcodeCB.RES_0_L:
                    case Z80OpcodeCB.RES_0_Ptr_HL:
                    case Z80OpcodeCB.RES_0_A:
                    case Z80OpcodeCB.RES_1_B:
                    case Z80OpcodeCB.RES_1_C:
                    case Z80OpcodeCB.RES_1_D:
                    case Z80OpcodeCB.RES_1_E:
                    case Z80OpcodeCB.RES_1_H:
                    case Z80OpcodeCB.RES_1_L:
                    case Z80OpcodeCB.RES_1_Ptr_HL:
                    case Z80OpcodeCB.RES_1_A:
                    case Z80OpcodeCB.RES_2_B:
                    case Z80OpcodeCB.RES_2_C:
                    case Z80OpcodeCB.RES_2_D:
                    case Z80OpcodeCB.RES_2_E:
                    case Z80OpcodeCB.RES_2_H:
                    case Z80OpcodeCB.RES_2_L:
                    case Z80OpcodeCB.RES_2_Ptr_HL:
                    case Z80OpcodeCB.RES_2_A:
                    case Z80OpcodeCB.RES_3_B:
                    case Z80OpcodeCB.RES_3_C:
                    case Z80OpcodeCB.RES_3_D:
                    case Z80OpcodeCB.RES_3_E:
                    case Z80OpcodeCB.RES_3_H:
                    case Z80OpcodeCB.RES_3_L:
                    case Z80OpcodeCB.RES_3_Ptr_HL:
                    case Z80OpcodeCB.RES_3_A:
                    case Z80OpcodeCB.RES_4_B:
                    case Z80OpcodeCB.RES_4_C:
                    case Z80OpcodeCB.RES_4_D:
                    case Z80OpcodeCB.RES_4_E:
                    case Z80OpcodeCB.RES_4_H:
                    case Z80OpcodeCB.RES_4_L:
                    case Z80OpcodeCB.RES_4_Ptr_HL:
                    case Z80OpcodeCB.RES_4_A:
                    case Z80OpcodeCB.RES_5_B:
                    case Z80OpcodeCB.RES_5_C:
                    case Z80OpcodeCB.RES_5_D:
                    case Z80OpcodeCB.RES_5_E:
                    case Z80OpcodeCB.RES_5_H:
                    case Z80OpcodeCB.RES_5_L:
                    case Z80OpcodeCB.RES_5_Ptr_HL:
                    case Z80OpcodeCB.RES_5_A:
                    case Z80OpcodeCB.RES_6_B:
                    case Z80OpcodeCB.RES_6_C:
                    case Z80OpcodeCB.RES_6_D:
                    case Z80OpcodeCB.RES_6_E:
                    case Z80OpcodeCB.RES_6_H:
                    case Z80OpcodeCB.RES_6_L:
                    case Z80OpcodeCB.RES_6_Ptr_HL:
                    case Z80OpcodeCB.RES_6_A:
                    case Z80OpcodeCB.RES_7_B:
                    case Z80OpcodeCB.RES_7_C:
                    case Z80OpcodeCB.RES_7_D:
                    case Z80OpcodeCB.RES_7_E:
                    case Z80OpcodeCB.RES_7_H:
                    case Z80OpcodeCB.RES_7_L:
                    case Z80OpcodeCB.RES_7_Ptr_HL:
                    case Z80OpcodeCB.RES_7_A:
                    case Z80OpcodeCB.SET_0_B:
                    case Z80OpcodeCB.SET_0_C:
                    case Z80OpcodeCB.SET_0_D:
                    case Z80OpcodeCB.SET_0_E:
                    case Z80OpcodeCB.SET_0_H:
                    case Z80OpcodeCB.SET_0_L:
                    case Z80OpcodeCB.SET_0_Ptr_HL:
                    case Z80OpcodeCB.SET_0_A:
                    case Z80OpcodeCB.SET_1_B:
                    case Z80OpcodeCB.SET_1_C:
                    case Z80OpcodeCB.SET_1_D:
                    case Z80OpcodeCB.SET_1_E:
                    case Z80OpcodeCB.SET_1_H:
                    case Z80OpcodeCB.SET_1_L:
                    case Z80OpcodeCB.SET_1_Ptr_HL:
                    case Z80OpcodeCB.SET_1_A:
                    case Z80OpcodeCB.SET_2_B:
                    case Z80OpcodeCB.SET_2_C:
                    case Z80OpcodeCB.SET_2_D:
                    case Z80OpcodeCB.SET_2_E:
                    case Z80OpcodeCB.SET_2_H:
                    case Z80OpcodeCB.SET_2_L:
                    case Z80OpcodeCB.SET_2_Ptr_HL:
                    case Z80OpcodeCB.SET_2_A:
                    case Z80OpcodeCB.SET_3_B:
                    case Z80OpcodeCB.SET_3_C:
                    case Z80OpcodeCB.SET_3_D:
                    case Z80OpcodeCB.SET_3_E:
                    case Z80OpcodeCB.SET_3_H:
                    case Z80OpcodeCB.SET_3_L:
                    case Z80OpcodeCB.SET_3_Ptr_HL:
                    case Z80OpcodeCB.SET_3_A:
                    case Z80OpcodeCB.SET_4_B:
                    case Z80OpcodeCB.SET_4_C:
                    case Z80OpcodeCB.SET_4_D:
                    case Z80OpcodeCB.SET_4_E:
                    case Z80OpcodeCB.SET_4_H:
                    case Z80OpcodeCB.SET_4_L:
                    case Z80OpcodeCB.SET_4_Ptr_HL:
                    case Z80OpcodeCB.SET_4_A:
                    case Z80OpcodeCB.SET_5_B:
                    case Z80OpcodeCB.SET_5_C:
                    case Z80OpcodeCB.SET_5_D:
                    case Z80OpcodeCB.SET_5_E:
                    case Z80OpcodeCB.SET_5_H:
                    case Z80OpcodeCB.SET_5_L:
                    case Z80OpcodeCB.SET_5_Ptr_HL:
                    case Z80OpcodeCB.SET_5_A:
                    case Z80OpcodeCB.SET_6_B:
                    case Z80OpcodeCB.SET_6_C:
                    case Z80OpcodeCB.SET_6_D:
                    case Z80OpcodeCB.SET_6_E:
                    case Z80OpcodeCB.SET_6_H:
                    case Z80OpcodeCB.SET_6_L:
                    case Z80OpcodeCB.SET_6_Ptr_HL:
                    case Z80OpcodeCB.SET_6_A:
                    case Z80OpcodeCB.SET_7_B:
                    case Z80OpcodeCB.SET_7_C:
                    case Z80OpcodeCB.SET_7_D:
                    case Z80OpcodeCB.SET_7_E:
                    case Z80OpcodeCB.SET_7_H:
                    case Z80OpcodeCB.SET_7_L:
                    case Z80OpcodeCB.SET_7_Ptr_HL:
                    case Z80OpcodeCB.SET_7_A:
                        instructions.Add(address, opcodeCB);
                        break;
                        #endregion

                    default:
                        throw new NotImplementedException();
                    }
                    break;
                    #endregion

                    #region FD Opcodes
                case Z80Opcode.PrefixFD:
                    var opcodeFD = _reader.ReadEnum <Z80OpcodeFD>();

                    switch (opcodeFD)
                    {
                        ////////////////////////////////////////////////////////////////
                        #region [FD] [Opcode]
                    case Z80OpcodeFD.ADD_IY_BC:
                    case Z80OpcodeFD.ADD_IY_DE:
                    case Z80OpcodeFD.INC_IY:
                    case Z80OpcodeFD.ADD_IY_IY:
                    case Z80OpcodeFD.DEC_IY:
                    case Z80OpcodeFD.ADD_IY_SP:
                    case Z80OpcodeFD.POP_IY:
                    case Z80OpcodeFD.EX_Ptr_SP_IY:
                    case Z80OpcodeFD.PUSH_IY:
                    case Z80OpcodeFD.JP_Ptr_IY:
                    case Z80OpcodeFD.LD_SP_IY:
                        instructions.Add(address, opcodeFD);
                        break;
                        #endregion

                        ////////////////////////////////////////////////////////////////
                        #region [FD] [Opcode] [Imm16]
                    case Z80OpcodeFD.LD_IY_NN:
                    case Z80OpcodeFD.LD_Ptr_NN_IY:
                    case Z80OpcodeFD.LD_IY_Ptr_NN:
                    case Z80OpcodeFD.LD_Ptr_IY_Plus_N_N:
                        instructions.Add(
                            address,
                            new Z80Instruction(opcodeFD, OperandType.Word, _reader.ReadUInt16()));
                        break;
                        #endregion

                    case Z80OpcodeFD.PrefixFDCB:
                        ////////////////////////////////////////////////////////////////
                        #region [FD] [CB] [Imm8] [Opcode]
                        var operand    = _reader.ReadByte();
                        var opcodeFDCB = _reader.ReadEnum <Z80OpcodeFDCB>();

                        switch (opcodeFDCB)
                        {
                        case Z80OpcodeFDCB.RLC_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.RRC_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.RL_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.RR_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.SLA_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.SRA_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.BIT_0_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.BIT_1_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.BIT_2_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.BIT_3_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.BIT_4_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.BIT_5_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.BIT_6_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.BIT_7_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.RES_0_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.RES_1_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.RES_2_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.RES_3_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.RES_4_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.RES_5_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.RES_6_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.RES_7_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.SET_0_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.SET_1_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.SET_2_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.SET_3_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.SET_4_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.SET_5_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.SET_6_Ptr_IY_Plus_N:
                        case Z80OpcodeFDCB.SET_7_Ptr_IY_Plus_N:
                            instructions.Add(
                                address,
                                new Z80Instruction(opcodeFDCB, _reader.ReadByte()));
                            break;

                        default:
                            throw new NotImplementedException();
                        }
                        #endregion

                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;
                    #endregion

                default:
                    throw new NotImplementedException();
                }
            }

            return(instructions
                   .OrderBy(x => x.Key)
                   .ToDictionary(x => x.Key, x => x.Value));;
        }