コード例 #1
0
ファイル: HLE.cpp プロジェクト: thesourcehim/ppsspp
u32 hleDelayResult(u32 result, const char *reason, int usec)
{
	if (__KernelIsDispatchEnabled())
	{
		CoreTiming::ScheduleEvent(usToCycles(usec), delayedResultEvent, __KernelGetCurThread());
		__KernelWaitCurThread(WAITTYPE_HLEDELAY, 1, result, 0, false, reason);
	}
	else
		WARN_LOG(HLE, "Dispatch disabled, not delaying HLE result (right thing to do?)");
	return result;
}
コード例 #2
0
ファイル: sceKernelEventFlag.cpp プロジェクト: 173210/ppsspp
int sceKernelWaitEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 timeoutPtr)
{
	DEBUG_LOG(HLE, "sceKernelWaitEventFlag(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr, timeoutPtr);

	if ((wait & ~PSP_EVENT_WAITKNOWN) != 0)
	{
		WARN_LOG_REPORT(HLE, "sceKernelWaitEventFlag(%i) invalid mode parameter: %08x", id, wait);
		return SCE_KERNEL_ERROR_ILLEGAL_MODE;
	}
	// Can't wait on 0, that's guaranteed to wait forever.
	if (bits == 0)
		return SCE_KERNEL_ERROR_EVF_ILPAT;

	if (!__KernelIsDispatchEnabled())
		return SCE_KERNEL_ERROR_CAN_NOT_WAIT;

	u32 error;
	EventFlag *e = kernelObjects.Get<EventFlag>(id, error);
	if (e)
	{
		EventFlagTh th;
		if (!__KernelEventFlagMatches(&e->nef.currentPattern, bits, wait, outBitsPtr))
		{
			// If this thread was left in waitingThreads after a timeout, remove it.
			// Otherwise we might write the outBitsPtr in the wrong place.
			__KernelEventFlagRemoveThread(e, __KernelGetCurThread());

			u32 timeout = 0xFFFFFFFF;
			if (Memory::IsValidAddress(timeoutPtr))
				timeout = Memory::Read_U32(timeoutPtr);

			// Do we allow more than one thread to wait?
			if (e->waitingThreads.size() > 0 && (e->nef.attr & PSP_EVENT_WAITMULTIPLE) == 0)
				return SCE_KERNEL_ERROR_EVF_MULTI;

			// No match - must wait.
			th.tid = __KernelGetCurThread();
			th.bits = bits;
			th.wait = wait;
			// If < 5ms, sometimes hardware doesn't write this, but it's unpredictable.
			th.outAddr = timeout == 0 ? 0 : outBitsPtr;
			e->waitingThreads.push_back(th);

			__KernelSetEventFlagTimeout(e, timeoutPtr);
			__KernelWaitCurThread(WAITTYPE_EVENTFLAG, id, 0, timeoutPtr, false, "event flag waited");
		}

		return 0;
	}
	else
	{
		return error;
	}
}
コード例 #3
0
ファイル: sceDisplay.cpp プロジェクト: oioitff/ppsspp
u32 sceDisplayWaitVblankCB() {
	if (!isVblank) {
		DEBUG_LOG(HLE,"sceDisplayWaitVblankCB()");
		vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread()));
		__KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, true, "vblank waited");
		return 0;
	} else {
		DEBUG_LOG(HLE,"sceDisplayWaitVblank() - not waiting since in vBlank");
		return 1;
	}
}
コード例 #4
0
ファイル: __sceAudio.cpp プロジェクト: tmaul/ppsspp
u32 __AudioEnqueue(AudioChannel &chan, int chanNum, bool blocking)
{
	section.lock();
	if (chan.sampleAddress == 0)
		return SCE_ERROR_AUDIO_NOT_OUTPUT;
	if (chan.sampleQueue.size() > chan.sampleCount*2*chanQueueMaxSizeFactor) {
		// Block!
		if (blocking) {
			chan.waitingThread = __KernelGetCurThread();
			// WARNING: This changes currentThread so must grab waitingThread before (line above).
			__KernelWaitCurThread(WAITTYPE_AUDIOCHANNEL, (SceUID)chanNum, 0, 0, false, "blocking audio waited");
			// Fall through to the sample queueing, don't want to lose the samples even though
			// we're getting full.
		}
		else
		{
			chan.waitingThread = 0;
			return SCE_ERROR_AUDIO_CHANNEL_BUSY;
		}
	}
	if (chan.format == PSP_AUDIO_FORMAT_STEREO)
	{
		const u32 totalSamples = chan.sampleCount * 2;

		if (IS_LITTLE_ENDIAN)
		{
			s16 *sampleData = (s16 *) Memory::GetPointer(chan.sampleAddress);

			// Walking a pointer for speed.  But let's make sure we wouldn't trip on an invalid ptr.
			if (Memory::IsValidAddress(chan.sampleAddress + (totalSamples - 1) * sizeof(s16)))
			{
				for (u32 i = 0; i < totalSamples; i++)
					chan.sampleQueue.push(*sampleData++);
			}
		}
		else
		{
			for (u32 i = 0; i < totalSamples; i++)
				chan.sampleQueue.push((s16)Memory::Read_U16(chan.sampleAddress + sizeof(s16) * i));
		}
	}
	else if (chan.format == PSP_AUDIO_FORMAT_MONO)
	{
		for (u32 i = 0; i < chan.sampleCount; i++)
		{
			// Expand to stereo
			s16 sample = (s16)Memory::Read_U16(chan.sampleAddress + 2 * i);
			chan.sampleQueue.push(sample);
			chan.sampleQueue.push(sample);
		}
	}
	section.unlock();
	return 0;
}
コード例 #5
0
ファイル: sceDisplay.cpp プロジェクト: A671DR218/ppsspp
u32 sceDisplayWaitVblankCB() {
	if (!isVblank) {
		VERBOSE_LOG(SCEDISPLAY,"sceDisplayWaitVblankCB()");
		vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread()));
		__KernelWaitCurThread(WAITTYPE_VBLANK, 1, 0, 0, true, "vblank waited");
		return 0;
	} else {
		DEBUG_LOG(SCEDISPLAY,"sceDisplayWaitVblankCB() - not waiting since in vBlank");
		hleEatCycles(1110);
		return 1;
	}
}
コード例 #6
0
ファイル: sceUmd.cpp プロジェクト: phaew/ppsspp
/** 
* Wait for a drive to reach a certain state
*
* @param stat - The drive stat to wait for.
* @return < 0 on error
*
*/
int sceUmdWaitDriveStat(u32 stat)
{
	DEBUG_LOG(HLE,"0=sceUmdWaitDriveStat(stat = %08x)", stat);

	if ((stat & __KernelUmdGetState()) == 0)
	{
		umdWaitingThreads.push_back(UmdWaitingThread::Make(__KernelGetCurThread(), stat));
		__KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, 0, "umd stat waited");
	}

	return 0;
}
コード例 #7
0
ファイル: scePower.cpp プロジェクト: CrazyMax/ppsspp
int sceKernelVolatileMemLock(int type, u32 paddr, u32 psize) {
	u32 error = 0;

	// If dispatch is disabled or in an interrupt, don't check, just return an error.
	// But still write the addr and size (some games require this to work, and it's testably true.)
	if (!__KernelIsDispatchEnabled()) {
		error = SCE_KERNEL_ERROR_CAN_NOT_WAIT;
	} else if (__IsInInterrupt()) {
		error = SCE_KERNEL_ERROR_ILLEGAL_CONTEXT;
	} else {
		error = __KernelVolatileMemLock(type, paddr, psize);
	}

	switch (error) {
	case 0:
		DEBUG_LOG(HLE, "sceKernelVolatileMemLock(%i, %08x, %08x) - success", type, paddr, psize);
		break;

	case ERROR_POWER_VMEM_IN_USE:
		{
			WARN_LOG(HLE, "sceKernelVolatileMemLock(%i, %08x, %08x) - already locked, waiting", type, paddr, psize);
			const VolatileWaitingThread waitInfo = { __KernelGetCurThread(), paddr, psize };
			volatileWaitingThreads.push_back(waitInfo);
			__KernelWaitCurThread(WAITTYPE_VMEM, 1, 0, 0, false, "volatile mem waited");
		}
		break;

	case SCE_KERNEL_ERROR_CAN_NOT_WAIT:
		{
			WARN_LOG(HLE, "sceKernelVolatileMemLock(%i, %08x, %08x): dispatch disabled", type, paddr, psize);
			Memory::Write_U32(0x08400000, paddr);
			Memory::Write_U32(0x00400000, psize);
		}
		break;

	case SCE_KERNEL_ERROR_ILLEGAL_CONTEXT:
		{
			WARN_LOG(HLE, "sceKernelVolatileMemLock(%i, %08x, %08x): in interrupt", type, paddr, psize);
			Memory::Write_U32(0x08400000, paddr);
			Memory::Write_U32(0x00400000, psize);
		}
		break;

	default:
		ERROR_LOG_REPORT(HLE, "%08x=sceKernelVolatileMemLock(%i, %08x, %08x) - error", type, paddr, psize, error);
		break;
	}

	return error;
}
コード例 #8
0
ファイル: sceUmd.cpp プロジェクト: Summeli/ppsspp
int sceUmdWaitDriveStatWithTimer(u32 stat, u32 timeout)
{
	DEBUG_LOG(HLE,"0=sceUmdWaitDriveStatWithTimer(stat = %08x, timeout = %d)", stat, timeout);

	if ((stat & __KernelUmdGetState()) == 0)
	{
		__UmdWaitStat(timeout);
		__KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, 0);
	}
	else
		hleReSchedule("umd stat waited with timer");

	return 0;
}
コード例 #9
0
ファイル: sceDisplay.cpp プロジェクト: A671DR218/ppsspp
u32 sceDisplayWaitVblankStartMultiCB(int vblanks) {
	if (vblanks <= 0) {
		WARN_LOG(SCEDISPLAY, "sceDisplayWaitVblankStartMultiCB(%d): invalid number of vblanks", vblanks);
		return SCE_KERNEL_ERROR_INVALID_VALUE;
	}
	VERBOSE_LOG(SCEDISPLAY,"sceDisplayWaitVblankStartMultiCB(%d)", vblanks);
	if (!__KernelIsDispatchEnabled())
		return SCE_KERNEL_ERROR_CAN_NOT_WAIT;
	if (__IsInInterrupt())
		return SCE_KERNEL_ERROR_ILLEGAL_CONTEXT;
	vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread(), vblanks));
	__KernelWaitCurThread(WAITTYPE_VBLANK, 1, 0, 0, true, "vblank start multi waited");
	return 0;
}
コード例 #10
0
ファイル: sceDisplay.cpp プロジェクト: RisingFog/ppsspp
static int DisplayWaitForVblanks(const char *reason, int vblanks, bool callbacks = false) {
	const s64 ticksIntoFrame = CoreTiming::GetTicks() - frameStartTicks;
	const s64 cyclesToNextVblank = msToCycles(frameMs) - ticksIntoFrame;

	// These syscalls take about 115 us, so if the next vblank is before then, we're waiting extra.
	// At least, on real firmware a wait >= 16500 into the frame will wait two.
	if (cyclesToNextVblank <= usToCycles(115)) {
		++vblanks;
	}

	vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread(), vblanks));
	__KernelWaitCurThread(WAITTYPE_VBLANK, 1, 0, 0, callbacks, reason);

	return hleLogSuccessVerboseI(SCEDISPLAY, 0, "waiting for %d vblanks", vblanks);
}
コード例 #11
0
ファイル: sceCtrl.cpp プロジェクト: Bulkman/ppsspp
void sceCtrlReadBufferNegative(u32 ctrlDataPtr, u32 nBufs)
{
	int done = __CtrlReadBuffer(ctrlDataPtr, nBufs, true, false);
	if (done != 0)
	{
		RETURN(done);
		DEBUG_LOG(SCECTRL, "%d=sceCtrlReadBufferNegative(%08x, %i)", done, ctrlDataPtr, nBufs);
	}
	else
	{
		waitingThreads.push_back(__KernelGetCurThread());
		__KernelWaitCurThread(WAITTYPE_CTRL, CTRL_WAIT_NEGATIVE, ctrlDataPtr, 0, false, "ctrl buffer waited");
		DEBUG_LOG(SCECTRL, "sceCtrlReadBufferNegative(%08x, %i) - waiting", ctrlDataPtr, nBufs);
	}
}
コード例 #12
0
ファイル: sceKernelMemory.cpp プロジェクト: glonerr/ppsspp
int sceKernelAllocateTls(SceUID uid)
{
	// TODO: Allocate downward if PSP_TLS_ATTR_HIGHMEM?
	DEBUG_LOG(HLE, "sceKernelAllocateTls(%08x)", uid);
	u32 error;
	TLS *tls = kernelObjects.Get<TLS>(uid, error);
	if (tls)
	{
		SceUID threadID = __KernelGetCurThread();
		int allocBlock = -1;

		// If the thread already has one, return it.
		for (size_t i = 0; i < tls->ntls.totalBlocks && allocBlock == -1; ++i)
		{
			if (tls->usage[i] == threadID)
				allocBlock = (int) i;
		}

		if (allocBlock == -1)
		{
			for (size_t i = 0; i < tls->ntls.totalBlocks && allocBlock == -1; ++i)
			{
				// The PSP doesn't give the same block out twice in a row, even if freed.
				if (tls->usage[tls->next] == 0)
					allocBlock = tls->next;
				tls->next = (tls->next + 1) % tls->ntls.totalBlocks;
			}

			if (allocBlock != -1)
			{
				tls->usage[allocBlock] = threadID;
				--tls->ntls.freeBlocks;
			}
		}

		if (allocBlock == -1)
		{
			tls->waitingThreads.push_back(threadID);
			__KernelWaitCurThread(WAITTYPE_TLS, uid, 1, 0, false, "allocate tls");
			return -1;
		}

		return tls->address + allocBlock * tls->ntls.blockSize;
	}
	else
		return error;
}
コード例 #13
0
int __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, bool processCallbacks)
{
	hleEatCycles(900);

	if (wantedCount <= 0)
		return SCE_KERNEL_ERROR_ILLEGAL_COUNT;

	hleEatCycles(500);

	u32 error;
	Semaphore *s = kernelObjects.Get<Semaphore>(id, error);
	if (s)
	{
		if (wantedCount > s->ns.maxCount)
			return SCE_KERNEL_ERROR_ILLEGAL_COUNT;

		// If there are any callbacks, we always wait, and wake after the callbacks.
		bool hasCallbacks = processCallbacks && __KernelCurHasReadyCallbacks();
		if (s->ns.currentCount >= wantedCount && s->waitingThreads.size() == 0 && !hasCallbacks)
		{
			if (hasCallbacks)
			{
				// Might actually end up having to wait, so set the timeout.
				__KernelSetSemaTimeout(s, timeoutPtr);
				__KernelWaitCallbacksCurThread(WAITTYPE_SEMA, id, wantedCount, timeoutPtr);
			}
			else
				s->ns.currentCount -= wantedCount;
		}
		else
		{
			SceUID threadID = __KernelGetCurThread();
			// May be in a tight loop timing out (where we don't remove from waitingThreads yet), don't want to add duplicates.
			if (std::find(s->waitingThreads.begin(), s->waitingThreads.end(), threadID) == s->waitingThreads.end())
				s->waitingThreads.push_back(threadID);
			__KernelSetSemaTimeout(s, timeoutPtr);
			__KernelWaitCurThread(WAITTYPE_SEMA, id, wantedCount, timeoutPtr, processCallbacks, "sema waited");
		}

		return 0;
	}
	else
		return error;
}
コード例 #14
0
ファイル: sceKernelMsgPipe.cpp プロジェクト: libretro/PSP1
static int __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int waitMode, u32 resultAddr, u32 timeoutPtr, bool cbEnabled, bool poll)
{
	bool needsResched = false;
	bool needsWait = false;

	int result = __KernelReceiveMsgPipe(m, receiveBufAddr, receiveSize, waitMode, resultAddr, timeoutPtr, cbEnabled, poll, needsResched, needsWait);

	if (needsResched)
		hleReSchedule(cbEnabled, "msgpipe data received");

	if (needsWait)
	{
		if (__KernelSetMsgPipeTimeout(timeoutPtr))
			__KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), MSGPIPE_WAIT_VALUE_RECV, timeoutPtr, cbEnabled, "msgpipe receive waited");
		else
			return SCE_KERNEL_ERROR_WAIT_TIMEOUT;
	}
	return result;
}
コード例 #15
0
ファイル: sceUmd.cpp プロジェクト: phaew/ppsspp
int sceUmdWaitDriveStatCB(u32 stat, u32 timeout)
{
	DEBUG_LOG(HLE,"0=sceUmdWaitDriveStatCB(stat = %08x, timeout = %d)", stat, timeout);

	hleCheckCurrentCallbacks();
	if ((stat & __KernelUmdGetState()) == 0)
	{
		if (timeout == 0)
			timeout = 8000;

		__UmdWaitStat(timeout);
		umdWaitingThreads.push_back(UmdWaitingThread::Make(__KernelGetCurThread(), stat));
		__KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, true, "umd stat waited");
	}
	else
		hleReSchedule("umd stat waited");

	return 0;
}
コード例 #16
0
ファイル: sceKernelMutex.cpp プロジェクト: fluffyfreak/ppsspp
// int sceKernelLockMutex(SceUID id, int count, int *timeout)
// void because it changes threads.
void sceKernelLockMutex(SceUID id, int count, u32 timeoutPtr)
{
	DEBUG_LOG(HLE,"sceKernelLockMutex(%i, %i, %08x)", id, count, timeoutPtr);
	u32 error;
	Mutex *mutex = kernelObjects.Get<Mutex>(id, error);

	if (__KernelLockMutex(mutex, count, error))
	{
		RETURN(0);
		__KernelReSchedule("mutex locked");
	}
	else if (error)
		RETURN(error);
	else
	{
		mutex->waitingThreads.push_back(__KernelGetCurThread());
		__KernelWaitMutex(mutex, timeoutPtr);
		__KernelWaitCurThread(WAITTYPE_MUTEX, id, count, timeoutPtr, false);
	}
}
コード例 #17
0
ファイル: sceKernelMsgPipe.cpp プロジェクト: libretro/PSP1
static int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, u32 resultAddr, u32 timeoutPtr, bool cbEnabled, bool poll)
{
	hleEatCycles(2400);

	bool needsResched = false;
	bool needsWait = false;

	int result = __KernelSendMsgPipe(m, sendBufAddr, sendSize, waitMode, resultAddr, timeoutPtr, cbEnabled, poll, needsResched, needsWait);

	if (needsResched)
		hleReSchedule(cbEnabled, "msgpipe data sent");

	if (needsWait)
	{
		if (__KernelSetMsgPipeTimeout(timeoutPtr))
			__KernelWaitCurThread(WAITTYPE_MSGPIPE, m->GetUID(), MSGPIPE_WAIT_VALUE_SEND, timeoutPtr, cbEnabled, "msgpipe send waited");
		else
			result = SCE_KERNEL_ERROR_WAIT_TIMEOUT;
	}
	return result;
}
コード例 #18
0
ファイル: sceKernelMemory.cpp プロジェクト: Ced2911/ppsspp
int sceKernelAllocateVpl(SceUID uid, u32 size, u32 addrPtr, u32 timeoutPtr)
{
	u32 error, ignore;
	if (__KernelAllocateVpl(uid, size, addrPtr, error, __FUNCTION__))
	{
		VPL *vpl = kernelObjects.Get<VPL>(uid, ignore);
		if (error == SCE_KERNEL_ERROR_NO_MEMORY)
		{
			if (vpl)
			{
				SceUID threadID = __KernelGetCurThread();
				__KernelVplRemoveThread(vpl, threadID);
				VplWaitingThread waiting = {threadID, addrPtr};
				vpl->waitingThreads.push_back(waiting);
			}

			__KernelSetVplTimeout(timeoutPtr);
			__KernelWaitCurThread(WAITTYPE_VPL, uid, size, timeoutPtr, false, "vpl waited");
		}
	}
	return error;
}
コード例 #19
0
ファイル: sceKernelMutex.cpp プロジェクト: 173210/ppsspp
// int sceKernelLockMutex(SceUID id, int count, int *timeout)
int sceKernelLockMutex(SceUID id, int count, u32 timeoutPtr)
{
	DEBUG_LOG(HLE, "sceKernelLockMutex(%i, %i, %08x)", id, count, timeoutPtr);
	u32 error;
	Mutex *mutex = kernelObjects.Get<Mutex>(id, error);

	if (__KernelLockMutex(mutex, count, error))
		return 0;
	else if (error)
		return error;
	else
	{
		SceUID threadID = __KernelGetCurThread();
		// May be in a tight loop timing out (where we don't remove from waitingThreads yet), don't want to add duplicates.
		if (std::find(mutex->waitingThreads.begin(), mutex->waitingThreads.end(), threadID) == mutex->waitingThreads.end())
			mutex->waitingThreads.push_back(threadID);
		__KernelWaitMutex(mutex, timeoutPtr);
		__KernelWaitCurThread(WAITTYPE_MUTEX, id, count, timeoutPtr, false, "mutex waited");

		// Return value will be overwritten by wait.
		return 0;
	}
}
コード例 #20
0
ファイル: GPUCommon.cpp プロジェクト: mykahfi/ppsspp
int GPUCommon::ListSync(int listid, int mode)
{
	if (listid < 0 || listid >= DisplayListMaxCount)
		return SCE_KERNEL_ERROR_INVALID_ID;

	if (mode < 0 || mode > 1)
		return SCE_KERNEL_ERROR_INVALID_MODE;

	DisplayList& dl = dls[listid];
	if (mode == 1) {
		switch (dl.state) {
		case PSP_GE_DL_STATE_QUEUED:
			if (dl.interrupted)
				return PSP_GE_LIST_PAUSED;
			return PSP_GE_LIST_QUEUED;

		case PSP_GE_DL_STATE_RUNNING:
			if (dl.pc == dl.stall)
				return PSP_GE_LIST_STALLING;
			return PSP_GE_LIST_DRAWING;

		case PSP_GE_DL_STATE_COMPLETED:
			return PSP_GE_LIST_COMPLETED;

		case PSP_GE_DL_STATE_PAUSED:
			return PSP_GE_LIST_PAUSED;

		default:
			return SCE_KERNEL_ERROR_INVALID_ID;
		}
	}

	if (dl.shouldWait) {
		__KernelWaitCurThread(WAITTYPE_GELISTSYNC, listid, 0, 0, false, "GeListSync");
	}
	return PSP_GE_LIST_COMPLETED;
}
コード例 #21
0
//int sceKernelWaitEventFlagCB(SceUID evid, u32 bits, u32 wait, u32 *outBits, SceUInt *timeout);
void sceKernelWaitEventFlagCB()
{
	SceUID id = PARAM(0);
	u32 bits = PARAM(1);
	u32 wait = PARAM(2);
	u32 outBitsPtr = PARAM(3);
	u32 timeoutPtr = PARAM(4);

	DEBUG_LOG(HLE,"sceKernelWaitEventFlagCB(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr, timeoutPtr);

	u32 error;
	EventFlag *e = kernelObjects.Get<EventFlag>(id, error);
	if (e)
	{
		EventFlagTh th;
		if (!__KernelEventFlagMatches(&e->nef.currentPattern, bits, wait, outBitsPtr))
		{
			// No match - must wait.
			e->nef.numWaitThreads++;
			th.tid = __KernelGetCurThread();
			th.bits = bits;
			th.wait = wait;
			th.outAddr = outBitsPtr;
			e->waitingThreads.push_back(th);
			u32 timeout;
			if (Memory::IsValidAddress(timeoutPtr))
				timeout = Memory::Read_U32(timeoutPtr);

			__KernelWaitCurThread(WAITTYPE_EVENTFLAG, id, 0, 0, true);
		}
		RETURN(0);
	}
	else
	{
		RETURN(error);
	}
}
コード例 #22
0
ファイル: sceKernelMutex.cpp プロジェクト: 173210/ppsspp
// int sceKernelLockMutexCB(SceUID id, int count, int *timeout)
int sceKernelLockMutexCB(SceUID id, int count, u32 timeoutPtr)
{
	DEBUG_LOG(HLE, "sceKernelLockMutexCB(%i, %i, %08x)", id, count, timeoutPtr);
	u32 error;
	Mutex *mutex = kernelObjects.Get<Mutex>(id, error);

	if (!__KernelLockMutexCheck(mutex, count, error))
	{
		if (error)
			return error;

		SceUID threadID = __KernelGetCurThread();
		// May be in a tight loop timing out (where we don't remove from waitingThreads yet), don't want to add duplicates.
		if (std::find(mutex->waitingThreads.begin(), mutex->waitingThreads.end(), threadID) == mutex->waitingThreads.end())
			mutex->waitingThreads.push_back(threadID);
		__KernelWaitMutex(mutex, timeoutPtr);
		__KernelWaitCurThread(WAITTYPE_MUTEX, id, count, timeoutPtr, true, "mutex waited");

		// Return value will be overwritten by wait.
		return 0;
	}
	else
	{
		if (__KernelCurHasReadyCallbacks())
		{
			// Might actually end up having to wait, so set the timeout.
			__KernelWaitMutex(mutex, timeoutPtr);
			__KernelWaitCallbacksCurThread(WAITTYPE_MUTEX, id, count, timeoutPtr);

			// Return value will be written to callback's v0, but... that's probably fine?
		}
		else
			__KernelLockMutex(mutex, count, error);

		return 0;
	}
}
コード例 #23
0
ファイル: sceDisplay.cpp プロジェクト: A671DR218/ppsspp
u32 sceDisplayWaitVblankStartCB() {
	VERBOSE_LOG(SCEDISPLAY,"sceDisplayWaitVblankStartCB()");
	vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread()));
	__KernelWaitCurThread(WAITTYPE_VBLANK, 1, 0, 0, true, "vblank start waited");
	return 0;
}
コード例 #24
0
ファイル: __sceAudio.cpp プロジェクト: Motaz-Alnuweiri/ppsspp
u32 __AudioEnqueue(AudioChannel &chan, int chanNum, bool blocking)
{
	u32 ret = chan.sampleCount;

	if (chan.sampleAddress == 0) {
		// For some reason, multichannel audio lies and returns the sample count here.
		if (chanNum == PSP_AUDIO_CHANNEL_SRC || chanNum == PSP_AUDIO_CHANNEL_OUTPUT2) {
			ret = 0;
		}
	}

	// If there's anything on the queue at all, it should be busy, but we try to be a bit lax.
	if (chan.sampleQueue.size() > chan.sampleCount * 2 * chanQueueMaxSizeFactor || chan.sampleAddress == 0) {
		if (blocking) {
			// TODO: Regular multichannel audio seems to block for 64 samples less?  Or enqueue the first 64 sync?
			int blockSamples = chan.sampleQueue.size() / 2 / chanQueueMinSizeFactor;

			AudioChannelWaitInfo waitInfo = {__KernelGetCurThread(), blockSamples};
			chan.waitingThreads.push_back(waitInfo);
			// Also remember the value to return in the waitValue.
			__KernelWaitCurThread(WAITTYPE_AUDIOCHANNEL, (SceUID)chanNum + 1, ret, 0, false, "blocking audio waited");

			// Fall through to the sample queueing, don't want to lose the samples even though
			// we're getting full.  The PSP would enqueue after blocking.
		} else {
			// Non-blocking doesn't even enqueue, but it's not commonly used.
			return SCE_ERROR_AUDIO_CHANNEL_BUSY;
		}
	}

	if (chan.sampleAddress == 0) {
		return ret;
	}

	if (chan.format == PSP_AUDIO_FORMAT_STEREO)
	{
		const u32 totalSamples = chan.sampleCount * 2;

		if (IS_LITTLE_ENDIAN)
		{
			s16 *sampleData = (s16 *) Memory::GetPointer(chan.sampleAddress);

			// Walking a pointer for speed.  But let's make sure we wouldn't trip on an invalid ptr.
			if (Memory::IsValidAddress(chan.sampleAddress + (totalSamples - 1) * sizeof(s16)))
			{
				for (u32 i = 0; i < totalSamples; i++)
					chan.sampleQueue.push(*sampleData++);
			}
		}
		else
		{
			for (u32 i = 0; i < totalSamples; i++)
				chan.sampleQueue.push((s16)Memory::Read_U16(chan.sampleAddress + sizeof(s16) * i));
		}
	}
	else if (chan.format == PSP_AUDIO_FORMAT_MONO)
	{
		for (u32 i = 0; i < chan.sampleCount; i++)
		{
			// Expand to stereo
			s16 sample = (s16)Memory::Read_U16(chan.sampleAddress + 2 * i);
			chan.sampleQueue.push(sample);
			chan.sampleQueue.push(sample);
		}
	}
	return ret;
}
コード例 #25
0
ファイル: __sceAudio.cpp プロジェクト: Bulkman/ppsspp
u32 __AudioEnqueue(AudioChannel &chan, int chanNum, bool blocking) {
	u32 ret = chan.sampleCount;

	if (chan.sampleAddress == 0) {
		// For some reason, multichannel audio lies and returns the sample count here.
		if (chanNum == PSP_AUDIO_CHANNEL_SRC || chanNum == PSP_AUDIO_CHANNEL_OUTPUT2) {
			ret = 0;
		}
	}

	// If there's anything on the queue at all, it should be busy, but we try to be a bit lax.
	//if (chan.sampleQueue.size() > chan.sampleCount * 2 * chanQueueMaxSizeFactor || chan.sampleAddress == 0) {
	if (chan.sampleQueue.size() > 0) {
		if (blocking) {
			// TODO: Regular multichannel audio seems to block for 64 samples less?  Or enqueue the first 64 sync?
			int blockSamples = (int)chan.sampleQueue.size() / 2 / chanQueueMinSizeFactor;

			if (__KernelIsDispatchEnabled()) {
				AudioChannelWaitInfo waitInfo = {__KernelGetCurThread(), blockSamples};
				chan.waitingThreads.push_back(waitInfo);
				// Also remember the value to return in the waitValue.
				__KernelWaitCurThread(WAITTYPE_AUDIOCHANNEL, (SceUID)chanNum + 1, ret, 0, false, "blocking audio");
			} else {
				// TODO: Maybe we shouldn't take this audio after all?
				ret = SCE_KERNEL_ERROR_CAN_NOT_WAIT;
			}

			// Fall through to the sample queueing, don't want to lose the samples even though
			// we're getting full.  The PSP would enqueue after blocking.
		} else {
			// Non-blocking doesn't even enqueue, but it's not commonly used.
			return SCE_ERROR_AUDIO_CHANNEL_BUSY;
		}
	}

	if (chan.sampleAddress == 0) {
		return ret;
	}

	if (chan.format == PSP_AUDIO_FORMAT_STEREO) {
		const u32 totalSamples = chan.sampleCount * 2;

		if (IS_LITTLE_ENDIAN) {
			s16 *sampleData = (s16 *) Memory::GetPointer(chan.sampleAddress);

			// Walking a pointer for speed.  But let's make sure we wouldn't trip on an invalid ptr.
			if (Memory::IsValidAddress(chan.sampleAddress + (totalSamples - 1) * sizeof(s16))) {
#if 0
				for (u32 i = 0; i < totalSamples; i += 2) {
					chan.sampleQueue.push(adjustvolume(*sampleData++, chan.leftVolume));
					chan.sampleQueue.push(adjustvolume(*sampleData++, chan.rightVolume));
				}
#else
				s16 *buf1 = 0, *buf2 = 0;
				size_t sz1, sz2;
				chan.sampleQueue.pushPointers(totalSamples, &buf1, &sz1, &buf2, &sz2);
				int leftVol = chan.leftVolume;
				int rightVol = chan.rightVolume;

				// TODO: SSE/NEON implementations
				for (u32 i = 0; i < sz1; i += 2) {
					buf1[i] = adjustvolume(sampleData[i], leftVol);
					buf1[i + 1] = adjustvolume(sampleData[i + 1], rightVol);
				}
				if (buf2) {
					sampleData += sz1;
					for (u32 i = 0; i < sz2; i += 2) {
						buf2[i] = adjustvolume(sampleData[i], leftVol);
						buf2[i + 1] = adjustvolume(sampleData[i + 1], rightVol);
					}
				}
#endif
			}
		} else {
			for (u32 i = 0; i < totalSamples; i++) {
				s16 sampleL = (s16)Memory::Read_U16(chan.sampleAddress + sizeof(s16) * i);
				sampleL = adjustvolume(sampleL, chan.leftVolume);
				chan.sampleQueue.push(sampleL);
				i++;
				s16 sampleR = (s16)Memory::Read_U16(chan.sampleAddress + sizeof(s16) * i);
				sampleR = adjustvolume(sampleR, chan.rightVolume);
				chan.sampleQueue.push(sampleR);
			}
		}
	}
	else if (chan.format == PSP_AUDIO_FORMAT_MONO) {
		for (u32 i = 0; i < chan.sampleCount; i++) {
			// Expand to stereo
			s16 sample = (s16)Memory::Read_U16(chan.sampleAddress + 2 * i);
			chan.sampleQueue.push(adjustvolume(sample, chan.leftVolume));
			chan.sampleQueue.push(adjustvolume(sample, chan.rightVolume));
		}
	}
	return ret;
}
コード例 #26
0
ファイル: __sceAudio.cpp プロジェクト: metalex10/ppsspp
u32 __AudioEnqueue(AudioChannel &chan, int chanNum, bool blocking) {
	u32 ret = chan.sampleCount;

	if (chan.sampleAddress == 0) {
		// For some reason, multichannel audio lies and returns the sample count here.
		if (chanNum == PSP_AUDIO_CHANNEL_SRC || chanNum == PSP_AUDIO_CHANNEL_OUTPUT2) {
			ret = 0;
		}
	}

	// If there's anything on the queue at all, it should be busy, but we try to be a bit lax.
	//if (chan.sampleQueue.size() > chan.sampleCount * 2 * chanQueueMaxSizeFactor || chan.sampleAddress == 0) {
	if (chan.sampleQueue.size() > 0) {
		if (blocking) {
			// TODO: Regular multichannel audio seems to block for 64 samples less?  Or enqueue the first 64 sync?
			int blockSamples = (int)chan.sampleQueue.size() / 2 / chanQueueMinSizeFactor;

			if (__KernelIsDispatchEnabled()) {
				AudioChannelWaitInfo waitInfo = {__KernelGetCurThread(), blockSamples};
				chan.waitingThreads.push_back(waitInfo);
				// Also remember the value to return in the waitValue.
				__KernelWaitCurThread(WAITTYPE_AUDIOCHANNEL, (SceUID)chanNum + 1, ret, 0, false, "blocking audio");
			} else {
				// TODO: Maybe we shouldn't take this audio after all?
				ret = SCE_KERNEL_ERROR_CAN_NOT_WAIT;
			}

			// Fall through to the sample queueing, don't want to lose the samples even though
			// we're getting full.  The PSP would enqueue after blocking.
		} else {
			// Non-blocking doesn't even enqueue, but it's not commonly used.
			return SCE_ERROR_AUDIO_CHANNEL_BUSY;
		}
	}

	if (chan.sampleAddress == 0) {
		return ret;
	}

	int leftVol = chan.leftVolume;
	int rightVol = chan.rightVolume;

	if (leftVol == (1 << 15) && rightVol == (1 << 15) && chan.format == PSP_AUDIO_FORMAT_STEREO && IS_LITTLE_ENDIAN) {
		// TODO: Add mono->stereo conversion to this path.

		// Good news: the volume doesn't affect the values at all.
		// We can just do a direct memory copy.
		const u32 totalSamples = chan.sampleCount * (chan.format == PSP_AUDIO_FORMAT_STEREO ? 2 : 1);
		s16 *buf1 = 0, *buf2 = 0;
		size_t sz1, sz2;
		chan.sampleQueue.pushPointers(totalSamples, &buf1, &sz1, &buf2, &sz2);

		if (Memory::IsValidAddress(chan.sampleAddress + (totalSamples - 1) * sizeof(s16_le))) {
			Memory::Memcpy(buf1, chan.sampleAddress, (u32)sz1 * sizeof(s16));
			if (buf2)
				Memory::Memcpy(buf2, chan.sampleAddress + (u32)sz1 * sizeof(s16), (u32)sz2 * sizeof(s16));
		}
	} else {
		// Remember that maximum volume allowed is 0xFFFFF so left shift is no issue.
		// This way we can optimally shift by 16.
		leftVol <<=1;
		rightVol <<=1;

		if (chan.format == PSP_AUDIO_FORMAT_STEREO) {
			const u32 totalSamples = chan.sampleCount * 2;

			s16_le *sampleData = (s16_le *) Memory::GetPointer(chan.sampleAddress);

			// Walking a pointer for speed.  But let's make sure we wouldn't trip on an invalid ptr.
			if (Memory::IsValidAddress(chan.sampleAddress + (totalSamples - 1) * sizeof(s16_le))) {
				s16 *buf1 = 0, *buf2 = 0;
				size_t sz1, sz2;
				chan.sampleQueue.pushPointers(totalSamples, &buf1, &sz1, &buf2, &sz2);
				AdjustVolumeBlock(buf1, sampleData, sz1, leftVol, rightVol);
				if (buf2) {
					AdjustVolumeBlock(buf2, sampleData + sz1, sz2, leftVol, rightVol);
				}
			}
		} else if (chan.format == PSP_AUDIO_FORMAT_MONO) {
			// Rare, so unoptimized. Expands to stereo.
			for (u32 i = 0; i < chan.sampleCount; i++) {
				s16 sample = (s16)Memory::Read_U16(chan.sampleAddress + 2 * i);
				chan.sampleQueue.push(ApplySampleVolume(sample, leftVol));
				chan.sampleQueue.push(ApplySampleVolume(sample, rightVol));
			}
		}
	}
	return ret;
}
コード例 #27
0
ファイル: sceDisplay.cpp プロジェクト: Ryalian/ppsspp
void sceDisplayWaitVblankStartCB()
{
	DEBUG_LOG(HLE,"sceDisplayWaitVblankStartCB()");	
	__KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, true);
	__KernelCheckCallbacks();
}
コード例 #28
0
ファイル: sceDisplay.cpp プロジェクト: Ryalian/ppsspp
void sceDisplayWaitVblank()
{
	DEBUG_LOG(HLE,"sceDisplayWaitVblank()");
	__KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, false);
}
コード例 #29
0
ファイル: sceDisplay.cpp プロジェクト: B1ackDaemon/ppsspp
u32 sceDisplayWaitVblankStartMultiCB(int vblanks) {
	VERBOSE_LOG(HLE,"sceDisplayWaitVblankStartMultiCB()");
	vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread(), vblanks));
	__KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, true, "vblank start multi waited");
	return 0;
}
コード例 #30
0
ファイル: sceDisplay.cpp プロジェクト: B1ackDaemon/ppsspp
u32 sceDisplayWaitVblankStart() {
	VERBOSE_LOG(HLE,"sceDisplayWaitVblankStart()");
	vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread()));
	__KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, false, "vblank start waited");
	return 0;
}