Implemented mem_func_ptr_t.

Improved cellFsAioRead.
Fixed cellAudioOut* return error codes.
This commit is contained in:
DH 2014-01-08 23:16:13 +02:00
parent 1d61e7b4a4
commit 76695a97b9
5 changed files with 214 additions and 83 deletions

View File

@ -418,12 +418,27 @@ public:
{
}
u32 GetAddr() const { return m_addr; }
__forceinline u32 GetAddr() const { return m_addr; }
bool IsGood() const
__forceinline bool IsGood() const
{
return Memory.IsGoodAddr(m_addr, sizeof(T));
}
__forceinline operator bool() const
{
return m_addr != 0;
}
__forceinline bool operator != (nullptr_t) const
{
return m_addr != 0;
}
__forceinline bool operator == (nullptr_t) const
{
return m_addr == 0;
}
};
template<typename T>
@ -434,6 +449,9 @@ public:
{
}
template<typename NT> operator mem_ptr_t<NT>&() { return (mem_ptr_t<NT>&)*this; }
template<typename NT> operator const mem_ptr_t<NT>&() const { return (const mem_ptr_t<NT>&)*this; }
T* operator -> ()
{
return (T*)&Memory[this->m_addr];
@ -512,8 +530,6 @@ public:
return (const T&)Memory[this->m_addr + sizeof(T) * index];
}
operator bool() const { return this->m_addr == 0; }
bool operator == (mem_ptr_t right) const { return this->m_addr == right.m_addr; }
bool operator != (mem_ptr_t right) const { return this->m_addr != right.m_addr; }
bool operator > (mem_ptr_t right) const { return this->m_addr > right.m_addr; }
@ -529,6 +545,32 @@ public:
bool operator <= (T* right) const { return (T*)&Memory[this->m_addr] <= right; }
};
template<>
class mem_ptr_t<void> : public mem_base_t<u8>
{
public:
mem_ptr_t(u32 addr) : mem_base_t<u8>(addr)
{
}
template<typename NT> operator mem_ptr_t<NT>&() { return (mem_ptr_t<NT>&)*this; }
template<typename NT> operator const mem_ptr_t<NT>&() const { return (const mem_ptr_t<NT>&)*this; }
bool operator == (mem_ptr_t right) const { return this->m_addr == right.m_addr; }
bool operator != (mem_ptr_t right) const { return this->m_addr != right.m_addr; }
bool operator > (mem_ptr_t right) const { return this->m_addr > right.m_addr; }
bool operator < (mem_ptr_t right) const { return this->m_addr < right.m_addr; }
bool operator >= (mem_ptr_t right) const { return this->m_addr >= right.m_addr; }
bool operator <= (mem_ptr_t right) const { return this->m_addr <= right.m_addr; }
bool operator == (void* right) const { return (void*)&Memory[this->m_addr] == right; }
bool operator != (void* right) const { return (void*)&Memory[this->m_addr] != right; }
bool operator > (void* right) const { return (void*)&Memory[this->m_addr] > right; }
bool operator < (void* right) const { return (void*)&Memory[this->m_addr] < right; }
bool operator >= (void* right) const { return (void*)&Memory[this->m_addr] >= right; }
bool operator <= (void* right) const { return (void*)&Memory[this->m_addr] <= right; }
};
template<typename T> static bool operator == (T* left, mem_ptr_t<T> right) { return left == (T*)&Memory[right.GetAddr()]; }
template<typename T> static bool operator != (T* left, mem_ptr_t<T> right) { return left != (T*)&Memory[right.GetAddr()]; }
template<typename T> static bool operator > (T* left, mem_ptr_t<T> right) { return left > (T*)&Memory[right.GetAddr()]; }
@ -638,6 +680,123 @@ public:
void SetAddr(const u64 addr) { m_addr = addr; }
};
template<typename T> class mem_func_ptr_t;
template<typename RT>
class mem_func_ptr_t<RT (*)()> : public mem_base_t<u64>
{
__forceinline void call_func(bool is_async)
{
Callback cb;
cb.SetAddr(m_addr);
cb.Branch(!is_async);
}
public:
__forceinline void operator()()
{
call_func(false);
}
__forceinline void async()
{
call_func(true);
}
};
template<typename RT, typename T1>
class mem_func_ptr_t<RT (*)(T1)> : public mem_base_t<u64>
{
__forceinline void call_func(bool is_async, T1 a1)
{
Callback cb;
cb.SetAddr(m_addr);
cb.Handle(a1);
cb.Branch(!is_async);
}
public:
__forceinline void operator()(T1 a1)
{
call_func(false, a1);
}
__forceinline void async(T1 a1)
{
call_func(true, a1);
}
};
template<typename RT, typename T1, typename T2>
class mem_func_ptr_t<RT (*)(T1, T2)> : public mem_base_t<u64>
{
__forceinline void call_func(bool is_async, T1 a1, T2 a2)
{
Callback cb;
cb.SetAddr(m_addr);
cb.Handle(a1, a2);
cb.Branch(!is_async);
}
public:
__forceinline void operator()(T1 a1, T2 a2)
{
call_func(false, a1, a2);
}
__forceinline void async(T1 a1, T2 a2)
{
call_func(true, a1, a2);
}
};
template<typename RT, typename T1, typename T2, typename T3>
class mem_func_ptr_t<RT (*)(T1, T2, T3)> : public mem_base_t<u64>
{
__forceinline void call_func(bool is_async, T1 a1, T2 a2, T3 a3)
{
Callback cb;
cb.SetAddr(m_addr);
cb.Handle(a1, a2, a3);
cb.Branch(!is_async);
}
public:
__forceinline void operator()(T1 a1, T2 a2, T3 a3)
{
call_func(false, a1, a2, a3);
}
__forceinline void async(T1 a1, T2 a2, T3 a3)
{
call_func(true, a1, a2, a3);
}
};
template<typename RT, typename T1, typename T2, typename T3, typename T4>
class mem_func_ptr_t<RT (*)(T1, T2, T3, T4)> : public mem_base_t<u64>
{
__forceinline void call_func(bool is_async, T1 a1, T2 a2, T3 a3, T4 a4)
{
Callback cb;
cb.SetAddr(m_addr);
cb.Handle(a1, a2, a3, a4);
cb.Branch(!is_async);
}
public:
__forceinline void operator()(T1 a1, T2 a2, T3 a3, T4 a4)
{
call_func(false, a1, a2, a3, a4);
}
__forceinline void async(T1 a1, T2 a2, T3 a3, T4 a4)
{
call_func(true, a1, a2, a3, a4);
}
};
template<typename T>
class MemoryAllocator
{

View File

@ -106,9 +106,6 @@ enum
CELL_SYSUTIL_PAD_RUMBLE_ON = 1,
};
void cellSysutil_init();
Module cellSysutil(0x0015, cellSysutil_init);
enum
{
@ -132,6 +129,11 @@ enum CellMsgDialogType
CELL_MSGDIALOG_DEFAULT_CURSOR_NO = 0x00000100,
};
typedef void (*CellMsgDialogCallback)(int buttonType, mem_ptr_t<void> userData);
void cellSysutil_init();
Module cellSysutil(0x0015, cellSysutil_init);
int cellSysutilGetSystemParamInt(int id, mem32_t value)
{
cellSysutil.Log("cellSysutilGetSystemParamInt(id=0x%x, value_addr=0x%x)", id, value.GetAddr());
@ -477,7 +479,7 @@ int cellSysutilUnregisterCallback(int slot)
return CELL_OK;
}
int cellMsgDialogOpen2(u32 type, char* msgString, u32 callback_addr, u32 userData, u32 extParam)
int cellMsgDialogOpen2(u32 type, char* msgString, mem_func_ptr_t<CellMsgDialogCallback> callback, mem_ptr_t<void> userData, u32 extParam)
{
long style = 0;
@ -520,17 +522,16 @@ int cellMsgDialogOpen2(u32 type, char* msgString, u32 callback_addr, u32 userDat
break;
}
Callback2 callback(0, callback_addr, userData);
callback.Handle(status);
callback.Branch(true);
if(callback)
callback(status, userData);
return CELL_OK;
}
int cellMsgDialogOpenErrorCode(u32 errorCode, u32 callback_addr, u32 userData, u32 extParam)
int cellMsgDialogOpenErrorCode(u32 errorCode, mem_func_ptr_t<CellMsgDialogCallback> callback, mem_ptr_t<void> userData, u32 extParam)
{
cellSysutil.Warning("cellMsgDialogOpenErrorCode(errorCode=0x%x, callback_addr=0x%x, userData=%d, extParam=%d)",
errorCode, callback_addr, userData, extParam);
errorCode, callback.GetAddr(), userData, extParam);
std::string errorMessage;
switch(errorCode)
@ -622,10 +623,8 @@ int cellMsgDialogOpenErrorCode(u32 errorCode, u32 callback_addr, u32 userData, u
break;
}
// TODO: The following lines produce an infinite loop of cellMsgDialogOpenErrorCode's
/*Callback2 callback(0, callback_addr, userData);
callback.Handle(status);
callback.Branch(true);*/
if(callback)
callback(status, userData);
return CELL_OK;
}
@ -649,7 +648,7 @@ int cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option)
case CELL_AUDIO_OUT_FS_192KHZ:
break;
default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
}
switch(type)
@ -659,7 +658,7 @@ int cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option)
case CELL_AUDIO_OUT_CODING_TYPE_DTS:
break;
default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
}
switch(audioOut)
@ -668,8 +667,7 @@ int cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option)
case CELL_AUDIO_OUT_SECONDARY: return 0;
}
CELL_AUDIO_OUT_ERROR_ILLEGAL_CONFIGURATION;
return CELL_AUDIO_OUT_ERROR_ILLEGAL_CONFIGURATION;
}
int cellAudioOutGetSoundAvailability2(u32 audioOut, u32 type, u32 fs, u32 ch, u32 option)
@ -690,7 +688,7 @@ int cellAudioOutGetSoundAvailability2(u32 audioOut, u32 type, u32 fs, u32 ch, u3
case CELL_AUDIO_OUT_FS_192KHZ:
break;
default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
}
switch(ch)
@ -700,7 +698,7 @@ int cellAudioOutGetSoundAvailability2(u32 audioOut, u32 type, u32 fs, u32 ch, u3
case 8:
break;
default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
}
switch(type)
@ -710,7 +708,7 @@ int cellAudioOutGetSoundAvailability2(u32 audioOut, u32 type, u32 fs, u32 ch, u3
case CELL_AUDIO_OUT_CODING_TYPE_DTS:
break;
default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_SOUND_MODE;
}
switch(audioOut)
@ -719,8 +717,7 @@ int cellAudioOutGetSoundAvailability2(u32 audioOut, u32 type, u32 fs, u32 ch, u3
case CELL_AUDIO_OUT_SECONDARY: return 0;
}
CELL_AUDIO_OUT_ERROR_ILLEGAL_CONFIGURATION;
return CELL_AUDIO_OUT_ERROR_ILLEGAL_CONFIGURATION;
}
int cellAudioOutGetState(u32 audioOut, u32 deviceIndex, u32 state_addr)
@ -831,7 +828,7 @@ int cellAudioOutGetNumberOfDevice(u32 audioOut)
case CELL_AUDIO_OUT_SECONDARY: return 0;
}
CELL_AUDIO_OUT_ERROR_UNSUPPORTED_AUDIO_OUT;
return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_AUDIO_OUT;
}
int cellAudioOutGetDeviceInfo(u32 audioOut, u32 deviceIndex, mem_ptr_t<CellAudioOutDeviceInfo> info)
@ -863,7 +860,7 @@ int cellAudioOutSetCopyControl(u32 audioOut, u32 control)
case CELL_AUDIO_OUT_SECONDARY:
break;
default: CELL_AUDIO_OUT_ERROR_UNSUPPORTED_AUDIO_OUT;
default: return CELL_AUDIO_OUT_ERROR_UNSUPPORTED_AUDIO_OUT;
}
switch(control)
@ -873,7 +870,7 @@ int cellAudioOutSetCopyControl(u32 audioOut, u32 control)
case CELL_AUDIO_OUT_COPY_CONTROL_COPY_NEVER:
break;
default: CELL_AUDIO_OUT_ERROR_ILLEGAL_PARAMETER;
default: return CELL_AUDIO_OUT_ERROR_ILLEGAL_PARAMETER;
}
return CELL_AUDIO_OUT_SUCCEEDED;

View File

@ -135,76 +135,52 @@ int cellFsSdataOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size)
return CELL_OK;
}
/*struct CellFsAio
{
be_t<u32> fd;
be_t<u64> offset;
be_t<u32> buf_addr;
be_t<u64> size;
be_t<u64> user_data;
};
int cellFsAioRead(mem_ptr_t<CellFsAio> aio, mem32_t id, mem32_t func_addr)
{
if(!aio.IsGood() || !id.IsGood() || !func_addr.IsGood())
return CELL_EFAULT;
//CellFsAio *xaio, CellFsErrno error, int xid, uint64_t size;
Callback callback;
callback.SetAddr(func_addr);
callback.SetName("cellFsAioReadCallback");
MemoryAllocator<be_t<u64>> nread;
int error = cellFsRead(aio->fd, id.GetAddr(), aio->size, nread);
callback.Handle(aio.GetAddr(), error, id, *nread);
callback.Branch(true);
return CELL_OK;
}*/
std::atomic<u32> g_FsAioReadID = 0;
int cellFsAioRead(mem_ptr_t<CellFsAio> aio, mem32_t aio_id, u32 func_addr)
int cellFsAioRead(mem_ptr_t<CellFsAio> aio, mem32_t aio_id, mem_func_ptr_t<void (*)(mem_ptr_t<CellFsAio> xaio, u32 error, int xid, u64 size)> func)
{
ID id;
u32 fd = (u32)aio->fd;
if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
vfsFileBase& orig_file = *(vfsFileBase*)id.m_data;
//open the file again (to prevent access conflicts roughly)
vfsStream& file = vfsLocalFile(orig_file.GetPath().AfterFirst('/'), vfsRead);
u64 nbytes = (u64)aio->size;
const u32 buf_addr = (u32)aio->buf_addr;
if(Memory.IsGoodAddr(buf_addr) && !Memory.IsGoodAddr(buf_addr, nbytes))
{
MemoryBlock& block = Memory.GetMemByAddr(buf_addr);
nbytes = block.GetSize() - (buf_addr - block.GetStartAddr());
}
//read data immediately (actually it should be read in special thread)
file.Seek((u64)aio->offset);
const u64 res = nbytes ? file.Read(Memory.GetMemFromAddr(buf_addr), nbytes) : 0;
file.Close();
u64 res;
u32 error;
if(Memory.IsGoodAddr(buf_addr))
{
vfsFile file(orig_file.GetPath().AfterFirst('/'), vfsRead);
if(!Memory.IsGoodAddr(buf_addr, nbytes))
{
MemoryBlock& block = Memory.GetMemByAddr(buf_addr);
nbytes = block.GetSize() - (buf_addr - block.GetStartAddr());
}
//read data immediately (actually it should be read in special thread)
file.Seek((u64)aio->offset);
res = nbytes ? file.Read(Memory.GetMemFromAddr(buf_addr), nbytes) : 0;
error = CELL_OK;
}
else
{
res = 0;
error = CELL_EFAULT;
}
//get a unique id for the callback
const u32 xid = g_FsAioReadID++;
aio_id = xid;
sys_fs.Warning("cellFsAioRead(aio_addr: 0x%x[%s], id_addr: 0x%x, func_addr: 0x%x[res=%d, addr=0x%x])", aio.GetAddr(),
orig_file.GetPath().c_str(), aio_id.GetAddr(), func_addr, res, (u32)aio->buf_addr);
orig_file.GetPath().c_str(), aio_id.GetAddr(), func.GetAddr(), res, (u32)aio->buf_addr);
if(func)
func(aio, error, xid, res);
//TODO: init the callback
CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU);
new_thread.SetEntry(func_addr);
new_thread.SetPrio(1001);
new_thread.SetStackSize(0x10000);
new_thread.SetName("FsAioReadCallback");
new_thread.SetArg(0, aio.GetAddr()); //xaio
new_thread.SetArg(1, CELL_OK); //error code
new_thread.SetArg(2, xid); //xid (unique id)
new_thread.SetArg(3, res); //size (bytes read)
new_thread.Run();
new_thread.Exec();
return CELL_OK;
}

View File

@ -302,6 +302,8 @@ public:
virtual void operator()() { declCPU(); m_call(ARG(1), ARG(2), ARG(3), ARG(4), ARG(5), ARG(6), ARG(7), ARG(8), ARG(9), ARG(10), ARG(11), ARG(12)); }
};
#undef ARG
template<typename TR>
func_caller* bind_func(TR (*call)())
{
@ -379,5 +381,3 @@ func_caller* bind_func(TR (*call)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
{
return new binder_func_12<TR, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(call);
}
#undef ARG(n)

View File

@ -225,7 +225,6 @@ extern int cellFsLseek(u32 fd, s64 offset, u32 whence, mem64_t pos);
extern int cellFsFtruncate(u32 fd, u64 size);
extern int cellFsTruncate(u32 path_addr, u64 size);
extern int cellFsFGetBlockSize(u32 fd, mem64_t sector_size, mem64_t block_size);
extern int cellFsAioRead(mem_ptr_t<CellFsAio> aio, mem32_t id, u32 func_addr);
//cellVideo
extern int cellVideoOutGetState(u32 videoOut, u32 deviceIndex, u32 state_addr);