@HLEFunction(nid = 0x4C06E472, version = 150) public int sceGeContinue() { PspGeList list; if (ExternalGE.isActive()) { list = ExternalGE.getCurrentList(); } else { list = VideoEngine.getInstance().getCurrentList(); } if (list != null) { synchronized (this) { if (list.status == PSP_GE_LIST_END_REACHED) { Memory mem = Memory.getInstance(); if (mem.read32(list.getPc()) == (GeCommands.FINISH << 24) && mem.read32(list.getPc() + 4) == (GeCommands.END << 24)) { list.readNextInstruction(); list.readNextInstruction(); } } list.restartList(); } } return 0; }
@HLEFunction(nid = 0x57C8945B, version = 150) public int sceGeGetMtx(int mtxType, TPointer mtxAddr) { if (mtxType < 0 || mtxType > PSP_GE_MATRIX_TEXGEN) { log.warn(String.format("sceGeGetMtx invalid type mtxType=%d", mtxType)); return SceKernelErrors.ERROR_INVALID_INDEX; } float[] mtx; if (ExternalGE.isActive()) { mtx = ExternalGE.getMatrix(mtxType); } else { mtx = VideoEngine.getInstance().getMatrix(mtxType); } for (int i = 0; i < mtx.length; i++) { // Float value is returned in lower 24 bits. mtxAddr.setValue32(i << 2, Float.floatToRawIntBits(mtx[i]) >>> 8); } if (log.isInfoEnabled()) { log.info(String.format("sceGeGetMtx mtxType=%d, mtxAddr=%s, mtx=%s", mtxType, mtxAddr, mtx)); } return 0; }
@HLEFunction(nid = 0xB448EC0D, version = 150) public int sceGeBreak(@CheckArgument("checkMode") int mode, TPointer brk_addr) { int result = 0; PspGeList list; if (ExternalGE.isActive()) { list = ExternalGE.getCurrentList(); } else { list = VideoEngine.getInstance().getCurrentList(); } if (mode == 0) { // Pause the current list only. if (list != null) { list.pauseList(); result = list.id; } } else if (mode == 1) { // Pause the current list and cancel the rest of the queue. if (list != null) { list.pauseList(); for (int i = 0; i < NUMBER_GE_LISTS; i++) { allGeLists[i].status = PSP_GE_LIST_CANCEL_DONE; } result = list.id; } } return result; }
@Override public void stop() { log.debug(String.format("Stopping %s", getName())); if (ExternalGE.isActive()) { ExternalGE.onGeUserStop(); } }
@HLEFunction(nid = 0x0BF608FB, version = 150) public int sceGeRestoreContext(TPointer contextAddr) { if (ExternalGE.isActive()) { return ExternalGE.restoreContext(contextAddr.getAddress()); } VideoEngine.getInstance().hleRestoreContext(contextAddr.getAddress()); return 0; }
@HLEFunction(nid = 0x438A385A, version = 150) public int sceGeSaveContext(TPointer contextAddr) { if (ExternalGE.isActive()) { return ExternalGE.saveContext(contextAddr.getAddress()); } VideoEngine.getInstance().hleSaveContext(contextAddr.getAddress()); return 0; }
@HLEFunction(nid = 0xB287BD61, version = 150) public int sceGeDrawSync(@CheckArgument("checkMode") int mode) { if (mode == 0 && IntrManager.getInstance().isInsideInterrupt()) { log.debug("sceGeDrawSync (mode==0) cannot be called inside an interrupt handler!"); return SceKernelErrors.ERROR_KERNEL_CANNOT_BE_CALLED_FROM_INTERRUPT; } // no synchronization on "this" required because we are not accessing // local data, only list information from the VideoEngine. int result = 0; if (mode == 0) { PspGeList lastList; if (ExternalGE.isActive()) { lastList = ExternalGE.getLastDrawList(); } else { lastList = VideoEngine.getInstance().getLastDrawList(); } if (lastList != null) { blockCurrentThreadOnList(lastList, new HLEAfterDrawSyncAction()); } else { if (log.isDebugEnabled()) { log.debug("sceGeDrawSync all lists completed, not waiting"); } hleGeAfterDrawSyncAction(); Modules.ThreadManForUserModule.hleRescheduleCurrentThread(); } } else if (mode == 1) { PspGeList currentList; if (ExternalGE.isActive()) { currentList = ExternalGE.getFirstDrawList(); } else { currentList = VideoEngine.getInstance().getFirstDrawList(); } if (currentList != null) { result = currentList.status; } if (log.isDebugEnabled()) { log.debug(String.format("sceGeDrawSync mode=%d, returning %d", mode, result)); } } return result; }
@HLEFunction(nid = 0xDC93CFEF, version = 150) public int sceGeGetCmd(int cmd) { VideoEngine ve = VideoEngine.getInstance(); int value; if (ExternalGE.isActive()) { value = ExternalGE.getCmd(cmd); } else { value = ve.getCommandValue(cmd); } if (log.isInfoEnabled()) { log.info( String.format( "sceGeGetCmd %s: cmd=0x%X, value=0x%06X", ve.commandToString(cmd).toUpperCase(), cmd, value)); } return value; }
@Override public boolean continueWaitState(SceKernelThreadInfo thread, ThreadWaitInfo wait) { // Continue the wait state until the list is done boolean contineWait = !list.isDone(); if (!contineWait) { ExternalGE.onGeStopWaitList(); } return contineWait; }
private void blockCurrentThreadOnList(PspGeList list, IAction action) { ThreadManForUser threadMan = Modules.ThreadManForUserModule; boolean blockCurrentThread = false; boolean executeAction = false; synchronized (this) { int currentThreadId = threadMan.getCurrentThreadID(); if (list.isDone()) { // There has been some race condition: the list has just completed // do not block the thread if (log.isDebugEnabled()) { log.debug( "blockCurrentThreadOnList not blocking thread " + Integer.toHexString(currentThreadId) + ", list completed " + list); } executeAction = true; } else { if (log.isDebugEnabled()) { log.debug( "blockCurrentThreadOnList blocking thread " + Integer.toHexString(currentThreadId) + " 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(); } }
public void step() { ThreadManForUser threadMan = Modules.ThreadManForUserModule; for (Integer thid = deferredThreadWakeupQueue.poll(); thid != null; thid = deferredThreadWakeupQueue.poll()) { if (log.isDebugEnabled()) { log.debug( "really waking thread " + Integer.toHexString(thid) + "(" + threadMan.getThreadName(thid) + ")"); } threadMan.hleUnblockThread(thid); ExternalGE.onGeStopWaitList(); } }
public int hleGeListEnQueue( TPointer listAddr, @CanBeNull TPointer stallAddr, int cbid, @CanBeNull TPointer argAddr, int saveContextAddr, boolean enqueueHead) { pspGeListOptParam optParams = null; int stackAddr = 0; if (argAddr.isNotNull()) { optParams = new pspGeListOptParam(); optParams.read(argAddr); stackAddr = optParams.stackAddr; if (log.isDebugEnabled()) { log.debug(String.format("hleGeListEnQueue optParams=%s", optParams)); } } if (Modules.SysMemUserForUserModule.hleKernelGetCompiledSdkVersion() >= 0x02000000) { boolean isBusy; if (ExternalGE.isActive()) { isBusy = ExternalGE.hasDrawList(listAddr.getAddress(), stackAddr); } else { isBusy = VideoEngine.getInstance().hasDrawList(listAddr.getAddress(), stackAddr); } if (isBusy) { log.warn( String.format( "hleGeListEnQueue can't enqueue duplicate list address %s, stack 0x%08X", listAddr, stackAddr)); return SceKernelErrors.ERROR_BUSY; } } int result; synchronized (this) { PspGeList list = listFreeQueue.poll(); if (list == null) { log.warn("hleGeListEnQueue no more free list available!"); if (log.isDebugEnabled()) { for (int i = 0; i < NUMBER_GE_LISTS; i++) { log.debug(String.format("List#%d: %s", i, allGeLists[i])); } } return SceKernelErrors.ERROR_OUT_OF_MEMORY; } list.init(listAddr.getAddress(), stallAddr.getAddress(), cbid, optParams); list.setSaveContextAddr(saveContextAddr); 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.setGeDirty(true); result = list.id; } if (log.isDebugEnabled()) { log.debug(String.format("hleGeListEnQueue returning 0x%X", result)); } return result; }