daedalus/Source/OSHLE/patch_mesg_hle.inl
2021-10-23 21:48:59 +11:00

322 lines
8 KiB
C++

#define TEST_DISABLE_MESG_FUNCS //return PATCH_RET_NOT_PROCESSED;
//*****************************************************************************
//
//*****************************************************************************
u32 Patch_osSetEventMesg_Mario()
{
TEST_DISABLE_MESG_FUNCS
u32 vent = gGPR[REG_a0]._u32_0;
u32 queue = gGPR[REG_a1]._u32_0;
u32 msg = gGPR[REG_a2]._u32_0;
/*if (vent < 23)
{
DBGConsole_Msg(0, "osSetEventMesg(%s, 0x%08x, 0x%08x)",
gEventStrings[vent], queue, msg);
}
else
{
DBGConsole_Msg(0, "osSetEventMesg(%d, 0x%08x, 0x%08x)",
vent, queue, msg);
}*/
const u32 p = VAR_ADDRESS(osEventMesgArray) + (vent * 8);
u8 * pEventBase = (u8 *)ReadAddress(p);
QuickWrite32Bits(pEventBase, 0x0, queue);
QuickWrite32Bits(pEventBase, 0x4, msg);
return PATCH_RET_JR_RA;
}
//*****************************************************************************
//
//*****************************************************************************
u32 Patch_osSetEventMesg_Zelda()
{
TEST_DISABLE_MESG_FUNCS
u32 vent = gGPR[REG_a0]._u32_0;
u32 queue = gGPR[REG_a1]._u32_0;
u32 msg = gGPR[REG_a2]._u32_0;
/*if (vent < 23)
{
DBGConsole_Msg(0, "osSetEventMesg(%s, 0x%08x, 0x%08x)",
gEventStrings[vent], queue, msg);
}
else
{
DBGConsole_Msg(0, "osSetEventMesg(%d, 0x%08x, 0x%08x)",
vent, queue, msg);
}*/
const u32 p = VAR_ADDRESS(osEventMesgArray) + (vent * 8);
u8 * pEventBase = (u8 *)ReadAddress(p);
QuickWrite32Bits(pEventBase, 0x0, queue);
QuickWrite32Bits(pEventBase, 0x4, msg);
return PATCH_RET_JR_RA;
}
//*****************************************************************************
//
//*****************************************************************************
u32 Patch_osCreateMesgQueue_Mario()
{
TEST_DISABLE_MESG_FUNCS
#ifdef DAED_OS_MESSAGE_QUEUES
u32 queue = gGPR[REG_a0]._u32_0;
u32 MsgBuf = gGPR[REG_a1]._u32_0;
u32 MsgCount = gGPR[REG_a2]._u32_0;
OS_HLE_osCreateMesgQueue(queue, MsgBuf, MsgCount);
return PATCH_RET_JR_RA;
#else
return PATCH_RET_NOT_PROCESSED;
#endif
}
//*****************************************************************************
//
//*****************************************************************************
// Exactly the same - just optimised slightly
u32 Patch_osCreateMesgQueue_Rugrats()
{
TEST_DISABLE_MESG_FUNCS
#ifdef DAED_OS_MESSAGE_QUEUES
u32 queue = gGPR[REG_a0]._u32_0;
u32 MsgBuf = gGPR[REG_a1]._u32_0;
u32 MsgCount = gGPR[REG_a2]._u32_0;
OS_HLE_osCreateMesgQueue(queue, MsgBuf, MsgCount);
return PATCH_RET_JR_RA;
#else
return PATCH_RET_NOT_PROCESSED;
#endif
}
//*****************************************************************************
//
//*****************************************************************************
u32 Patch_osRecvMesg()
{
TEST_DISABLE_MESG_FUNCS
u32 queue = gGPR[REG_a0]._u32_0;
u32 msg = gGPR[REG_a1]._u32_0;
u32 BlockFlag = gGPR[REG_a2]._u32_0;
u8 * pBase = (u8 *)ReadAddress(queue);
u32 ValidCount= QuickRead32Bits(pBase, 0x8);
u32 MsgCount = QuickRead32Bits(pBase, 0x10);
/*if (queue == 0x80007d40)
{
DBGConsole_Msg(0, "Thread: 0x%08x", Read32Bits(VAR_ADDRESS(osActiveThread)));
DBGConsole_Msg(0, "osRecvMsg(0x%08x, 0x%08x, %s) (%d/%d pending)",
queue, msg, BlockFlag == OS_MESG_BLOCK ? "Block" : "Don't Block",
ValidCount, MsgCount);
}*/
// If there are no valid messages, then we either block until
// one becomes available, or return immediately
if (ValidCount == 0)
{
if (BlockFlag == OS_MESG_NOBLOCK)
{
// Don't block
gGPR[REG_v0]._s64 = (s64)(s32)~0;
return PATCH_RET_JR_RA;
}
else
{
// We can't handle, as this would result in a yield (tricky)
return PATCH_RET_NOT_PROCESSED0(osRecvMesg);
}
}
//DBGConsole_Msg(0, " Processing Pending");
u32 first = QuickRead32Bits(pBase, 0x0c);
//Store message in pointer
if (msg != 0)
{
//DBGConsole_Msg(0, " Retrieving message");
u32 MsgBase = QuickRead32Bits(pBase, 0x14);
// Offset to first valid message
MsgBase += first * 4;
Write32Bits(msg, Read32Bits(MsgBase));
}
first = (first + 1) % MsgCount;
#ifdef DAEDALUS_ENABLE_ASSERTS
DAEDALUS_ASSERT( MsgCount != 0, "Invalid message count" );
DAEDALUS_ASSERT( MsgCount != u32(~0) && first+ValidCount != 0x80000000, "Invalid message count" );
#endif
// Point first to the next valid message
/*if (MsgCount == 0)
{
DBGConsole_Msg(0, "Invalid message count");
// We would break here!
}
else if (MsgCount == u32(~0) && first+1 == 0x80000000)
{
DBGConsole_Msg(0, "Invalid message count/first");
// We would break here!
}
else*/
//{
//DBGConsole_Msg(0, " Generating next valid message number");
QuickWrite32Bits(pBase, 0x0c, first);
//}
// Decrease the number of valid messages
ValidCount--;
QuickWrite32Bits(pBase, 0x8, ValidCount);
// Start thread pending on the fullqueue
u32 FullQueueThread = QuickRead32Bits(pBase, 0x04);
u32 NextThread = Read32Bits(FullQueueThread + 0x00);
// If the first thread is not the idle thread, start it
if (NextThread != 0)
{
//DBGConsole_Msg(0, " Activating sleeping thread");
// From Patch___osPopThread():
QuickWrite32Bits(pBase, 0x04, NextThread);
gGPR[REG_a0]._u32_0 = FullQueueThread;
// FIXME - How to we set the status flag here?
return Patch_osStartThread();
}
// Set success status
gGPR[REG_v0]._u64 = 0;
return PATCH_RET_JR_RA;
}
//*****************************************************************************
//
//*****************************************************************************
u32 Patch_osSendMesg()
{
TEST_DISABLE_MESG_FUNCS
// Zelda Hack handled now in Patch_RecurseAndFind
// osSendMesg brakes OOT's in-game menu
// ToDo : Fix Me
/*if( g_ROM.GameHacks == ZELDA_OOT )
{
return PATCH_RET_NOT_PROCESSED0(osSendMesg);
}*/
u32 queue = gGPR[REG_a0]._u32_0;
u32 msg = gGPR[REG_a1]._u32_0;
u32 BlockFlag = gGPR[REG_a2]._u32_0;
u8 * pBase = (u8 *)ReadAddress(queue);
u32 ValidCount= QuickRead32Bits(pBase, 0x8);
u32 MsgCount = QuickRead32Bits(pBase, 0x10);
/*if (queue == 0x80007d40)
{
DBGConsole_Msg(0, "Thread: 0x%08x", Read32Bits(VAR_ADDRESS(osActiveThread)));
DBGConsole_Msg(0, "osSendMsg(0x%08x, 0x%08x, %s) (%d/%d pending)",
queue, msg, BlockFlag == OS_MESG_BLOCK ? "Block" : "Don't Block",
ValidCount, MsgCount);
}*/
// If the message queue is full, then we either block until
// space becomes available, or return immediately
if (ValidCount >= MsgCount)
{
if (BlockFlag == OS_MESG_NOBLOCK)
{
// Don't block
gGPR[REG_v0]._s64 = (s64)(s32)~0;
return PATCH_RET_JR_RA;
}
else
{
// We can't handle, as this would result in a yield (tricky)
return PATCH_RET_NOT_PROCESSED0(osSendMesg);
}
}
u32 first = QuickRead32Bits(pBase, 0x0c);
//DBGConsole_Msg(0, " Processing Pending");
#ifdef DAEDALUS_ENABLE_ASSERTS
DAEDALUS_ASSERT( MsgCount != 0, "Invalid message count" );
DAEDALUS_ASSERT( MsgCount != u32(~0) && first+ValidCount != 0x80000000, "Invalid message count" );
#endif
// Point first to the next valid message
/*if (MsgCount == 0)
{
DBGConsole_Msg(0, "Invalid message count");
// We would break here!
}
else if (MsgCount == u32(~0) && first+ValidCount == 0x80000000)
{
DBGConsole_Msg(0, "Invalid message count/first");
// We would break here!
}
else*/
//{
u32 slot = (first + ValidCount) % MsgCount;
u32 MsgBase = QuickRead32Bits(pBase, 0x14);
// Offset to first valid message
MsgBase += slot * 4;
Write32Bits(MsgBase, msg);
//}
// Increase the number of valid messages
ValidCount++;
QuickWrite32Bits(pBase, 0x8, ValidCount);
// Start thread pending on the fullqueue
u32 EmptyQueueThread = QuickRead32Bits(pBase, 0x00);
u32 NextThread = Read32Bits(EmptyQueueThread + 0x00);
// If the first thread is not the idle thread, start it
if (NextThread != 0)
{
//DBGConsole_Msg(0, " Activating sleeping thread");
// From Patch___osPopThread():
QuickWrite32Bits(pBase, 0x00, NextThread);
gGPR[REG_a0]._u32_0 = EmptyQueueThread;
// FIXME - How to we set the status flag here?
return Patch_osStartThread();
}
// Set success status
gGPR[REG_v0]._u64 = 0;
return PATCH_RET_JR_RA;
}