Exemplo n.º 1
0
        public void Unload()
        {
            //x86.Unmap_Print = unloadPrint;

            for (int i = 0; i < CodePages.Keys.Count && i < CodePages.Values.Count; i++)
            {
#if MEMLAYOUT_TRACE
                BasicConsole.WriteLine("Unloading code page...");
#endif

                //if (unloadPrint)
                //{
                //    BasicConsole.WriteLine("Unloading code page");
                //}

                //TODO: Revert to the following line of code and then work out why it results in so many page faults
                //          VirtMemManager.Unmap(CodePages.Keys[i], UpdateUsedPagesFlags.Virtual);
                //      Also see the similar line further down
                VirtMemManager.Unmap(CodePages.Keys[i], UpdateUsedPagesFlags.None);
            }
            for (int i = 0; i < DataPages.Keys.Count && i < DataPages.Values.Count; i++)
            {
#if MEMLAYOUT_TRACE
                BasicConsole.WriteLine("Unloading data page...");
#endif

                //if (unloadPrint)
                //{
                //    FOS_System.String str = "Unloading data page 0x--------";
                //    ExceptionMethods.FillString(DataPages.Keys[i], 29, str);
                //    BasicConsole.WriteLine(str);
                //}

                //TODO: Revert line - see above
                VirtMemManager.Unmap(DataPages.Keys[i], UpdateUsedPagesFlags.None);

                //if (unloadPrint)
                //{
                //    BasicConsole.WriteLine(" > Done.");
                //}
            }

            //if (unloadPrint)
            //{
            //    BasicConsole.WriteLine("Unload complete.");
            //}

            //x86.Unmap_Print = false;
        }
Exemplo n.º 2
0
        protected ushort MapPort(uint portOffset)
        {
            uint portAddr = (uint)(usbBaseAddress + portOffset);

            if ((portAddr & 0xFFFFF000) !=
                ((uint)usbBaseAddress & 0xFFFFF000))
            {
                Processes.ProcessManager.CurrentProcess.TheMemoryLayout.AddDataPage(
                    portAddr & 0xFFFFF000,
                    portAddr & 0xFFFFF000);
                VirtMemManager.Map(portAddr & 0xFFFFF000, portAddr & 0xFFFFF000, 4096,
                                   VirtMem.VirtMemImpl.PageFlags.KernelOnly);
            }

            return((ushort)portAddr);
        }
Exemplo n.º 3
0
        protected void CreateQH(UHCI_QueueHead_Struct *head, uint horizPtr, UHCI_qTD_Struct *firstTD)
        {
#if UHCI_TRACE
            BasicConsole.WriteLine("UHCI: Create QH");
            BasicConsole.DelayOutput(5);
#endif

            head->next = (UHCI_QueueHead_Struct *)UHCI_Consts.BIT_T; // (paging_getPhysAddr((void*)horizPtr) & 0xFFFFFFF0) | BIT_QH;

            if (firstTD == null)
            {
                head->transfer = (UHCI_qTD_Struct *)UHCI_Consts.BIT_T;
            }
            else
            {
                head->transfer = (UHCI_qTD_Struct *)((uint)VirtMemManager.GetPhysicalAddress(firstTD) & 0xFFFFFFF0);
                head->q_first  = firstTD;
            }
        }
Exemplo n.º 4
0
        public void Load(bool ProcessIsUM)
        {
            VirtMemImpl.PageFlags flags = ProcessIsUM ? VirtMemImpl.PageFlags.None : VirtMemImpl.PageFlags.KernelOnly;
            for (int i = 0; i < CodePages.Keys.Count; i++)
            {
                uint vAddr = CodePages.Keys[i];
                uint pAddr = CodePages[vAddr];

#if MEMLAYOUT_TRACE
                BasicConsole.WriteLine("Loading code page...");
#endif
                //if (loadPrint)
                //{
                //    BasicConsole.WriteLine(((FOS_System.String)"Loading code page v->p: ") + vAddr + " -> " + pAddr);
                //}
                VirtMemManager.Map(pAddr, vAddr, 4096, flags, UpdateUsedPagesFlags.Virtual);
            }

            flags = ProcessIsUM ? VirtMemImpl.PageFlags.None : VirtMemImpl.PageFlags.KernelOnly;
            for (int i = 0; i < DataPages.Keys.Count; i++)
            {
                uint vAddr = DataPages.Keys[i];
                uint pAddr = DataPages[vAddr];

#if MEMLAYOUT_TRACE
                BasicConsole.WriteLine("Loading data page...");
#endif

                //if (loadPrint)
                //{
                //    BasicConsole.WriteLine(((FOS_System.String)"Loading data page v->p: ") + vAddr + " -> " + pAddr);
                //}

                VirtMemManager.Map(pAddr, vAddr, 4096, flags, UpdateUsedPagesFlags.Virtual);
            }

            //if (loadPrint)
            //{
            //    //BasicConsole.DelayOutput(1);
            //    loadPrint = false;
            //}
        }
Exemplo n.º 5
0
        protected override void _INTransaction(USBTransfer transfer, USBTransaction uTransaction, bool toggle, void *buffer, ushort length)
        {
#if UHCI_TRACE
            BasicConsole.WriteLine("UHCI: IN Transaction");
            BasicConsole.DelayOutput(5);
#endif

            UHCITransaction uT = new UHCITransaction();
            uTransaction.underlyingTz = uT;
            uT.inBuffer = buffer;
            uT.inLength = length;

            uT.qTD       = CreateQTD_IO((UHCI_QueueHead_Struct *)transfer.underlyingTransferData, (uint *)1, UHCI_Consts.TD_IN, toggle, length, transfer.device.address, transfer.endpoint, transfer.packetSize);
            uT.qTDBuffer = uT.qTD->virtBuffer;

            if (transfer.transactions.Count > 0)
            {
                UHCITransaction uLastTransaction = (UHCITransaction)((USBTransaction)(transfer.transactions[transfer.transactions.Count - 1])).underlyingTz;
                uLastTransaction.qTD->next   = (((uint)VirtMemManager.GetPhysicalAddress(uT.qTD) & 0xFFFFFFF0) | UHCI_Consts.BIT_Vf); // build TD queue
                uLastTransaction.qTD->q_next = uT.qTD;
            }
        }
Exemplo n.º 6
0
        protected override void _SETUPTransaction(USBTransfer transfer, USBTransaction uTransaction, bool toggle, ushort tokenBytes, byte type, byte req, byte hiVal, byte loVal, ushort index, ushort length)
        {
#if UHCI_TRACE
            BasicConsole.WriteLine("UHCI: SETUP Transaction");
            BasicConsole.DelayOutput(5);
#endif

            UHCITransaction uT = new UHCITransaction();
            uTransaction.underlyingTz = uT;
            uT.inBuffer = null;
            uT.inLength = 0;

            uT.qTD       = CreateQTD_SETUP((UHCI_QueueHead_Struct *)transfer.underlyingTransferData, (uint *)1, toggle, tokenBytes, type, req, hiVal, loVal, index, length, transfer.device.address, transfer.endpoint, transfer.packetSize);
            uT.qTDBuffer = uT.qTD->virtBuffer;

            if (transfer.transactions.Count > 0)
            {
                UHCITransaction uLastTransaction = (UHCITransaction)((USBTransaction)(transfer.transactions[transfer.transactions.Count - 1])).underlyingTz;
                uLastTransaction.qTD->next   = (((uint)VirtMemManager.GetPhysicalAddress(uT.qTD) & 0xFFFFFFF0) | UHCI_Consts.BIT_Vf); // build TD queue
                uLastTransaction.qTD->q_next = uT.qTD;
            }
        }
Exemplo n.º 7
0
 /// <summary>
 /// Initialises virtual memory for the x86.
 /// </summary>
 static x86()
 {
     VirtMemManager.Init(new x86());
 }
Exemplo n.º 8
0
        protected override void _IssueTransfer(USBTransfer transfer)
        {
#if UHCI_TRACE
            BasicConsole.WriteLine("UHCI: Issue Transfer");
            BasicConsole.DelayOutput(5);
#endif

            UHCITransaction firstTransaction = (UHCITransaction)((USBTransaction)transfer.transactions[0]).underlyingTz;
            UHCITransaction lastTransaction  = (UHCITransaction)((USBTransaction)transfer.transactions[transfer.transactions.Count - 1]).underlyingTz;
            UHCI_qTD.SetIntOnComplete(lastTransaction.qTD, true);  // We want an interrupt after complete transfer
            CreateQH((UHCI_QueueHead_Struct *)transfer.underlyingTransferData, (uint)transfer.underlyingTransferData, firstTransaction.qTD);

#if UHCI_TRACE
            BasicConsole.WriteLine("    Queue head data:");
            BasicConsole.DumpMemory(transfer.underlyingTransferData, sizeof(UHCI_QueueHead_Struct));
            BasicConsole.WriteLine("    Transactions data:");
            for (int i = 0; i < transfer.transactions.Count; i++)
            {
                BasicConsole.Write(" ");
                BasicConsole.Write(i);
                BasicConsole.WriteLine(" : ");
                BasicConsole.WriteLine("  - qTD:");
                BasicConsole.DumpMemory(
                    ((UHCITransaction)((USBTransaction)transfer.transactions[i]).underlyingTz).qTD, sizeof(UHCI_qTD_Struct));
                BasicConsole.WriteLine("  - qTDBuffer:");
                BasicConsole.DumpMemory(
                    ((UHCITransaction)((USBTransaction)transfer.transactions[i]).underlyingTz).qTDBuffer, 16);
            }
            BasicConsole.DelayOutput(60);

            BasicConsole.WriteLine("UHCI: Issuing transfer...");
#endif

            for (byte i = 0; i < UHCI_Consts.NUMBER_OF_UHCI_RETRIES && !transfer.success; i++)
            {
                TransactionsCompleted = 0;
                for (int j = 0; j < transfer.transactions.Count; j++)
                {
                    USBTransaction  elem = (USBTransaction)transfer.transactions[j];
                    UHCITransaction uT   = (UHCITransaction)(elem.underlyingTz);
                    uT.qTD->u1 = uT.qTD->u1 & 0xFF00FFFF;
                    UHCI_qTD.SetActive(uT.qTD, true);
                }

                // stop scheduler
                USBSTS.Write_UInt16(UHCI_Consts.STS_MASK);
                USBCMD.Write_UInt16((ushort)(USBCMD.Read_UInt16() & ~UHCI_Consts.CMD_RS));
                while ((USBSTS.Read_UInt16() & UHCI_Consts.STS_HCHALTED) == 0)
                {
                    Hardware.Devices.Timer.Default.Wait(10);
                }

                // update scheduler
                uint qhPhysAddr = ((uint)VirtMemManager.GetPhysicalAddress(transfer.underlyingTransferData) | UHCI_Consts.BIT_QH);
                FrameList[0] = qhPhysAddr;
                FRBASEADD.Write_UInt32((uint)VirtMemManager.GetPhysicalAddress(FrameList));
                FRNUM.Write_UInt16(0);
                // start scheduler
                USBSTS.Write_UInt16(UHCI_Consts.STS_MASK);
                USBCMD.Write_UInt16((ushort)(USBCMD.Read_UInt16() | UHCI_Consts.CMD_RS));
                while ((USBSTS.Read_UInt16() & UHCI_Consts.STS_HCHALTED) != 0)
                {
                    Hardware.Devices.Timer.Default.Wait(10);
                }

#if UHCI_TRACE
                BasicConsole.WriteLine(((FOS_System.String) "USBINT val: ") + USBINTR.Read_UInt16());
#endif

                // run transactions
                bool active  = true;
                int  timeout = 100; //5 seconds
                while (active && timeout > 0)
                {
                    active = false;
                    for (int j = 0; j < transfer.transactions.Count; j++)
                    {
                        USBTransaction  elem = (USBTransaction)transfer.transactions[j];
                        UHCITransaction uT   = (UHCITransaction)(elem.underlyingTz);
                        active = active || ((uT.qTD->u1 & 0x00FF0000) == 0x00800000);
                    }

                    Hardware.Devices.Timer.Default.Wait(50);
                    timeout--;
                }

#if UHCI_TRACE
                BasicConsole.WriteLine("Finished waiting.");
#endif

                FrameList[0] = UHCI_Consts.BIT_T;

                if (timeout == 0 ||
                    TransactionsCompleted != transfer.transactions.Count)
                {
#if UHCI_TRACE
                    BasicConsole.SetTextColour(BasicConsole.error_colour);
                    BasicConsole.WriteLine("UHCI: Error! Transactions wait timed out or wrong number of transactions completed.");
                    BasicConsole.SetTextColour(BasicConsole.default_colour);

                    BasicConsole.WriteLine(((FOS_System.String) "Transactions completed: ") + TransactionsCompleted);

                    if (timeout == 0)
                    {
                        BasicConsole.SetTextColour(BasicConsole.error_colour);
                        BasicConsole.WriteLine("UHCI: Error! Transfer timed out.");
                        BasicConsole.SetTextColour(BasicConsole.default_colour);
                    }
#endif

                    transfer.success = false;

                    bool completeDespiteNoInterrupt = true;
                    for (int j = 0; j < transfer.transactions.Count; j++)
                    {
                        USBTransaction  elem = (USBTransaction)transfer.transactions[j];
                        UHCITransaction uT   = (UHCITransaction)(elem.underlyingTz);

#if UHCI_TRACE
                        BasicConsole.WriteLine(((FOS_System.String) "u1=") + uT.qTD->u1 + ", u2=" + uT.qTD->u2);
                        BasicConsole.WriteLine(((FOS_System.String) "Status=") + (byte)(uT.qTD->u1 >> 16));
#endif
                        completeDespiteNoInterrupt = completeDespiteNoInterrupt && isTransactionSuccessful(uT);
                    }

                    transfer.success = completeDespiteNoInterrupt;

#if UHCI_TRACE
                    BasicConsole.SetTextColour(BasicConsole.warning_colour);
                    BasicConsole.WriteLine(((FOS_System.String) "Complete despite no interrupts: ") + completeDespiteNoInterrupt);
                    BasicConsole.SetTextColour(BasicConsole.default_colour);

                    BasicConsole.DelayOutput(5);
#endif
                }
                else
                {
                    transfer.success = true;
                }

                if (transfer.success)
                {
                    // check conditions and save data
                    for (int j = 0; j < transfer.transactions.Count; j++)
                    {
                        USBTransaction  elem = (USBTransaction)transfer.transactions[j];
                        UHCITransaction uT   = (UHCITransaction)(elem.underlyingTz);
                        transfer.success = transfer.success && isTransactionSuccessful(uT); // executed w/o error

                        if (uT.inBuffer != null && uT.inLength != 0)
                        {
                            MemoryUtils.MemCpy_32((byte *)uT.inBuffer, (byte *)uT.qTDBuffer, uT.inLength);
                        }
                    }
                }

#if UHCI_TRACE
                if (!transfer.success)
                {
                    BasicConsole.SetTextColour(BasicConsole.error_colour);
                    BasicConsole.WriteLine("UHCI: Transfer failed.");
                    BasicConsole.SetTextColour(BasicConsole.default_colour);
                }
                else
                {
                    BasicConsole.SetTextColour((char)0x0200);
                    BasicConsole.WriteLine("Transfer succeeded.");
                    BasicConsole.SetTextColour(BasicConsole.default_colour);
                }
#endif
            }
        }
Exemplo n.º 9
0
        protected void ResetHC()
        {
#if UHCI_TRACE
            BasicConsole.WriteLine("UHCI: ResetHC");
            BasicConsole.DelayOutput(5);
#endif

            //Processes.Scheduler.Disable();

            // http://www.lowlevel.eu/wiki/Universal_Host_Controller_Interface#Informationen_vom_PCI-Treiber_holen

            ushort legacySupport = pciDevice.ReadRegister16(UHCI_Consts.PCI_LEGACY_SUPPORT);
            pciDevice.WriteRegister16(UHCI_Consts.PCI_LEGACY_SUPPORT, UHCI_Consts.PCI_LEGACY_SUPPORT_STATUS); // resets support status bits in Legacy support register

            USBCMD.Write_UInt16(UHCI_Consts.CMD_GRESET);
            Hardware.Devices.Timer.Default.Wait(50);
            USBCMD.Write_UInt16(0);

            RootPortCount = (byte)(pciDevice.BaseAddresses[4].Size() / 2);
#if UHCI_TRACE
            BasicConsole.WriteLine(((FOS_System.String) "UHCI: RootPortCount=") + RootPortCount);
#endif
            for (byte i = 2; i < RootPortCount; i++)
            {
                if ((PORTSC1.Read_UInt16((ushort)(i * 2)) & UHCI_Consts.PORT_VALID) == 0 ||
                    (PORTSC1.Read_UInt16((ushort)(i * 2)) == 0xFFFF))
                {
                    RootPortCount = i;
                    break;
                }
            }
#if UHCI_TRACE
            BasicConsole.WriteLine(((FOS_System.String) "UHCI: RootPortCount=") + RootPortCount);
#endif

            if (RootPortCount > UHCI_Consts.PORTMAX)
            {
                RootPortCount = UHCI_Consts.PORTMAX;
            }
#if UHCI_TRACE
            BasicConsole.WriteLine(((FOS_System.String) "UHCI: RootPortCount=") + RootPortCount);
            BasicConsole.DelayOutput(1);
#endif

            RootPorts.Empty();
            for (byte i = 0; i < RootPortCount; i++)
            {
                RootPorts.Add(new HCPort()
                {
                    portNum = i
                });
            }

#if UHCI_TRACE
            BasicConsole.WriteLine("UHCI: Checking HC state: Get USBCMD...");
            BasicConsole.DelayOutput(1);
#endif

            ushort usbcmd = USBCMD.Read_UInt16();
#if UHCI_TRACE
            BasicConsole.WriteLine("UHCI: Checking HC state: Check...");
            BasicConsole.DelayOutput(1);
#endif
            if ((legacySupport & ~(UHCI_Consts.PCI_LEGACY_SUPPORT_STATUS | UHCI_Consts.PCI_LEGACY_SUPPORT_NO_CHG | UHCI_Consts.PCI_LEGACY_SUPPORT_PIRQ)) != 0 ||
                (usbcmd & UHCI_Consts.CMD_RS) != 0 ||
                (usbcmd & UHCI_Consts.CMD_CF) != 0 ||
                (usbcmd & UHCI_Consts.CMD_EGSM) == 0 ||
                (USBINTR.Read_UInt16() & UHCI_Consts.INT_MASK) != 0)
            {
#if UHCI_TRACE
                BasicConsole.WriteLine("UHCI: Checking HC state: Do reset...");
                BasicConsole.DelayOutput(1);
#endif

                USBSTS.Write_UInt16(UHCI_Consts.STS_MASK);
                Hardware.Devices.Timer.Default.Wait(1);
                USBCMD.Write_UInt16(UHCI_Consts.CMD_HCRESET);

                byte timeout = 50;
                while ((USBCMD.Read_UInt16() & UHCI_Consts.CMD_HCRESET) != 0)
                {
                    if (timeout == 0)
                    {
#if UHCI_TRACE
                        BasicConsole.WriteLine("UHCI: HC Reset timed out!");
                        BasicConsole.DelayOutput(1);
#endif
                        break;
                    }
                    Hardware.Devices.Timer.Default.Wait(10);
                    timeout--;
                }

#if UHCI_TRACE
                BasicConsole.WriteLine("UHCI: Checking HC state: Turning off interrupts and HC...");
                BasicConsole.DelayOutput(1);
#endif

                USBINTR.Write_UInt16(0); // switch off all interrupts
                USBCMD.Write_UInt16(0);  // switch off the host controller

#if UHCI_TRACE
                BasicConsole.WriteLine("UHCI: Checking HC state: Disabling ports...");
                BasicConsole.DelayOutput(1);
#endif

                for (byte i = 0; i < RootPortCount; i++) // switch off the valid root ports
                {
                    PORTSC1.Write_UInt16(0, (ushort)(i * 2));
                }
            }

            // TODO: mutex for frame list

#if UHCI_TRACE
            BasicConsole.WriteLine("UHCI: Creating queue head...");
            BasicConsole.DelayOutput(1);
#endif

            UHCI_QueueHead_Struct *qh = (UHCI_QueueHead_Struct *)FOS_System.Heap.AllocZeroedAPB((uint)sizeof(UHCI_QueueHead_Struct), 32, "UHCI : ResetHC");
            qh->next     = (UHCI_QueueHead_Struct *)UHCI_Consts.BIT_T;
            qh->transfer = (UHCI_qTD_Struct *)UHCI_Consts.BIT_T;
            qh->q_first  = null;
            qh->q_last   = null;
            qhPointer    = qh;

#if UHCI_TRACE
            BasicConsole.WriteLine("UHCI: Setting up frame list entries...");
            BasicConsole.DelayOutput(1);
#endif

            for (ushort i = 0; i < 1024; i++)
            {
                FrameList[i] = UHCI_Consts.BIT_T;
            }

#if UHCI_TRACE
            BasicConsole.WriteLine("UHCI: Setting SOFMOD...");
            BasicConsole.DelayOutput(1);
#endif

            // define each millisecond one frame, provide physical address of frame list, and start at frame 0
            SOFMOD.Write_Byte(0x40); // SOF cycle time: 12000. For a 12 MHz SOF counter clock input, this produces a 1 ms Frame period.

#if UHCI_TRACE
            BasicConsole.WriteLine("UHCI: Setting frame base addr and frame num...");
            BasicConsole.DelayOutput(1);
#endif

            FRBASEADD.Write_UInt32((uint)VirtMemManager.GetPhysicalAddress(FrameList));
            FRNUM.Write_UInt16(0);

#if UHCI_TRACE
            BasicConsole.WriteLine("UHCI: Setting PCI PIRQ...");
            BasicConsole.DelayOutput(1);
#endif

            // set PIRQ
            pciDevice.WriteRegister16(UHCI_Consts.PCI_LEGACY_SUPPORT, UHCI_Consts.PCI_LEGACY_SUPPORT_PIRQ);

#if UHCI_TRACE
            BasicConsole.WriteLine("UHCI: Starting HC...");
            BasicConsole.DelayOutput(1);
#endif

            // start host controller and mark it configured with a 64-byte max packet
            USBSTS.Write_UInt16(UHCI_Consts.STS_MASK);
            USBINTR.Write_UInt16(UHCI_Consts.INT_MASK); // switch on all interrupts
            USBCMD.Write_UInt16((ushort)(UHCI_Consts.CMD_RS | UHCI_Consts.CMD_CF | UHCI_Consts.CMD_MAXP));

#if UHCI_TRACE
            BasicConsole.WriteLine("UHCI: Reset CSC ports...");
            BasicConsole.DelayOutput(1);
#endif

            for (byte i = 0; i < RootPortCount; i++) // reset the CSC of the valid root ports
            {
                PORTSC1.Write_UInt16(UHCI_Consts.PORT_CS_CHANGE, (ushort)(i * 2));
            }

#if UHCI_TRACE
            BasicConsole.WriteLine("UHCI: Forcing global resume...");
            BasicConsole.DelayOutput(1);
#endif

            USBSTS.Write_UInt16(UHCI_Consts.STS_MASK);
#if UHCI_TRACE
            BasicConsole.WriteLine("     - STS MASK set");
#endif
            USBCMD.Write_UInt16((ushort)(UHCI_Consts.CMD_RS | UHCI_Consts.CMD_CF | UHCI_Consts.CMD_MAXP | UHCI_Consts.CMD_FGR));
#if UHCI_TRACE
            BasicConsole.WriteLine("     - FGR issued");
#endif
            Hardware.Devices.Timer.Default.Wait(20);
            USBCMD.Write_UInt16((ushort)(UHCI_Consts.CMD_RS | UHCI_Consts.CMD_CF | UHCI_Consts.CMD_MAXP));
#if UHCI_TRACE
            BasicConsole.WriteLine("     - FGR cleared");
            BasicConsole.DelayOutput(1);
#endif

            Hardware.Devices.Timer.Default.Wait(100);

#if UHCI_TRACE
            BasicConsole.WriteLine("UHCI: Getting run state...");
            BasicConsole.DelayOutput(1);
#endif

            run = (USBCMD.Read_UInt16() & UHCI_Consts.CMD_RS) != 0;



            if (!run)
            {
                BasicConsole.SetTextColour(BasicConsole.error_colour);
                BasicConsole.WriteLine("UHCI: Run/Stop not set!");
                BasicConsole.SetTextColour(BasicConsole.default_colour);
                BasicConsole.DelayOutput(5);
            }
            else
            {
                if ((USBSTS.Read_UInt16() & UHCI_Consts.STS_HCHALTED) == 0)
                {
                    Status = HCIStatus.Active;

                    EnablePorts(); // attaches the ports
                }
                else
                {
                    BasicConsole.SetTextColour(BasicConsole.error_colour);
                    BasicConsole.WriteLine("UHCI: HC Halted!");
                    BasicConsole.SetTextColour(BasicConsole.default_colour);
                    BasicConsole.DelayOutput(5);
                }
            }
        }