using System;
using System.Reflection.PortableExecutable;
using System.Text;
using System.Windows.Forms;
using Core.Audio;
using Core.Cpu;
using Core.Memory;

namespace Desktop
{
    public partial class DebuggerForm : Form
    {
        private readonly Z80 _cpu;
        private readonly SmsMemoryBus _memoryBus;
        private readonly ParsonsForm1 _mainForm;

        public DebuggerForm(Z80 cpu, SmsMemoryBus memoryBus, ParsonsForm1 mainForm)
        {
            InitializeComponent();
            _cpu = cpu;
            _memoryBus = memoryBus;
            _mainForm = mainForm;

            // Set default memory view address
            txtMemoryStart.Text = "0000";
            UpdateDisplay();
            UpdateStackView();
            UpdateDisassemblyView();
            _mainForm = mainForm;
            CpuRun.Text = _mainForm.IsRunning ? "CPU Stop" : "CPU Run";
        }

        private void CpuRun_Click(object sender, EventArgs e)
        {
            if (_mainForm.IsRunning)
            {
                // Stop the machine
                _mainForm.StopEmulator();

                // Stop the live UI updates and do one final manual refresh
                uiUpdateTimer.Stop();
                UpdateDisplay();
            }
            else
            {
                // Start the machine
                _mainForm.StartEmulator();

                // Start the timer so the debugger screen updates automatically
                // (Make sure your uiUpdateTimer Interval in the designer is set to something like 100ms)
                uiUpdateTimer.Start();
            }
            CpuRun.Text = _mainForm.IsRunning ? "CPU Stop" : "CPU Run";
        }

        private void btnStep_Click(object sender, EventArgs e)
        {
            try
            {
                // Ask the main form to step the WHOLE machine, not just the Z80!
                //_mainForm.StepEmulator();
                UpdateDisplay();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "CPU Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnSetBreakpoint_Click(object sender, EventArgs e) // Hook this to a button or text changed event
        {
            if (ushort.TryParse(txtBreakpoint.Text, System.Globalization.NumberStyles.HexNumber, null, out ushort parsedBp))
            {
                _mainForm.Breakpoint = parsedBp;
            }
            else
            {
                _mainForm.Breakpoint = null;
            }
        }

        private void btnRefreshMemory_Click(object sender, EventArgs e)
        {
            UpdateDisplay();
        }

        public void uiUpdateTimer_Tick(object sender, EventArgs e)
        {
            UpdateDisplay();
        }

        // Current Emulator State
        private void UpdateDisplay()
        {
            CpuRun.Text = _mainForm.IsRunning ? "CPU Stop" : "CPU Run";
            btnCpuStep.Enabled = _mainForm.IsRunning ? false : true;
            lblAF.Text = $"AF: {_cpu.AF.Word:X4}";
            lblBC.Text = $"BC: {_cpu.BC.Word:X4}";
            lblDE.Text = $"DE: {_cpu.DE.Word:X4}";
            lblHL.Text = $"HL: {_cpu.HL.Word:X4}";
            lblPC.Text = $"PC: {_cpu.PC:X4}";
            lblSP.Text = $"SP: {_cpu.SP:X4}";
            lblIX.Text = $"IX: {_cpu.IX.Word:X4}";
            lblIY.Text = $"IY: {_cpu.IY.Word:X4}";
            lblIff1.Text = $"IFF1: {_cpu.IFF1}";
            lblIff2.Text = $"IFF2: {_cpu.IFF2}";
            lblIE.Text = $"IM: {_cpu.InterruptMode}";
            lblFlags.Text = $"Flags: {_cpu.GetFlagsString()}";
            lblTStates.Text = $"T-States: {_cpu.TotalTStates}";
            lblFrames.Text = $"Frames Rendered: {_mainForm.TotalFrameCount}";
            lblFrameTime.Text = $"Frame Time: {((float)_mainForm.FrameTime):F1}ms";
            lblFPS.Text = $"FPS: {_mainForm.FramesPerSecond:F2}";
            lblHalt.Text = $"CPU Halted: {_cpu.IsHalted}";
            lblR.Text = $"R: {_cpu.R:X2}";
            UpdateMemoryView();
            UpdateStackView();
            UpdateDisassemblyView();
            // --- AUDIO REGISTERS ---//
            if (_mainForm._machine != null && _mainForm._machine.AudioProcessor != null)
            {
                ushort[] apuRegs = _mainForm._machine.AudioProcessor.Registers;

                lblTone0.Text = $"Tone 0: 0x{apuRegs[0]:X4}  (Vol: 0x{apuRegs[1]:X1})";
                lblTone1.Text = $"Tone 1: 0x{apuRegs[2]:X4}  (Vol: 0x{apuRegs[3]:X1})";
                lblTone2.Text = $"Tone 2: 0x{apuRegs[4]:X4}  (Vol: 0x{apuRegs[5]:X1})";

                lblNoise.Text = $"Noise : 0x{apuRegs[6]:X1}     (Vol: 0x{apuRegs[7]:X1})";
            }
        }

        private void UpdateMemoryView()
        {
            int count = 20;
            // Try to parse the hex string the user typed in
            if (!ushort.TryParse(txtMemoryStart.Text, System.Globalization.NumberStyles.HexNumber, null, out ushort startAddress))
            {
                txtMemoryView.Text = "Invalid Hex Address!";
                return;
            }

            StringBuilder sb = new StringBuilder();

            // Read 100 bytes (or roughly 6 lines of 16 bytes)
            for (int line = 0; line < count; line++)
            {
                ushort currentAddr = (ushort)(startAddress + (line * 16));

                // Print the address header for this line (e.g., "0000: ")
                sb.Append($"{currentAddr:X4}: ");

                // Print 16 bytes across
                for (int i = 0; i < 16; i++)
                {
                    // Careful not to overflow the 64k address space!
                    if (currentAddr + i <= 0xFFFF)
                    {
                        byte b = _memoryBus.Read((ushort)(currentAddr + i));
                        sb.Append($"{b:X2} ");
                    }
                }
                sb.AppendLine();
            }

            txtMemoryView.Text = sb.ToString();
        }

        private void UpdateStackView()
        {
            lstStack.Items.Clear();
            int itemsToShow = 5;
            ushort currentSp = _cpu.SP;

            for (int i = 0; i < itemsToShow; i++)
            {
                // Prevent reading past 0xFFFF
                if (currentSp >= 0xFFFE)
                {
                    lstStack.Items.Add($"{currentSp:X4}: [End of Mem]");
                    break;
                }

                // Read the 16-bit value (Little-Endian: Low byte first, then High byte)
                byte low = _memoryBus.Read(currentSp);
                byte high = _memoryBus.Read((ushort)(currentSp + 1));
                ushort value = (ushort)((high << 8) | low);

                lstStack.Items.Add($"{currentSp:X4}: {value:X4}");

                // Move to the next 16-bit word on the stack
                currentSp += 2;
            }
        }

        private void UpdateDisassemblyView()
        {
            lstDisassembly.Items.Clear();

            ushort currentPc = _cpu.PC;

            int instructionsToShow = 8;

            for (int i = 0; i < instructionsToShow; i++)
            {
                byte opcode = _memoryBus.Read(currentPc);
                string mnemonic;
                int instructionLength = 1; // Default to 1
                byte cbOp = 0;
                int opGroup = 0;
                int targetBit = 0;
                int regIdx = 0;
                string[] regNames = { "B", "C", "D", "E", "H", "L", "(HL)", "A" };
                string targetReg = "";

                switch (opcode)
                {
                    case 0x00: mnemonic = "NOP"; break;
                    case 0x01:
                        ushort bcVal = (ushort)(_memoryBus.Read((ushort)(currentPc + 1)) | (_memoryBus.Read((ushort)(currentPc + 2)) << 8));
                        mnemonic = $"LD BC, 0x{bcVal:X4}";
                        instructionLength = 3;
                        break;
                    case 0x02: mnemonic = "LD (BC), A"; break;
                    // --- 16-Bit Increments ---
                    case 0x03: mnemonic = "INC BC"; break;
                    case 0x07:
                        mnemonic = "RLCA";
                        break;
                    case 0x08:
                        mnemonic = "EX AF, AF'";
                        break;
                    case 0x0A: mnemonic = "LD A, (BC)"; break;
                    case 0x12: mnemonic = "LD (DE), A"; break;
                    case 0x13: mnemonic = "INC DE"; break;
                    case 0x33: mnemonic = "INC SP"; break;

                    // --- 16-Bit Decrements ---
                    case 0x0B: mnemonic = "DEC BC"; break;
                    case 0x3B: mnemonic = "DEC SP"; break;
                    // --- 8-Bit Increments ---
                    case 0x04: mnemonic = "INC B"; break;
                    case 0x0C: mnemonic = "INC C"; break;
                    case 0x14: mnemonic = "INC D"; break;
                    case 0x1C: mnemonic = "INC E"; break;
                    case 0x24: mnemonic = "INC H"; break;
                    case 0x2C: mnemonic = "INC L"; break;
                    case 0x34: mnemonic = "INC (HL)"; break;
                    case 0x3C: mnemonic = "INC A"; break;

                    // --- 8-Bit Decrements ---
                    case 0x05: mnemonic = "DEC B"; break;
                    case 0x0D: mnemonic = "DEC C"; break;
                    case 0x15: mnemonic = "DEC D"; break;
                    case 0x1D: mnemonic = "DEC E"; break;
                    case 0x25: mnemonic = "DEC H"; break;
                    case 0x2D: mnemonic = "DEC L"; break;
                    case 0x35: mnemonic = "DEC (HL)"; break;
                    case 0x3D: mnemonic = "DEC A"; break;
                    case 0x06:
                        byte bImm = _memoryBus.Read((ushort)(currentPc + 1));
                        mnemonic = $"LD B, 0x{bImm:X2}";
                        instructionLength = 2;
                        break;
                    // --- ADD HL, rr ---
                    case 0x09: mnemonic = "ADD HL, BC"; break;
                    case 0x19: mnemonic = "ADD HL, DE"; break;
                    case 0x29: mnemonic = "ADD HL, HL"; break;
                    case 0x39: mnemonic = "ADD HL, SP"; break;
                    case 0x0E:
                        byte cImm = _memoryBus.Read((ushort)(currentPc + 1));
                        mnemonic = $"LD C, 0x{cImm:X2}";
                        instructionLength = 2;
                        break;
                    case 0x0F:
                        mnemonic = "RRCA";
                        break;
                    case 0x10:
                        sbyte djnzOffset = (sbyte)_memoryBus.Read((ushort)(currentPc + 1));
                        ushort djnzDest = (ushort)(currentPc + 2 + djnzOffset);
                        mnemonic = $"DJNZ 0x{djnzDest:X4}";
                        instructionLength = 2;
                        break;
                    case 0x11:
                        // LD DE, nn
                        byte deLow = _memoryBus.Read((ushort)(currentPc + 1));
                        byte deHigh = _memoryBus.Read((ushort)(currentPc + 2));
                        mnemonic = $"LD DE, 0x{deHigh:X2}{deLow:X2}";
                        instructionLength = 3;
                        break;
                    case 0x16:
                        byte dImm = _memoryBus.Read((ushort)(currentPc + 1));
                        mnemonic = $"LD D, 0x{dImm:X2}";
                        instructionLength = 2;
                        break;
                    case 0x17: // RLA
                        mnemonic = "RLA";
                        instructionLength = 1;
                        break;
                    case 0x18:
                        sbyte dUnconditional = (sbyte)_memoryBus.Read((ushort)(currentPc + 1));
                        ushort targetAddressUnconditional = (ushort)(currentPc + 2 + dUnconditional);
                        mnemonic = $"JR 0x{targetAddressUnconditional:X4}";
                        instructionLength = 2;
                        break;
                    case 0x1A:
                        mnemonic = "LD A, (DE)";
                        break;
                    case 0x1B:
                        mnemonic = "DEC DE";
                        break;
                    case 0x1E:
                        byte val1E = _memoryBus.Read((ushort)(currentPc + 1));
                        mnemonic = $"LD E, 0x{val1E:X2}";
                        instructionLength = 2;
                        break;
                    case 0x1F:
                        mnemonic = $"RRA";
                        break;
                    case 0x20:
                        sbyte jrOffset = (sbyte)_memoryBus.Read((ushort)(currentPc + 1));
                        ushort destination = (ushort)(currentPc + 2 + jrOffset);
                        mnemonic = $"JR NZ, 0x{destination:X4}";
                        instructionLength = 2;
                        break;
                    case 0x21:
                        {
                            ushort hlImm = (ushort)(_memoryBus.Read((ushort)(currentPc + 1)) | (_memoryBus.Read((ushort)(currentPc + 2)) << 8));
                            mnemonic = $"LD HL, 0x{hlImm:X4}";
                            instructionLength = 3;
                            break;
                        }
                    case 0x22:
                        ushort hlAddr = (ushort)(_memoryBus.Read((ushort)(currentPc + 1)) | (_memoryBus.Read((ushort)(currentPc + 2)) << 8));
                        mnemonic = $"LD (0x{hlAddr:X4}), HL";
                        instructionLength = 3;
                        break;
                    case 0x23:
                        mnemonic = "INC HL";
                        break;
                    case 0x26:
                        byte hImm = _memoryBus.Read((ushort)(currentPc + 1));
                        mnemonic = $"LD H, 0x{hImm:X2}";
                        instructionLength = 2;
                        break;
                    case 0x27: // DAA
                        mnemonic = "DAA";
                        instructionLength = 1;
                        break;
                    case 0x28:
                        sbyte jrZOffset = (sbyte)_memoryBus.Read((ushort)(currentPc + 1));
                        ushort jrZDest = (ushort)(currentPc + 2 + jrZOffset);
                        mnemonic = $"JR Z, 0x{jrZDest:X4}";
                        instructionLength = 2;
                        break;
                    case 0x2A:
                        {
                            ushort addr2A = (ushort)(_memoryBus.Read((ushort)(currentPc + 1)) | (_memoryBus.Read((ushort)(currentPc + 2)) << 8));
                            mnemonic = $"LD HL, (0x{addr2A:X4})";
                            instructionLength = 3;
                            break;
                        }
                    case 0x2B:
                        mnemonic = "DEC HL";
                        break;
                    case 0x2E:
                        byte lImm = _memoryBus.Read((ushort)(currentPc + 1));
                        mnemonic = $"LD L, 0x{lImm:X2}";
                        instructionLength = 2;
                        break;
                    case 0x2F:
                        mnemonic = "CPL";
                        break;
                    case 0x30:
                        sbyte jrNcOffset = (sbyte)_memoryBus.Read((ushort)(currentPc + 1));
                        ushort dest = (ushort)(currentPc + 2 + jrNcOffset);
                        mnemonic = $"JR NC, 0x{dest:X4}";
                        instructionLength = 2;
                        break;
                    case 0x31:
                        mnemonic = "LD SP, nn";
                        instructionLength = 3;
                        break;
                    case 0x32:
                        {
                            ushort addr32 = (ushort)(_memoryBus.Read((ushort)(currentPc + 1)) | (_memoryBus.Read((ushort)(currentPc + 2)) << 8));
                            mnemonic = $"LD (0x{addr32:X4}), A";
                            instructionLength = 3;
                            break;
                        }
                    case 0x36:
                        byte memValue = _memoryBus.Read((ushort)(currentPc + 1));
                        mnemonic = $"LD (HL), 0x{memValue:X2}";
                        instructionLength = 2;
                        break;
                    case 0x37:
                        mnemonic = "SCF";
                        break;
                    case 0x38:
                        sbyte dC = (sbyte)_memoryBus.Read((ushort)(currentPc + 1));
                        ushort targetC = (ushort)(currentPc + 2 + dC);

                        mnemonic = $"JR C, 0x{targetC:X4}";
                        instructionLength = 2;
                        break;
                    case 0x3A:
                        ushort addr3A = (ushort)(_memoryBus.Read((ushort)(currentPc + 1)) | (_memoryBus.Read((ushort)(currentPc + 2)) << 8));
                        mnemonic = $"LD A, (0x{addr3A:X4})";
                        instructionLength = 3;
                        break;
                    case 0x3E:
                        mnemonic = $"LD A, 0x{_memoryBus.Read((ushort)(currentPc + 1)):X2}";
                        instructionLength = 2;
                        break;
                    case 0x3F:
                        mnemonic = "CCF";
                        break;
                    // --- LD B, r ---
                    case 0x40: mnemonic = "LD B, B"; break;
                    case 0x41: mnemonic = "LD B, C"; break;
                    case 0x42: mnemonic = "LD B, D"; break;
                    case 0x43: mnemonic = "LD B, E"; break;
                    case 0x44: mnemonic = "LD B, H"; break;
                    case 0x45: mnemonic = "LD B, L"; break;
                    case 0x46: mnemonic = "LD B, (HL)"; break;
                    case 0x47: mnemonic = "LD B, A"; break;

                    // --- LD C, r ---
                    case 0x48: mnemonic = "LD C, B"; break;
                    case 0x49: mnemonic = "LD C, C"; break;
                    case 0x4A: mnemonic = "LD C, D"; break;
                    case 0x4B: mnemonic = "LD C, E"; break;
                    case 0x4C: mnemonic = "LD C, H"; break;
                    case 0x4D: mnemonic = "LD C, L"; break;
                    case 0x4E: mnemonic = "LD C, (HL)"; break;
                    case 0x4F: mnemonic = "LD C, A"; break;

                    // --- LD D, r ---
                    case 0x50: mnemonic = "LD D, B"; break;
                    case 0x51: mnemonic = "LD D, C"; break;
                    case 0x52: mnemonic = "LD D, D"; break;
                    case 0x53: mnemonic = "LD D, E"; break;
                    case 0x54: mnemonic = "LD D, H"; break;
                    case 0x55: mnemonic = "LD D, L"; break;
                    case 0x56: mnemonic = "LD D, (HL)"; break;
                    case 0x57: mnemonic = "LD D, A"; break;

                    // --- LD E, r ---
                    case 0x58: mnemonic = "LD E, B"; break;
                    case 0x59: mnemonic = "LD E, C"; break;
                    case 0x5A: mnemonic = "LD E, D"; break;
                    case 0x5B: mnemonic = "LD E, E"; break;
                    case 0x5C: mnemonic = "LD E, H"; break;
                    case 0x5D: mnemonic = "LD E, L"; break;
                    case 0x5E: mnemonic = "LD E, (HL)"; break;
                    case 0x5F: mnemonic = "LD E, A"; break;

                    // --- LD H, r ---
                    case 0x60: mnemonic = "LD H, B"; break;
                    case 0x61: mnemonic = "LD H, C"; break;
                    case 0x62: mnemonic = "LD H, D"; break;
                    case 0x63: mnemonic = "LD H, E"; break;
                    case 0x64: mnemonic = "LD H, H"; break;
                    case 0x65: mnemonic = "LD H, L"; break;
                    case 0x66: mnemonic = "LD H, (HL)"; break;
                    case 0x67: mnemonic = "LD H, A"; break;

                    // --- LD L, r ---
                    case 0x68: mnemonic = "LD L, B"; break;
                    case 0x69: mnemonic = "LD L, C"; break;
                    case 0x6A: mnemonic = "LD L, D"; break;
                    case 0x6B: mnemonic = "LD L, E"; break;
                    case 0x6C: mnemonic = "LD L, H"; break;
                    case 0x6D: mnemonic = "LD L, L"; break;
                    case 0x6E: mnemonic = "LD L, (HL)"; break;
                    case 0x6F: mnemonic = "LD L, A"; break;

                    // --- LD (HL), r --- (Note: 0x76 is HALT, so it is skipped)
                    case 0x70: mnemonic = "LD (HL), B"; break;
                    case 0x71: mnemonic = "LD (HL), C"; break;
                    case 0x72: mnemonic = "LD (HL), D"; break;
                    case 0x73: mnemonic = "LD (HL), E"; break;
                    case 0x74: mnemonic = "LD (HL), H"; break;
                    case 0x75: mnemonic = "LD (HL), L"; break;
                    case 0x77: mnemonic = "LD (HL), A"; break;

                    // --- LD A, r ---
                    case 0x78: mnemonic = "LD A, B"; break;
                    case 0x79: mnemonic = "LD A, C"; break;
                    case 0x7A: mnemonic = "LD A, D"; break;
                    case 0x7B: mnemonic = "LD A, E"; break;
                    case 0x7C: mnemonic = "LD A, H"; break;
                    case 0x7D: mnemonic = "LD A, L"; break;
                    case 0x7E: mnemonic = "LD A, (HL)"; break;
                    case 0x7F: mnemonic = "LD A, A"; break;

                    // --- ADD A, r ---
                    case 0x80: mnemonic = "ADD A, B"; break;
                    case 0x81: mnemonic = "ADD A, C"; break;
                    case 0x82: mnemonic = "ADD A, D"; break;
                    case 0x83: mnemonic = "ADD A, E"; break;
                    case 0x84: mnemonic = "ADD A, H"; break;
                    case 0x85: mnemonic = "ADD A, L"; break;
                    case 0x86: mnemonic = "ADD A, (HL)"; break;
                    case 0x87: mnemonic = "ADD A, A"; break;
                    case 0x88:
                    case 0x89:
                    case 0x8A:
                    case 0x8B:
                    case 0x8C:
                    case 0x8D:
                    case 0x8E:
                    case 0x8F:
                        string[] registers = { "B", "C", "D", "E", "H", "L", "(HL)", "A" };
                        mnemonic = $"ADC A, {registers[opcode - 0x88]}";
                        instructionLength = 1;
                        break;
                    // --- SUB r ---
                    case 0x90: mnemonic = "SUB B"; break;
                    case 0x91: mnemonic = "SUB C"; break;
                    case 0x92: mnemonic = "SUB D"; break;
                    case 0x93: mnemonic = "SUB E"; break;
                    case 0x94: mnemonic = "SUB H"; break;
                    case 0x95: mnemonic = "SUB L"; break;
                    case 0x96: mnemonic = "SUB (HL)"; break;
                    case 0x97: mnemonic = "SUB A"; break;

                    // --- SBC A, r ---
                    case 0x98: mnemonic = "SBC A, B"; break;
                    case 0x99: mnemonic = "SBC A, C"; break;
                    case 0x9A: mnemonic = "SBC A, D"; break;
                    case 0x9B: mnemonic = "SBC A, E"; break;
                    case 0x9C: mnemonic = "SBC A, H"; break;
                    case 0x9D: mnemonic = "SBC A, L"; break;
                    case 0x9E: mnemonic = "SBC A, (HL)"; break;
                    case 0x9F: mnemonic = "SBC A, A"; break;

                    // --- AND r ---
                    case 0xA0: mnemonic = "AND B"; break;
                    case 0xA1: mnemonic = "AND C"; break;
                    case 0xA2: mnemonic = "AND D"; break;
                    case 0xA3: mnemonic = "AND E"; break;
                    case 0xA4: mnemonic = "AND H"; break;
                    case 0xA5: mnemonic = "AND L"; break;
                    case 0xA6: mnemonic = "AND (HL)"; break;
                    case 0xA7: mnemonic = "AND A"; break;

                    // --- XOR r ---
                    case 0xA8: mnemonic = "XOR B"; break;
                    case 0xA9: mnemonic = "XOR C"; break;
                    case 0xAA: mnemonic = "XOR D"; break;
                    case 0xAB: mnemonic = "XOR E"; break;
                    case 0xAC: mnemonic = "XOR H"; break;
                    case 0xAD: mnemonic = "XOR L"; break;
                    case 0xAE: mnemonic = "XOR (HL)"; break;
                    case 0xAF: mnemonic = "XOR A"; break;

                    // --- OR r ---
                    case 0xB0: mnemonic = "OR B"; break;
                    case 0xB1: mnemonic = "OR C"; break;
                    case 0xB2: mnemonic = "OR D"; break;
                    case 0xB3: mnemonic = "OR E"; break;
                    case 0xB4: mnemonic = "OR H"; break;
                    case 0xB5: mnemonic = "OR L"; break;
                    case 0xB6: mnemonic = "OR (HL)"; break;
                    case 0xB7: mnemonic = "OR A"; break;

                    // --- CP r ---
                    case 0xB8: mnemonic = "CP B"; break;
                    case 0xB9: mnemonic = "CP C"; break;
                    case 0xBA: mnemonic = "CP D"; break;
                    case 0xBB: mnemonic = "CP E"; break;
                    case 0xBC: mnemonic = "CP H"; break;
                    case 0xBD: mnemonic = "CP L"; break;
                    case 0xBE: mnemonic = "CP (HL)"; break;
                    case 0xBF: mnemonic = "CP A"; break;
                    case 0xC1: mnemonic = "POP BC"; break;
                    case 0xC2:
                    case 0xCA:
                    case 0xD2:
                    case 0xDA:
                    case 0xE2:
                    case 0xEA:
                    case 0xF2:
                    case 0xFA:
                        {
                            // Read the 16-bit target address
                            ushort jumpAddr = (ushort)(_memoryBus.Read((ushort)(currentPc + 1)) | (_memoryBus.Read((ushort)(currentPc + 2)) << 8));
                            string condition = "";

                            switch (opcode)
                            {
                                case 0xC2: condition = "NZ"; break;
                                case 0xCA: condition = "Z"; break;
                                case 0xD2: condition = "NC"; break;
                                case 0xDA: condition = "C"; break;
                                case 0xE2: condition = "PO"; break;
                                case 0xEA: condition = "PE"; break;
                                case 0xF2: condition = "P"; break;
                                case 0xFA: condition = "M"; break;
                            }

                            mnemonic = $"JP {condition}, 0x{jumpAddr:X4}";
                            instructionLength = 3;
                            break;
                        }
                    // --- Conditional Returns ---
                    case 0xC0: mnemonic = "RET NZ"; break;
                    case 0xE0: mnemonic = "RET PO"; break;
                    case 0xE8: mnemonic = "RET PE"; break;
                    case 0xF0: mnemonic = "RET P"; break;
                    case 0xF8: mnemonic = "RET M"; break;
                    case 0xC3:
                        // JP nn
                        byte jpLow = _memoryBus.Read((ushort)(currentPc + 1));
                        byte jpHigh = _memoryBus.Read((ushort)(currentPc + 2));
                        mnemonic = $"JP 0x{jpHigh:X2}{jpLow:X2}";
                        instructionLength = 3;
                        break;
                    case 0xC4:
                    case 0xCC:
                    case 0xD4:
                    case 0xDC:
                    case 0xE4:
                    case 0xEC:
                    case 0xF4:
                    case 0xFC:
                        {
                            // Read the 16-bit target address
                            ushort callAddr = (ushort)(_memoryBus.Read((ushort)(currentPc + 1)) | (_memoryBus.Read((ushort)(currentPc + 2)) << 8));
                            string condition = "";

                            switch (opcode)
                            {
                                case 0xC4: condition = "NZ"; break;
                                case 0xCC: condition = "Z"; break;
                                case 0xD4: condition = "NC"; break;
                                case 0xDC: condition = "C"; break;
                                case 0xE4: condition = "PO"; break;
                                case 0xEC: condition = "PE"; break;
                                case 0xF4: condition = "P"; break;
                                case 0xFC: condition = "M"; break;
                            }

                            mnemonic = $"CALL {condition}, 0x{callAddr:X4}";
                            instructionLength = 3;
                            break;
                        }
                    case 0xc5:
                        mnemonic = "PUSH BC";
                        break;
                    case 0xC6:
                        {
                            byte addImm = _memoryBus.Read((ushort)(currentPc + 1));
                            mnemonic = $"ADD A, 0x{addImm:X2}";
                            instructionLength = 2;
                            break;
                        }
                    // --- RST Instructions ---
                    case 0xC7: mnemonic = "RST 00h"; break;
                    case 0xCF: mnemonic = "RST 08h"; break;
                    case 0xD7: mnemonic = "RST 10h"; break;
                    case 0xDF: mnemonic = "RST 18h"; break;
                    case 0xE7: mnemonic = "RST 20h"; break;
                    case 0xEF: mnemonic = "RST 28h"; break;
                    case 0xF7: mnemonic = "RST 30h"; break;
                    case 0xFF: mnemonic = "RST 38h"; break;
                    case 0xC8:
                        mnemonic = "RET Z";
                        break;
                    case 0xC9:
                        mnemonic = "RET";
                        break;
                    case 0x76:
                        mnemonic = "HALT!";
                        break;
                    case 0xCB:
                        cbOp = _memoryBus.Read((ushort)(currentPc + 1));

                        opGroup = cbOp >> 6;           // 00 = Shift, 01 = BIT, 10 = RES, 11 = SET
                        targetBit = (cbOp >> 3) & 0x07; // Extracts a number 0-7
                        regIdx = cbOp & 0x07;           // Extracts register index 0-7

                        // Map the 0-7 index directly to the Z80 register names
                        targetReg = regNames[regIdx];

                        if (opGroup == 0) // Shift/Rotate Group (0x00 to 0x3F)
                        {
                            string[] shiftNames = { "RLC", "RRC", "RL", "RR", "SLA", "SRA", "SLL", "SRL" };
                            string shiftOp = shiftNames[(cbOp >> 3) & 0x07];
                            mnemonic = $"{shiftOp} {targetReg}";
                        }
                        else if (opGroup == 1) // BIT Group (0x40 to 0x7F)
                        {
                            mnemonic = $"BIT {targetBit}, {targetReg}";
                        }
                        else if (opGroup == 2) // RES Group (0x80 to 0xBF)
                        {
                            mnemonic = $"RES {targetBit}, {targetReg}";
                        }
                        else if (opGroup == 3) // SET Group (0xC0 to 0xFF)
                        {
                            mnemonic = $"SET {targetBit}, {targetReg}";
                        }
                        else
                        {
                            mnemonic = $"CB UNKNOWN (CB {cbOp:X2})";
                        }
                        instructionLength = 2;
                        break;
                    case 0xCD:
                        ushort callDest = (ushort)(_memoryBus.Read((ushort)(currentPc + 1)) | (_memoryBus.Read((ushort)(currentPc + 2)) << 8));
                        mnemonic = $"CALL 0x{callDest:X4}";
                        instructionLength = 3;
                        break;
                    case 0xCE: // ADC A, n
                        byte n = _memoryBus.Read((ushort)(currentPc + 1));
                        mnemonic = $"ADC A, 0x{n:X2}";
                        instructionLength = 2;
                        break;
                    case 0xD0:
                        mnemonic = "RET NC";
                        break;
                    case 0xD1: mnemonic = "POP DE"; break;
                    case 0xD3:
                        byte outPort = _memoryBus.Read((ushort)(currentPc + 1));
                        mnemonic = $"OUT (0x{outPort:X2}), A";
                        instructionLength = 2;
                        break;
                    case 0xD9:
                        mnemonic = "EXX";
                        break;
                    case 0xd5:
                        mnemonic = "PUSH DE";
                        break;
                    case 0xD6:
                        byte subImm = _memoryBus.Read((ushort)(currentPc + 1));
                        mnemonic = $"SUB 0x{subImm:X2}";
                        instructionLength = 2;
                        break;
                    case 0xD8:
                        mnemonic = "RET C";
                        break;
                    case 0xDB: // IN A, (n)
                        n = _memoryBus.Read((ushort)(currentPc + 1));
                        mnemonic = $"IN A, (0x{n:X2})";
                        instructionLength = 2;
                        break;
                    case 0xDD:
                        {
                            byte ddOpcode = _memoryBus.Read((ushort)(currentPc + 1));
                            if (ddOpcode == 0x09) { mnemonic = "ADD IX, BC"; instructionLength = 2; }
                            else if (ddOpcode == 0x19) { mnemonic = "ADD IX, DE"; instructionLength = 2; }
                            else if (ddOpcode == 0x29) { mnemonic = "ADD IX, IX"; instructionLength = 2; }
                            else if (ddOpcode == 0x39) { mnemonic = "ADD IX, SP"; instructionLength = 2; }
                            else if (ddOpcode == 0x21) // LD IX, nn
                            {
                                ushort ixVal = (ushort)(_memoryBus.Read((ushort)(currentPc + 2)) | (_memoryBus.Read((ushort)(currentPc + 3)) << 8));
                                mnemonic = $"LD IX, 0x{ixVal:X4}";
                                instructionLength = 4;
                            }
                            else if (ddOpcode == 0x22) // LD (nn), IX
                            {
                                ushort nn = (ushort)(_memoryBus.Read((ushort)(currentPc + 2)) | (_memoryBus.Read((ushort)(currentPc + 3)) << 8));
                                mnemonic = $"LD (0x{nn:X4}), IX";
                                instructionLength = 4;
                            }
                            else if (ddOpcode == 0x23) // INC IX
                            {
                                mnemonic = "INC IX";
                                instructionLength = 2;
                            }
                            else if (ddOpcode == 0x24) // INC IXH
                            {
                                mnemonic = "INC IXH";
                                instructionLength = 2;
                            }
                            else if (ddOpcode == 0x25) // DEC IXH
                            {
                                mnemonic = "DEC IXH";
                                instructionLength = 2;
                            }
                            else if (ddOpcode == 0x26) // LD IXH, n
                            {
                                byte nValue = _memoryBus.Read((ushort)(currentPc + 2));
                                mnemonic = $"LD IXH, 0x{nValue:X2}";
                                instructionLength = 3;
                            }
                            else if (ddOpcode == 0x2A) // LD IX, (nn)
                            {
                                ushort nn = (ushort)(_memoryBus.Read((ushort)(currentPc + 2)) | (_memoryBus.Read((ushort)(currentPc + 3)) << 8));
                                mnemonic = $"LD IX, (0x{nn:X4})";
                                instructionLength = 4;
                            }
                            else if (ddOpcode == 0x2B) // DEC IX
                            {
                                mnemonic = "DEC IX";
                                instructionLength = 2;
                            }
                            else if (ddOpcode == 0x2D) // DEC IXL
                            {
                                mnemonic = "DEC IXL";
                                instructionLength = 2;
                            }
                            else if (ddOpcode == 0x2E) // LD IXL, n
                            {
                                byte nValue = _memoryBus.Read((ushort)(currentPc + 2));
                                mnemonic = $"LD IXL, 0x{nValue:X2}";
                                instructionLength = 3;
                            }
                            else if (ddOpcode == 0x34) // INC (IX+d)
                            {
                                sbyte offset = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = offset >= 0 ? "+" : "";
                                mnemonic = $"INC (IX{sign}{offset})";
                                instructionLength = 3;
                            }
                            else if (ddOpcode == 0x35) // DEC (IX+d)
                            {
                                sbyte offset = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = offset >= 0 ? "+" : "";
                                mnemonic = $"DEC (IX{sign}{offset})";
                                instructionLength = 3;
                            }
                            else if (ddOpcode == 0x36) // LD (IX+d), n
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                n = _memoryBus.Read((ushort)(currentPc + 3));

                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"LD (IX{sign}{d}), 0x{n:X2}";
                                instructionLength = 4;
                            }
                            else if (ddOpcode == 0x46) // LD B, (IX+d)
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"LD B, (IX{sign}{d})";
                                instructionLength = 3;
                            }
                            else if (ddOpcode == 0x4E) // LD C, (IX+d)
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"LD C, (IX{sign}{d})";
                                instructionLength = 3;
                            }
                            else if (ddOpcode == 0x56) // LD D, (IX+d)
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"LD D, (IX{sign}{d})";
                                instructionLength = 3;
                            }
                            else if (ddOpcode == 0x5E) // LD E, (IX+d)
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"LD E, (IX{sign}{d})";
                                instructionLength = 3;
                            }
                            else if (ddOpcode == 0x66) // LD H, (IX+d)
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"LD H, (IX{sign}{d})";
                                instructionLength = 3;
                            }
                            else if (ddOpcode == 0x67) // LD IXH, A
                            {
                                mnemonic = "LD IXH, A";
                                instructionLength = 2;
                            }
                            else if (ddOpcode == 0x68) // LD IXL, B
                            {
                                mnemonic = "LD IXL, B";
                                instructionLength = 2;
                            }
                            else if (ddOpcode == 0x69) // LD IXL, C
                            {
                                mnemonic = "LD IXL, C";
                                instructionLength = 2;
                            }
                            else if (ddOpcode == 0x6A) // LD IXL, D
                            {
                                mnemonic = "LD IXL, D";
                                instructionLength = 2;
                            }
                            else if (ddOpcode == 0x6E) // LD L, (IX+d)
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"LD L, (IX{sign}{d})";
                                instructionLength = 3;
                            }
                            else if (ddOpcode == 0x6F) // LD IXL, A
                            {
                                mnemonic = $"LD IXL, A)";
                                instructionLength = 2;
                            }
                            else if (ddOpcode == 0x71) // LD (IX+d), B
                            {
                                sbyte offset = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = offset >= 0 ? "+" : "";
                                mnemonic = $"LD (IX{sign}{offset}), B";
                                instructionLength = 3;
                            }
                            else if (ddOpcode == 0x71) // LD (IX+d), C
                            {
                                sbyte offset = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = offset >= 0 ? "+" : "";
                                mnemonic = $"LD (IX{sign}{offset}), C";
                                instructionLength = 3;
                            }
                            else if (ddOpcode == 0x72) // LD (IX+d), D
                            {
                                sbyte offset = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = offset >= 0 ? "+" : "";
                                mnemonic = $"LD (IX{sign}{offset}), D";
                                instructionLength = 3;
                            }
                            else if (ddOpcode == 0x73) // LD (IX+d), E
                            {
                                sbyte offset = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = offset >= 0 ? "+" : "";
                                mnemonic = $"LD (IX{sign}{offset}), E";
                                instructionLength = 3;
                            }
                            else if (ddOpcode == 0x74) // LD (IX+d), H
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"LD (IX{sign}{d}), H";
                                instructionLength = 3;
                            }
                            else if (ddOpcode == 0x75) // LD (IX+d), L
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"LD (IX{sign}{d}), L";
                                instructionLength = 3;
                            }
                            else if (ddOpcode == 0x77) // LD (IX+d), A
                            {
                                // Read the 3rd byte (the displacement)
                                sbyte offset = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));

                                // Format nicely with a + or - sign
                                string sign = offset >= 0 ? "+" : "";
                                mnemonic = $"LD (IX{sign}{offset}), A";

                                instructionLength = 3;
                            }
                            else if (ddOpcode == 0x7C) // LD A, IXH
                            {
                                mnemonic = "LD A, IXH";
                                instructionLength = 2;
                            }
                            else if (ddOpcode == 0x7E) // LD A, (IX+d)
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"LD A, (IX{sign}{d})";
                                instructionLength = 3;
                            }
                            else if (ddOpcode == 0x86)
                            {
                                sbyte offset = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = offset >= 0 ? "+" : "";
                                mnemonic = $"ADD A, (IX{sign}{offset})";
                                instructionLength = 3;
                            }
                            else if (ddOpcode == 0x96)
                            {
                                sbyte offset = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = offset >= 0 ? "+" : "";
                                mnemonic = $"SUB (IX{sign}{offset})";
                                instructionLength = 3;
                            }
                            else if (ddOpcode == 0xCB)
                            {
                                // DD CB instructions are 4 bytes long!
                                sbyte offset = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                cbOp = _memoryBus.Read((ushort)(currentPc + 3));

                                int operation = cbOp >> 6;
                                int bitIndex = (cbOp >> 3) & 0x07;
                                string sign = offset >= 0 ? "+" : "";

                                if (operation == 1) mnemonic = $"BIT {bitIndex}, (IX{sign}{offset})";
                                else mnemonic = $"DD CB (IX{sign}{offset}) {cbOp:X2}"; // Fallback

                                instructionLength = 4;
                            }
                            else if (ddOpcode == 0xBE) // CP (IX+d)
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"CP (IX{sign}{d})";
                                instructionLength = 3;
                            }
                            else if (ddOpcode == 0xE1) // POP IX
                            {
                                mnemonic = "POP IX";
                                instructionLength = 2;
                            }
                            else if (ddOpcode == 0xE5) // PUSH IX
                            {
                                mnemonic = "PUSH IX";
                                instructionLength = 2;
                            }
                            else if (ddOpcode == 0xE9) // JP (IX)
                            {
                                mnemonic = "JP (IX)";
                                instructionLength = 2;
                            }
                            else
                            {
                                mnemonic = $"DD PREFIX UNKNOWN (0x{ddOpcode:X2})";
                                instructionLength = 2; // Fallback to prevent UI freezing
                            }
                            break;
                        }
                    case 0xDE:
                        byte sbcValue = _memoryBus.Read((ushort)(currentPc + 1));
                        mnemonic = $"SBC A, 0x{sbcValue:X2}";
                        instructionLength = 2;
                        break;
                    case 0xE1: mnemonic = "POP HL"; break;
                    case 0xE3:
                        mnemonic = "EX (SP), HL";
                        break;
                    case 0xE5:
                        mnemonic = "PUSH HL";
                        break;
                    case 0xE6:
                        byte andImm = _memoryBus.Read((ushort)(currentPc + 1));
                        mnemonic = $"AND 0x{andImm:X2}";
                        instructionLength = 2;
                        break;
                    case 0xE9:
                        mnemonic = "JP (HL)";
                        break;
                    case 0xEB:
                        mnemonic = "EX DE, HL";
                        break;
                    case 0xED:
                        byte extendedOp = _memoryBus.Read((ushort)(currentPc + 1));

                        switch (extendedOp)
                        {
                            case 0x42: mnemonic = "SBC HL, BC"; instructionLength = 2; break;
                            case 0x43:
                                ushort bcAddr = (ushort)(_memoryBus.Read((ushort)(currentPc + 2)) | (_memoryBus.Read((ushort)(currentPc + 3)) << 8));
                                mnemonic = $"LD (0x{bcAddr:X4}), BC";
                                instructionLength = 4;
                                break;
                            case 0x44: // NEG
                                mnemonic = "NEG";
                                instructionLength = 2;
                                break;
                            case 0x47:
                                mnemonic = "LD I, A";
                                instructionLength = 2; // 0xED + 0x47
                                break;
                            // Inside your ED prefix switch statement in the debugger:
                            case 0x4A: mnemonic = "ADC HL, BC"; instructionLength = 2; break;
                            case 0x4B:
                                ushort addr4B = (ushort)(_memoryBus.Read((ushort)(currentPc + 2)) | (_memoryBus.Read((ushort)(currentPc + 3)) << 8));
                                mnemonic = $"LD BC, (0x{addr4B:X4})";
                                instructionLength = 4;
                                break;
                            case 0x4D:
                                mnemonic = "RETI";
                                instructionLength = 2;
                                break;
                            case 0x52:
                                mnemonic = "SBC HL, DE";
                                instructionLength = 2; // ED 52
                                break;
                            case 0x53:
                                ushort deAddr = (ushort)(_memoryBus.Read((ushort)(currentPc + 2)) | (_memoryBus.Read((ushort)(currentPc + 3)) << 8));
                                mnemonic = $"LD (0x{deAddr:X4}), DE";
                                instructionLength = 4;
                                break;
                            case 0x56:
                                mnemonic = "IM 1";
                                instructionLength = 2;
                                break;
                            case 0x58:
                                mnemonic = "IN E, (C)";
                                instructionLength = 2;
                                break;
                            case 0x5A: mnemonic = "ADC HL, DE"; instructionLength = 2; break;
                            case 0x5B:
                                ushort addr5B = (ushort)(_memoryBus.Read((ushort)(currentPc + 2)) | (_memoryBus.Read((ushort)(currentPc + 3)) << 8));
                                mnemonic = $"LD DE, (0x{addr5B:X4})";
                                instructionLength = 4;
                                break;
                            case 0x5E: mnemonic = "IM 2"; instructionLength = 2; break;
                            case 0x5F: mnemonic = "LD A, R"; instructionLength = 2; break;
                            case 0x6A: mnemonic = "ADC HL, HL"; instructionLength = 2; break;
                            case 0x62: mnemonic = "SBC HL, HL"; instructionLength = 2; break;
                            case 0x73:
                                ushort addr73 = (ushort)(_memoryBus.Read((ushort)(currentPc + 2)) | (_memoryBus.Read((ushort)(currentPc + 3)) << 8));
                                mnemonic = $"LD (0x{addr73:X4}), SP";
                                instructionLength = 4;
                                break;
                            case 0x72: // SBC HL, SP
                                mnemonic = "SBC HL, SP";
                                instructionLength = 2;
                                break;
                            case 0x78:
                                mnemonic = "IN A, (C)";
                                instructionLength = 2;
                                break;
                            case 0x7A: mnemonic = "ADC HL, SP"; instructionLength = 2; break;
                            case 0x7B: // LD SP, (nn)
                                ushort nn = (ushort)(_memoryBus.Read((ushort)(currentPc + 2)) | (_memoryBus.Read((ushort)(currentPc + 3)) << 8));
                                mnemonic = $"LD SP, (0x{nn:X4})";
                                instructionLength = 4;
                                break;
                            case 0xA0: mnemonic = "LDI"; instructionLength = 2; break;
                            case 0xB0:
                                mnemonic = "LDIR";
                                instructionLength = 2;
                                break;
                            case 0xB1:
                                mnemonic = "CPIR";
                                instructionLength = 2;
                                break;
                            case 0xB8:
                                mnemonic = "LDDR";
                                instructionLength = 2;
                                break;

                            default:
                                mnemonic = $"EXT UNKNOWN (ED {extendedOp:X2})";
                                instructionLength = 2; // Most ED instructions are 2 bytes, but some have operands!
                                break;
                        }
                        break;
                    case 0xEE:
                        byte xorVal = _memoryBus.Read((ushort)(currentPc + 1));
                        mnemonic = $"XOR 0x{xorVal:X2}";
                        instructionLength = 2;
                        break;
                    case 0xF1: mnemonic = "POP AF"; break;
                    case 0xF3:
                        mnemonic = "DI";
                        break;
                    case 0xf5:
                        mnemonic = "PUSH AF";
                        break;
                    case 0xF6:
                        byte orImm = _memoryBus.Read((ushort)(currentPc + 1));
                        mnemonic = $"OR 0x{orImm:X2}";
                        instructionLength = 2;
                        break;
                    case 0xF9:
                        mnemonic = "LD SP, HL";
                        break;
                    case 0xFB:
                        mnemonic = "EI";
                        break;
                    case 0xFD:
                        {
                            byte fdOpcode = _memoryBus.Read((ushort)(currentPc + 1));
                            if (fdOpcode == 0x09) // ADD IY, BC
                            {
                                mnemonic = $"ADD IY, BC";
                                instructionLength = 2;
                            }
                            else if (fdOpcode == 0x19) // ADD IY, DE
                            {
                                mnemonic = $"ADD IY, DE";
                                instructionLength = 2;
                            }
                            else if (fdOpcode == 0x21) // LD IY, nn
                            {
                                ushort iyVal = (ushort)(_memoryBus.Read((ushort)(currentPc + 2)) | (_memoryBus.Read((ushort)(currentPc + 3)) << 8));
                                mnemonic = $"LD IY, 0x{iyVal:X4}";
                                instructionLength = 4;
                            }
                            else if (fdOpcode == 0x29) //Add IY, IY
                            {
                                mnemonic = $"ADD IY, IY";
                                instructionLength = 2;
                            }
                            else if (fdOpcode == 0x34) // INC IY
                            {
                                //sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                //string sign = d >= 0 ? "+" : "";
                                mnemonic = $"INC IY";
                                instructionLength = 2;
                            }
                            else if (fdOpcode == 0x34) // INC (IY+d)
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"INC (IY{sign}{d})";
                                instructionLength = 3;
                            }
                            else if (fdOpcode == 0x35) // DEC (IY+d)
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : ""; // Gives us a clean + or - 
                                mnemonic = $"DEC (IY{sign}{d})";
                                instructionLength = 3;
                            }
                            else if (fdOpcode == 0x36) // LD (IY+d), n
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                n = _memoryBus.Read((ushort)(currentPc + 3));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"LD (IY{sign}{d}), 0x{n:X2}";
                                instructionLength = 4;
                            }
                            else if (fdOpcode == 0x46) // LD B, (IY+d)
                            {
                                sbyte dB = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string signB = dB >= 0 ? "+" : "";

                                mnemonic = $"LD B, (IY{signB}{dB})";
                                instructionLength = 3;
                            }
                            else if (fdOpcode == 0x4E) // LD C, (IY+d)
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"LD C, (IY{sign}{d})";
                                instructionLength = 3;
                            }
                            else if (fdOpcode == 0x56) // LD D, (IY+d)
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"LD D, (IY{sign}{d})";
                                instructionLength = 3;
                            }
                            else if (fdOpcode == 0x5E) // LD E, (IY+d)
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"LD E, (IY{sign}{d})";
                                instructionLength = 3;
                            }
                            else if (fdOpcode == 0x66)
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"LD H, (IY{sign}{d})";
                                instructionLength = 3;
                            }
                            else if (fdOpcode == 0x6E)
                            {
                                sbyte offsetL = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string signL = offsetL >= 0 ? "+" : "";

                                mnemonic = $"LD L, (IY{signL}{offsetL})";
                                instructionLength = 3;
                            }
                            else if (fdOpcode == 0x72) // LD (IY+d), D
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"LD (IY{sign}{d}), D";
                                instructionLength = 3;
                            }
                            else if (fdOpcode == 0x73) // LD (IY+d), E
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"LD (IY{sign}{d}), E";
                                instructionLength = 3;
                            }
                            else if (fdOpcode == 0x74) // LD (IY+d), H
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"LD (IY{sign}{d}), H";
                                instructionLength = 3;
                            }
                            else if (fdOpcode == 0x77) // LD (IY+d), A
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"LD (IY{sign}{d}), A";
                                instructionLength = 3;
                            }
                            else if (fdOpcode == 0x7E) // LD A, (IY+d)
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"LD A, (IY{sign}{d})";
                                instructionLength = 3;
                            }
                            else if (fdOpcode == 0x84) // ADD A, IYH
                            {

                                mnemonic = $"ADD A, IYH";
                                instructionLength = 2;
                            }
                            else if (fdOpcode == 0x85) // ADD A, IYL
                            {
                                mnemonic = $"ADD A, IYL";
                                instructionLength = 2;
                            }
                            else if (fdOpcode == 0x86) // ADD A, (IY+d)
                            {
                                sbyte dAdd = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string signAdd = dAdd >= 0 ? "+" : "";

                                mnemonic = $"ADD A, (IY{signAdd}{dAdd})";
                                instructionLength = 3;
                            }
                            else if (fdOpcode == 0x96) // SUB (IY+d)
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"SUB (IY{sign}{d})";
                                instructionLength = 3;
                            }
                            else if (fdOpcode == 0xA6) //AND (IY+d)
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"AND (IY{sign}{d})";
                                instructionLength = 3;
                            }
                            else if (fdOpcode == 0xCB) // FD CB prefix
                            {
                                cbOp = _memoryBus.Read((ushort)(currentPc + 1));

                                opGroup = cbOp >> 6;
                                targetBit = (cbOp >> 3) & 0x07;
                                regIdx = cbOp & 0x07;

                                targetReg = regNames[regIdx];

                                if (opGroup == 1) mnemonic = $"BIT {targetBit}, {targetReg}";
                                else if (opGroup == 2) mnemonic = $"RES {targetBit}, {targetReg}";
                                else if (opGroup == 3) mnemonic = $"SET {targetBit}, {targetReg}";
                                else mnemonic = $"CB SHIFT/ROTATE (0x{cbOp:X2})";

                                instructionLength = 2;
                            }
                            else if (fdOpcode == 0x71) // LD (IY+d), C
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"LD (IY{sign}{d}), C";
                                instructionLength = 3;
                            }
                            else if (fdOpcode == 0x75) // LD (IY+d), L
                            {
                                sbyte d = (sbyte)_memoryBus.Read((ushort)(currentPc + 2));
                                string sign = d >= 0 ? "+" : "";
                                mnemonic = $"LD (IY{sign}{d}), L";
                                instructionLength = 3;
                            }
                            else if (fdOpcode == 0xE1)
                            {
                                mnemonic = "POP IY";
                                instructionLength = 2;
                            }
                            else if (fdOpcode == 0xE5)
                            {
                                mnemonic = "PUSH IY";
                                instructionLength = 2;
                            }
                            else
                            {
                                mnemonic = $"FD PREFIX UNKNOWN (0x{fdOpcode:X2})";
                                instructionLength = 2; // Fallback so we don't freeze the UI
                            }
                            break;
                        }
                    case 0xFE:
                        byte cpImm = _memoryBus.Read((ushort)(currentPc + 1));
                        mnemonic = $"CP 0x{cpImm:X2}";
                        instructionLength = 2;
                        break;
                    default:
                        mnemonic = $"UNKNOWN (0x{opcode:X2})";
                        break;
                }

                lstDisassembly.Items.Add($"{currentPc:X4}: {mnemonic}");

                // Advance the fake PC just for drawing the next line in the UI
                currentPc += (ushort)instructionLength;
            }
        }
    }
}