Exemple #1
0
void __UmdBeginCallback(SceUID threadID, SceUID prevCallbackId)
{
	SceUID pauseKey = prevCallbackId == 0 ? threadID : prevCallbackId;

	if (HLEKernel::VerifyWait(threadID, WAITTYPE_UMD, 1))
	{
		// This means two callbacks in a row.  PSP crashes if the same callback runs inside itself.
		// TODO: Handle this better?
		if (umdPausedWaits.find(pauseKey) != umdPausedWaits.end())
			return;

		_dbg_assert_msg_(SCEIO, umdStatTimeoutEvent != -1, "Must have a umd timer");
		s64 cyclesLeft = CoreTiming::UnscheduleEvent(umdStatTimeoutEvent, threadID);
		if (cyclesLeft != 0)
			umdPausedWaits[pauseKey] = CoreTiming::GetTicks() + cyclesLeft;
		else
			umdPausedWaits[pauseKey] = 0;

		HLEKernel::RemoveWaitingThread(umdWaitingThreads, threadID);

		DEBUG_LOG(SCEIO, "sceUmdWaitDriveStatCB: Suspending lock wait for callback");
	}
	else
		WARN_LOG_REPORT(SCEIO, "sceUmdWaitDriveStatCB: beginning callback with bad wait id?");
}
Exemple #2
0
static u32 sceDmacMemcpy(u32 dst, u32 src, u32 size) {
	if (size == 0) {
		// Some games seem to do this frequently.
		DEBUG_LOG(HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i): invalid size", dst, src, size);
		return SCE_KERNEL_ERROR_INVALID_SIZE;
	}
	if (!Memory::IsValidAddress(dst) || !Memory::IsValidAddress(src)) {
		ERROR_LOG(HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i): invalid address", dst, src, size);
		return SCE_KERNEL_ERROR_INVALID_POINTER;
	}
	if (dst + size >= 0x80000000 || src + size >= 0x80000000 || size >= 0x80000000) {
		ERROR_LOG(HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i): illegal size", dst, src, size);
		return SCE_KERNEL_ERROR_PRIV_REQUIRED;
	}

	if (dmacMemcpyDeadline > CoreTiming::GetTicks()) {
		WARN_LOG_REPORT(HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i): overlapping read", dst, src, size);
		// TODO: Should block, seems like copy doesn't start until previous finishes.
		// Might matter for overlapping copies.
	} else {
		DEBUG_LOG(HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i)", dst, src, size);
	}

	return __DmacMemcpy(dst, src, size);
}
Exemple #3
0
void PostPutAction::run(MipsCall &call) {
	SceMpegRingBuffer ringbuffer;
	Memory::ReadStruct(ringAddr_, &ringbuffer);

	MpegContext *ctx = getMpegCtx(ringbuffer.mpeg);

	int packetsAdded = currentMIPS->r[2];
	if (ringbuffer.packetsRead == 0 && ctx->mediaengine && packetsAdded > 0) {
		// init mediaEngine
		AnalyzeMpeg(ctx->mpegheader, ctx);
		ctx->mediaengine->loadStream(ctx->mpegheader, 2048, ringbuffer.packets * ringbuffer.packetSize);
	}
	if (packetsAdded > 0) {
		if (packetsAdded > ringbuffer.packetsFree) {
			WARN_LOG(ME, "sceMpegRingbufferPut clamping packetsAdded old=%i new=%i", packetsAdded, ringbuffer.packetsFree);
			packetsAdded = ringbuffer.packetsFree;
		}
		int actuallyAdded = ctx->mediaengine == NULL ? 8 : ctx->mediaengine->addStreamData(Memory::GetPointer(ringbuffer.data), packetsAdded * 2048) / 2048;
		if (actuallyAdded != packetsAdded) {
			WARN_LOG_REPORT(ME, "sceMpegRingbufferPut(): unable to enqueue all added packets, going to overwrite some frames.");
		}
		ringbuffer.packetsRead += packetsAdded;
		ringbuffer.packetsWritten += packetsAdded;
		ringbuffer.packetsFree -= packetsAdded;
	}
	DEBUG_LOG(ME, "packetAdded: %i packetsRead: %i packetsTotal: %i", packetsAdded, ringbuffer.packetsRead, ringbuffer.packets);

	Memory::WriteStruct(ringAddr_, &ringbuffer);
	call.setReturnValue(packetsAdded);
}
Exemple #4
0
int MetaFileSystem::ChDir(const std::string &dir)
{
	lock_guard guard(lock);
	// Retain the old path and fail if the arg is 1023 bytes or longer.
	if (dir.size() >= 1023)
		return SCE_KERNEL_ERROR_NAMETOOLONG;

	int curThread = __KernelGetCurThread();
	
	std::string of;
	MountPoint *mountPoint;
	if (MapFilePath(dir, of, &mountPoint))
	{
		currentDir[curThread] = mountPoint->prefix + of;
		return 0;
	}
	else
	{
		for (size_t i = 0; i < fileSystems.size(); i++)
		{
			const std::string &prefix = fileSystems[i].prefix;
			if (strncasecmp(prefix.c_str(), dir.c_str(), prefix.size()) == 0)
			{
				// The PSP is completely happy with invalid current dirs as long as they have a valid device.
				WARN_LOG(HLE, "ChDir failed to map path \"%s\", saving as current directory anyway", dir.c_str());
				currentDir[curThread] = dir;
				return 0;
			}
		}

		WARN_LOG_REPORT(HLE, "ChDir failed to map device for \"%s\", failing", dir.c_str());
		return SCE_KERNEL_ERROR_NODEV;
	}
}
Exemple #5
0
void __KernelMutexBeginCallback(SceUID threadID, SceUID prevCallbackId)
{
    SceUID pauseKey = prevCallbackId == 0 ? threadID : prevCallbackId;

    u32 error;
    SceUID mutexID = __KernelGetWaitID(threadID, WAITTYPE_MUTEX, error);
    u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error);
    Mutex *mutex = mutexID == 0 ? NULL : kernelObjects.Get<Mutex>(mutexID, error);
    if (mutex)
    {
        // This means two callbacks in a row.  PSP crashes if the same callback runs inside itself.
        // TODO: Handle this better?
        if (mutex->pausedWaitTimeouts.find(pauseKey) != mutex->pausedWaitTimeouts.end())
            return;

        if (timeoutPtr != 0 && mutexWaitTimer != -1)
        {
            s64 cyclesLeft = CoreTiming::UnscheduleEvent(mutexWaitTimer, threadID);
            mutex->pausedWaitTimeouts[pauseKey] = CoreTiming::GetTicks() + cyclesLeft;
        }
        else
            mutex->pausedWaitTimeouts[pauseKey] = 0;

        // TODO: Hmm, what about priority/fifo order?  Does it lose its place in line?
        mutex->waitingThreads.erase(std::remove(mutex->waitingThreads.begin(), mutex->waitingThreads.end(), threadID), mutex->waitingThreads.end());

        DEBUG_LOG(HLE, "sceKernelLockMutexCB: Suspending lock wait for callback");
    }
    else
        WARN_LOG_REPORT(HLE, "sceKernelLockMutexCB: beginning callback with bad wait id?");
}
Exemple #6
0
void __DisplayVblankBeginCallback(SceUID threadID, SceUID prevCallbackId) {
	SceUID pauseKey = prevCallbackId == 0 ? threadID : prevCallbackId;

	// This means two callbacks in a row.  PSP crashes if the same callback waits inside itself (may need more testing.)
	// TODO: Handle this better?
	if (vblankPausedWaits.find(pauseKey) != vblankPausedWaits.end()) {
		return;
	}

	WaitVBlankInfo waitData(0);
	for (size_t i = 0; i < vblankWaitingThreads.size(); i++) {
		WaitVBlankInfo *t = &vblankWaitingThreads[i];
		if (t->threadID == threadID) {
			waitData = *t;
			vblankWaitingThreads.erase(vblankWaitingThreads.begin() + i);
			break;
		}
	}

	if (waitData.threadID != threadID) {
		WARN_LOG_REPORT(SCEDISPLAY, "sceDisplayWaitVblankCB: could not find waiting thread info.");
		return;
	}

	vblankPausedWaits[pauseKey] = vCount + waitData.vcountUnblock;
	DEBUG_LOG(SCEDISPLAY, "sceDisplayWaitVblankCB: Suspending vblank wait for callback");
}
u32 sceKernelRegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handler, u32 handlerArg) {
	if (intrNumber >= PSP_NUMBER_INTERRUPTS) {
		ERROR_LOG_REPORT(SCEINTC, "sceKernelRegisterSubIntrHandler(%i, %i, %08x, %08x): invalid interrupt", intrNumber, subIntrNumber, handler, handlerArg);
		return SCE_KERNEL_ERROR_ILLEGAL_INTRCODE;
	}
	if (subIntrNumber >= PSP_NUMBER_SUBINTERRUPTS) {
		ERROR_LOG_REPORT(SCEINTC, "sceKernelRegisterSubIntrHandler(%i, %i, %08x, %08x): invalid subinterrupt", intrNumber, subIntrNumber, handler, handlerArg);
		return SCE_KERNEL_ERROR_ILLEGAL_INTRCODE;
	}

	u32 error;
	SubIntrHandler *subIntrHandler = __RegisterSubIntrHandler(intrNumber, subIntrNumber, handler, handlerArg, error);
	if (subIntrHandler) {
		if (handler == 0) {
			WARN_LOG_REPORT(SCEINTC, "sceKernelRegisterSubIntrHandler(%i, %i, %08x, %08x): ignored NULL handler", intrNumber, subIntrNumber, handler, handlerArg);
		} else {
			DEBUG_LOG(SCEINTC, "sceKernelRegisterSubIntrHandler(%i, %i, %08x, %08x)", intrNumber, subIntrNumber, handler, handlerArg);
		}
	} else if (error = SCE_KERNEL_ERROR_FOUND_HANDLER) {
		ERROR_LOG_REPORT(SCEINTC, "sceKernelRegisterSubIntrHandler(%i, %i, %08x, %08x): duplicate handler", intrNumber, subIntrNumber, handler, handlerArg);
	} else {
		ERROR_LOG_REPORT(SCEINTC, "sceKernelRegisterSubIntrHandler(%i, %i, %08x, %08x): error %08x", intrNumber, subIntrNumber, handler, handlerArg, error);
	}
	return error;
}
Exemple #8
0
static u32 sceHeapAllocHeapMemoryWithOption(u32 heapAddr, u32 memSize, u32 paramsPtr) {
	Heap *heap = getHeap(heapAddr);
	u32 grain = 4;
	if (!heap) {
		ERROR_LOG(HLE, "sceHeapAllocHeapMemoryWithOption(%08x, %08x, %08x): invalid heap", heapAddr, memSize, paramsPtr);
		return 0;
	}

	// 0 is ignored.
	if (paramsPtr != 0) {
		u32 size = Memory::Read_U32(paramsPtr);
		if (size < 8) {
			ERROR_LOG(HLE, "sceHeapAllocHeapMemoryWithOption(%08x, %08x, %08x): invalid param size", heapAddr, memSize, paramsPtr);
			return 0;
		}
		if (size > 8) {
			WARN_LOG_REPORT(HLE, "sceHeapAllocHeapMemoryWithOption(): unexpected param size %d", size);
		}
		grain = Memory::Read_U32(paramsPtr + 4);
	}

	DEBUG_LOG(HLE,"sceHeapAllocHeapMemoryWithOption(%08x, %08x, %08x)", heapAddr, memSize, paramsPtr);
	// There's 8 bytes at the end of every block, reserved.
	memSize += 8;
	u32 addr = heap->alloc.AllocAligned(memSize, grain, grain, true);
	return addr;
}
Exemple #9
0
int sceHeapCreateHeap(const char* name, u32 heapSize, int attr, u32 paramsPtr) {
	if (paramsPtr != 0) {
		u32 size = Memory::Read_U32(paramsPtr);
		WARN_LOG_REPORT(SCEKERNEL, "sceHeapCreateHeap(): unsupported options parameter, size = %d", size);
	}	
	if (name == NULL) {
		WARN_LOG(SCEKERNEL,"sceHeapCreateHeap(): name is NULL");
		return 0;
	}
	int allocSize = (heapSize + 3) & ~3;

	Heap *heap = new Heap;
	heap->size = allocSize;
	heap->fromtop = (attr & PSP_HEAP_ATTR_HIGHMEM) != 0;
	u32 addr = userMemory.Alloc(heap->size, heap->fromtop, "Heap");
	if (addr == (u32)-1) {
		ERROR_LOG(SCEKERNEL, "sceHeapCreateHeap(): Failed to allocate %i bytes memory", allocSize);	
		delete heap;
		return 0;
	}
	heap->address = addr;
	heap->alloc.Init(heap->address,heap->size);
	heapList[heap->address] = heap;
	DEBUG_LOG(HLE,"sceHeapCreateHeap(%s, %08x, %08x, %08x)", name, heapSize, attr, paramsPtr);
	return heap->address;
}
Exemple #10
0
int sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 optionsPtr)
{
	if (!name)
	{
		WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateMutex(): invalid name", SCE_KERNEL_ERROR_ERROR);
		return SCE_KERNEL_ERROR_ERROR;
	}
	if (attr & ~0xBFF)
	{
		WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateMutex(): invalid attr parameter: %08x", SCE_KERNEL_ERROR_ILLEGAL_ATTR, attr);
		return SCE_KERNEL_ERROR_ILLEGAL_ATTR;
	}

	if (initialCount < 0)
		return SCE_KERNEL_ERROR_ILLEGAL_COUNT;
	if ((attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE) == 0 && initialCount > 1)
		return SCE_KERNEL_ERROR_ILLEGAL_COUNT;

	Mutex *mutex = new Mutex();
	SceUID id = kernelObjects.Create(mutex);

	mutex->nm.size = sizeof(mutex->nm);
	strncpy(mutex->nm.name, name, KERNELOBJECT_MAX_NAME_LENGTH);
	mutex->nm.name[KERNELOBJECT_MAX_NAME_LENGTH] = 0;
	mutex->nm.attr = attr;
	mutex->nm.initialCount = initialCount;
	if (initialCount == 0)
	{
		mutex->nm.lockLevel = 0;
		mutex->nm.lockThread = -1;
	}
	else
		__KernelMutexAcquireLock(mutex, initialCount);

	DEBUG_LOG(HLE, "%i=sceKernelCreateMutex(%s, %08x, %d, %08x)", id, name, attr, initialCount, optionsPtr);

	if (optionsPtr != 0)
	{
		u32 size = Memory::Read_U32(optionsPtr);
		if (size != 0)
			WARN_LOG_REPORT(HLE, "sceKernelCreateMutex(%s) unsupported options parameter, size = %d", name, size);
	}
	if ((attr & ~PSP_MUTEX_ATTR_KNOWN) != 0)
		WARN_LOG_REPORT(HLE, "sceKernelCreateMutex(%s) unsupported attr parameter: %08x", name, attr);

	return id;
}
void __KernelSemaBeginCallback(SceUID threadID, SceUID prevCallbackId)
{
	auto result = HLEKernel::WaitBeginCallback<Semaphore, WAITTYPE_SEMA, SceUID>(threadID, prevCallbackId, semaWaitTimer);
	if (result == HLEKernel::WAIT_CB_SUCCESS)
		DEBUG_LOG(SCEKERNEL, "sceKernelWaitSemaCB: Suspending sema wait for callback")
	else
		WARN_LOG_REPORT(SCEKERNEL, "sceKernelWaitSemaCB: beginning callback with bad wait id?");
}
Exemple #12
0
void __AudioSetOutputFrequency(int freq) {
	if (freq != 44100) {
		WARN_LOG_REPORT(SCEAUDIO, "Switching audio frequency to %i", freq);
	} else {
		DEBUG_LOG(SCEAUDIO, "Switching audio frequency to %i", freq);
	}
	mixFrequency = freq;
}
void __KernelLwMutexBeginCallback(SceUID threadID, SceUID prevCallbackId)
{
	auto result = HLEKernel::WaitBeginCallback<LwMutex, WAITTYPE_LWMUTEX, SceUID>(threadID, prevCallbackId, lwMutexWaitTimer);
	if (result == HLEKernel::WAIT_CB_SUCCESS)
		DEBUG_LOG(SCEKERNEL, "sceKernelLockLwMutexCB: Suspending lock wait for callback");
	else
		WARN_LOG_REPORT(SCEKERNEL, "sceKernelLockLwMutexCB: beginning callback with bad wait id?");
}
Exemple #14
0
int ISOFileSystem::Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) {
	EntryMap::iterator iter = entries.find(handle);
	if (iter == entries.end()) {
		ERROR_LOG(FILESYS, "Ioctl on a bad file handle");
		return SCE_KERNEL_ERROR_BADF;
	}

	OpenFileEntry &e = iter->second;

	switch (cmd) {
	// Get ISO9660 volume descriptor (from open ISO9660 file.)
	case 0x01020001:
		if (e.isBlockSectorMode) {
			ERROR_LOG(FILESYS, "Unsupported read volume descriptor command on a umd block device");
			return SCE_KERNEL_ERROR_ERRNO_FUNCTION_NOT_SUPPORTED;
		}

		if (!Memory::IsValidAddress(outdataPtr) || outlen < 0x800) {
			WARN_LOG_REPORT(FILESYS, "sceIoIoctl: Invalid out pointer while reading ISO9660 volume descriptor");
			return SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT;
		}

		INFO_LOG(SCEIO, "sceIoIoctl: reading ISO9660 volume descriptor read");
		blockDevice->ReadBlock(16, Memory::GetPointer(outdataPtr));
		return 0;

	// Get ISO9660 path table (from open ISO9660 file.)
	case 0x01020002:
		if (e.isBlockSectorMode) {
			ERROR_LOG(FILESYS, "Unsupported read path table command on a umd block device");
			return SCE_KERNEL_ERROR_ERRNO_FUNCTION_NOT_SUPPORTED;
		}

		VolDescriptor desc;
		blockDevice->ReadBlock(16, (u8 *)&desc);
		if (outlen < (u32)desc.pathTableLengthLE) {
			return SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT;
		} else {
			int block = (u16)desc.firstLETableSectorLE;
			u32 size = (u32)desc.pathTableLengthLE;
			u8 *out = Memory::GetPointer(outdataPtr);

			int blocks = size / blockDevice->GetBlockSize();
			blockDevice->ReadBlocks(block, blocks, out);
			size -= blocks * blockDevice->GetBlockSize();
			out += blocks * blockDevice->GetBlockSize();

			// The remaining (or, usually, only) partial sector.
			if (size > 0) {
				u8 temp[2048];
				blockDevice->ReadBlock(block, temp);
				memcpy(out, temp, size);
			}
			return 0;
		}
	}
	return SCE_KERNEL_ERROR_ERRNO_FUNCTION_NOT_SUPPORTED;
}
void PSPSaveDialog::StartIOThread() {
	if (ioThread) {
		WARN_LOG_REPORT(SCEUTILITY, "Starting a save io thread when one already pending, uh oh.");
		JoinIOThread();
	}

	ioThreadStatus = SAVEIO_PENDING;
	ioThread = new std::thread(&DoExecuteIOAction, this);
}
Exemple #16
0
int sceKernelPollEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 timeoutPtr)
{
	DEBUG_LOG(HLE, "sceKernelPollEventFlag(%i, %08x, %i, %08x, %08x)", id, bits, wait, outBitsPtr, timeoutPtr);

	if ((wait & ~PSP_EVENT_WAITKNOWN) != 0)
	{
		WARN_LOG_REPORT(HLE, "sceKernelPollEventFlag(%i) invalid mode parameter: %08x", id, wait);
		return SCE_KERNEL_ERROR_ILLEGAL_MODE;
	}
	// Poll seems to also fail when CLEAR and CLEARALL are used together, but not wait.
	if ((wait & PSP_EVENT_WAITCLEAR) != 0 && (wait & PSP_EVENT_WAITCLEARALL) != 0)
	{
		WARN_LOG_REPORT(HLE, "sceKernelPollEventFlag(%i) invalid mode parameter: %08x", id, wait);
		return SCE_KERNEL_ERROR_ILLEGAL_MODE;
	}
	// Can't wait on 0, it never matches.
	if (bits == 0)
		return SCE_KERNEL_ERROR_EVF_ILPAT;

	u32 error;
	EventFlag *e = kernelObjects.Get<EventFlag>(id, error);
	if (e)
	{
		if (!__KernelEventFlagMatches(&e->nef.currentPattern, bits, wait, outBitsPtr))
		{
			if (Memory::IsValidAddress(outBitsPtr))
				Memory::Write_U32(e->nef.currentPattern, outBitsPtr);

			if (e->waitingThreads.size() > 0 && (e->nef.attr & PSP_EVENT_WAITMULTIPLE) == 0)
				return SCE_KERNEL_ERROR_EVF_MULTI;

			// No match - return that, this is polling, not waiting.
			return SCE_KERNEL_ERROR_EVF_COND;
		}
		else
		{
			return 0;
		}
	}
	else
	{
		return error;
	}
}
Exemple #17
0
void __KernelMbxBeginCallback(SceUID threadID, SceUID prevCallbackId)
{
	auto result = HLEKernel::WaitBeginCallback<Mbx, WAITTYPE_SEMA, MbxWaitingThread>(threadID, prevCallbackId, mbxWaitTimer);
	if (result == HLEKernel::WAIT_CB_SUCCESS)
		DEBUG_LOG(SCEKERNEL, "sceKernelReceiveMbxCB: Suspending mbx wait for callback");
	else if (result == HLEKernel::WAIT_CB_BAD_WAIT_DATA)
		ERROR_LOG_REPORT(SCEKERNEL, "sceKernelReceiveMbxCB: wait not found to pause for callback");
	else
		WARN_LOG_REPORT(SCEKERNEL, "sceKernelReceiveMbxCB: beginning callback with bad wait id?");
}
void __KernelEventFlagBeginCallback(SceUID threadID, SceUID prevCallbackId)
{
	auto result = HLEKernel::WaitBeginCallback<EventFlag, WAITTYPE_EVENTFLAG, EventFlagTh>(threadID, prevCallbackId, eventFlagWaitTimer);
	if (result == HLEKernel::WAIT_CB_SUCCESS)
		DEBUG_LOG(SCEKERNEL, "sceKernelWaitEventFlagCB: Suspending lock wait for callback")
	else if (result == HLEKernel::WAIT_CB_BAD_WAIT_DATA)
		ERROR_LOG_REPORT(SCEKERNEL, "sceKernelWaitEventFlagCB: wait not found to pause for callback")
	else
		WARN_LOG_REPORT(SCEKERNEL, "sceKernelWaitEventFlagCB: beginning callback with bad wait id?");
}
Exemple #19
0
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;
	}
}
Exemple #20
0
bool MediaEngine::openContext() {
#ifdef USE_FFMPEG
	InitFFmpeg();

	if (m_pFormatCtx || !m_pdata)
		return false;
	m_mpegheaderReadPos = 0;
	m_decodingsize = 0;

	u8* tempbuf = (u8*)av_malloc(m_bufSize);

	m_pFormatCtx = avformat_alloc_context();
	m_pIOContext = avio_alloc_context(tempbuf, m_bufSize, 0, (void*)this, _MpegReadbuffer, NULL, 0);
	m_pFormatCtx->pb = m_pIOContext;

	// Open video file
	if (avformat_open_input((AVFormatContext**)&m_pFormatCtx, NULL, NULL, NULL) != 0)
		return false;

	if (avformat_find_stream_info(m_pFormatCtx, NULL) < 0) {
		closeContext();
		return false;
	}

	if (m_videoStream >= (int)m_pFormatCtx->nb_streams) {
		WARN_LOG_REPORT(ME, "Bad video stream %d", m_videoStream);
		m_videoStream = -1;
	}

	if (m_videoStream == -1) {
		// Find the first video stream
		for(int i = 0; i < (int)m_pFormatCtx->nb_streams; i++) {
			if(m_pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
				m_videoStream = i;
				break;
			}
		}
		if(m_videoStream == -1)
			return false;
	}

	if (!setVideoStream(m_videoStream, true))
		return false;

	setVideoDim();
	m_audioContext = AT3Create();
	m_isVideoEnd = false;
	m_noAudioData = false;
	m_mpegheaderReadPos++;
	av_seek_frame(m_pFormatCtx, m_videoStream, 0, 0);
#endif // USE_FFMPEG
	return true;
}
Exemple #21
0
void __KernelStartModule(Module *m, int args, const char *argp, SceKernelSMOption *options)
{
	if (m->nm.module_start_func != 0 && m->nm.module_start_func != (u32)-1)
	{
		if (m->nm.module_start_func != m->nm.entry_addr)
			WARN_LOG_REPORT(LOADER, "Main module has start func (%08x) different from entry (%08x)?", m->nm.module_start_func, m->nm.entry_addr);
	}

	__KernelSetupRootThread(m->GetUID(), args, argp, options->priority, options->stacksize, options->attribute);
	mainModuleID = m->GetUID();
	//TODO: if current thread, put it in wait state, waiting for the new thread
}
Exemple #22
0
//SceUID sceKernelCreateEventFlag(const char *name, int attr, int bits, SceKernelEventFlagOptParam *opt);
int sceKernelCreateEventFlag(const char *name, u32 flag_attr, u32 flag_initPattern, u32 optPtr)
{
	if (!name)
	{
		WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateEventFlag(): invalid name", SCE_KERNEL_ERROR_ERROR);
		return SCE_KERNEL_ERROR_ERROR;
	}

	// These attributes aren't valid.
	if ((flag_attr & 0x100) != 0 || flag_attr >= 0x300)
	{
		WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateEventFlag(): invalid attr parameter: %08x", SCE_KERNEL_ERROR_ILLEGAL_ATTR, flag_attr);
		return SCE_KERNEL_ERROR_ILLEGAL_ATTR;
	}

	EventFlag *e = new EventFlag();
	SceUID id = kernelObjects.Create(e);

	e->nef.size = sizeof(NativeEventFlag);
	strncpy(e->nef.name, name, KERNELOBJECT_MAX_NAME_LENGTH);
	e->nef.name[KERNELOBJECT_MAX_NAME_LENGTH] = 0;
	e->nef.attr = flag_attr;
	e->nef.initPattern = flag_initPattern;
	e->nef.currentPattern = e->nef.initPattern;
	e->nef.numWaitThreads = 0;

	DEBUG_LOG(HLE, "%i=sceKernelCreateEventFlag(\"%s\", %08x, %08x, %08x)", id, e->nef.name, e->nef.attr, e->nef.currentPattern, optPtr);

	if (optPtr != 0)
	{
		u32 size = Memory::Read_U32(optPtr);
		if (size > 4)
			WARN_LOG_REPORT(HLE, "sceKernelCreateEventFlag(%s) unsupported options parameter, size = %d", name, size);
	}
	if ((flag_attr & ~PSP_EVENT_WAITMULTIPLE) != 0)
		WARN_LOG_REPORT(HLE, "sceKernelCreateEventFlag(%s) unsupported attr parameter: %08x", name, flag_attr);

	return id;
}
int sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u32 optionPtr)
{
	if (!name)
	{
		WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateSema(): invalid name", SCE_KERNEL_ERROR_ERROR);
		return SCE_KERNEL_ERROR_ERROR;
	}
	if (attr >= 0x200)
	{
		WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateSema(): invalid attr parameter: %08x", SCE_KERNEL_ERROR_ILLEGAL_ATTR, attr);
		return SCE_KERNEL_ERROR_ILLEGAL_ATTR;
	}

	Semaphore *s = new Semaphore;
	SceUID id = kernelObjects.Create(s);

	s->ns.size = sizeof(NativeSemaphore);
	strncpy(s->ns.name, name, KERNELOBJECT_MAX_NAME_LENGTH);
	s->ns.name[KERNELOBJECT_MAX_NAME_LENGTH] = 0;
	s->ns.attr = attr;
	s->ns.initCount = initVal;
	s->ns.currentCount = s->ns.initCount;
	s->ns.maxCount = maxVal;
	s->ns.numWaitThreads = 0;

	DEBUG_LOG(HLE, "%i=sceKernelCreateSema(%s, %08x, %i, %i, %08x)", id, s->ns.name, s->ns.attr, s->ns.initCount, s->ns.maxCount, optionPtr);

	if (optionPtr != 0)
	{
		u32 size = Memory::Read_U32(optionPtr);
		if (size > 4)
			WARN_LOG_REPORT(HLE, "sceKernelCreateSema(%s) unsupported options parameter, size = %d", name, size);
	}
	if ((attr & ~PSP_SEMA_ATTR_PRIORITY) != 0)
		WARN_LOG_REPORT(HLE, "sceKernelCreateSema(%s) unsupported attr parameter: %08x", name, attr);

	return id;
}
Exemple #24
0
SceUID sceKernelCreateMbx(const char *name, u32 attr, u32 optAddr)
{
	if (!name)
	{
		WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateMbx(): invalid name", SCE_KERNEL_ERROR_ERROR);
		return SCE_KERNEL_ERROR_ERROR;
	}
	// Accepts 0x000 - 0x0FF, 0x100 - 0x1FF, and 0x400 - 0x4FF.
	if (((attr & ~SCE_KERNEL_MBA_ATTR_KNOWN) & ~0xFF) != 0)
	{
		WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateMbx(): invalid attr parameter: %08x", SCE_KERNEL_ERROR_ILLEGAL_ATTR, attr);
		return SCE_KERNEL_ERROR_ILLEGAL_ATTR;
	}

	Mbx *m = new Mbx();
	SceUID id = kernelObjects.Create(m);

	m->nmb.size = sizeof(NativeMbx);
	strncpy(m->nmb.name, name, KERNELOBJECT_MAX_NAME_LENGTH);
	m->nmb.name[KERNELOBJECT_MAX_NAME_LENGTH] = 0;
	m->nmb.attr = attr;
	m->nmb.numWaitThreads = 0;
	m->nmb.numMessages = 0;
	m->nmb.packetListHead = 0;

	DEBUG_LOG(HLE, "%i=sceKernelCreateMbx(%s, %08x, %08x)", id, name, attr, optAddr);

	if (optAddr != 0)
	{
		u32 size = Memory::Read_U32(optAddr);
		if (size > 4)
			WARN_LOG_REPORT(HLE, "sceKernelCreateMbx(%s) unsupported options parameter, size = %d", name, size);
	}
	if ((attr & ~SCE_KERNEL_MBA_ATTR_KNOWN) != 0)
		WARN_LOG_REPORT(HLE, "sceKernelCreateMbx(%s) unsupported attr parameter: %08x", name, attr);

	return id;
}
Exemple #25
0
bool MetaFileSystem::MapFilePath(const std::string &_inpath, std::string &outpath, MountPoint **system)
{
	std::string realpath;

	// Special handling: host0:command.txt (as seen in Super Monkey Ball Adventures, for example)
	// appears to mean the current directory on the UMD. Let's just assume the current directory.
	std::string inpath = _inpath;
	if (strncasecmp(inpath.c_str(), "host0:", strlen("host0:")) == 0) {
		INFO_LOG(HLE, "Host0 path detected, stripping: %s", inpath.c_str());
		inpath = inpath.substr(strlen("host0:"));
	}

	const std::string *currentDirectory = &startingDirectory;

	int currentThread = __KernelGetCurThread();
	currentDir_t::iterator it = currentDir.find(currentThread);
	if (it == currentDir.end()) 
	{
		//Attempt to emulate SCE_KERNEL_ERROR_NOCWD / 8002032C: may break things requiring fixes elsewhere
		if (inpath.find(':') == std::string::npos /* means path is relative */) 
		{
			ioErrorCode = SCE_KERNEL_ERROR_NOCWD;
			WARN_LOG_REPORT(HLE, "Path is relative, but current directory not set for thread %i. returning 8002032C(SCE_KERNEL_ERROR_NOCWD) instead.", currentThread);
		}
	}
	else
	{
		currentDirectory = &(it->second);
	}

	if ( RealPath(*currentDirectory, inpath, realpath) )
	{
		for (size_t i = 0; i < fileSystems.size(); i++)
		{
			size_t prefLen = fileSystems[i].prefix.size();
			if (strncasecmp(fileSystems[i].prefix.c_str(), realpath.c_str(), prefLen) == 0)
			{
				outpath = realpath.substr(prefLen);
				*system = &(fileSystems[i]);

				VERBOSE_LOG(HLE, "MapFilePath: mapped \"%s\" to prefix: \"%s\", path: \"%s\"", inpath.c_str(), fileSystems[i].prefix.c_str(), outpath.c_str());

				return true;
			}
		}
	}

	DEBUG_LOG(HLE, "MapFilePath: failed mapping \"%s\", returning false", inpath.c_str());
	return false;
}
Exemple #26
0
//TODO: Implement all sceUtilityScreenshot* for real, it doesn't seem to be complex
//but it requires more investigation
u32 sceUtilityScreenshotInitStart(u32 unknown1, u32 unknown2, u32 unknown3, u32 unknown4, u32 unknown5, u32 unknown6)
{
	if (currentDialogActive && currentDialogType != UTILITY_DIALOG_SCREENSHOT)
	{
		WARN_LOG(HLE, "sceUtilityScreenshotInitStart(%x, %x, %x, %x, %x, %x): wrong dialog type", unknown1, unknown2, unknown3, unknown4, unknown5, unknown6);
		return SCE_ERROR_UTILITY_WRONG_TYPE;
	}
	currentDialogType = UTILITY_DIALOG_SCREENSHOT;
	currentDialogActive = true;

	u32 retval = screenshotDialog.Init();
	WARN_LOG_REPORT(HLE, "UNIMPL %i=sceUtilityScreenshotInitStart(%x, %x, %x, %x, %x, %x)", retval, unknown1, unknown2, unknown3, unknown4, unknown5, unknown6);
	return retval;
}
Exemple #27
0
//TODO: Implement all sceUtilityScreenshot* for real, it doesn't seem to be complex
//but it requires more investigation
u32 sceUtilityScreenshotInitStart(u32 paramAddr)
{
	if (currentDialogActive && currentDialogType != UTILITY_DIALOG_SCREENSHOT)
	{
		WARN_LOG(SCEUTILITY, "sceUtilityScreenshotInitStart(%08x): wrong dialog type", paramAddr);
		return SCE_ERROR_UTILITY_WRONG_TYPE;
	}
	
	currentDialogType = UTILITY_DIALOG_SCREENSHOT;
	currentDialogActive = true;
	u32 retval = screenshotDialog.Init();
	WARN_LOG_REPORT(SCEUTILITY, "%08x=sceUtilityScreenshotInitStart(%08x)", retval, paramAddr);
	return retval;
}
Exemple #28
0
void __KernelEventFlagBeginCallback(SceUID threadID, SceUID prevCallbackId)
{
	SceUID pauseKey = prevCallbackId == 0 ? threadID : prevCallbackId;

	u32 error;
	SceUID flagID = __KernelGetWaitID(threadID, WAITTYPE_EVENTFLAG, error);
	u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error);
	EventFlag *flag = flagID == 0 ? NULL : kernelObjects.Get<EventFlag>(flagID, error);
	if (flag)
	{

		// This means two callbacks in a row.  PSP crashes if the same callback runs inside itself.
		// TODO: Handle this better?
		if (flag->pausedWaits.find(pauseKey) != flag->pausedWaits.end())
			return;

		EventFlagTh waitData = {0};
		for (size_t i = 0; i < flag->waitingThreads.size(); i++)
		{
			EventFlagTh *t = &flag->waitingThreads[i];
			if (t->tid == threadID)
			{
				waitData = *t;
				// TODO: Hmm, what about priority/fifo order?  Does it lose its place in line?
				flag->waitingThreads.erase(flag->waitingThreads.begin() + i);
				break;
			}
		}

		if (waitData.tid != threadID)
		{
			ERROR_LOG_REPORT(HLE, "sceKernelWaitEventFlagCB: wait not found to pause for callback");
			return;
		}

		if (timeoutPtr != 0 && eventFlagWaitTimer != -1)
		{
			s64 cyclesLeft = CoreTiming::UnscheduleEvent(eventFlagWaitTimer, threadID);
			waitData.pausedTimeout = CoreTiming::GetTicks() + cyclesLeft;
		}
		else
			waitData.pausedTimeout = 0;

		flag->pausedWaits[pauseKey] = waitData;
		DEBUG_LOG(HLE, "sceKernelWaitEventFlagCB: Suspending lock wait for callback");
	}
	else
		WARN_LOG_REPORT(HLE, "sceKernelWaitEventFlagCB: beginning callback with bad wait id?");
}
u32 sceKernelCreateVTimer(const char *name, u32 optParamAddr) {
	if (!name) {
		WARN_LOG_REPORT(HLE, "%08x=sceKernelCreateVTimer(): invalid name", SCE_KERNEL_ERROR_ERROR);
		return SCE_KERNEL_ERROR_ERROR;
	}
	DEBUG_LOG(HLE, "sceKernelCreateVTimer(%s, %08x)", name, optParamAddr);

	VTimer *vtimer = new VTimer;
	SceUID id = kernelObjects.Create(vtimer);

	memset(&vtimer->nvt, 0, sizeof(NativeVTimer));
	vtimer->nvt.size = sizeof(NativeVTimer);
	strncpy(vtimer->nvt.name, name, KERNELOBJECT_MAX_NAME_LENGTH);
	vtimer->nvt.name[KERNELOBJECT_MAX_NAME_LENGTH] = '\0';
	vtimer->memoryPtr = 0;

	if (optParamAddr != 0) {
		u32 size = Memory::Read_U32(optParamAddr);
		if (size > 4)
			WARN_LOG_REPORT(HLE, "sceKernelCreateVTimer(%s) unsupported options parameter, size = %d", name, size);
	}

	return id;
}
Exemple #30
0
u32 BlockAllocator::GetTotalFreeBytes() const
{
	u32 sum = 0;
	for (const Block *bp = bottom_; bp != NULL; bp = bp->next)
	{
		const Block &b = *bp;
		if (!b.taken)
		{
			sum += b.size;
		}
	}
	if (sum & (grain_ - 1))
		WARN_LOG_REPORT(HLE, "GetTotalFreeBytes: free size %08x does not align to grain %08x.", sum, grain_);
	return sum;
}