diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index dd684e8007..2d560cc0b7 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -260,6 +260,11 @@ template void WrapI_CU() { RETURN(retval); } +template void WrapI_CUU() { + int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2)); + RETURN(retval); +} + template void WrapI_CUUU() { int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3)); diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index f733834392..662cc30d68 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -435,11 +435,11 @@ const HLEFunction ThreadManForUser[] = {0x2A3D44FF,sceKernelGetCallbackCount,"sceKernelGetCallbackCount"}, {0x730ED8BC,sceKernelReferCallbackStatus,"sceKernelReferCallbackStatus"}, - {0x8125221D,&WrapU_CIUIU,"sceKernelCreateMbx"}, + {0x8125221D,&WrapI_CUU,"sceKernelCreateMbx"}, {0x86255ADA,&WrapI_I,"sceKernelDeleteMbx"}, - {0xE9B3061E,&WrapV_IU,"sceKernelSendMbx"}, - {0x18260574,&WrapV_IUU,"sceKernelReceiveMbx"}, - {0xF3986382,&WrapV_IUU,"sceKernelReceiveMbxCB"}, + {0xE9B3061E,&WrapI_IU,"sceKernelSendMbx"}, + {0x18260574,&WrapI_IUU,"sceKernelReceiveMbx"}, + {0xF3986382,&WrapI_IUU,"sceKernelReceiveMbxCB"}, {0x0D81716A,&WrapI_IU,"sceKernelPollMbx"}, {0x87D4DD36,&WrapI_IU,"sceKernelCancelReceiveMbx"}, {0xA8E8C846,&WrapI_IU,"sceKernelReferMbxStatus"}, diff --git a/Core/HLE/sceKernelEventFlag.cpp b/Core/HLE/sceKernelEventFlag.cpp index c3b4122166..2ba4f23cf3 100644 --- a/Core/HLE/sceKernelEventFlag.cpp +++ b/Core/HLE/sceKernelEventFlag.cpp @@ -30,7 +30,7 @@ void __KernelEventFlagTimeout(u64 userdata, int cycleslate); struct NativeEventFlag { u32 size; - char name[32]; + char name[KERNELOBJECT_MAX_NAME_LENGTH + 1]; u32 attr; u32 initPattern; u32 currentPattern; @@ -188,8 +188,8 @@ int sceKernelCreateEventFlag(const char *name, u32 flag_attr, u32 flag_initPatte SceUID id = kernelObjects.Create(e); e->nef.size = sizeof(NativeEventFlag); - strncpy(e->nef.name, name, 31); - e->nef.name[31] = 0; + 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; diff --git a/Core/HLE/sceKernelMbx.cpp b/Core/HLE/sceKernelMbx.cpp index ee6073e6a2..bcd3b74d84 100644 --- a/Core/HLE/sceKernelMbx.cpp +++ b/Core/HLE/sceKernelMbx.cpp @@ -19,16 +19,24 @@ #include "sceKernelThread.h" #include "sceKernelMbx.h" #include "HLE.h" +#include "../../Core/CoreTiming.h" #define SCE_KERNEL_MBA_THPRI 0x100 #define SCE_KERNEL_MBA_MSPRI 0x400 +#define SCE_KERNEL_MBA_ATTR_KNOWN (SCE_KERNEL_MBA_THPRI | SCE_KERNEL_MBA_MSPRI) -// TODO: when a thread is being resumed (message received or cancellation), sceKernelReceiveMbx() always returns 0 +const int PSP_MBX_ERROR_DUPLICATE_MSG = 0x800201C9; + +typedef std::pair MbxWaitingThread; +void __KernelMbxTimeout(u64 userdata, int cyclesLate); + +bool mbxInitComplete = false; +int mbxWaitTimer = 0; struct NativeMbx { SceSize size; - char name[32]; + char name[KERNELOBJECT_MAX_NAME_LENGTH + 1]; SceUInt attr; int numWaitThreads; int numMessages; @@ -44,43 +52,250 @@ struct Mbx : public KernelObject void AddWaitingThread(SceUID id, u32 addr) { + bool inserted = false; if (nmb.attr & SCE_KERNEL_MBA_THPRI) { - for (std::vector >::iterator it = waitingThreads.begin(); it != waitingThreads.end(); it++) + for (std::vector::iterator it = waitingThreads.begin(); it != waitingThreads.end(); it++) { - if (__KernelGetThreadPrio(id) >= __KernelGetThreadPrio((*it).first)) + if (__KernelGetThreadPrio(id) < __KernelGetThreadPrio((*it).first)) { waitingThreads.insert(it, std::make_pair(id, addr)); + inserted = true; break; } } } + if (!inserted) + waitingThreads.push_back(std::make_pair(id, addr)); + } + + inline void AddInitialMessage(u32 ptr) + { + nmb.numMessages++; + Memory::Write_U32(ptr, ptr); + nmb.packetListHead = ptr; + } + + inline void AddFirstMessage(u32 endPtr, u32 ptr) + { + nmb.numMessages++; + Memory::Write_U32(nmb.packetListHead, ptr); + Memory::Write_U32(ptr, endPtr); + nmb.packetListHead = ptr; + } + + inline void AddLastMessage(u32 endPtr, u32 ptr) + { + nmb.numMessages++; + Memory::Write_U32(ptr, endPtr); + Memory::Write_U32(nmb.packetListHead, ptr); + } + + inline void AddMessage(u32 beforePtr, u32 afterPtr, u32 ptr) + { + nmb.numMessages++; + Memory::Write_U32(afterPtr, ptr); + Memory::Write_U32(ptr, beforePtr); + } + + int ReceiveMessage(u32 receivePtr) + { + u32 ptr = nmb.packetListHead; + + if (nmb.numMessages == 991) + { + u32 next = Memory::Read_U32(nmb.packetListHead); + u32 next2 = Memory::Read_U32(next); + if (next2 == ptr && next != ptr) + { + Memory::Write_U32(next, next); + nmb.packetListHead = next; + } + else + nmb.packetListHead = 0; + } else { - waitingThreads.push_back(std::make_pair(id, addr)); + // Check over the linked list and reset the head. + int c = 0; + while (true) + { + u32 next = Memory::Read_U32(nmb.packetListHead); + if (!Memory::IsValidAddress(next)) + return SCE_KERNEL_ERROR_ILLEGAL_ADDR; + if (next == ptr) + { + if (nmb.packetListHead != ptr) + { + next = Memory::Read_U32(next); + Memory::Write_U32(next, nmb.packetListHead); + nmb.packetListHead = next; + break; + } + else + { + if (c < nmb.numMessages - 1) + return PSP_MBX_ERROR_DUPLICATE_MSG; + + nmb.packetListHead = 0; + break; + } + } + + nmb.packetListHead = next; + c++; + } } + + // Tell the receiver about the message. + Memory::Write_U32(ptr, receivePtr); + nmb.numMessages--; + + return 0; } NativeMbx nmb; - std::vector > waitingThreads; - std::vector messageQueue; + std::vector waitingThreads; }; -SceUID sceKernelCreateMbx(const char *name, int memoryPartition, SceUInt attr, int size, u32 optAddr) +void __KernelMbxInit() { - DEBUG_LOG(HLE, "sceKernelCreateMbx(%s, %i, %08x, %i, %08x)", name, memoryPartition, attr, size, optAddr); + mbxWaitTimer = CoreTiming::RegisterEvent("MbxTimeout", &__KernelMbxTimeout); + + mbxInitComplete = true; +} + +bool __KernelUnlockMbxForThread(Mbx *m, MbxWaitingThread &th, u32 &error, int result, bool &wokeThreads) +{ + SceUID waitID = __KernelGetWaitID(th.first, WAITTYPE_MBX, error); + u32 timeoutPtr = __KernelGetWaitTimeoutPtr(th.first, error); + + // The waitID may be different after a timeout. + if (waitID != m->GetUID()) + return true; + + if (timeoutPtr != 0 && mbxWaitTimer != 0) + { + // Remove any event for this thread. + u64 cyclesLeft = CoreTiming::UnscheduleEvent(mbxWaitTimer, th.first); + Memory::Write_U32((u32) cyclesToUs(cyclesLeft), timeoutPtr); + } + + __KernelResumeThreadFromWait(th.first, result); + wokeThreads = true; + return true; +} + +void __KernelMbxTimeout(u64 userdata, int cyclesLate) +{ + SceUID threadID = (SceUID)userdata; + + u32 error; + u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); + if (timeoutPtr != 0) + Memory::Write_U32(0, timeoutPtr); + + SceUID mbxID = __KernelGetWaitID(threadID, WAITTYPE_MBX, error); + Mbx *m = kernelObjects.Get(mbxID, error); + if (m) + { + // This thread isn't waiting anymore, but we'll remove it from waitingThreads later. + // The reason is, if it times out, but what it was waiting on is DELETED prior to it + // actually running, it will get a DELETE result instead of a TIMEOUT. + // So, we need to remember it or we won't be able to mark it DELETE instead later. + + // TODO: Should numWaitThreads be decreased yet? + } + + __KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_TIMEOUT); +} + +void __KernelWaitMbx(Mbx *m, u32 timeoutPtr) +{ + if (timeoutPtr == 0 || mbxWaitTimer == 0) + return; + + int micro = (int) Memory::Read_U32(timeoutPtr); + + // This seems to match the actual timing. + if (micro <= 2) + micro = 10; + else if (micro <= 209) + micro = 250; + + // This should call __KernelMbxTimeout() later, unless we cancel it. + CoreTiming::ScheduleEvent(usToCycles(micro), mbxWaitTimer, __KernelGetCurThread()); +} + +void __KernelMbxRemoveThread(Mbx *m, SceUID threadID) +{ + for (size_t i = 0; i < m->waitingThreads.size(); i++) + { + MbxWaitingThread *t = &m->waitingThreads[i]; + if (t->first == threadID) + { + m->waitingThreads.erase(m->waitingThreads.begin() + i); + break; + } + } +} + +std::vector::iterator __KernelMbxFindPriority(std::vector &waiting) +{ + _dbg_assert_msg_(HLE, !waiting.empty(), "__KernelMutexFindPriority: Trying to find best of no threads."); + + std::vector::iterator iter, end, best = waiting.end(); + u32 best_prio = 0xFFFFFFFF; + for (iter = waiting.begin(), end = waiting.end(); iter != end; ++iter) + { + u32 iter_prio = __KernelGetThreadPrio(iter->first); + if (iter_prio < best_prio) + { + best = iter; + best_prio = iter_prio; + } + } + + _dbg_assert_msg_(HLE, best != waiting.end(), "__KernelMutexFindPriority: Returning invalid best thread."); + return best; +} + +SceUID sceKernelCreateMbx(const char *name, u32 attr, u32 optAddr) +{ + if (!mbxInitComplete) + __KernelMbxInit(); + + if (!name) + { + WARN_LOG(HLE, "%08x=%s(): invalid name", SCE_KERNEL_ERROR_ERROR, __FUNCTION__); + return SCE_KERNEL_ERROR_ERROR; + } + // Accepts 0x000 - 0x0FF, 0x100 - 0x1FF, and 0x400 - 0x4FF. + if (((attr & ~SCE_KERNEL_MBA_ATTR_KNOWN) & ~0xFF) != 0) + { + WARN_LOG(HLE, "%08x=%s(): invalid attr parameter: %08x", SCE_KERNEL_ERROR_ILLEGAL_ATTR, __FUNCTION__, 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, sizeof(m->nmb.name)); + 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) + WARN_LOG(HLE, "%s(%s) unsupported options parameter: %08x", __FUNCTION__, name, optAddr); + if ((attr & ~SCE_KERNEL_MBA_ATTR_KNOWN) != 0) + WARN_LOG(HLE, "%s(%s) unsupported attr parameter: %08x", __FUNCTION__, name, attr); + return id; } @@ -91,11 +306,14 @@ int sceKernelDeleteMbx(SceUID id) if (m) { DEBUG_LOG(HLE, "sceKernelDeleteMbx(%i)", id); + + bool wokeThreads = false; for (size_t i = 0; i < m->waitingThreads.size(); i++) - { - Memory::Write_U32(0, m->waitingThreads[i].second); - __KernelResumeThreadFromWait(m->waitingThreads[i].first); - } + __KernelUnlockMbxForThread(m, m->waitingThreads[i], error, SCE_KERNEL_ERROR_WAIT_DELETE, wokeThreads); + m->waitingThreads.clear(); + + if (wokeThreads) + hleReSchedule("mbx deleted"); } else { @@ -104,63 +322,99 @@ int sceKernelDeleteMbx(SceUID id) return kernelObjects.Destroy(id); } -void sceKernelSendMbx(SceUID id, u32 packetAddr) +int sceKernelSendMbx(SceUID id, u32 packetAddr) { u32 error; Mbx *m = kernelObjects.Get(id, error); + if (!m) + { + ERROR_LOG(HLE, "sceKernelSendMbx(%i, %08x): invalid mbx id", id, packetAddr); + return error; + } + NativeMbxPacket *addPacket = (NativeMbxPacket*)Memory::GetPointer(packetAddr); if (addPacket == 0) { ERROR_LOG(HLE, "sceKernelSendMbx(%i, %08x): invalid packet address", id, packetAddr); - RETURN(-1); - return; + return -1; } - if (!m) + // If the queue is empty, maybe someone is waiting. + // We have to check them first, they might've timed out. + if (m->nmb.numMessages == 0) { - ERROR_LOG(HLE, "sceKernelSendMbx(%i, %08x): invalid mbx id", id, packetAddr); - RETURN(error); - return; - } - - if (m->waitingThreads.empty()) - { - DEBUG_LOG(HLE, "sceKernelSendMbx(%i, %08x): no threads currently waiting, adding message to queue", id, packetAddr); - if (m->nmb.attr & SCE_KERNEL_MBA_MSPRI) + bool wokeThreads = false; + std::vector::iterator iter; + while (!wokeThreads && !m->waitingThreads.empty()) { - for (std::vector::iterator it = m->messageQueue.begin(); it != m->messageQueue.end(); it++) + if ((m->nmb.attr & SCE_KERNEL_MBA_THPRI) != 0) + iter = __KernelMbxFindPriority(m->waitingThreads); + else + iter = m->waitingThreads.begin(); + + MbxWaitingThread t = *iter; + __KernelUnlockMbxForThread(m, t, error, 0, wokeThreads); + m->waitingThreads.erase(iter); + + if (wokeThreads) { - NativeMbxPacket *p = (NativeMbxPacket*)Memory::GetPointer(*it); - if (addPacket->priority >= p->priority) - { - m->messageQueue.insert(it, packetAddr); - break; - } + DEBUG_LOG(HLE, "sceKernelSendMbx(%i, %08x): threads waiting, resuming %d", id, packetAddr, t.first); + Memory::Write_U32(packetAddr, t.second); + hleReSchedule("mbx sent"); + + // We don't need to do anything else, finish here. + return 0; } } - else - { - m->messageQueue.push_back(packetAddr); - } - RETURN(0); - } - else if (m->messageQueue.empty()) - { - Memory::Write_U32(packetAddr, m->waitingThreads.front().second); - __KernelResumeThreadFromWait(m->waitingThreads.front().first); - DEBUG_LOG(HLE, "sceKernelSendMbx(%i, %08x): threads waiting, resuming %d", id, packetAddr, m->waitingThreads.front().first); - m->waitingThreads.erase(m->waitingThreads.begin()); - RETURN(0); - __KernelReSchedule(); } + + DEBUG_LOG(HLE, "sceKernelSendMbx(%i, %08x): no threads currently waiting, adding message to queue", id, packetAddr); + + if (m->nmb.numMessages == 0) + m->AddInitialMessage(packetAddr); else { - ERROR_LOG(HLE, "sceKernelSendMbx(%i, %08x): WTF!? thread waiting while there is a message in the queue?", id, packetAddr); - RETURN(-1); + u32 next = m->nmb.packetListHead, prev; + for (int i = 0, n = m->nmb.numMessages; i < n; i++) + { + if (next == packetAddr) + return PSP_MBX_ERROR_DUPLICATE_MSG; + if (!Memory::IsValidAddress(next)) + return SCE_KERNEL_ERROR_ILLEGAL_ADDR; + + prev = next; + next = Memory::Read_U32(next); + } + + bool inserted = false; + if (m->nmb.attr & SCE_KERNEL_MBA_MSPRI) + { + NativeMbxPacket p; + for (int i = 0, n = m->nmb.numMessages; i < n; i++) + { + Memory::ReadStruct(next, &p); + if (addPacket->priority < p.priority) + { + if (i == 0) + m->AddFirstMessage(prev, packetAddr); + else + m->AddMessage(prev, next, packetAddr); + inserted = true; + break; + } + + prev = next; + next = Memory::Read_U32(next); + } + } + if (!inserted) + m->AddLastMessage(prev, packetAddr); } + + return 0; } -void sceKernelReceiveMbx(SceUID id, u32 packetAddrPtr, u32 timeoutPtr) +int sceKernelReceiveMbx(SceUID id, u32 packetAddrPtr, u32 timeoutPtr) { u32 error; Mbx *m = kernelObjects.Get(id, error); @@ -168,52 +422,50 @@ void sceKernelReceiveMbx(SceUID id, u32 packetAddrPtr, u32 timeoutPtr) if (!m) { ERROR_LOG(HLE, "sceKernelReceiveMbx(%i, %08x, %08x): invalid mbx id", id, packetAddrPtr, timeoutPtr); - RETURN(error); - return; + return error; } - if (!m->messageQueue.empty()) + if (m->nmb.numMessages > 0) { DEBUG_LOG(HLE, "sceKernelReceiveMbx(%i, %08x, %08x): sending first queue message", id, packetAddrPtr, timeoutPtr); - Memory::Write_U32(m->messageQueue.front(), packetAddrPtr); - m->messageQueue.erase(m->messageQueue.begin()); - RETURN(0); + return m->ReceiveMessage(packetAddrPtr); } else { DEBUG_LOG(HLE, "sceKernelReceiveMbx(%i, %08x, %08x): no message in queue, waiting", id, packetAddrPtr, timeoutPtr); + __KernelMbxRemoveThread(m, __KernelGetCurThread()); m->AddWaitingThread(__KernelGetCurThread(), packetAddrPtr); - RETURN(0); - __KernelWaitCurThread(WAITTYPE_MBX, 0, 0, 0, false); // ? + __KernelWaitMbx(m, timeoutPtr); + __KernelWaitCurThread(WAITTYPE_MBX, id, 0, timeoutPtr, false); + return 0; } } -void sceKernelReceiveMbxCB(SceUID id, u32 packetAddrPtr, u32 timeoutPtr) +int sceKernelReceiveMbxCB(SceUID id, u32 packetAddrPtr, u32 timeoutPtr) { u32 error; Mbx *m = kernelObjects.Get(id, error); - __KernelCheckCallbacks(); if (!m) { ERROR_LOG(HLE, "sceKernelReceiveMbxCB(%i, %08x, %08x): invalid mbx id", id, packetAddrPtr, timeoutPtr); - RETURN(error); - return; + return error; } - if (!m->messageQueue.empty()) + if (m->nmb.numMessages > 0) { DEBUG_LOG(HLE, "sceKernelReceiveMbxCB(%i, %08x, %08x): sending first queue message", id, packetAddrPtr, timeoutPtr); - Memory::Write_U32(m->messageQueue.front(), packetAddrPtr); - m->messageQueue.erase(m->messageQueue.begin()); - RETURN(0); + hleCheckCurrentCallbacks(); + return m->ReceiveMessage(packetAddrPtr); } else { DEBUG_LOG(HLE, "sceKernelReceiveMbxCB(%i, %08x, %08x): no message in queue, waiting", id, packetAddrPtr, timeoutPtr); - m->AddWaitingThread(id, packetAddrPtr); - RETURN(0); - __KernelWaitCurThread(WAITTYPE_MBX, 0, 0, 0, true); // ? + __KernelMbxRemoveThread(m, __KernelGetCurThread()); + m->AddWaitingThread(__KernelGetCurThread(), packetAddrPtr); + __KernelWaitMbx(m, timeoutPtr); + __KernelWaitCurThread(WAITTYPE_MBX, id, 0, timeoutPtr, true); + return 0; } } @@ -228,12 +480,10 @@ int sceKernelPollMbx(SceUID id, u32 packetAddrPtr) return error; } - if (!m->messageQueue.empty()) + if (m->nmb.numMessages > 0) { DEBUG_LOG(HLE, "sceKernelPollMbx(%i, %08x): sending first queue message", id, packetAddrPtr); - Memory::Write_U32(m->messageQueue.front(), packetAddrPtr); - m->messageQueue.erase(m->messageQueue.begin()); - return 0; + return m->ReceiveMessage(packetAddrPtr); } else { @@ -255,13 +505,15 @@ int sceKernelCancelReceiveMbx(SceUID id, u32 numWaitingThreadsAddr) u32 count = m->waitingThreads.size(); DEBUG_LOG(HLE, "sceKernelCancelReceiveMbx(%i, %08x): cancelling %d threads", id, numWaitingThreadsAddr, count); + + bool wokeThreads = false; for (size_t i = 0; i < m->waitingThreads.size(); i++) - { - Memory::Write_U32(0, m->waitingThreads[i].second); - __KernelResumeThreadFromWait(m->waitingThreads[i].first); - } + __KernelUnlockMbxForThread(m, m->waitingThreads[i], error, SCE_KERNEL_ERROR_WAIT_CANCEL, wokeThreads); m->waitingThreads.clear(); + if (wokeThreads) + hleReSchedule("mbx canceled"); + if (numWaitingThreadsAddr) Memory::Write_U32(count, numWaitingThreadsAddr); return 0; @@ -277,34 +529,19 @@ int sceKernelReferMbxStatus(SceUID id, u32 infoAddr) return error; } - SceKernelMbxInfo *info = (SceKernelMbxInfo*)Memory::GetPointer(infoAddr); - DEBUG_LOG(HLE, "sceKernelReferMbxStatus(%i, %08x)", id, infoAddr); - if (info) - { - strncpy(info->name, m->nmb.name, 32); - info->attr = m->nmb.attr; - info->numWaitThreads = m->waitingThreads.size(); - info->numMessage = m->messageQueue.size(); - // Fill the 'next' parameter of packets which we don't use by default but could be used by a game - if (m->messageQueue.size() != 0) - { - info->topPacketAddr = m->messageQueue[0]; - for (u32 i = 0; i < m->messageQueue.size() - 1; i++) - { - Memory::Write_U32(m->messageQueue[i + 1], Memory::Read_U32(m->messageQueue[i])); - } - Memory::Write_U32(m->messageQueue[m->messageQueue.size() - 1], 0); - } - else - { - info->topPacketAddr = 0; - } - } - else - { + // Should we crash the thread somehow? + if (!Memory::IsValidAddress(infoAddr)) return -1; + + for (int i = 0, n = m->nmb.numMessages; i < n; ++i) + m->nmb.packetListHead = Memory::Read_U32(m->nmb.packetListHead); + + // For whatever reason, it won't write if the size (first member) is 0. + if (Memory::Read_U32(infoAddr) != 0) + { + m->nmb.numWaitThreads = m->waitingThreads.size(); + Memory::WriteStruct(infoAddr, &m->nmb); } return 0; } - diff --git a/Core/HLE/sceKernelMbx.h b/Core/HLE/sceKernelMbx.h index e841dcb6d0..1470e1119b 100644 --- a/Core/HLE/sceKernelMbx.h +++ b/Core/HLE/sceKernelMbx.h @@ -24,22 +24,11 @@ struct NativeMbxPacket u8 padding[3]; }; -struct SceKernelMbxInfo -{ - SceSize size; - char name[KERNELOBJECT_MAX_NAME_LENGTH+1]; - SceUInt attr; - int numWaitThreads; - int numMessage; - u32 topPacketAddr; -}; - -SceUID sceKernelCreateMbx(const char *name, int memoryPartition, SceUInt attr, int size, u32 optAddr); +SceUID sceKernelCreateMbx(const char *name, u32 attr, u32 optAddr); int sceKernelDeleteMbx(SceUID id); -void sceKernelSendMbx(SceUID id, u32 addPacketAddr); -void sceKernelReceiveMbx(SceUID id, u32 packetAddrPtr, u32 timeoutPtr); -void sceKernelReceiveMbxCB(SceUID id, u32 packetAddrPtr, u32 timeoutPtr); +int sceKernelSendMbx(SceUID id, u32 addPacketAddr); +int sceKernelReceiveMbx(SceUID id, u32 packetAddrPtr, u32 timeoutPtr); +int sceKernelReceiveMbxCB(SceUID id, u32 packetAddrPtr, u32 timeoutPtr); int sceKernelPollMbx(SceUID id, u32 packetAddrPtr); int sceKernelCancelReceiveMbx(SceUID id, u32 numWaitingThreadsAddr); int sceKernelReferMbxStatus(SceUID id, u32 infoAddr); - diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index 4dcea03d7f..77d2a957c6 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -49,7 +49,7 @@ struct NativeMutex { SceSize size; - char name[32]; + char name[KERNELOBJECT_MAX_NAME_LENGTH + 1]; SceUInt attr; int lockLevel; @@ -70,7 +70,7 @@ struct Mutex : public KernelObject struct NativeLwMutex { SceSize size; - char name[32]; + char name[KERNELOBJECT_MAX_NAME_LENGTH + 1]; SceUInt attr; SceUInt workareaPtr; }; @@ -207,8 +207,8 @@ int sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 optio SceUID id = kernelObjects.Create(mutex); mutex->nm.size = sizeof(mutex); - strncpy(mutex->nm.name, name, 31); - mutex->nm.name[31] = 0; + strncpy(mutex->nm.name, name, KERNELOBJECT_MAX_NAME_LENGTH); + mutex->nm.name[KERNELOBJECT_MAX_NAME_LENGTH] = 0; mutex->nm.attr = attr; if (initialCount == 0) { @@ -522,8 +522,8 @@ int sceKernelCreateLwMutex(u32 workareaPtr, const char *name, u32 attr, int init LwMutex *mutex = new LwMutex(); SceUID id = kernelObjects.Create(mutex); mutex->nm.size = sizeof(mutex); - strncpy(mutex->nm.name, name, 31); - mutex->nm.name[31] = 0; + strncpy(mutex->nm.name, name, KERNELOBJECT_MAX_NAME_LENGTH); + mutex->nm.name[KERNELOBJECT_MAX_NAME_LENGTH] = 0; mutex->nm.attr = attr; mutex->nm.workareaPtr = workareaPtr; diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index dedfa8b8d1..5b9bdd3d7a 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -35,7 +35,7 @@ struct NativeSemaphore /** Size of the ::SceKernelSemaInfo structure. */ SceSize size; /** NUL-terminated name of the semaphore. */ - char name[32]; + char name[KERNELOBJECT_MAX_NAME_LENGTH + 1]; /** Attributes. */ SceUInt attr; /** The initial count the semaphore was created with. */ @@ -191,8 +191,8 @@ int sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u32 SceUID id = kernelObjects.Create(s); s->ns.size = sizeof(NativeSemaphore); - strncpy(s->ns.name, name, 31); - s->ns.name[31] = 0; + 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; diff --git a/pspautotests b/pspautotests index 700e0df918..8c1284c758 160000 --- a/pspautotests +++ b/pspautotests @@ -1 +1 @@ -Subproject commit 700e0df918512a0fc4105c23ce2198fbfbefb5ae +Subproject commit 8c1284c758c05811517c043bbc781ba8ab724d5e diff --git a/test.py b/test.py index 5a4a3f8647..4ac98e263e 100755 --- a/test.py +++ b/test.py @@ -75,6 +75,14 @@ tests_good = [ "threads/lwmutex/try600/try600", "threads/lwmutex/unlock/unlock", "threads/mbx/mbx", + "threads/mbx/cancel/cancel", + "threads/mbx/create/create", + "threads/mbx/delete/delete", + "threads/mbx/poll/poll", + "threads/mbx/priority/priority", + "threads/mbx/receive/receive", + "threads/mbx/refer/refer", + "threads/mbx/send/send", "threads/mutex/mutex", "threads/mutex/create/create", "threads/mutex/delete/delete",