mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-11 01:08:39 +12:00
cellSyncQueuePush implemented
This commit is contained in:
parent
f55afc27a9
commit
3d184b3a59
2 changed files with 65 additions and 3 deletions
|
@ -360,7 +360,7 @@ s32 cellSyncRwmTryWrite(mem_ptr_t<CellSyncRwm> rwm, u32 buffer_addr)
|
||||||
|
|
||||||
s32 cellSyncQueueInitialize(mem_ptr_t<CellSyncQueue> queue, u32 buffer_addr, u32 size, u32 depth)
|
s32 cellSyncQueueInitialize(mem_ptr_t<CellSyncQueue> queue, u32 buffer_addr, u32 size, u32 depth)
|
||||||
{
|
{
|
||||||
cellSync->Todo("cellSyncQueueInitialize(queue_addr=0x%x, buffer_addr=0x%x, size=0x%x, depth=0x%x)", queue.GetAddr(), buffer_addr, size, depth);
|
cellSync->Log("cellSyncQueueInitialize(queue_addr=0x%x, buffer_addr=0x%x, size=0x%x, depth=0x%x)", queue.GetAddr(), buffer_addr, size, depth);
|
||||||
|
|
||||||
if (!queue)
|
if (!queue)
|
||||||
{
|
{
|
||||||
|
@ -390,8 +390,69 @@ s32 cellSyncQueueInitialize(mem_ptr_t<CellSyncQueue> queue, u32 buffer_addr, u32
|
||||||
|
|
||||||
s32 cellSyncQueuePush(mem_ptr_t<CellSyncQueue> queue, u32 buffer_addr)
|
s32 cellSyncQueuePush(mem_ptr_t<CellSyncQueue> queue, u32 buffer_addr)
|
||||||
{
|
{
|
||||||
cellSync->Todo("cellSyncQueuePush(queue_addr=0x%x, buffer_addr=0x%x)", queue.GetAddr(), buffer_addr);
|
cellSync->Log("cellSyncQueuePush(queue_addr=0x%x, buffer_addr=0x%x)", queue.GetAddr(), buffer_addr);
|
||||||
|
|
||||||
|
if (!queue || !buffer_addr)
|
||||||
|
{
|
||||||
|
return CELL_SYNC_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
if (queue.GetAddr() % 32)
|
||||||
|
{
|
||||||
|
return CELL_SYNC_ERROR_ALIGN;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 size = (u32)queue->m_size;
|
||||||
|
const u32 depth = (u32)queue->m_depth;
|
||||||
|
if (((u32)queue->m_v1 & 0xffffff) > depth || ((u32)queue->m_v2 & 0xffffff) > depth)
|
||||||
|
{
|
||||||
|
cellSync->Error("cellSyncQueuePush(queue_addr=0x%x): m_depth limit broken", queue.GetAddr());
|
||||||
|
Emu.Pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 position;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
const u64 old_data = queue->m_data();
|
||||||
|
CellSyncQueue new_queue;
|
||||||
|
new_queue.m_data() = old_data;
|
||||||
|
|
||||||
|
const u32 v1 = (u32)new_queue.m_v1;
|
||||||
|
const u32 v2 = (u32)new_queue.m_v2;
|
||||||
|
// prx: compare 5th u8 with zero (repeat if not zero)
|
||||||
|
// prx: compare (second u32 (u24) + first u8) with depth (repeat if greater or equal)
|
||||||
|
if ((v2 >> 24) || ((v2 & 0xffffff) + (v1 >> 24)) >= depth)
|
||||||
|
{
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||||
|
if (Emu.IsStopped())
|
||||||
|
{
|
||||||
|
cellSync->Warning("cellSyncQueuePush(queue_addr=0x%x) aborted", queue.GetAddr());
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prx: extract first u32 (u24) (-> position), calculate (position + 1) % depth, insert it back
|
||||||
|
// prx: insert 1 in 5th u8
|
||||||
|
// prx: extract second u32 (u24), increase it, insert it back
|
||||||
|
position = (v1 & 0xffffff);
|
||||||
|
new_queue.m_v1 = (v1 & 0xff000000) | ((position + 1) % depth);
|
||||||
|
new_queue.m_v2 = (1 << 24) | ((v2 & 0xffffff) + 1);
|
||||||
|
if (InterlockedCompareExchange(&queue->m_data(), new_queue.m_data(), old_data) == old_data) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prx: memcpy(position * m_size + m_addr, buffer_addr, m_size), sync
|
||||||
|
memcpy(Memory + (u64)queue->m_addr + position * size, Memory + buffer_addr, size);
|
||||||
|
|
||||||
|
// prx: atomically insert 0 in 5th u8
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
const u64 old_data = queue->m_data();
|
||||||
|
CellSyncQueue new_queue;
|
||||||
|
new_queue.m_data() = old_data;
|
||||||
|
|
||||||
|
new_queue.m_v2 &= 0xffffff; // TODO: use InterlockedAnd() or something
|
||||||
|
if (InterlockedCompareExchange(&queue->m_data(), new_queue.m_data(), old_data) == old_data) break;
|
||||||
|
}
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,8 @@ static_assert(sizeof(CellSyncRwm) == 16, "CellSyncBarrier: wrong size");
|
||||||
|
|
||||||
struct CellSyncQueue
|
struct CellSyncQueue
|
||||||
{
|
{
|
||||||
be_t<u64> m_value;
|
be_t<u32> m_v1;
|
||||||
|
be_t<u32> m_v2;
|
||||||
be_t<u32> m_size;
|
be_t<u32> m_size;
|
||||||
be_t<u32> m_depth;
|
be_t<u32> m_depth;
|
||||||
be_t<u64> m_addr;
|
be_t<u64> m_addr;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue