mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-21 12:05:23 +00:00
cellSyncRwmInitialize implemented
cellSyncRwmRead implemented (SPU sample works)
This commit is contained in:
parent
356904d198
commit
1c32a284e1
2 changed files with 178 additions and 12 deletions
|
@ -225,6 +225,139 @@ s32 cellSyncBarrierTryWait(mem_ptr_t<CellSyncBarrier> barrier)
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSyncRwmInitialize(mem_ptr_t<CellSyncRwm> rwm, u32 buffer_addr, u32 buffer_size)
|
||||
{
|
||||
cellSync->Log("cellSyncRwmInitialize(rwm_addr=0x%x, buffer_addr=0x%x, buffer_size=0x%x)", rwm.GetAddr(), buffer_addr, buffer_size);
|
||||
|
||||
if (!rwm || !buffer_addr)
|
||||
{
|
||||
return CELL_SYNC_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (rwm.GetAddr() % 16 || buffer_addr % 128)
|
||||
{
|
||||
return CELL_SYNC_ERROR_ALIGN;
|
||||
}
|
||||
if (buffer_size % 128 || buffer_size > 0x4000)
|
||||
{
|
||||
return CELL_SYNC_ERROR_INVAL;
|
||||
}
|
||||
|
||||
// prx: zeroize first u16 and second u16, write buffer_size in second u32, write buffer_addr in second u64 and sync
|
||||
rwm->m_data() = 0;
|
||||
rwm->m_size = buffer_size;
|
||||
rwm->m_addr = (u64)buffer_addr;
|
||||
InterlockedCompareExchange(&rwm->m_data(), 0, 0);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSyncRwmRead(mem_ptr_t<CellSyncRwm> rwm, u32 buffer_addr)
|
||||
{
|
||||
cellSync->Log("cellSyncRwmRead(rwm_addr=0x%x, buffer_addr=0x%x)", rwm.GetAddr(), buffer_addr);
|
||||
|
||||
if (!rwm || !buffer_addr)
|
||||
{
|
||||
return CELL_SYNC_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (rwm.GetAddr() % 16)
|
||||
{
|
||||
return CELL_SYNC_ERROR_ALIGN;
|
||||
}
|
||||
|
||||
// prx: atomically load first u32, repeat until second u16 == 0, increase first u16 and sync
|
||||
while (true)
|
||||
{
|
||||
const u32 old_data = rwm->m_data();
|
||||
CellSyncRwm new_rwm;
|
||||
new_rwm.m_data() = old_data;
|
||||
|
||||
if (new_rwm.m_writers.ToBE())
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
cellSync->Warning("cellSyncRwmRead(rwm_addr=0x%x) aborted", rwm.GetAddr());
|
||||
return CELL_OK;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
new_rwm.m_readers++;
|
||||
if (InterlockedCompareExchange(&rwm->m_data(), new_rwm.m_data(), old_data) == old_data) break;
|
||||
}
|
||||
|
||||
// copy data to buffer_addr
|
||||
memcpy(Memory + buffer_addr, Memory + (u64)rwm->m_addr, (u32)rwm->m_size);
|
||||
|
||||
// prx: load first u32, return 0x8041010C if first u16 == 0, atomically decrease it
|
||||
while (true)
|
||||
{
|
||||
const u32 old_data = rwm->m_data();
|
||||
CellSyncRwm new_rwm;
|
||||
new_rwm.m_data() = old_data;
|
||||
|
||||
if (!new_rwm.m_readers.ToBE())
|
||||
{
|
||||
cellSync->Error("cellSyncRwmRead(rwm_addr=0x%x): m_readers == 0 (m_writers=%d)", rwm.GetAddr(), (u16)new_rwm.m_writers);
|
||||
return CELL_SYNC_ERROR_ABORT;
|
||||
}
|
||||
|
||||
new_rwm.m_readers--;
|
||||
if (InterlockedCompareExchange(&rwm->m_data(), new_rwm.m_data(), old_data) == old_data) break;
|
||||
}
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSyncRwmTryRead(mem_ptr_t<CellSyncRwm> rwm, u32 buffer_addr)
|
||||
{
|
||||
cellSync->Todo("cellSyncRwmTryRead(rwm_addr=0x%x, buffer_addr=0x%x)", rwm.GetAddr(), buffer_addr);
|
||||
|
||||
if (!rwm || !buffer_addr)
|
||||
{
|
||||
return CELL_SYNC_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (rwm.GetAddr() % 16)
|
||||
{
|
||||
return CELL_SYNC_ERROR_ALIGN;
|
||||
}
|
||||
|
||||
// TODO
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSyncRwmWrite(mem_ptr_t<CellSyncRwm> rwm, u32 buffer_addr)
|
||||
{
|
||||
cellSync->Todo("cellSyncRwmWrite(rwm_addr=0x%x, buffer_addr=0x%x)", rwm.GetAddr(), buffer_addr);
|
||||
|
||||
if (!rwm || !buffer_addr)
|
||||
{
|
||||
return CELL_SYNC_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (rwm.GetAddr() % 16)
|
||||
{
|
||||
return CELL_SYNC_ERROR_ALIGN;
|
||||
}
|
||||
|
||||
// TODO
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSyncRwmTryWrite(mem_ptr_t<CellSyncRwm> rwm, u32 buffer_addr)
|
||||
{
|
||||
cellSync->Todo("cellSyncRwmTryWrite(rwm_addr=0x%x, buffer_addr=0x%x)", rwm.GetAddr(), buffer_addr);
|
||||
|
||||
if (!rwm || !buffer_addr)
|
||||
{
|
||||
return CELL_SYNC_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (rwm.GetAddr() % 16)
|
||||
{
|
||||
return CELL_SYNC_ERROR_ALIGN;
|
||||
}
|
||||
|
||||
// TODO
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
void cellSync_init()
|
||||
{
|
||||
cellSync->AddFunc(0xa9072dee, cellSyncMutexInitialize);
|
||||
|
@ -237,4 +370,10 @@ void cellSync_init()
|
|||
cellSync->AddFunc(0x268edd6d, cellSyncBarrierTryNotify);
|
||||
cellSync->AddFunc(0x35f21355, cellSyncBarrierWait);
|
||||
cellSync->AddFunc(0x6c272124, cellSyncBarrierTryWait);
|
||||
|
||||
cellSync->AddFunc(0xfc48b03f, cellSyncRwmInitialize);
|
||||
cellSync->AddFunc(0xcece771f, cellSyncRwmRead);
|
||||
cellSync->AddFunc(0xa6669751, cellSyncRwmTryRead);
|
||||
cellSync->AddFunc(0xed773f5f, cellSyncRwmWrite);
|
||||
cellSync->AddFunc(0xba5bee48, cellSyncRwmTryWrite);
|
||||
}
|
||||
|
|
|
@ -3,18 +3,30 @@
|
|||
// Return Codes
|
||||
enum
|
||||
{
|
||||
CELL_SYNC_ERROR_AGAIN = 0x80410101,
|
||||
CELL_SYNC_ERROR_INVAL = 0x80410102,
|
||||
CELL_SYNC_ERROR_NOMEM = 0x80410104,
|
||||
CELL_SYNC_ERROR_AGAIN = 0x80410101,
|
||||
CELL_SYNC_ERROR_INVAL = 0x80410102,
|
||||
CELL_SYNC_ERROR_NOSYS = 0x80410103, // ???
|
||||
CELL_SYNC_ERROR_NOMEM = 0x80410104,
|
||||
CELL_SYNC_ERROR_SRCH = 0x80410105, // ???
|
||||
CELL_SYNC_ERROR_NOENT = 0x80410106, // ???
|
||||
CELL_SYNC_ERROR_NOEXEC = 0x80410107, // ???
|
||||
CELL_SYNC_ERROR_DEADLK = 0x80410108,
|
||||
CELL_SYNC_ERROR_PERM = 0x80410109,
|
||||
CELL_SYNC_ERROR_BUSY = 0x8041010A,
|
||||
CELL_SYNC_ERROR_STAT = 0x8041010F,
|
||||
CELL_SYNC_ERROR_ALIGN = 0x80410110,
|
||||
CELL_SYNC_ERROR_NULL_POINTER = 0x80410111,
|
||||
CELL_SYNC_ERROR_NOT_SUPPORTED_THREAD = 0x80410112,
|
||||
CELL_SYNC_ERROR_NO_NOTIFIER = 0x80410113,
|
||||
CELL_SYNC_ERROR_NO_SPU_CONTEXT_STORAGE = 0x80410114,
|
||||
CELL_SYNC_ERROR_PERM = 0x80410109,
|
||||
CELL_SYNC_ERROR_BUSY = 0x8041010A,
|
||||
//////////////////////// 0x8041010B, // ???
|
||||
CELL_SYNC_ERROR_ABORT = 0x8041010C, // ???
|
||||
CELL_SYNC_ERROR_FAULT = 0x8041010D, // ???
|
||||
CELL_SYNC_ERROR_CHILD = 0x8041010E, // ???
|
||||
CELL_SYNC_ERROR_STAT = 0x8041010F,
|
||||
CELL_SYNC_ERROR_ALIGN = 0x80410110,
|
||||
|
||||
CELL_SYNC_ERROR_NULL_POINTER = 0x80410111,
|
||||
|
||||
CELL_SYNC_ERROR_NOT_SUPPORTED_THREAD = 0x80410112, // ???
|
||||
CELL_SYNC_ERROR_SHOTAGE = 0x80410112, // ???
|
||||
CELL_SYNC_ERROR_NO_NOTIFIER = 0x80410113, // ???
|
||||
CELL_SYNC_ERROR_UNKNOWNKEY = 0x80410113, // ???
|
||||
CELL_SYNC_ERROR_NO_SPU_CONTEXT_STORAGE = 0x80410114, // ???
|
||||
};
|
||||
|
||||
struct CellSyncMutex
|
||||
|
@ -41,4 +53,19 @@ struct CellSyncBarrier
|
|||
};
|
||||
};
|
||||
|
||||
static_assert(sizeof(CellSyncBarrier) == 4, "CellSyncBarrier: wrong size");
|
||||
static_assert(sizeof(CellSyncBarrier) == 4, "CellSyncBarrier: wrong size");
|
||||
|
||||
struct CellSyncRwm
|
||||
{
|
||||
be_t<u16> m_readers;
|
||||
be_t<u16> m_writers;
|
||||
be_t<u32> m_size;
|
||||
be_t<u64> m_addr;
|
||||
|
||||
volatile u32& m_data()
|
||||
{
|
||||
return *reinterpret_cast<u32*>(this);
|
||||
};
|
||||
};
|
||||
|
||||
static_assert(sizeof(CellSyncRwm) == 16, "CellSyncBarrier: wrong size");
|
||||
|
|
Loading…
Add table
Reference in a new issue