Fixed conflicts and minor changes (2)

This commit is contained in:
Alexandro Sánchez Bach 2014-07-06 18:05:52 +02:00
parent 0002cc0af3
commit 230ba0d360
15 changed files with 35 additions and 1278 deletions

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "SPUThread.h" #include "SPUThread.h"
#include "Emu/event.h" #include "Emu/Event.h"
__forceinline static u32 GetRawSPURegAddrByNum(int num, int offset) __forceinline static u32 GetRawSPURegAddrByNum(int num, int offset)
{ {

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "PPCThread.h" #include "PPCThread.h"
#include "Emu/event.h" #include "Emu/Event.h"
#include "Emu/SysCalls/lv2/sys_spu.h" #include "Emu/SysCalls/lv2/sys_spu.h"
#include "MFC.h" #include "MFC.h"
#include "Emu/SysCalls/ErrorCodes.h" #include "Emu/SysCalls/ErrorCodes.h"

View File

@ -2,7 +2,7 @@
#include "Utilities/Log.h" #include "Utilities/Log.h"
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "event.h" #include "Event.h"
void EventManager::Init() void EventManager::Init()
{ {

View File

@ -24,7 +24,7 @@
#include "lv2/sys_tty.h" #include "lv2/sys_tty.h"
#include "lv2/sys_vm.h" #include "lv2/sys_vm.h"
#include "Emu/event.h" #include "Emu/Event.h"
//#define SYSCALLS_DEBUG //#define SYSCALLS_DEBUG

View File

@ -1,388 +0,0 @@
#include "stdafx.h"
#include "Utilities/Log.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/Cell/PPUThread.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/Cell/SPUThread.h"
#include "Emu/event.h"
SysCallBase sys_event("sys_event");
//128
int sys_event_queue_create(mem32_t equeue_id, mem_ptr_t<sys_event_queue_attr> attr, u64 event_queue_key, int size)
{
sys_event.Warning("sys_event_queue_create(equeue_id_addr=0x%x, attr_addr=0x%x, event_queue_key=0x%llx, size=%d)",
equeue_id.GetAddr(), attr.GetAddr(), event_queue_key, size);
if(size <= 0 || size > 127)
{
return CELL_EINVAL;
}
if(!equeue_id.IsGood() || !attr.IsGood())
{
return CELL_EFAULT;
}
switch (attr->protocol.ToBE())
{
case se32(SYS_SYNC_PRIORITY): break;
case se32(SYS_SYNC_RETRY): sys_event.Error("Invalid SYS_SYNC_RETRY protocol attr"); return CELL_EINVAL;
case se32(SYS_SYNC_PRIORITY_INHERIT): sys_event.Error("Invalid SYS_SYNC_PRIORITY_INHERIT protocol attr"); return CELL_EINVAL;
case se32(SYS_SYNC_FIFO): break;
default: sys_event.Error("Unknown 0x%x protocol attr", (u32)attr->protocol); return CELL_EINVAL;
}
switch (attr->type.ToBE())
{
case se32(SYS_PPU_QUEUE): break;
case se32(SYS_SPU_QUEUE): break;
default: sys_event.Error("Unknown 0x%x type attr", (u32)attr->type); return CELL_EINVAL;
}
if (event_queue_key && Emu.GetEventManager().CheckKey(event_queue_key))
{
return CELL_EEXIST;
}
EventQueue* eq = new EventQueue((u32)attr->protocol, (int)attr->type, attr->name_u64, event_queue_key, size);
if (event_queue_key && !Emu.GetEventManager().RegisterKey(eq, event_queue_key))
{
delete eq;
return CELL_EAGAIN;
}
equeue_id = sys_event.GetNewId(eq);
sys_event.Warning("*** event_queue created [%s] (protocol=0x%x, type=0x%x): id = %d",
std::string(attr->name, 8).c_str(), (u32)attr->protocol, (int)attr->type, equeue_id.GetValue());
return CELL_OK;
}
int sys_event_queue_destroy(u32 equeue_id, int mode)
{
sys_event.Error("sys_event_queue_destroy(equeue_id=%d, mode=0x%x)", equeue_id, mode);
EventQueue* eq;
if (!Emu.GetIdManager().GetIDData(equeue_id, eq))
{
return CELL_ESRCH;
}
if (mode && mode != SYS_EVENT_QUEUE_DESTROY_FORCE)
{
return CELL_EINVAL;
}
u32 tid = GetCurrentPPUThread().GetId();
eq->sq.m_mutex.lock();
eq->owner.lock(tid);
// check if some threads are waiting for an event
if (!mode && eq->sq.list.size())
{
eq->owner.unlock(tid);
eq->sq.m_mutex.unlock();
return CELL_EBUSY;
}
eq->owner.unlock(tid, ~0);
eq->sq.m_mutex.unlock();
while (eq->sq.list.size())
{
Sleep(1);
if (Emu.IsStopped())
{
LOG_WARNING(HLE, "sys_event_queue_destroy(equeue=%d) aborted", equeue_id);
break;
}
}
Emu.GetEventManager().UnregisterKey(eq->key);
eq->ports.clear();
Emu.GetIdManager().RemoveID(equeue_id);
return CELL_OK;
}
int sys_event_queue_tryreceive(u32 equeue_id, mem_ptr_t<sys_event_data> event_array, int size, mem32_t number)
{
sys_event.Error("sys_event_queue_tryreceive(equeue_id=%d, event_array_addr=0x%x, size=%d, number_addr=0x%x)",
equeue_id, event_array.GetAddr(), size, number.GetAddr());
if (size < 0 || !number.IsGood())
{
return CELL_EFAULT;
}
if (size && !Memory.IsGoodAddr(event_array.GetAddr(), sizeof(sys_event_data) * size))
{
return CELL_EFAULT;
}
EventQueue* eq;
if (!Emu.GetIdManager().GetIDData(equeue_id, eq))
{
return CELL_ESRCH;
}
if (eq->type != SYS_PPU_QUEUE)
{
return CELL_EINVAL;
}
if (size == 0)
{
number = 0;
return CELL_OK;
}
u32 tid = GetCurrentPPUThread().GetId();
eq->sq.m_mutex.lock();
eq->owner.lock(tid);
if (eq->sq.list.size())
{
number = 0;
eq->owner.unlock(tid);
eq->sq.m_mutex.unlock();
return CELL_OK;
}
number = eq->events.pop_all((sys_event_data*)(Memory + event_array.GetAddr()), size);
eq->owner.unlock(tid);
eq->sq.m_mutex.unlock();
return CELL_OK;
}
int sys_event_queue_receive(u32 equeue_id, mem_ptr_t<sys_event_data> event, u64 timeout)
{
sys_event.Log("sys_event_queue_receive(equeue_id=%d, event_addr=0x%x, timeout=%lld)",
equeue_id, event.GetAddr(), timeout);
if (!event.IsGood())
{
return CELL_EFAULT;
}
EventQueue* eq;
if (!Emu.GetIdManager().GetIDData(equeue_id, eq))
{
return CELL_ESRCH;
}
if (eq->type != SYS_PPU_QUEUE)
{
return CELL_EINVAL;
}
u32 tid = GetCurrentPPUThread().GetId();
eq->sq.push(tid); // add thread to sleep queue
timeout = timeout ? (timeout / 1000) : ~0;
u64 counter = 0;
while (true)
{
switch (eq->owner.trylock(tid))
{
case SMR_OK:
if (!eq->events.count())
{
eq->owner.unlock(tid);
break;
}
else
{
u32 next = (eq->protocol == SYS_SYNC_FIFO) ? eq->sq.pop() : eq->sq.pop_prio();
if (next != tid)
{
eq->owner.unlock(tid, next);
break;
}
}
case SMR_SIGNAL:
{
eq->events.pop(*event);
eq->owner.unlock(tid);
sys_event.Log(" *** event received: source=0x%llx, d1=0x%llx, d2=0x%llx, d3=0x%llx",
(u64)event->source, (u64)event->data1, (u64)event->data2, (u64)event->data3);
/* passing event data in registers */
PPUThread& t = GetCurrentPPUThread();
t.GPR[4] = event->source;
t.GPR[5] = event->data1;
t.GPR[6] = event->data2;
t.GPR[7] = event->data3;
return CELL_OK;
}
case SMR_FAILED: break;
default: eq->sq.invalidate(tid); return CELL_ECANCELED;
}
Sleep(1);
if (counter++ > timeout || Emu.IsStopped())
{
if (Emu.IsStopped()) LOG_WARNING(HLE, "sys_event_queue_receive(equeue=%d) aborted", equeue_id);
eq->sq.invalidate(tid);
return CELL_ETIMEDOUT;
}
}
}
int sys_event_queue_drain(u32 equeue_id)
{
sys_event.Log("sys_event_queue_drain(equeue_id=%d)", equeue_id);
EventQueue* eq;
if (!Emu.GetIdManager().GetIDData(equeue_id, eq))
{
return CELL_ESRCH;
}
eq->events.clear();
return CELL_OK;
}
int sys_event_port_create(mem32_t eport_id, int port_type, u64 name)
{
sys_event.Warning("sys_event_port_create(eport_id_addr=0x%x, port_type=0x%x, name=0x%llx)",
eport_id.GetAddr(), port_type, name);
if (!eport_id.IsGood())
{
return CELL_EFAULT;
}
if (port_type != SYS_EVENT_PORT_LOCAL)
{
sys_event.Error("sys_event_port_create: invalid port_type(0x%x)", port_type);
return CELL_EINVAL;
}
EventPort* eport = new EventPort();
u32 id = sys_event.GetNewId(eport);
eport->name = name ? name : ((u64)sys_process_getpid() << 32) | (u64)id;
eport_id = id;
sys_event.Warning("*** sys_event_port created: id = %d", id);
return CELL_OK;
}
int sys_event_port_destroy(u32 eport_id)
{
sys_event.Warning("sys_event_port_destroy(eport_id=%d)", eport_id);
EventPort* eport;
if (!Emu.GetIdManager().GetIDData(eport_id, eport))
{
return CELL_ESRCH;
}
if (!eport->m_mutex.try_lock())
{
return CELL_EISCONN;
}
if (eport->eq)
{
eport->m_mutex.unlock();
return CELL_EISCONN;
}
eport->m_mutex.unlock();
Emu.GetIdManager().RemoveID(eport_id);
return CELL_OK;
}
int sys_event_port_connect_local(u32 eport_id, u32 equeue_id)
{
sys_event.Warning("sys_event_port_connect_local(eport_id=%d, equeue_id=%d)", eport_id, equeue_id);
EventPort* eport;
if (!Emu.GetIdManager().GetIDData(eport_id, eport))
{
return CELL_ESRCH;
}
if (!eport->m_mutex.try_lock())
{
return CELL_EISCONN;
}
if (eport->eq)
{
eport->m_mutex.unlock();
return CELL_EISCONN;
}
EventQueue* equeue;
if (!Emu.GetIdManager().GetIDData(equeue_id, equeue))
{
sys_event.Error("sys_event_port_connect_local: event_queue(%d) not found!", equeue_id);
eport->m_mutex.unlock();
return CELL_ESRCH;
}
else
{
equeue->ports.add(eport);
}
eport->eq = equeue;
eport->m_mutex.unlock();
return CELL_OK;
}
int sys_event_port_disconnect(u32 eport_id)
{
sys_event.Warning("sys_event_port_disconnect(eport_id=%d)", eport_id);
EventPort* eport;
if (!Emu.GetIdManager().GetIDData(eport_id, eport))
{
return CELL_ESRCH;
}
if (!eport->eq)
{
return CELL_ENOTCONN;
}
if (!eport->m_mutex.try_lock())
{
return CELL_EBUSY;
}
eport->eq->ports.remove(eport);
eport->eq = nullptr;
eport->m_mutex.unlock();
return CELL_OK;
}
int sys_event_port_send(u32 eport_id, u64 data1, u64 data2, u64 data3)
{
sys_event.Log("sys_event_port_send(eport_id=%d, data1=0x%llx, data2=0x%llx, data3=0x%llx)",
eport_id, data1, data2, data3);
EventPort* eport;
if (!Emu.GetIdManager().GetIDData(eport_id, eport))
{
return CELL_ESRCH;
}
std::lock_guard<std::mutex> lock(eport->m_mutex);
EventQueue* eq = eport->eq;
if (!eq)
{
return CELL_ENOTCONN;
}
if (!eq->events.push(eport->name, data1, data2, data3))
{
return CELL_EBUSY;
}
return CELL_OK;
}

View File

@ -1,370 +0,0 @@
#include "stdafx.h"
#include "Utilities/Log.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/Cell/PPUThread.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/lv2/SC_Event_flag.h"
SysCallBase sys_event_flag("sys_event_flag");
int sys_event_flag_create(mem32_t eflag_id, mem_ptr_t<sys_event_flag_attr> attr, u64 init)
{
sys_event_flag.Warning("sys_event_flag_create(eflag_id_addr=0x%x, attr_addr=0x%x, init=0x%llx)",
eflag_id.GetAddr(), attr.GetAddr(), init);
if(!eflag_id.IsGood() || !attr.IsGood())
{
return CELL_EFAULT;
}
switch (attr->protocol.ToBE())
{
case se32(SYS_SYNC_PRIORITY): break;
case se32(SYS_SYNC_RETRY): sys_event_flag.Warning("TODO: SYS_SYNC_RETRY attr"); break;
case se32(SYS_SYNC_PRIORITY_INHERIT): sys_event_flag.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break;
case se32(SYS_SYNC_FIFO): break;
default: return CELL_EINVAL;
}
if (attr->pshared.ToBE() != se32(0x200))
{
return CELL_EINVAL;
}
switch (attr->type.ToBE())
{
case se32(SYS_SYNC_WAITER_SINGLE): break;
case se32(SYS_SYNC_WAITER_MULTIPLE): break;
default: return CELL_EINVAL;
}
eflag_id = sys_event_flag.GetNewId(new EventFlag(init, (u32)attr->protocol, (int)attr->type));
sys_event_flag.Warning("*** event_flag created [%s] (protocol=0x%x, type=0x%x): id = %d",
std::string(attr->name, 8).c_str(), (u32)attr->protocol, (int)attr->type, eflag_id.GetValue());
return CELL_OK;
}
int sys_event_flag_destroy(u32 eflag_id)
{
sys_event_flag.Warning("sys_event_flag_destroy(eflag_id=%d)", eflag_id);
EventFlag* ef;
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
if (ef->waiters.size()) // ???
{
return CELL_EBUSY;
}
Emu.GetIdManager().RemoveID(eflag_id);
return CELL_OK;
}
int sys_event_flag_wait(u32 eflag_id, u64 bitptn, u32 mode, mem64_t result, u64 timeout)
{
sys_event_flag.Log("sys_event_flag_wait(eflag_id=%d, bitptn=0x%llx, mode=0x%x, result_addr=0x%x, timeout=%lld)",
eflag_id, bitptn, mode, result.GetAddr(), timeout);
if (result.IsGood()) result = 0;
switch (mode & 0xf)
{
case SYS_EVENT_FLAG_WAIT_AND: break;
case SYS_EVENT_FLAG_WAIT_OR: break;
default: return CELL_EINVAL;
}
switch (mode & ~0xf)
{
case 0: break; // ???
case SYS_EVENT_FLAG_WAIT_CLEAR: break;
case SYS_EVENT_FLAG_WAIT_CLEAR_ALL: break;
default: return CELL_EINVAL;
}
EventFlag* ef;
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
u32 tid = GetCurrentPPUThread().GetId();
{
SMutexLocker lock(ef->m_mutex);
if (ef->m_type == SYS_SYNC_WAITER_SINGLE && ef->waiters.size() > 0)
{
return CELL_EPERM;
}
EventFlagWaiter rec;
rec.bitptn = bitptn;
rec.mode = mode;
rec.tid = tid;
ef->waiters.push_back(rec);
if (ef->check() == tid)
{
u64 flags = ef->flags;
ef->waiters.erase(ef->waiters.end() - 1);
if (mode & SYS_EVENT_FLAG_WAIT_CLEAR)
{
ef->flags &= ~bitptn;
}
else if (mode & SYS_EVENT_FLAG_WAIT_CLEAR_ALL)
{
ef->flags = 0;
}
if (result.IsGood())
{
result = flags;
return CELL_OK;
}
if (!result.GetAddr())
{
return CELL_OK;
}
return CELL_EFAULT;
}
}
u32 counter = 0;
const u32 max_counter = timeout ? (timeout / 1000) : ~0;
while (true)
{
if (ef->signal.unlock(tid, tid) == SMR_OK)
{
SMutexLocker lock(ef->m_mutex);
u64 flags = ef->flags;
for (u32 i = 0; i < ef->waiters.size(); i++)
{
if (ef->waiters[i].tid == tid)
{
ef->waiters.erase(ef->waiters.begin() +i);
if (mode & SYS_EVENT_FLAG_WAIT_CLEAR)
{
ef->flags &= ~bitptn;
}
else if (mode & SYS_EVENT_FLAG_WAIT_CLEAR_ALL)
{
ef->flags = 0;
}
if (u32 target = ef->check())
{
// if signal, leave both mutexes locked...
ef->signal.unlock(tid, target);
ef->m_mutex.unlock(tid, target);
}
else
{
ef->signal.unlock(tid);
}
if (result.IsGood())
{
result = flags;
return CELL_OK;
}
if (!result.GetAddr())
{
return CELL_OK;
}
return CELL_EFAULT;
}
}
ef->signal.unlock(tid);
return CELL_ECANCELED;
}
Sleep(1);
if (counter++ > max_counter)
{
SMutexLocker lock(ef->m_mutex);
for (u32 i = 0; i < ef->waiters.size(); i++)
{
if (ef->waiters[i].tid == tid)
{
ef->waiters.erase(ef->waiters.begin() + i);
break;
}
}
return CELL_ETIMEDOUT;
}
if (Emu.IsStopped())
{
LOG_WARNING(HLE, "sys_event_flag_wait(id=%d) aborted", eflag_id);
return CELL_OK;
}
}
}
int sys_event_flag_trywait(u32 eflag_id, u64 bitptn, u32 mode, mem64_t result)
{
sys_event_flag.Log("sys_event_flag_trywait(eflag_id=%d, bitptn=0x%llx, mode=0x%x, result_addr=0x%x)",
eflag_id, bitptn, mode, result.GetAddr());
if (result.IsGood()) result = 0;
switch (mode & 0xf)
{
case SYS_EVENT_FLAG_WAIT_AND: break;
case SYS_EVENT_FLAG_WAIT_OR: break;
default: return CELL_EINVAL;
}
switch (mode & ~0xf)
{
case 0: break; // ???
case SYS_EVENT_FLAG_WAIT_CLEAR: break;
case SYS_EVENT_FLAG_WAIT_CLEAR_ALL: break;
default: return CELL_EINVAL;
}
EventFlag* ef;
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
SMutexLocker lock(ef->m_mutex);
u64 flags = ef->flags;
if (((mode & SYS_EVENT_FLAG_WAIT_AND) && (flags & bitptn) == bitptn) ||
((mode & SYS_EVENT_FLAG_WAIT_OR) && (flags & bitptn)))
{
if (mode & SYS_EVENT_FLAG_WAIT_CLEAR)
{
ef->flags &= ~bitptn;
}
else if (mode & SYS_EVENT_FLAG_WAIT_CLEAR_ALL)
{
ef->flags = 0;
}
if (result.IsGood())
{
result = flags;
return CELL_OK;
}
if (!result.GetAddr())
{
return CELL_OK;
}
return CELL_EFAULT;
}
return CELL_EBUSY;
}
int sys_event_flag_set(u32 eflag_id, u64 bitptn)
{
sys_event_flag.Log("sys_event_flag_set(eflag_id=%d, bitptn=0x%llx)", eflag_id, bitptn);
EventFlag* ef;
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
u32 tid = GetCurrentPPUThread().GetId();
ef->m_mutex.lock(tid);
ef->flags |= bitptn;
if (u32 target = ef->check())
{
// if signal, leave both mutexes locked...
ef->signal.lock(target);
ef->m_mutex.unlock(tid, target);
}
else
{
ef->m_mutex.unlock(tid);
}
return CELL_OK;
}
int sys_event_flag_clear(u32 eflag_id, u64 bitptn)
{
sys_event_flag.Log("sys_event_flag_clear(eflag_id=%d, bitptn=0x%llx)", eflag_id, bitptn);
EventFlag* ef;
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
SMutexLocker lock(ef->m_mutex);
ef->flags &= bitptn;
return CELL_OK;
}
int sys_event_flag_cancel(u32 eflag_id, mem32_t num)
{
sys_event_flag.Log("sys_event_flag_cancel(eflag_id=%d, num_addr=0x%x)", eflag_id, num.GetAddr());
EventFlag* ef;
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
std::vector<u32> tids;
{
SMutexLocker lock(ef->m_mutex);
tids.resize(ef->waiters.size());
for (u32 i = 0; i < ef->waiters.size(); i++)
{
tids[i] = ef->waiters[i].tid;
}
ef->waiters.clear();
}
for (u32 i = 0; i < tids.size(); i++)
{
ef->signal.lock(tids[i]);
}
if (Emu.IsStopped())
{
LOG_WARNING(HLE, "sys_event_flag_cancel(id=%d) aborted", eflag_id);
return CELL_OK;
}
if (num.IsGood())
{
num = tids.size();
return CELL_OK;
}
if (!num.GetAddr())
{
return CELL_OK;
}
return CELL_EFAULT;
}
int sys_event_flag_get(u32 eflag_id, mem64_t flags)
{
sys_event_flag.Log("sys_event_flag_get(eflag_id=%d, flags_addr=0x%x)", eflag_id, flags.GetAddr());
EventFlag* ef;
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
if (!flags.IsGood())
{
return CELL_EFAULT;
}
SMutexLocker lock(ef->m_mutex);
flags = ef->flags;
return CELL_OK;
}

View File

@ -1,32 +0,0 @@
#include "stdafx.h"
#include "Utilities/Log.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/Cell/PPUThread.h"
#include "Emu/SysCalls/SC_FUNC.h"
#include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/GS/GCM.h"
extern Module cellGcmSys;
extern gcmInfo gcm_info;
int cellGcmCallback(u32 context_addr, u32 count)
{
GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH);
CellGcmContextData& ctx = (CellGcmContextData&)Memory[context_addr];
CellGcmControl& ctrl = (CellGcmControl&)Memory[gcm_info.control_addr];
const s32 res = ctx.current - ctx.begin - ctrl.put;
if(res > 0) Memory.Copy(ctx.begin, ctx.current - res, res);
ctx.current = ctx.begin + res;
//InterlockedExchange64((volatile long long*)((u8*)&ctrl + offsetof(CellGcmControl, put)), (u64)(u32)re(res));
ctrl.put = res;
ctrl.get = 0;
return CELL_OK;
}

View File

@ -1,50 +0,0 @@
#include "stdafx.h"
#include "Utilities/Log.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/SysCalls/SysCalls.h"
SysCallBase sc_heap("sys_heap");
struct HeapInfo
{
u32 heap_addr;
u32 align;
u32 size;
HeapInfo(u32 _heap_addr, u32 _align, u32 _size)
: heap_addr(_heap_addr)
, align(_align)
, size(_size)
{
}
};
int sys_heap_create_heap(const u32 heap_addr, const u32 align, const u32 size)
{
sc_heap.Warning("sys_heap_create_heap(heap_addr=0x%x, align=0x%x, size=0x%x)", heap_addr, align, size);
u32 heap_id = sc_heap.GetNewId(new HeapInfo(heap_addr, align, size));
sc_heap.Warning("*** sys_heap created: id = %d", heap_id);
return heap_id;
}
int sys_heap_malloc(const u32 heap_id, const u32 size)
{
sc_heap.Warning("sys_heap_malloc(heap_id=%d, size=0x%x)", heap_id, size);
HeapInfo* heap;
if(!sc_heap.CheckId(heap_id, heap)) return CELL_ESRCH;
return Memory.Alloc(size, 1);
}
int _sys_heap_memalign(u32 heap_id, u32 align, u32 size)
{
sc_heap.Warning("_sys_heap_memalign(heap_id=%d, align=0x%x, size=0x%x)", heap_id, align, size);
HeapInfo* heap;
if(!sc_heap.CheckId(heap_id, heap)) return CELL_ESRCH;
return Memory.Alloc(size, align);
}

View File

@ -1,423 +0,0 @@
#include "stdafx.h"
#include "Utilities/Log.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/SysCalls/SysCalls.h"
#include "SC_Memory.h"
#include <map>
SysCallBase sc_mem("memory");
std::map<u32, u32> mmapper_info_map;
int sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr)
{
sc_mem.Log("sys_memory_allocate(size=0x%x, flags=0x%x)", size, flags);
// Check page size.
u32 addr;
switch(flags)
{
case SYS_MEMORY_PAGE_SIZE_1M:
if(size & 0xfffff) return CELL_EALIGN;
addr = Memory.Alloc(size, 0x100000);
break;
case SYS_MEMORY_PAGE_SIZE_64K:
if(size & 0xffff) return CELL_EALIGN;
addr = Memory.Alloc(size, 0x10000);
break;
default: return CELL_EINVAL;
}
if(!addr)
return CELL_ENOMEM;
// Write back the start address of the allocated area.
sc_mem.Log("Memory allocated! [addr: 0x%x, size: 0x%x]", addr, size);
Memory.Write32(alloc_addr_addr, addr);
return CELL_OK;
}
int sys_memory_allocate_from_container(u32 size, u32 cid, u32 flags, u32 alloc_addr_addr)
{
sc_mem.Log("sys_memory_allocate_from_container(size=0x%x, cid=0x%x, flags=0x%x)", size, cid, flags);
// Check if this container ID is valid.
MemoryContainerInfo* ct;
if(!sc_mem.CheckId(cid, ct))
return CELL_ESRCH;
// Check page size.
switch(flags)
{
case SYS_MEMORY_PAGE_SIZE_1M:
if(size & 0xfffff) return CELL_EALIGN;
ct->addr = Memory.Alloc(size, 0x100000);
break;
case SYS_MEMORY_PAGE_SIZE_64K:
if(size & 0xffff) return CELL_EALIGN;
ct->addr = Memory.Alloc(size, 0x10000);
break;
default: return CELL_EINVAL;
}
// Store the address and size in the container.
if(!ct->addr)
return CELL_ENOMEM;
ct->size = size;
// Write back the start address of the allocated area.
sc_mem.Log("Memory allocated! [addr: 0x%x, size: 0x%x]", ct->addr, ct->size);
Memory.Write32(alloc_addr_addr, ct->addr);
return CELL_OK;
}
int sys_memory_free(u32 start_addr)
{
sc_mem.Log("sys_memory_free(start_addr=0x%x)", start_addr);
// Release the allocated memory.
if(!Memory.Free(start_addr))
return CELL_EFAULT;
return CELL_OK;
}
int sys_memory_get_page_attribute(u32 addr, mem_ptr_t<sys_page_attr_t> attr)
{
sc_mem.Warning("sys_memory_get_page_attribute(addr=0x%x, attr_addr=0x%x)", addr, attr.GetAddr());
if (!attr.IsGood())
return CELL_EFAULT;
// TODO: Implement per thread page attribute setting.
attr->attribute = 0;
attr->page_size = 0;
attr->access_right = 0;
attr->pad = 0;
return CELL_OK;
}
int sys_memory_get_user_memory_size(mem_ptr_t<sys_memory_info_t> mem_info)
{
sc_mem.Warning("sys_memory_get_user_memory_size(mem_info_addr=0x%x)", mem_info.GetAddr());
// Fetch the user memory available.
mem_info->total_user_memory = Memory.GetUserMemTotalSize();
mem_info->available_user_memory = Memory.GetUserMemAvailSize();
return CELL_OK;
}
int sys_memory_container_create(mem32_t cid, u32 yield_size)
{
sc_mem.Warning("sys_memory_container_create(cid_addr=0x%x, yield_size=0x%x)", cid.GetAddr(), yield_size);
if (!cid.IsGood())
return CELL_EFAULT;
yield_size &= ~0xfffff; //round down to 1 MB granularity
u64 addr = Memory.Alloc(yield_size, 0x100000); //1 MB alignment
if(!addr)
return CELL_ENOMEM;
// Wrap the allocated memory in a memory container.
MemoryContainerInfo *ct = new MemoryContainerInfo(addr, yield_size);
cid = sc_mem.GetNewId(ct);
procObjects.mem_objects.insert(cid);
sc_mem.Warning("*** memory_container created(addr=0x%llx): id = %d", addr, cid.GetValue());
return CELL_OK;
}
int sys_memory_container_destroy(u32 cid)
{
sc_mem.Warning("sys_memory_container_destroy(cid=%d)", cid);
// Check if this container ID is valid.
MemoryContainerInfo* ct;
if(!sc_mem.CheckId(cid, ct))
return CELL_ESRCH;
// Release the allocated memory and remove the ID.
Memory.Free(ct->addr);
Emu.GetIdManager().RemoveID(cid);
return CELL_OK;
}
int sys_memory_container_get_size(mem_ptr_t<sys_memory_info_t> mem_info, u32 cid)
{
sc_mem.Warning("sys_memory_container_get_size(mem_info_addr=0x%x, cid=%d)", mem_info.GetAddr(), cid);
// Check if this container ID is valid.
MemoryContainerInfo* ct;
if(!sc_mem.CheckId(cid, ct))
return CELL_ESRCH;
// HACK: Return all memory.
sys_memory_info_t info;
mem_info->total_user_memory = ct->size;
mem_info->available_user_memory = ct->size;
return CELL_OK;
}
int sys_mmapper_allocate_address(u32 size, u64 flags, u32 alignment, u32 alloc_addr)
{
sc_mem.Warning("sys_mmapper_allocate_address(size=0x%x, flags=0x%llx, alignment=0x%x, alloc_addr=0x%x)",
size, flags, alignment, alloc_addr);
if(!Memory.IsGoodAddr(alloc_addr))
return CELL_EFAULT;
// Check for valid alignment.
if(alignment > 0x80000000)
return CELL_EALIGN;
// Check page size.
u32 addr;
switch(flags & (SYS_MEMORY_PAGE_SIZE_1M | SYS_MEMORY_PAGE_SIZE_64K))
{
default:
case SYS_MEMORY_PAGE_SIZE_1M:
if(Memory.AlignAddr(size, alignment) & 0xfffff)
return CELL_EALIGN;
addr = Memory.Alloc(size, 0x100000);
break;
case SYS_MEMORY_PAGE_SIZE_64K:
if(Memory.AlignAddr(size, alignment) & 0xffff)
return CELL_EALIGN;
addr = Memory.Alloc(size, 0x10000);
break;
}
// Write back the start address of the allocated area.
Memory.Write32(alloc_addr, addr);
return CELL_OK;
}
int sys_mmapper_allocate_fixed_address()
{
sc_mem.Warning("sys_mmapper_allocate_fixed_address");
// Allocate a fixed size from user memory.
if (!Memory.Alloc(SYS_MMAPPER_FIXED_SIZE, 0x100000))
return CELL_EEXIST;
return CELL_OK;
}
int sys_mmapper_allocate_memory(u32 size, u64 flags, mem32_t mem_id)
{
sc_mem.Warning("sys_mmapper_allocate_memory(size=0x%x, flags=0x%llx, mem_id_addr=0x%x)", size, flags, mem_id.GetAddr());
if(!mem_id.IsGood())
return CELL_EFAULT;
// Check page granularity.
u32 addr;
switch(flags & (SYS_MEMORY_PAGE_SIZE_1M | SYS_MEMORY_PAGE_SIZE_64K))
{
case SYS_MEMORY_PAGE_SIZE_1M:
if(size & 0xfffff)
return CELL_EALIGN;
addr = Memory.Alloc(size, 0x100000);
break;
case SYS_MEMORY_PAGE_SIZE_64K:
if(size & 0xffff)
return CELL_EALIGN;
addr = Memory.Alloc(size, 0x10000);
break;
default:
return CELL_EINVAL;
}
if(!addr)
return CELL_ENOMEM;
// Generate a new mem ID.
mem_id = sc_mem.GetNewId(new mmapper_info(addr, size, flags));
return CELL_OK;
}
int sys_mmapper_allocate_memory_from_container(u32 size, u32 cid, u64 flags, mem32_t mem_id)
{
sc_mem.Warning("sys_mmapper_allocate_memory_from_container(size=0x%x, cid=%d, flags=0x%llx, mem_id_addr=0x%x)",
size, cid, flags, mem_id.GetAddr());
if(!mem_id.IsGood())
return CELL_EFAULT;
// Check if this container ID is valid.
MemoryContainerInfo* ct;
if(!sc_mem.CheckId(cid, ct))
return CELL_ESRCH;
// Check page granularity.
switch(flags & (SYS_MEMORY_PAGE_SIZE_1M | SYS_MEMORY_PAGE_SIZE_64K))
{
case SYS_MEMORY_PAGE_SIZE_1M:
if(size & 0xfffff)
return CELL_EALIGN;
ct->addr = Memory.Alloc(size, 0x100000);
break;
case SYS_MEMORY_PAGE_SIZE_64K:
if(size & 0xffff)
return CELL_EALIGN;
ct->addr = Memory.Alloc(size, 0x10000);
break;
default:
return CELL_EINVAL;
}
if(!ct->addr)
return CELL_ENOMEM;
ct->size = size;
// Generate a new mem ID.
mem_id = sc_mem.GetNewId(new mmapper_info(ct->addr, ct->size, flags));
return CELL_OK;
}
int sys_mmapper_change_address_access_right(u32 start_addr, u64 flags)
{
sc_mem.Warning("sys_mmapper_change_address_access_right(start_addr=0x%x, flags=0x%llx)", start_addr, flags);
if (!Memory.IsGoodAddr(start_addr))
return CELL_EINVAL;
// TODO
return CELL_OK;
}
int sys_mmapper_free_address(u32 start_addr)
{
sc_mem.Warning("sys_mmapper_free_address(start_addr=0x%x)", start_addr);
if(!Memory.IsGoodAddr(start_addr))
return CELL_EINVAL;
// Free the address.
Memory.Free(start_addr);
return CELL_OK;
}
int sys_mmapper_free_memory(u32 mem_id)
{
sc_mem.Warning("sys_mmapper_free_memory(mem_id=0x%x)", mem_id);
// Check if this mem ID is valid.
mmapper_info* info;
if(!sc_mem.CheckId(mem_id, info))
return CELL_ESRCH;
// Release the allocated memory and remove the ID.
Memory.Free(info->addr);
Emu.GetIdManager().RemoveID(mem_id);
return CELL_OK;
}
int sys_mmapper_map_memory(u32 start_addr, u32 mem_id, u64 flags)
{
sc_mem.Warning("sys_mmapper_map_memory(start_addr=0x%x, mem_id=0x%x, flags=0x%llx)", start_addr, mem_id, flags);
// Check if this mem ID is valid.
mmapper_info* info;
if(!sc_mem.CheckId(mem_id, info))
return CELL_ESRCH;
// Map the memory into the process address.
if(!Memory.Map(start_addr, info->addr, info->size))
sc_mem.Error("sys_mmapper_map_memory failed!");
// Keep track of mapped addresses.
mmapper_info_map[mem_id] = start_addr;
return CELL_OK;
}
int sys_mmapper_search_and_map(u32 start_addr, u32 mem_id, u64 flags, u32 alloc_addr)
{
sc_mem.Warning("sys_mmapper_search_and_map(start_addr=0x%x, mem_id=0x%x, flags=0x%llx, alloc_addr=0x%x)",
start_addr, mem_id, flags, alloc_addr);
if(!Memory.IsGoodAddr(alloc_addr))
return CELL_EFAULT;
// Check if this mem ID is valid.
mmapper_info* info;
if(!sc_mem.CheckId(mem_id, info))
return CELL_ESRCH;
// Search for a mappable address.
u32 addr;
bool found;
for (int i = 0; i < SYS_MMAPPER_FIXED_SIZE; i += 0x100000)
{
addr = start_addr + i;
found = Memory.Map(addr, info->addr, info->size);
if(found)
{
sc_mem.Warning("Found and mapped address 0x%x", addr);
break;
}
}
// Check if the address is valid.
if (!Memory.IsGoodAddr(addr) || !found)
return CELL_ENOMEM;
// Write back the start address of the allocated area.
Memory.Write32(alloc_addr, addr);
// Keep track of mapped addresses.
mmapper_info_map[mem_id] = addr;
return CELL_OK;
}
int sys_mmapper_unmap_memory(u32 start_addr, u32 mem_id_addr)
{
sc_mem.Warning("sys_mmapper_unmap_memory(start_addr=0x%x, mem_id_addr=0x%x)", start_addr, mem_id_addr);
if (!Memory.IsGoodAddr(start_addr))
return CELL_EINVAL;
if (!Memory.IsGoodAddr(mem_id_addr))
return CELL_EFAULT;
// Write back the mem ID of the unmapped area.
u32 mem_id = mmapper_info_map.find(start_addr)->first;
Memory.Write32(mem_id_addr, mem_id);
return CELL_OK;
}
int sys_mmapper_enable_page_fault_notification(u32 start_addr, u32 q_id)
{
sc_mem.Warning("sys_mmapper_enable_page_fault_notification(start_addr=0x%x, q_id=0x%x)", start_addr, q_id);
if (!Memory.IsGoodAddr(start_addr))
return CELL_EINVAL;
// TODO
return CELL_OK;
}

View File

@ -6,7 +6,7 @@
#include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/SysCalls.h"
#include "Emu/Cell/SPUThread.h" #include "Emu/Cell/SPUThread.h"
#include "Emu/event.h" #include "Emu/Event.h"
#include "sys_lwmutex.h" #include "sys_lwmutex.h"
#include "sys_event.h" #include "sys_event.h"

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#include "Emu/event.h" #include "Emu/Event.h"
enum enum
{ {

View File

@ -3,7 +3,7 @@
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/SysCalls.h"
#include "Emu/event.h" #include "Emu/Event.h"
#include "sys_timer.h" #include "sys_timer.h"
SysCallBase sys_timer("sys_timer"); SysCallBase sys_timer("sys_timer");

View File

@ -7,7 +7,7 @@
s32 sys_tty_read(u32 ch, u64 buf_addr, u32 len, u64 preadlen_addr) s32 sys_tty_read(u32 ch, u64 buf_addr, u32 len, u64 preadlen_addr)
{ {
//we currently do not support reading from the Console // We currently do not support reading from the Console
LOG_WARNING(HLE, "sys_tty_read: ch: %d, buf addr: %llx, len: %d", ch, buf_addr, len); LOG_WARNING(HLE, "sys_tty_read: ch: %d, buf addr: %llx, len: %d", ch, buf_addr, len);
Memory.Write32NN(preadlen_addr, len); Memory.Write32NN(preadlen_addr, len);
Emu.Pause(); Emu.Pause();
@ -20,15 +20,12 @@ s32 sys_tty_write(u32 ch, u64 buf_addr, u32 len, u64 pwritelen_addr)
if(ch > 15 || (s32)len <= 0) return CELL_EINVAL; if(ch > 15 || (s32)len <= 0) return CELL_EINVAL;
if(!Memory.IsGoodAddr(buf_addr)) return CELL_EFAULT; if(!Memory.IsGoodAddr(buf_addr)) return CELL_EFAULT;
//ch 0 seems to be stdout and ch 1 stderr if (ch == SYS_TTYP_PPU_STDOUT || ch == SYS_TTYP_SPU_STDOUT || (ch >= SYS_TTYP_USER1 && ch <= SYS_TTYP_USER13)) {
if (ch == 1)
{
LOG_ERROR(TTY, Memory.ReadString(buf_addr, len));
}
else
{
LOG_NOTICE(TTY, Memory.ReadString(buf_addr, len)); LOG_NOTICE(TTY, Memory.ReadString(buf_addr, len));
} }
if (ch == SYS_TTYP_PPU_STDERR) {
LOG_ERROR(TTY, Memory.ReadString(buf_addr, len));
}
if(!Memory.IsGoodAddr(pwritelen_addr)) return CELL_EFAULT; if(!Memory.IsGoodAddr(pwritelen_addr)) return CELL_EFAULT;

View File

@ -1,4 +1,27 @@
#pragma once #pragma once
// TTY channels
enum
{
SYS_TTYP_PPU_STDIN = 0,
SYS_TTYP_PPU_STDOUT = 0,
SYS_TTYP_PPU_STDERR = 1,
SYS_TTYP_SPU_STDOUT = 2,
SYS_TTYP_USER1 = 3,
SYS_TTYP_USER2 = 4,
SYS_TTYP_USER3 = 5,
SYS_TTYP_USER4 = 6,
SYS_TTYP_USER5 = 7,
SYS_TTYP_USER6 = 8,
SYS_TTYP_USER7 = 9,
SYS_TTYP_USER8 = 10,
SYS_TTYP_USER9 = 11,
SYS_TTYP_USER10 = 12,
SYS_TTYP_USER11 = 13,
SYS_TTYP_USER12 = 14,
SYS_TTYP_USER13 = 15,
};
// SysCalls
s32 sys_tty_read(u32 ch, u64 buf_addr, u32 len, u64 preadlen_addr); s32 sys_tty_read(u32 ch, u64 buf_addr, u32 len, u64 preadlen_addr);
s32 sys_tty_write(u32 ch, u64 buf_addr, u32 len, u64 pwritelen_addr); s32 sys_tty_write(u32 ch, u64 buf_addr, u32 len, u64 pwritelen_addr);