예제 #1
0
 public static void onGeStartList(PspGeList list)
 {
     if (Available && DurationStatistics.collectStatistics)
     {
         NativeUtils.notifyEvent(NativeUtils.EVENT_GE_START_LIST);
     }
 }
예제 #2
0
 public static void onGeFinishList(PspGeList list)
 {
     if (Available && DurationStatistics.collectStatistics)
     {
         NativeUtils.notifyEvent(NativeUtils.EVENT_GE_FINISH_LIST);
     }
 }
예제 #3
0
        private static void addListToHead(PspGeList list)
        {
            lock (drawListQueue)
            {
                // The ConcurrentLinkedQueue type doesn't allow adding
                // objects directly at the head of the queue.

                // This function creates a new array using the given list as it's head
                // and constructs a new ConcurrentLinkedQueue based on it.
                // The actual drawListQueue is then replaced by this new one.
                int arraySize = drawListQueue.size();

                if (arraySize > 0)
                {
                    PspGeList[] array = drawListQueue.toArray(new PspGeList[arraySize]);

                    ConcurrentLinkedQueue <PspGeList> newQueue = new ConcurrentLinkedQueue <PspGeList>();
                    PspGeList[] newArray = new PspGeList[arraySize + 1];

                    newArray[0] = list;
                    for (int i = 0; i < arraySize; i++)
                    {
                        newArray[i + 1] = array[i];
                        newQueue.add(newArray[i]);
                    }

                    drawListQueue = newQueue;
                }
                else
                {                 // If the queue is empty.
                    drawListQueue.add(list);
                }
            }
        }
예제 #4
0
 public static void onGeUserStop()
 {
     lock (drawListQueue)
     {
         drawListQueue.clear();
         if (currentList != null)
         {
             currentList.sync();
         }
         currentList = null;
         CoreThread.Instance.sync();
     }
 }
예제 #5
0
        public virtual int sceGeListDeQueue(int id)
        {
            lock (this)
            {
                PspGeList list = allGeLists[id];
                list.reset();
                if (!listFreeQueue.contains(list))
                {
                    listFreeQueue.add(list);
                }
            }

            return(0);
        }
예제 #6
0
        private void executeCommandFINISH(PspGeList list)
        {
            //if (log.DebugEnabled)
            {
                Console.WriteLine(string.Format("FINISH {0}", list));
            }

            list.clearRestart();
            list.finishList();
            list.pushFinishCallback(list.id, NativeUtils.getCoreCmdArray(GeCommands.FINISH) & 0x00FFFFFF);
            list.endList();
            list.status = sceGe_user.PSP_GE_LIST_DONE;
            ExternalGE.finishList(list);
        }
예제 #7
0
        public static void startCapture(string filename, PspGeList list)
        {
            //public static void startCapture(int displayBufferAddress, int displayBufferWidth, int displayBufferPsm,
            //    int drawBufferAddress, int drawBufferWidth, int drawBufferPsm,
            //    int depthBufferAddress, int depthBufferWidth) {
            if (captureInProgress)
            {
                VideoEngine.log_Renamed.error("Ignoring startCapture, capture is already in progress");
                return;
            }

            // Set the VideoEngine log level to TRACE when capturing,
            // the information in the log file is also interesting
            logLevel = VideoEngine.log_Renamed.Level;
            VideoEngine.Instance.LogLevel = Level.TRACE;
            capturedImages = new HashSet <int>();

            try
            {
                VideoEngine.log_Renamed.info("Starting capture... (list=" + list.id + ")");
                @out = new BufferedOutputStream(new System.IO.FileStream(filename, System.IO.FileMode.Create, System.IO.FileAccess.Write));

                CaptureHeader header;

                /*
                 * // write render target details
                 * header = new CaptureHeader(CaptureHeader.PACKET_TYPE_DISPLAY_DETAILS);
                 * header.write(out);
                 * CaptureDisplayDetails displayDetails = new CaptureDisplayDetails();
                 * displayDetails.write(out);
                 */

                // write command buffer
                header = new CaptureHeader(CaptureHeader.PACKET_TYPE_LIST);
                header.write(@out);
                CaptureList commandList = new CaptureList(list);
                commandList.write(@out);

                captureInProgress = true;
                listExecuted      = false;
            }
            catch (Exception e)
            {
                VideoEngine.log_Renamed.error("Failed to start capture: " + e.Message);
                Console.WriteLine(e.ToString());
                Console.Write(e.StackTrace);
                Emulator.PauseEmu();
            }
        }
예제 #8
0
        public static void startList(PspGeList list)
        {
            if (list == null)
            {
                return;
            }

            lock (drawListQueue)
            {
                if (currentList == null)
                {
                    if (State.captureGeNextFrame)
                    {
                        State.captureGeNextFrame         = false;
                        CaptureManager.captureInProgress = true;
                        NativeUtils.DumpFrames           = true;
                        NativeUtils.DumpTextures         = true;
                        logLevel  = log.Level;
                        log.Level = Level.TRACE;
                    }

                    // Save the context at the beginning of the list processing to the given address (used by sceGu).
                    if (list.hasSaveContextAddr())
                    {
                        saveContext(list.SaveContextAddr);
                    }

                    list.status = sceGe_user.PSP_GE_LIST_DRAWING;
                    NativeUtils.setLogLevel();
                    NativeUtils.CoreSadr = list.StallAddr;
                    NativeUtils.setCoreCtrlActive();
                    lock (screenScaleLock)
                    {
                        // Update the screen scale only at the start of a new list
                        NativeUtils.ScreenScale = ScreenScale;
                    }
                    currentList = list;
                    currentList.sync();
                    CoreThread.Instance.sync();
                }
                else
                {
                    drawListQueue.add(list);
                }
            }
        }
예제 #9
0
        private void blockCurrentThreadOnList(PspGeList list, IAction action)
        {
            ThreadManForUser threadMan = Modules.ThreadManForUserModule;

            bool blockCurrentThread = false;
            bool executeAction      = false;

            lock (this)
            {
                int currentThreadId = threadMan.CurrentThreadID;
                if (list.Done)
                {
                    // There has been some race condition: the list has just completed
                    // do not block the thread
                    //if (log.DebugEnabled)
                    {
                        Console.WriteLine("blockCurrentThreadOnList not blocking thread " + currentThreadId.ToString("x") + ", list completed " + list);
                    }
                    executeAction = true;
                }
                else
                {
                    //if (log.DebugEnabled)
                    {
                        Console.WriteLine("blockCurrentThreadOnList blocking thread " + currentThreadId.ToString("x") + " on list " + list);
                    }
                    list.blockedThreadIds.Add(currentThreadId);
                    blockCurrentThread = true;
                }
            }

            // Execute the action outside of the synchronized block
            if (executeAction && action != null)
            {
                action.execute();
            }

            // Block the thread outside of the synchronized block
            if (blockCurrentThread)
            {
                // Block the thread, but do not execute callbacks.
                threadMan.hleBlockCurrentThread(SceKernelThreadInfo.JPCSP_WAIT_GE_LIST, list.id, false, action, new ListSyncWaitStateChecker(list));

                ExternalGE.onGeStartWaitList();
            }
        }
예제 #10
0
        public virtual int hleGeListSync(int id)
        {
            if (id < 0 || id >= NUMBER_GE_LISTS)
            {
                return(-1);
            }

            PspGeList list = null;
            int       result;

            lock (this)
            {
                list   = allGeLists[id];
                result = list.status;
            }

            return(result);
        }
예제 #11
0
        public virtual int sceGeListSync(int id, int mode)
        {
            if (mode == 0 && IntrManager.Instance.InsideInterrupt)
            {
                Console.WriteLine("sceGeListSync (mode==0) cannot be called inside an interrupt handler!");
                return(SceKernelErrors.ERROR_KERNEL_CANNOT_BE_CALLED_FROM_INTERRUPT);
            }

            PspGeList list = null;
            bool      blockCurrentThread = false;
            int       result;

            lock (this)
            {
                list = allGeLists[id];
                //if (log.DebugEnabled)
                {
                    Console.WriteLine(string.Format("sceGeListSync on list: {0}", list));
                }

                if (list.Reset)
                {
                    throw new SceKernelErrorException(SceKernelErrors.ERROR_INVALID_ID);
                }

                if (mode == 0 && !list.Done)
                {
                    result             = 0;
                    blockCurrentThread = true;
                }
                else
                {
                    result = list.SyncStatus;
                }
            }

            // Block the current thread outside of the synchronized block
            if (blockCurrentThread)
            {
                blockCurrentThreadOnList(list, null);
            }

            return(result);
        }
예제 #12
0
        private void setStallAddressWithCachedMemory(PspGeList list, int stallAddr)
        {
            int startAddress = list.list_addr;
            int Length;

            if (stallAddr != 0)
            {
                Length = stallAddr - startAddress;
            }
            else
            {
                // The list has no stall address, scan for the FINISH command
                IMemoryReader memoryReader = MemoryReader.getMemoryReader(startAddress, 4);
                Length = 0;
                while (true)
                {
                    int instruction = memoryReader.readNext();
                    int command     = VideoEngine.command(instruction);
                    if (command == GeCommands.FINISH)
                    {
                        // Add 4 to include the END command that follows the FINISH command
                        Length = memoryReader.CurrentAddress - startAddress + 4;
                        break;
                    }
                }
            }

            if (Length >= 0)
            {
                int[] baseMemoryInts = Utilities.readInt32(startAddress, Length);
                list.setStallAddr(stallAddr, MemoryReader.getMemoryReader(startAddress, baseMemoryInts, 0, Length), startAddress, startAddress + Length);

                //if (log.DebugEnabled)
                {
                    Console.WriteLine(string.Format("setStallAddressWithCachedMemory [0x{0:X8}-0x{1:X8}] {2}", startAddress, startAddress + Length, list));
                }
            }
            else
            {
                list.StallAddr = stallAddr;
            }
        }
예제 #13
0
        public virtual void hleGeOnAfterCallback(int listId, int behavior, bool hasCallback)
        {
            // (gid15) I could not make any difference between
            //    PSP_GE_BEHAVIOR_CONTINUE and PSP_GE_BEHAVIOR_SUSPEND
            // Both wait for the completion of the callback before continuing
            // the list processing...
            if (behavior == PSP_GE_SIGNAL_HANDLER_CONTINUE || behavior == PSP_GE_SIGNAL_HANDLER_SUSPEND || !hasCallback)
            {
                if (listId >= 0 && listId < NUMBER_GE_LISTS)
                {
                    PspGeList list = allGeLists[listId];
                    //if (log.DebugEnabled)
                    {
                        Console.WriteLine("hleGeOnAfterCallback restarting list " + list);
                    }

                    list.restartList();
                }
            }
        }
예제 #14
0
        /// <summary>
        /// Called from VideoEngine </summary>
        public virtual void hleGeListSyncDone(PspGeList list)
        {
            //if (log.DebugEnabled)
            {
                string msg = "hleGeListSyncDone list " + list;

                if (list.Done)
                {
                    msg += ", done";
                }
                else
                {
                    msg += ", NOT done";
                }

                if (list.blockedThreadIds.Count > 0 && list.status != PSP_GE_LIST_END_REACHED)
                {
                    msg += ", waking thread";
                    foreach (int threadId in list.blockedThreadIds)
                    {
                        msg += " " + threadId.ToString("x");
                    }
                }

                Console.WriteLine(msg);
            }

            lock (this)
            {
                if (list.blockedThreadIds.Count > 0 && list.status != PSP_GE_LIST_END_REACHED)
                {
                    // things might go wrong if the thread already exists in the queue
                    deferredThreadWakeupQueue.addAll(list.blockedThreadIds);
                }

                if (list.Done)
                {
                    listFreeQueue.add(list);
                }
            }
        }
예제 #15
0
        public virtual int sceGeListUpdateStallAddr(int id, TPointer stallAddr)
        {
            lock (this)
            {
                PspGeList list = allGeLists[id];
                if (list.StallAddr != stallAddr.Address)
                {
                    if (list.hasBaseMemoryReader())
                    {
                        setStallAddressWithCachedMemory(list, stallAddr.Address);
                    }
                    else
                    {
                        list.StallAddr = stallAddr.Address;
                    }
                    Modules.sceDisplayModule.GeDirty = true;
                }
            }

            return(0);
        }
예제 #16
0
        public static void onStallAddrUpdated(PspGeList list)
        {
            if (Available && DurationStatistics.collectStatistics)
            {
                NativeUtils.stopEvent(NativeUtils.EVENT_GE_UPDATE_STALL_ADDR);
            }

            if (Active)
            {
                if (list == null)
                {
                    return;
                }

                if (list == currentList)
                {
                    NativeUtils.CoreSadr = list.StallAddr;
                    CoreThread.Instance.sync();
                }
            }
        }
예제 #17
0
        public static void onRestartList(PspGeList list)
        {
            if (Active)
            {
                if (list == null || list.Finished)
                {
                    return;
                }

                lock (drawListQueue)
                {
                    if (list == currentList)
                    {
                        list.status = sceGe_user.PSP_GE_LIST_DRAWING;
                        NativeUtils.setCoreCtrlActive();
                        CoreThread.Instance.sync();
                        list.sync();
                    }
                }
            }
        }
예제 #18
0
        public static void startListHead(PspGeList list)
        {
            if (list == null)
            {
                return;
            }

            if (currentList == null)
            {
                startList(list);
                //		} else if (!currentList.isDrawing()) {
                //			if (!drawListQueue.contains(currentList)) {
                //				addListToHead(currentList);
                //			}
                //			currentList = null;
                //			startList(list);
            }
            else
            {
                addListToHead(list);
            }
        }
예제 #19
0
        public static void finishList(PspGeList list)
        {
            Modules.sceGe_userModule.hleGeListSyncDone(list);

            lock (drawListQueue)
            {
                if (list == currentList)
                {
                    if (CaptureManager.captureInProgress)
                    {
                        log.Level = logLevel;
                        NativeUtils.DumpFrames   = false;
                        NativeUtils.DumpTextures = false;
                        NativeUtils.setLogLevel();
                        CaptureManager.captureInProgress = false;
                        Emulator.PauseEmu();
                    }

                    // Restore the context to the state at the beginning of the list processing (used by sceGu).
                    if (list.hasSaveContextAddr())
                    {
                        restoreContext(list.SaveContextAddr);
                    }

                    currentList = null;
                }
                else
                {
                    drawListQueue.remove(list);
                }
            }

            if (currentList == null)
            {
                startList(drawListQueue.poll());
            }
        }
예제 #20
0
        public override void start()
        {
            Console.WriteLine(string.Format("Starting {0}", Name));

            waitingForSync = false;
            syncDone       = false;

            signalCallbacks = new Dictionary <int, SceKernelCallbackInfo>();
            finishCallbacks = new Dictionary <int, SceKernelCallbackInfo>();

            listFreeQueue = new ConcurrentLinkedQueue <PspGeList>();
            allGeLists    = new PspGeList[NUMBER_GE_LISTS];
            for (int i = 0; i < NUMBER_GE_LISTS; i++)
            {
                allGeLists[i] = new PspGeList(i);
                listFreeQueue.add(allGeLists[i]);
            }

            deferredThreadWakeupQueue = new ConcurrentLinkedQueue <int>();

            eDRAMMemoryWidth = 1024;

            base.start();
        }
예제 #21
0
        public override void run()
        {
            setLog4jMDC();
            bool doCoreInterpret = false;

            while (!exit_Renamed)
            {
                PspGeList list = ExternalGE.CurrentList;

                if (list == null)
                {
                    if (!Emulator.pause && log.DebugEnabled)
                    {
                        Console.WriteLine(string.Format("CoreThread no current list available... waiting"));
                    }

                    waitForSync(100);
                }
                else if (doCoreInterpret || list.waitForSync(100))
                {
                    InsideRendering = true;

                    doCoreInterpret      = false;
                    NativeUtils.CoreMadr = list.Pc;
                    NativeUtils.updateMemoryUnsafeAddr();

                    //if (log.DebugEnabled)
                    {
                        Console.WriteLine(string.Format("CoreThread processing {0}", list));
                    }

                    while (NativeUtils.coreInterpret())
                    {
                        NativeUtils.updateMemoryUnsafeAddr();

                        //if (log.DebugEnabled)
                        {
                            list.Pc = NativeUtils.CoreMadr;
                            Console.WriteLine(string.Format("CoreThread looping {0}", list));
                        }

                        if (ExternalGE.numberRendererThread > 0 && NativeUtils.RendererIndexCount > 0)
                        {
                            break;
                        }
                    }

                    list.Pc = NativeUtils.CoreMadr;

                    int intrStat = NativeUtils.CoreIntrStat;
                    if ((intrStat & INTR_STAT_END) != 0)
                    {
                        if ((intrStat & INTR_STAT_SIGNAL) != 0)
                        {
                            executeCommandSIGNAL(list);
                        }
                        if ((intrStat & INTR_STAT_FINISH) != 0)
                        {
                            executeCommandFINISH(list);
                        }
                        intrStat &= ~(INTR_STAT_END | INTR_STAT_SIGNAL | INTR_STAT_FINISH);
                        NativeUtils.CoreIntrStat = intrStat;
                    }

                    if (ExternalGE.numberRendererThread > 0 && NativeUtils.RendererIndexCount > 0)
                    {
                        ExternalGE.render();
                        doCoreInterpret = true;
                    }

                    InsideRendering = false;
                }
            }

            Console.WriteLine(string.Format("CoreThread exited"));
        }
예제 #22
0
        private void executeCommandSIGNAL(PspGeList list)
        {
            int args     = NativeUtils.getCoreCmdArray(GeCommands.SIGNAL) & 0x00FFFFFF;
            int behavior = (args >> 16) & 0xFF;
            int signal   = args & 0xFFFF;

            //if (log.DebugEnabled)
            {
                Console.WriteLine(string.Format("SIGNAL (behavior={0:D}, signal=0x{1:X})",behavior,signal));
            }

            switch (behavior)
            {
            case sceGe_user.PSP_GE_SIGNAL_SYNC:
            {
                // Skip FINISH / END
                Memory mem = Memory.Instance;
                if (command(mem.read32(list.Pc)) == FINISH)
                {
                    list.readNextInstruction();
                    if (command(mem.read32(list.Pc)) == END)
                    {
                        list.readNextInstruction();
                    }
                }
                //if (log.DebugEnabled)
                {
                    Console.WriteLine(string.Format("PSP_GE_SIGNAL_SYNC ignored PC: 0x{0:X8}", list.Pc));
                }
                break;
            }

            case sceGe_user.PSP_GE_SIGNAL_CALL:
            {
                // Call list using absolute address from SIGNAL + END.
                int hi16  = signal & 0x0FFF;
                int lo16  = NativeUtils.getCoreCmdArray(GeCommands.END) & 0xFFFF;
                int addr  = (hi16 << 16) | lo16;
                int oldPc = list.Pc;
                list.callAbsolute(addr);
                int newPc = list.Pc;
                //if (log.DebugEnabled)
                {
                    Console.WriteLine(string.Format("PSP_GE_SIGNAL_CALL old PC: 0x{0:X8}, new PC: 0x{1:X8}", oldPc, newPc));
                }
                break;
            }

            case sceGe_user.PSP_GE_SIGNAL_RETURN:
            {
                // Return from PSP_GE_SIGNAL_CALL.
                int oldPc = list.Pc;
                list.ret();
                int newPc = list.Pc;
                //if (log.DebugEnabled)
                {
                    Console.WriteLine(string.Format("PSP_GE_SIGNAL_RETURN old PC: 0x{0:X8}, new PC: 0x{1:X8}", oldPc, newPc));
                }
                break;
            }

            case sceGe_user.PSP_GE_SIGNAL_TBP0_REL:
            case sceGe_user.PSP_GE_SIGNAL_TBP1_REL:
            case sceGe_user.PSP_GE_SIGNAL_TBP2_REL:
            case sceGe_user.PSP_GE_SIGNAL_TBP3_REL:
            case sceGe_user.PSP_GE_SIGNAL_TBP4_REL:
            case sceGe_user.PSP_GE_SIGNAL_TBP5_REL:
            case sceGe_user.PSP_GE_SIGNAL_TBP6_REL:
            case sceGe_user.PSP_GE_SIGNAL_TBP7_REL:
            {
                // Overwrite TBPn and TBPw with SIGNAL + END (uses relative address only).
                int hi16     = signal & 0xFFFF;
                int end      = NativeUtils.getCoreCmdArray(GeCommands.END);
                int lo16     = end & 0xFFFF;
                int width    = (end >> 16) & 0xFF;
                int addr     = list.getAddressRel((hi16 << 16) | lo16);
                int tbpValue = (behavior - sceGe_user.PSP_GE_SIGNAL_TBP0_REL + GeCommands.TBP0) << 24 | (addr & 0x00FFFFFF);
                int tbwValue = (behavior - sceGe_user.PSP_GE_SIGNAL_TBP0_REL + GeCommands.TBW0) << 24 | ((addr >> 8) & 0x00FF0000) | (width & 0xFFFF);
                NativeUtils.interpretCoreCmd(command(tbpValue), tbpValue, NativeUtils.CoreMadr);
                NativeUtils.interpretCoreCmd(command(tbwValue), tbwValue, NativeUtils.CoreMadr);
                break;
            }

            case sceGe_user.PSP_GE_SIGNAL_TBP0_REL_OFFSET:
            case sceGe_user.PSP_GE_SIGNAL_TBP1_REL_OFFSET:
            case sceGe_user.PSP_GE_SIGNAL_TBP2_REL_OFFSET:
            case sceGe_user.PSP_GE_SIGNAL_TBP3_REL_OFFSET:
            case sceGe_user.PSP_GE_SIGNAL_TBP4_REL_OFFSET:
            case sceGe_user.PSP_GE_SIGNAL_TBP5_REL_OFFSET:
            case sceGe_user.PSP_GE_SIGNAL_TBP6_REL_OFFSET:
            case sceGe_user.PSP_GE_SIGNAL_TBP7_REL_OFFSET:
            {
                // Overwrite TBPn and TBPw with SIGNAL + END (uses relative address with offset).
                int hi16 = signal & 0xFFFF;
                // Read & skip END
                int end      = NativeUtils.getCoreCmdArray(GeCommands.END);
                int lo16     = end & 0xFFFF;
                int width    = (end >> 16) & 0xFF;
                int addr     = list.getAddressRelOffset((hi16 << 16) | lo16);
                int tbpValue = (behavior - sceGe_user.PSP_GE_SIGNAL_TBP0_REL + GeCommands.TBP0) << 24 | (addr & 0x00FFFFFF);
                int tbwValue = (behavior - sceGe_user.PSP_GE_SIGNAL_TBP0_REL + GeCommands.TBW0) << 24 | ((addr >> 8) & 0x00FF0000) | (width & 0xFFFF);
                NativeUtils.interpretCoreCmd(command(tbpValue), tbpValue, NativeUtils.CoreMadr);
                NativeUtils.interpretCoreCmd(command(tbwValue), tbwValue, NativeUtils.CoreMadr);
                break;
            }

            case sceGe_user.PSP_GE_SIGNAL_HANDLER_SUSPEND:
            case sceGe_user.PSP_GE_SIGNAL_HANDLER_CONTINUE:
            case sceGe_user.PSP_GE_SIGNAL_HANDLER_PAUSE:
            {
                list.clearRestart();
                list.pushSignalCallback(list.id, behavior, signal);
                list.endList();
                list.status = sceGe_user.PSP_GE_LIST_END_REACHED;
                break;
            }

            default:
            {
                if (log.InfoEnabled)
                {
                    Console.WriteLine(string.Format("SIGNAL (behavior={0:D}, signal=0x{1:X}) unknown behavior at 0x{2:X8}", behavior, signal, list.Pc - 4));
                }
            }
            break;
            }

            if (list.Drawing)
            {
                list.sync();
                NativeUtils.setCoreCtrlActive();
            }
        }
예제 #23
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: public int hleGeListEnQueue(pspsharp.HLE.TPointer listAddr, @CanBeNull pspsharp.HLE.TPointer stallAddr, int cbid, @CanBeNull pspsharp.HLE.TPointer argAddr, int saveContextAddr, bool enqueueHead)
        public virtual int hleGeListEnQueue(TPointer listAddr, TPointer stallAddr, int cbid, TPointer argAddr, int saveContextAddr, bool enqueueHead)
        {
            pspGeListOptParam optParams = null;
            int stackAddr = 0;

            if (argAddr.NotNull)
            {
                optParams = new pspGeListOptParam();
                optParams.read(argAddr);
                stackAddr       = optParams.stackAddr;
                saveContextAddr = optParams.contextAddr;
                //if (log.DebugEnabled)
                {
                    Console.WriteLine(string.Format("hleGeListEnQueue optParams={0}", optParams));
                }
            }

            bool useCachedMemory = false;

            if (Modules.SysMemUserForUserModule.hleKernelGetCompiledSdkVersion() >= 0x02000000)
            {
                bool isBusy;
                if (ExternalGE.Active)
                {
                    isBusy = ExternalGE.hasDrawList(listAddr.Address, stackAddr);
                }
                else
                {
                    isBusy = VideoEngine.Instance.hasDrawList(listAddr.Address, stackAddr);
                }
                if (isBusy)
                {
                    Console.WriteLine(string.Format("hleGeListEnQueue can't enqueue duplicate list address {0}, stack 0x{1:X8}", listAddr, stackAddr));
                    return(SceKernelErrors.ERROR_BUSY);
                }
            }
            else
            {
                // Old games (i.e. having PSP SDK version < 2.00) are sometimes
                // reusing the same address for multiple lists, without waiting
                // for the previous list to complete. They assume that the lists
                // are being executed quite quickly, which is not the case when
                // using the OpenGL rendering engine. There is some delay before
                // the OpenGL frame refresh is being processed.
                useCachedMemory = true;
            }

            // No need to cache any memory when using the external software renderer
            if (ExternalGE.Active)
            {
                useCachedMemory = false;
            }

            int result;

            lock (this)
            {
                PspGeList list = listFreeQueue.poll();
                if (list == null)
                {
                    Console.WriteLine("hleGeListEnQueue no more free list available!");
                    //if (log.DebugEnabled)
                    {
                        for (int i = 0; i < NUMBER_GE_LISTS; i++)
                        {
                            Console.WriteLine(string.Format("List#{0:D}: {1}", i, allGeLists[i]));
                        }
                    }
                    return(SceKernelErrors.ERROR_OUT_OF_MEMORY);
                }

                list.init(listAddr.Address, stallAddr.Address, cbid, optParams);
                list.SaveContextAddr = saveContextAddr;
                if (useCachedMemory)
                {
                    setStallAddressWithCachedMemory(list, stallAddr.Address);
                }
                if (enqueueHead)
                {
                    // Send the list to the VideoEngine at the head of the queue.
                    list.startListHead();
                }
                else
                {
                    // Send the list to the VideoEngine before triggering the display (setting GE dirty)
                    list.startList();
                }
                Modules.sceDisplayModule.GeDirty = true;
                result = list.id;
            }

            //if (log.DebugEnabled)
            {
                Console.WriteLine(string.Format("hleGeListEnQueue returning 0x{0:X}", result));
            }

            return(result);
        }
예제 #24
0
 public ListSyncWaitStateChecker(PspGeList list)
 {
     this.list = list;
 }