1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 02:32:36 +01:00

- Implemented be_t, mem_struct_ptr_t, vfsFile.

- Improved sys_fs, cellPngDec, cellJpgDec, cellGifDec modules.
This commit is contained in:
DH 2013-10-06 15:07:42 +03:00
parent efd336b743
commit dd48f827c3
23 changed files with 1292 additions and 679 deletions

154
Utilities/BEType.h Normal file
View File

@ -0,0 +1,154 @@
#pragma once
#pragma warning(disable: 4739)
template<typename T>
class be_t
{
static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Bad be_t type");
T m_data;
public:
be_t()
{
}
be_t(const T& value)
{
FromLE(value);
}
template<typename T1>
be_t(const be_t<T1>& value)
{
FromBE(value.ToBE());
}
T ToBE() const
{
return m_data;
}
T ToLE() const
{
T res;
switch(sizeof(T))
{
case 1:
res = m_data;
break;
case 2:
(u16&)res = _byteswap_ushort((u16&)m_data);
break;
case 4:
(u32&)res = _byteswap_ulong((u32&)m_data);
break;
case 8:
(u64&)res = _byteswap_uint64((u64&)m_data);
break;
default:
assert(0);
break;
}
return res;
}
void FromBE(const T& value)
{
m_data = value;
}
void FromLE(const T& value)
{
switch(sizeof(T))
{
case 1:
m_data = value;
return;
case 2:
(u16&)m_data = _byteswap_ushort((u16&)value);
return;
case 4:
(u32&)m_data = _byteswap_ulong((u32&)value);
return;
case 8:
(u64&)m_data = _byteswap_uint64((u64&)value);
return;
}
assert(0);
m_data = value;
}
//template<typename T1>
operator const T() const
{
return ToLE();
}
template<typename T1>
operator const be_t<T1>() const
{
be_t<T1> res;
res.FromBE(ToBE());
return res;
}
be_t& operator = (const T& right)
{
FromLE(right);
return *this;
}
be_t& operator = (const be_t& right)
{
m_data = right.m_data;
return *this;
}
template<typename T1> be_t& operator += (T1 right) { return *this = T(*this) + right; }
template<typename T1> be_t& operator -= (T1 right) { return *this = T(*this) - right; }
template<typename T1> be_t& operator *= (T1 right) { return *this = T(*this) * right; }
template<typename T1> be_t& operator /= (T1 right) { return *this = T(*this) / right; }
template<typename T1> be_t& operator %= (T1 right) { return *this = T(*this) % right; }
template<typename T1> be_t& operator &= (T1 right) { return *this = T(*this) & right; }
template<typename T1> be_t& operator |= (T1 right) { return *this = T(*this) | right; }
template<typename T1> be_t& operator ^= (T1 right) { return *this = T(*this) ^ right; }
template<typename T1> be_t& operator <<= (T1 right) { return *this = T(*this) << right; }
template<typename T1> be_t& operator >>= (T1 right) { return *this = T(*this) >> right; }
template<typename T1> be_t& operator += (const be_t<T1>& right) { return *this = ToLE() + right.ToLE(); }
template<typename T1> be_t& operator -= (const be_t<T1>& right) { return *this = ToLE() - right.ToLE(); }
template<typename T1> be_t& operator *= (const be_t<T1>& right) { return *this = ToLE() * right.ToLE(); }
template<typename T1> be_t& operator /= (const be_t<T1>& right) { return *this = ToLE() / right.ToLE(); }
template<typename T1> be_t& operator %= (const be_t<T1>& right) { return *this = ToLE() % right.ToLE(); }
template<typename T1> be_t& operator &= (const be_t<T1>& right) { return *this = ToBE() & right.ToBE(); }
template<typename T1> be_t& operator |= (const be_t<T1>& right) { return *this = ToBE() | right.ToBE(); }
template<typename T1> be_t& operator ^= (const be_t<T1>& right) { return *this = ToBE() ^ right.ToBE(); }
template<typename T1> be_t operator & (const be_t<T1>& right) const { be_t<T> res; res.FromBE(ToBE() & right.ToBE()); return res; }
template<typename T1> be_t operator | (const be_t<T1>& right) const { be_t<T> res; res.FromBE(ToBE() | right.ToBE()); return res; }
template<typename T1> be_t operator ^ (const be_t<T1>& right) const { be_t<T> res; res.FromBE(ToBE() ^ right.ToBE()); return res; }
template<typename T1> bool operator == (T1 right) const { return ToLE() == right; }
template<typename T1> bool operator != (T1 right) const { return !(*this == right); }
template<typename T1> bool operator > (T1 right) const { return ToLE() > right; }
template<typename T1> bool operator < (T1 right) const { return ToLE() < right; }
template<typename T1> bool operator >= (T1 right) const { return ToLE() >= right; }
template<typename T1> bool operator <= (T1 right) const { return ToLE() <= right; }
template<typename T1> bool operator == (const be_t<T1>& right) const { return ToBE() == right.ToBE(); }
template<typename T1> bool operator != (const be_t<T1>& right) const { return !(*this == right); }
template<typename T1> bool operator > (const be_t<T1>& right) const { return ToLE() > right.ToLE(); }
template<typename T1> bool operator < (const be_t<T1>& right) const { return ToLE() < right.ToLE(); }
template<typename T1> bool operator >= (const be_t<T1>& right) const { return ToLE() >= right.ToLE(); }
template<typename T1> bool operator <= (const be_t<T1>& right) const { return ToLE() <= right.ToLE(); }
};

View File

@ -101,6 +101,28 @@ vfsDevice* VFS::GetDevice(const wxString& ps3_path, wxString& path)
return &m_devices[max_i];
}
vfsDevice* VFS::GetDeviceLocal(const wxString& local_path, wxString& path)
{
u32 max_eq;
s32 max_i=-1;
for(u32 i=0; i<m_devices.GetCount(); ++i)
{
const u32 eq = m_devices[i].CmpLocalPath(local_path);
if(max_i < 0 || eq > max_eq)
{
max_eq = eq;
max_i = i;
}
}
if(max_i < 0) return nullptr;
path = vfsDevice::GetPs3Path(m_devices[max_i].GetPs3Path(), local_path(max_eq, local_path.Len() - max_eq));
return &m_devices[max_i];
}
void VFS::Init(const wxString& path)
{
Array<VFSManagerEntry> entries;

View File

@ -36,6 +36,7 @@ struct VFS
void Create(const wxString& ps3_path);
void Close(vfsStream*& device);
vfsDevice* GetDevice(const wxString& ps3_path, wxString& path);
vfsDevice* GetDeviceLocal(const wxString& local_path, wxString& path);
void Init(const wxString& path);
void SaveLoadDevices(Array<VFSManagerEntry>& res, bool is_load);

View File

@ -36,6 +36,19 @@ u32 vfsDevice::CmpPs3Path(const wxString& ps3_path)
return ret;
}
u32 vfsDevice::CmpLocalPath(const wxString& local_path)
{
const u32 lim = min(m_local_path.Len(), local_path.Len());
u32 ret = 0;
for(u32 i=0; i<lim; ++i, ++ret)
{
if(m_local_path[i] != local_path[i]) break;
}
return ret;
}
wxString vfsDevice::ErasePath(const wxString& path, u32 start_dir_count, u32 end_dir_count)
{
u32 from = 0;

View File

@ -32,6 +32,7 @@ public:
void SetPath(const wxString& ps3_path, const wxString& local_path);
u32 CmpPs3Path(const wxString& ps3_path);
u32 CmpLocalPath(const wxString& local_path);
static wxString ErasePath(const wxString& local_path, u32 start_dir_count, u32 end_dir_count);
static wxString GetRoot(const wxString& local_path);

84
rpcs3/Emu/FS/vfsFile.cpp Normal file
View File

@ -0,0 +1,84 @@
#include "stdafx.h"
#include "vfsFile.h"
vfsFile::vfsFile()
: vfsFileBase()
, m_stream(nullptr)
{
}
vfsFile::vfsFile(const wxString path, vfsOpenMode mode)
: vfsFileBase()
, m_stream(nullptr)
{
Open(path, mode);
}
vfsFile::~vfsFile()
{
Close();
}
vfsDevice* vfsFile::GetNew()
{
return new vfsFile();
}
bool vfsFile::Open(const wxString& path, vfsOpenMode mode)
{
Close();
m_stream = Emu.GetVFS().Open(path, mode);
return m_stream && m_stream->IsOpened();
}
bool vfsFile::Create(const wxString& path)
{
if(wxFileExists(path)) return false;
wxFile f;
return f.Create(path);
}
bool vfsFile::Close()
{
if(m_stream)
{
delete m_stream;
m_stream = nullptr;
return vfsFileBase::Close();
}
return false;
}
u64 vfsFile::GetSize()
{
return m_stream->GetSize();
}
u64 vfsFile::Write(const void* src, u64 size)
{
return m_stream->Write(src, size);
}
u64 vfsFile::Read(void* dst, u64 size)
{
return m_stream->Read(dst, size);
}
u64 vfsFile::Seek(s64 offset, vfsSeekMode mode)
{
return m_stream->Seek(offset, mode);
}
u64 vfsFile::Tell() const
{
return m_stream->Tell();
}
bool vfsFile::IsOpened() const
{
return m_stream && m_stream->IsOpened() && vfsFileBase::IsOpened();
}

29
rpcs3/Emu/FS/vfsFile.h Normal file
View File

@ -0,0 +1,29 @@
#pragma once
#include "vfsFileBase.h"
class vfsFile : public vfsFileBase
{
private:
vfsStream* m_stream;
public:
vfsFile();
vfsFile(const wxString path, vfsOpenMode mode = vfsRead);
~vfsFile();
virtual vfsDevice* GetNew() override;
virtual bool Open(const wxString& path, vfsOpenMode mode = vfsRead) override;
virtual bool Create(const wxString& path) override;
virtual bool Close() override;
virtual u64 GetSize() override;
virtual u64 Write(const void* src, u64 size) override;
virtual u64 Read(void* dst, u64 size) override;
virtual u64 Seek(s64 offset, vfsSeekMode mode = vfsSeekSet) override;
virtual u64 Tell() const override;
virtual bool IsOpened() const override;
};

View File

@ -5,21 +5,32 @@ vfsStreamMemory::vfsStreamMemory() : vfsStream()
{
}
vfsStreamMemory::vfsStreamMemory(u64 addr) : vfsStream()
vfsStreamMemory::vfsStreamMemory(u64 addr, u64 size) : vfsStream()
{
Open(addr);
Open(addr, size);
}
void vfsStreamMemory::Open(u64 addr)
void vfsStreamMemory::Open(u64 addr, u64 size)
{
m_addr = addr;
m_size = size ? size : ~0ULL;
vfsStream::Reset();
}
u64 vfsStreamMemory::GetSize()
{
return m_size;
}
u64 vfsStreamMemory::Write(const void* src, u64 size)
{
if(!Memory.IsGoodAddr(m_addr + Tell(), size)) return 0;
if(Tell() + size > GetSize())
{
size = GetSize() - Tell();
}
if(!size || !Memory.IsGoodAddr(m_addr + Tell(), size)) return 0;
memcpy(&Memory[m_addr + Tell()], src, size);
@ -28,7 +39,12 @@ u64 vfsStreamMemory::Write(const void* src, u64 size)
u64 vfsStreamMemory::Read(void* dst, u64 size)
{
if(!Memory.IsGoodAddr(m_addr + Tell(), size)) return 0;
if(Tell() + size > GetSize())
{
size = GetSize() - Tell();
}
if(!size || !Memory.IsGoodAddr(m_addr + Tell(), size)) return 0;
memcpy(dst, &Memory[m_addr + Tell()], size);

View File

@ -4,12 +4,15 @@
struct vfsStreamMemory : public vfsStream
{
u64 m_addr;
u64 m_size;
public:
vfsStreamMemory();
vfsStreamMemory(u64 addr);
vfsStreamMemory(u64 addr, u64 size = 0);
void Open(u64 addr);
void Open(u64 addr, u64 size = 0);
virtual u64 GetSize() override;
virtual u64 Write(const void* src, u64 size) override;
virtual u64 Read(void* dst, u64 size) override;

View File

@ -310,7 +310,7 @@ void FragmentDecompilerThread::Task()
if(dst.end) break;
data.SetOffset(m_offset);
data.Skip(m_offset);
}
m_shader = BuildCode();

View File

@ -369,24 +369,56 @@ public:
extern MemoryBase Memory;
class MemoryAllocator
template<typename T> class mem_struct_ptr_t
{
u32 m_addr;
const u32 m_addr;
public:
MemoryAllocator(u32 size, u32 align = 1)
mem_struct_ptr_t(u32 addr) : m_addr(addr)
{
m_addr = Memory.Alloc(size, align);
}
~MemoryAllocator()
operator T&()
{
Memory.Free(m_addr);
return (T&)Memory[m_addr];
}
operator u32() const
operator const T&() const
{
return m_addr;
return (const T&)Memory[m_addr];
}
T* operator -> ()
{
return (T*)&Memory[m_addr];
}
const T* operator -> () const
{
return (const T*)&Memory[m_addr];
}
T& operator [](uint index)
{
return (T&)Memory[m_addr + sizeof(T) * index];
}
const T& operator [](uint index) const
{
return (const T&)Memory[m_addr + sizeof(T) * index];
}
u32 GetAddr() const { return m_addr; }
bool IsGood() const
{
return Memory.IsGoodAddr(m_addr, sizeof(T));
}
mem_struct_ptr_t& operator = (const T& right)
{
memcpy(&Memory[m_addr], &right, sizeof(T));
return *this;
}
};
@ -395,35 +427,20 @@ template<typename T> class mem_t
const u32 m_addr;
public:
mem_t(u64 addr) : m_addr(addr)
mem_t(u32 addr) : m_addr(addr)
{
}
mem_t& operator = (T right)
{
switch(sizeof(T))
{
case 1: Memory.Write8(m_addr, right); return *this;
case 2: Memory.Write16(m_addr, right); return *this;
case 4: Memory.Write32(m_addr, right); return *this;
case 8: Memory.Write64(m_addr, right); return *this;
}
(be_t<T>&)Memory[m_addr] = right;
assert(0);
return *this;
}
operator const T() const
{
switch(sizeof(T))
{
case 1: return Memory.Read8(m_addr);
case 2: return Memory.Read16(m_addr);
case 4: return Memory.Read32(m_addr);
case 8: return Memory.Read64(m_addr);
}
assert(0);
return (be_t<T>&)Memory[m_addr];
}
mem_t& operator += (T right) { return *this = (*this) + right; }
@ -437,7 +454,7 @@ public:
mem_t& operator <<= (T right) { return *this = (*this) << right; }
mem_t& operator >>= (T right) { return *this = (*this) >> right; }
u64 GetAddr() const { return m_addr; }
u32 GetAddr() const { return m_addr; }
bool IsGood() const
{
@ -447,88 +464,181 @@ public:
template<typename T> class mem_ptr_t
{
u64 m_addr;
const u64 m_iaddr;
u32 m_addr;
public:
mem_ptr_t(u64 addr)
: m_addr(addr)
, m_iaddr(addr)
mem_ptr_t(u32 addr) : m_addr(addr)
{
}
void operator = (T right)
{
switch(sizeof(T))
{
case 1: Memory.Write8(m_addr, right); return;
case 2: Memory.Write16(m_addr, right); return;
case 4: Memory.Write32(m_addr, right); return;
case 8: Memory.Write64(m_addr, right); return;
}
ConLog.Error("Bad mem_t size! (%d : 0x%llx)", sizeof(T), m_addr);
(be_t<T>&)Memory[m_addr] = right;
}
operator u8() const { return Memory.Read8(m_addr); }
operator u16() const { return Memory.Read16(m_addr); }
operator u32() const { return Memory.Read32(m_addr); }
operator u64() const { return Memory.Read64(m_addr); }
u64 operator += (T right)
u32 operator += (T right)
{
*this = right;
m_addr += sizeof(T);
return m_addr;
}
const T operator [] (u64 i) const
u32 GetAddr() const { return m_addr; }
u32 Skip(const u32 offset) { return m_addr += offset; }
operator be_t<T>*() { return GetPtr(); }
operator void*() { return GetPtr(); }
operator be_t<T>*() const { return GetPtr(); }
operator void*() const { return GetPtr(); }
const char* GetString() const
{
const u64 offset = i*sizeof(T);
(*(mem_ptr_t*)this).m_addr += offset;
const T ret = *this;
(*(mem_ptr_t*)this).m_addr -= offset;
return ret;
return (const char*)&Memory[m_addr];
}
void Reset() { m_addr = m_iaddr; }
u64 GetCurAddr() const { return m_addr; }
u64 GetAddr() const { return m_iaddr; }
u64 SetOffset(const u32 offset) { return m_addr += offset; }
be_t<T>* GetPtr()
{
return (be_t<T>*)&Memory[m_addr];
}
const be_t<T>* GetPtr() const
{
return (const be_t<T>*)&Memory[m_addr];
}
};
class mem_class_t
{
u64 addr;
const u64 iaddr;
u32 m_addr;
public:
mem_class_t(u64 _addr)
: addr(_addr)
, iaddr(_addr)
mem_class_t(u32 addr) : m_addr(addr)
{
}
template<typename T> u64 operator += (T right)
template<typename T> u32 operator += (T right)
{
mem_t<T> m(addr);
mem_t<T>& m((mem_t<T>&)*this);
m = right;
addr += sizeof(T);
return addr;
m_addr += sizeof(T);
return m_addr;
}
template<typename T> operator T()
{
mem_t<T> m(addr);
mem_t<T>& m((mem_t<T>&)*this);
const T ret = m;
addr += sizeof(T);
m_addr += sizeof(T);
return ret;
}
void Reset() { addr = iaddr; }
u64 GetCurAddr() const { return addr; }
u64 GetAddr() const { return iaddr; }
void SetAddr(const u64 _addr) { addr = _addr; }
u64 GetAddr() const { return m_addr; }
void SetAddr(const u64 addr) { m_addr = addr; }
};
template<typename T>
class MemoryAllocator
{
u32 m_addr;
u32 m_size;
T* m_ptr;
public:
MemoryAllocator(u32 size = sizeof(T), u32 align = 1)
: m_size(size)
, m_addr(Memory.Alloc(size, align))
, m_ptr((T*)&Memory[m_addr])
{
}
~MemoryAllocator()
{
Memory.Free(m_addr);
}
T* operator -> ()
{
return m_ptr;
}
T* GetPtr()
{
return m_ptr;
}
const T* GetPtr() const
{
return m_ptr;
}
const T* operator -> () const
{
return m_ptr;
}
u32 GetAddr() const
{
return m_addr;
}
u32 GetSize() const
{
return m_size;
}
bool IsGood() const
{
return Memory.IsGoodAddr(m_addr, sizeof(T));
}
template<typename T1>
operator const T1() const
{
return T1(*m_ptr);
}
template<typename T1>
operator T1()
{
return T1(*m_ptr);
}
operator const T&() const
{
return *m_ptr;
}
operator T&()
{
return *m_ptr;
}
operator const T*() const
{
return m_ptr;
}
operator T*()
{
return m_ptr;
}
template<typename T1>
operator const mem_t<T1>() const
{
return GetAddr();
}
operator const mem_struct_ptr_t<T>() const
{
return GetAddr();
}
template<typename NT>
NT* To(uint offset = 0)
{
return (NT*)(m_ptr + offset);
}
};
typedef mem_t<u8> mem8_t;

View File

@ -2297,22 +2297,22 @@ s64 SysCalls::DoFunc(const u32 id)
case 0x1ea02e2f: FUNC_LOG_ERROR("TODO: cellFsArcadeHddSerialNumber");
case 0x2664c8ae: FUNC_LOG_ERROR("TODO: cellFsStReadInit");
case 0x27800c6b: FUNC_LOG_ERROR("TODO: cellFsStRead");
case 0x2796fdf3: return cellFsRmdir(SC_ARGS_1);//FUNC_LOG_ERROR("TODO: cellFsRmdir");
case 0x2cb51f0d: return cellFsClose(SC_ARGS_1);//FUNC_LOG_ERROR("TODO: cellFsClose");
case 0x2796fdf3: FUNC_LOG_ERROR("TODO: cellFsRmdir");
case 0x2cb51f0d: FUNC_LOG_ERROR("TODO: cellFsClose");
case 0x2cf1296b: FUNC_LOG_ERROR("TODO: cellFsAllocateFileAreaByFdWithoutZeroFill");
case 0x3140f6e1: FUNC_LOG_ERROR("TODO: cellFsSetIoBuffer");
case 0x3394f037: FUNC_LOG_ERROR("TODO: cellFsAllocateFileAreaByFdWithInitialData");
case 0x3a1c8393: FUNC_LOG_ERROR("TODO: cellFsTruncate2");
case 0x3f61245c: return cellFsOpendir(SC_ARGS_2);//FUNC_LOG_ERROR("TODO: cellFsOpendir");
case 0x3f61245c: FUNC_LOG_ERROR("TODO: cellFsOpendir");
case 0x4cef342e: FUNC_LOG_ERROR("TODO: cellFsAioWrite");
case 0x4d5ff8e2: return cellFsRead(SC_ARGS_4);//FUNC_LOG_ERROR("TODO: cellFsRead");
case 0x5c74903d: return cellFsReaddir(SC_ARGS_3);//FUNC_LOG_ERROR("TODO: cellFsReaddir");
case 0x4d5ff8e2: FUNC_LOG_ERROR("TODO: cellFsRead");
case 0x5c74903d: FUNC_LOG_ERROR("TODO: cellFsReaddir");
case 0x606f9f42: FUNC_LOG_ERROR("TODO: cellFsChangeFileSizeWithoutAllocation");
case 0x6d3bb15b: FUNC_LOG_ERROR("TODO: cellFsSdataOpenByFd");
case 0x718bf5f8: return cellFsOpen(SC_ARGS_5);//FUNC_LOG_ERROR("TODO: cellFsOpen");
case 0x718bf5f8: FUNC_LOG_ERROR("TODO: cellFsOpen");
case 0x75f16dc5: FUNC_LOG_ERROR("TODO: cellFsSetIoBufferFromDefaultContainer");
case 0x7a0329a1: FUNC_LOG_ERROR("TODO: cellFsAllocateFileAreaWithoutZeroFill");
case 0x7de6dced: return cellFsStat(SC_ARGS_2); //FUNC_LOG_ERROR("TODO: cellFsStat");
case 0x7de6dced: FUNC_LOG_ERROR("TODO: cellFsStat");
case 0x7f13fc8c: FUNC_LOG_ERROR("TODO: cellFsAioCancel");
case 0x7f4677a8: FUNC_LOG_ERROR("TODO: cellFsUnlink");
case 0x81f33783: FUNC_LOG_ERROR("TODO: cellFsStReadPutCurrentAddr");
@ -2326,11 +2326,11 @@ s64 SysCalls::DoFunc(const u32 id)
case 0x9b882495: FUNC_LOG_ERROR("TODO: cellFsGetDirectoryEntries");
case 0x9f951810: FUNC_LOG_ERROR("TODO: cellFsAioFinish");
case 0xa01ee33a: FUNC_LOG_ERROR("TODO: cellFsRegisterConversionCallback");
case 0xa397d042: return cellFsLseek(SC_ARGS_4);//FUNC_LOG_ERROR("TODO: cellFsLseek");
case 0xa397d042: FUNC_LOG_ERROR("TODO: cellFsLseek");
case 0xaa3b4bcd: FUNC_LOG_ERROR("TODO: cellFsGetFreeSize");
case 0xb1840b53: FUNC_LOG_ERROR("TODO: cellFsSdataOpen");
case 0xb3afee8b: FUNC_LOG_ERROR("TODO: cellFsStReadGetRingBuf");
case 0xba901fe6: return cellFsMkdir(SC_ARGS_2);//FUNC_LOG_ERROR("TODO: cellFsMkdir");
case 0xba901fe6: FUNC_LOG_ERROR("TODO: cellFsMkdir");
case 0xbd273a88: FUNC_LOG_ERROR("TODO: cellFsStReadGetRegid");
case 0xbef554a4: FUNC_LOG_ERROR("TODO: cellFsUtime");
case 0xc1c507e7: FUNC_LOG_ERROR("TODO: cellFsAioRead");
@ -2340,16 +2340,16 @@ s64 SysCalls::DoFunc(const u32 id)
case 0xd73938df: FUNC_LOG_ERROR("TODO: cellFsStReadFinish");
case 0xdb869f20: FUNC_LOG_ERROR("TODO: cellFsAioInit");
case 0xe15939c3: FUNC_LOG_ERROR("TODO: cellFsChangeFileSizeByFdWithoutAllocation");
case 0xecdcf2ab: return cellFsWrite(SC_ARGS_4);//FUNC_LOG_ERROR("TODO: cellFsWrite");
case 0xef3efa34: return cellFsFstat(SC_ARGS_2);//FUNC_LOG_ERROR("TODO: cellFsFstat");
case 0xf12eecc8: return cellFsRename(SC_ARGS_2);//FUNC_LOG_ERROR("TODO: cellFsRename");
case 0xecdcf2ab: FUNC_LOG_ERROR("TODO: cellFsWrite");
case 0xef3efa34: FUNC_LOG_ERROR("TODO: cellFsFstat");
case 0xf12eecc8: FUNC_LOG_ERROR("TODO: cellFsRename");
case 0xf8e5d9a0: FUNC_LOG_ERROR("TODO: cellFsStReadStop");
case 0xf94baa80: FUNC_LOG_ERROR("TODO: cellFsUnregisterL10nCallbacks");
case 0xff42dcc3: return cellFsClosedir(SC_ARGS_1);//FUNC_LOG_ERROR("TODO: cellFsClosedir");
case 0xff42dcc3: FUNC_LOG_ERROR("TODO: cellFsClosedir");
case 0x068fcbc6: FUNC_LOG_ERROR("TODO: sys_config_start");
case 0x0d5f2c14: FUNC_LOG_ERROR("TODO: cellPadClearBuf");
case 0x0e2dfaad: FUNC_LOG_ERROR("TODO: cellPadInfoPressMode");
case 0x1cf98800: return cellPadInit(SC_ARGS_1);//FUNC_LOG_ERROR("TODO: cellPadInit");
case 0x1cf98800: FUNC_LOG_ERROR("TODO: cellPadInit");
case 0x1f71ecbe: FUNC_LOG_ERROR("TODO: cellKbGetConfiguration");
case 0x2073b7f6: FUNC_LOG_ERROR("TODO: cellKbClearBuf");
case 0x20a97ba2: FUNC_LOG_ERROR("TODO: cellPadLddRegisterController");
@ -2365,24 +2365,24 @@ s64 SysCalls::DoFunc(const u32 id)
case 0x4ab1fa77: FUNC_LOG_ERROR("TODO: cellKbCnvRawCode");
case 0x4cc9b68d: FUNC_LOG_ERROR("TODO: cellPadPeriphGetInfo");
case 0x4d0b3b1f: FUNC_LOG_ERROR("TODO: cellMouseInfoTabletMode");
case 0x4d9b75d5: return cellPadEnd();//FUNC_LOG_ERROR("TODO: cellPadEnd");
case 0x578e3c98: return cellPadSetPortSetting(SC_ARGS_2);//FUNC_LOG_ERROR("TODO: cellPadSetPortSetting");
case 0x4d9b75d5: FUNC_LOG_ERROR("TODO: cellPadEnd");
case 0x578e3c98: FUNC_LOG_ERROR("TODO: cellPadSetPortSetting");
case 0x5baf30fb: FUNC_LOG_ERROR("TODO: cellMouseGetInfo");
case 0x5f81900c: FUNC_LOG_ERROR("TODO: sys_config_unregister_service");
case 0x6ae10596: FUNC_LOG_ERROR("TODO: sys_config_add_service_listener");
case 0x6bc09c61: return cellPadGetDataExtra(SC_ARGS_3);//FUNC_LOG_ERROR("TODO: cellPadGetDataExtra");
case 0x6bc09c61: FUNC_LOG_ERROR("TODO: cellPadGetDataExtra");
case 0x6bd131f0: FUNC_LOG_ERROR("TODO: cellMouseGetDataList");
case 0x6d367953: FUNC_LOG_ERROR("TODO: sys_config_stop");
case 0x78200559: FUNC_LOG_ERROR("TODO: cellPadInfoSensorMode");
case 0x78f058a2: FUNC_LOG_ERROR("TODO: sys_config_register_service");
case 0x7c5d5fc1: FUNC_LOG_ERROR("TODO: cellPadDbgPeriphRegisterDevice");
case 0x8a00f264: FUNC_LOG_ERROR("TODO: cellPadPeriphGetData");
case 0x8b72cda1: return cellPadGetData(SC_ARGS_2);//FUNC_LOG_ERROR("TODO: cellPadGetData");
case 0x8b72cda1: FUNC_LOG_ERROR("TODO: cellPadGetData");
case 0x8b8231e5: FUNC_LOG_ERROR("TODO: cellPadLddGetPortNo");
case 0x94b98e39: FUNC_LOG_ERROR("TODO: cellPadDbgLddSetDataInsertMode");
case 0xa328cc35: FUNC_LOG_ERROR("TODO: cellMouseGetRawData");
case 0xa5f85e4d: FUNC_LOG_ERROR("TODO: cellKbSetCodeType");
case 0xa703a51d: return cellPadGetInfo2(SC_ARGS_1);//FUNC_LOG_ERROR("TODO: cellPadGetInfo2");
case 0xa703a51d: FUNC_LOG_ERROR("TODO: cellPadGetInfo2");
case 0xa74396e5: FUNC_LOG_ERROR("TODO: cellPadDbgLddRegisterController");
case 0xbafd6409: FUNC_LOG_ERROR("TODO: cellPadLddDataInsert");
case 0xbe5be3ba: FUNC_LOG_ERROR("TODO: cellPadSetSensorMode");

View File

@ -21,53 +21,95 @@ enum
CELL_GIFDEC_ERROR_CB_PARAM = 0x80611307,
};
enum CellGifDecStreamSrcSel
{
CELL_GIFDEC_FILE = 0, //Input from a file
CELL_GIFDEC_BUFFER = 1, //Input from a buffer
};
enum CellGifDecColorSpace
{
CELL_GIFDEC_RGBA = 10,
CELL_GIFDEC_ARGB = 20,
};
enum CellGifDecRecordType
{
CELL_GIFDEC_RECORD_TYPE_IMAGE_DESC = 1, // Image data block
CELL_GIFDEC_RECORD_TYPE_EXTENSION = 2, // Extension block
CELL_GIFDEC_RECORD_TYPE_TERMINATE = 3, // Trailer block
};
enum CellGifDecDecodeStatus
{
CELL_GIFDEC_DEC_STATUS_FINISH = 0, //Decoding finished
CELL_GIFDEC_DEC_STATUS_STOP = 1, //Decoding halted
};
struct CellGifDecInfo
{
u32 SWidth;
u32 SHeight;
u32 SGlobalColorTableFlag;
u32 SColorResolution;
u32 SSortFlag;
u32 SSizeOfGlobalColorTable;
u32 SBackGroundColor;
u32 SPixelAspectRatio;
be_t<u32> SWidth;
be_t<u32> SHeight;
be_t<u32> SGlobalColorTableFlag;
be_t<u32> SColorResolution;
be_t<u32> SSortFlag;
be_t<u32> SSizeOfGlobalColorTable;
be_t<u32> SBackGroundColor;
be_t<u32> SPixelAspectRatio;
};
struct CellGifDecSrc
{
u32 srcSelect; // CellGifDecStreamSrcSel
u32 fileName; // const char*
u64 fileOffset; // int64_t
u32 fileSize;
u32 streamPtr;
u32 streamSize;
u32 spuThreadEnable; // CellGifDecSpuThreadEna
be_t<u32> srcSelect;
be_t<u32> fileName;
be_t<s64> fileOffset;
be_t<u64> fileSize;
be_t<u32> streamPtr;
be_t<u32> streamSize;
be_t<u32> spuThreadEnable;
};
struct CellGifDecInParam
{
u32 *commandPtr;
u32 colorSpace; // CellGifDecColorSpace
u8 outputColorAlpha1;
u8 outputColorAlpha2;
u8 reserved[2];
be_t<u32> commandPtr;
be_t<u32> colorSpace; // CellGifDecColorSpace
be_t<u8> outputColorAlpha1;
be_t<u8> outputColorAlpha2;
be_t<u8> reserved[2];
};
struct CellGifDecOutParam
{
u64 outputWidthByte;
u32 outputWidth;
u32 outputHeight;
u32 outputComponents;
u32 outputBitDepth;
u32 outputColorSpace; // CellGifDecColorSpace
u32 useMemorySpace;
be_t<u64> outputWidthByte;
be_t<u32> outputWidth;
be_t<u32> outputHeight;
be_t<u32> outputComponents;
be_t<u32> outputBitDepth;
be_t<u32> outputColorSpace; // CellGifDecColorSpace
be_t<u32> useMemorySpace;
};
struct CellGifDecExtension
{
be_t<u8> label;
be_t<u32> data;
};
struct CellGifDecDataOutInfo
{
be_t<u32> recordType;
CellGifDecExtension outExtension;
be_t<u32> status;
};
struct CellGifDecOpnInfo
{
be_t<u32> initSpaceAllocated;
};
struct CellGifDecDataCtrlParam
{
be_t<u64> outputBytesPerLine;
};
struct CellGifDecSubHandle //Custom struct
@ -78,7 +120,6 @@ struct CellGifDecSubHandle //Custom struct
CellGifDecOutParam outParam;
};
int cellGifDecCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam)
{
UNIMPLEMENTED_FUNC(cellGifDec);
@ -91,164 +132,188 @@ int cellGifDecExtCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam, u
return CELL_OK;
}
int cellGifDecOpen(u32 mainHandle, mem32_t subHandle, u32 src_addr, u32 openInfo)
int cellGifDecOpen(u32 mainHandle, mem32_t subHandle, const mem_struct_ptr_t<CellGifDecSrc> src, mem_struct_ptr_t<CellGifDecOpnInfo> openInfo)
{
//u32 srcSelect = Memory.Read32(src_addr);
u32 fileName = Memory.Read32(src_addr+4);
//u64 fileOffset = Memory.Read32(src_addr+8);
//u32 fileSize = Memory.Read32(src_addr+12);
//u32 streamPtr = Memory.Read32(src_addr+16);
//u32 streamSize = Memory.Read32(src_addr+20);
//u32 spuThreadEnable = Memory.Read32(src_addr+24);
/*
vfsStream* stream;
switch(src->srcSelect)
{
case CELL_GIFDEC_FILE:
stream = Emu.GetVFS().Open(src->fileName.GetString(), vfsRead);
stream->Seek(src->fileOffset);
src->fileSize;
break;
case CELL_GIFDEC_BUFFER:
if(src->streamSize < 5)
return CELL_GIFDEC_ERROR_ARG;
stream = new vfsStreamMemory(src->streamPtr.GetAddr(), src->streamSize);
break;
default:
return CELL_GIFDEC_ERROR_ARG;
}
if(!stream->IsOpened())
{
return CELL_GIFDEC_ERROR_OPEN_FILE;
}
*/
CellGifDecSubHandle *current_subHandle = new CellGifDecSubHandle;
// Get file descriptor
u32 fd_addr = Memory.Alloc(sizeof(u32), 1);
int ret = cellFsOpen(fileName, 0, fd_addr, NULL, 0);
current_subHandle->fd = Memory.Read32(fd_addr);
Memory.Free(fd_addr);
if(ret != 0) return CELL_GIFDEC_ERROR_OPEN_FILE;
MemoryAllocator<be_t<u32>> fd;
int ret = cellFsOpen(src->fileName, 0, fd, NULL, 0);
current_subHandle->fd = fd->ToLE();
if(ret != CELL_OK) return CELL_GIFDEC_ERROR_OPEN_FILE;
// Get size of file
u32 sb_addr = Memory.Alloc(52,1); // Alloc a CellFsStat struct
cellFsFstat(current_subHandle->fd, sb_addr);
current_subHandle->fileSize = Memory.Read64(sb_addr+36); // Get CellFsStat.st_size
Memory.Free(sb_addr);
MemoryAllocator<CellFsStat> sb; // Alloc a CellFsStat struct
ret = cellFsFstat(current_subHandle->fd, sb);
if(ret != CELL_OK) return ret;
current_subHandle->fileSize = sb->st_size; // Get CellFsStat.st_size
// From now, every u32 subHandle argument is a pointer to a CellPngDecSubHandle struct.
subHandle += (u32)current_subHandle;
subHandle = cellGifDec.GetNewId(current_subHandle);
return CELL_OK;
}
int cellGifDecReadHeader(u32 mainHandle, u32 subHandle, mem_class_t info)
int cellGifDecReadHeader(u32 mainHandle, u32 subHandle, mem_struct_ptr_t<CellGifDecInfo> info)
{
const u32& fd = ((CellGifDecSubHandle*)subHandle)->fd;
const u64& fileSize = ((CellGifDecSubHandle*)subHandle)->fileSize;
CellGifDecInfo& current_info = ((CellGifDecSubHandle*)subHandle)->info;
ID sub_handle_id_data;
if(!cellGifDec.CheckId(subHandle, sub_handle_id_data))
return CELL_GIFDEC_ERROR_FATAL;
auto subHandle_data = (CellGifDecSubHandle*)sub_handle_id_data.m_data;
const u32& fd = subHandle_data->fd;
const u64& fileSize = subHandle_data->fileSize;
CellGifDecInfo& current_info = subHandle_data->info;
//Write the header to buffer
u32 buffer = Memory.Alloc(13,1); // Alloc buffer for GIF header
u32 nread = Memory.Alloc(8,1);
u32 pos_addr = Memory.Alloc(8,1);
cellFsLseek(fd, 0, 0, pos_addr);
cellFsRead(fd, buffer, 13, nread);
Memory.Free(nread);
Memory.Free(pos_addr);
MemoryAllocator<u8> buffer(13); // Alloc buffer for GIF header
MemoryAllocator<be_t<u64>> pos, nread;
if (Memory.Read32(buffer) != 0x47494638 ||
(Memory.Read16(buffer+4) != 0x3961 &&
Memory.Read16(buffer+4) != 0x3761)) // Error: The first 6 bytes are not a valid GIF signature
cellFsLseek(fd, 0, CELL_SEEK_SET, pos);
cellFsRead(fd, buffer.GetAddr(), buffer.GetSize(), nread);
if (*buffer.To<be_t<u32>>(0) != 0x47494638 ||
(*buffer.To<u16>(4) != 0x6139 && *buffer.To<u16>(4) != 0x6137)) // Error: The first 6 bytes are not a valid GIF signature
{
Memory.Free(buffer);
return CELL_GIFDEC_ERROR_STREAM_FORMAT; // Surprisingly there is no error code related with headerss
}
u8 packedField = Memory.Read8(buffer+10);
current_info.SWidth = Memory.Read8(buffer+6) + Memory.Read8(buffer+7) * 256;
current_info.SHeight = Memory.Read8(buffer+8) + Memory.Read8(buffer+9) * 256;
u8 packedField = buffer[10];
current_info.SWidth = buffer[6] + buffer[7] * 0x100;
current_info.SHeight = buffer[8] + buffer[9] * 0x100;
current_info.SGlobalColorTableFlag = packedField >> 7;
current_info.SColorResolution = ((packedField >> 4) & 7)+1;
current_info.SSortFlag = (packedField >> 3) & 1;
current_info.SSizeOfGlobalColorTable = (packedField & 7)+1;
current_info.SBackGroundColor = Memory.Read8(buffer+11);
current_info.SPixelAspectRatio = Memory.Read8(buffer+12);
current_info.SBackGroundColor = buffer[11];
current_info.SPixelAspectRatio = buffer[12];
info += current_info.SWidth;
info += current_info.SHeight;
info += current_info.SGlobalColorTableFlag;
info += current_info.SColorResolution;
info += current_info.SSortFlag;
info += current_info.SSizeOfGlobalColorTable;
info += current_info.SBackGroundColor;
info += current_info.SPixelAspectRatio;
Memory.Free(buffer);
info = current_info;
return CELL_OK;
}
int cellGifDecSetParameter(u32 mainHandle, u32 subHandle, u32 inParam_addr, mem_class_t outParam)
int cellGifDecSetParameter(u32 mainHandle, u32 subHandle, const mem_struct_ptr_t<CellGifDecInParam> inParam, mem_struct_ptr_t<CellGifDecOutParam> outParam)
{
CellGifDecInfo& current_info = ((CellGifDecSubHandle*)subHandle)->info;
CellGifDecOutParam& current_outParam = ((CellGifDecSubHandle*)subHandle)->outParam;
ID sub_handle_id_data;
if(!cellGifDec.CheckId(subHandle, sub_handle_id_data))
return CELL_GIFDEC_ERROR_FATAL;
auto subHandle_data = (CellGifDecSubHandle*)sub_handle_id_data.m_data;
CellGifDecInfo& current_info = subHandle_data->info;
CellGifDecOutParam& current_outParam = subHandle_data->outParam;
current_outParam.outputWidthByte = (current_info.SWidth * current_info.SColorResolution * 3)/8;
current_outParam.outputWidth = current_info.SWidth;
current_outParam.outputHeight = current_info.SHeight;
current_outParam.outputColorSpace = Memory.Read32(inParam_addr+4);
current_outParam.outputWidth = current_info.SWidth;
current_outParam.outputHeight = current_info.SHeight;
current_outParam.outputColorSpace = inParam->colorSpace;
switch (current_outParam.outputColorSpace)
{
case CELL_GIFDEC_RGBA: current_outParam.outputComponents = 4; break;
case CELL_GIFDEC_ARGB: current_outParam.outputComponents = 4; break;
default: return CELL_GIFDEC_ERROR_ARG; // Not supported color space
case CELL_GIFDEC_RGBA:
case CELL_GIFDEC_ARGB: current_outParam.outputComponents = 4; break;
default: return CELL_GIFDEC_ERROR_ARG; // Not supported color space
}
current_outParam.outputBitDepth = 0; // Unimplemented
current_outParam.useMemorySpace = 0; // Unimplemented
current_outParam.outputBitDepth = 0; // Unimplemented
current_outParam.useMemorySpace = 0; // Unimplemented
outParam += current_outParam.outputWidthByte;
outParam += current_outParam.outputWidth;
outParam += current_outParam.outputHeight;
outParam += current_outParam.outputComponents;
outParam += current_outParam.outputBitDepth;
outParam += current_outParam.outputColorSpace;
outParam += current_outParam.useMemorySpace;
outParam = current_outParam;
return CELL_OK;
}
int cellGifDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, u32 dataCtrlParam_addr, mem_class_t dataOutInfo)
int cellGifDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, const mem_struct_ptr_t<CellGifDecDataCtrlParam> dataCtrlParam, mem_struct_ptr_t<CellGifDecDataOutInfo> dataOutInfo)
{
const u32& fd = ((CellGifDecSubHandle*)subHandle)->fd;
const u64& fileSize = ((CellGifDecSubHandle*)subHandle)->fileSize;
const CellGifDecOutParam& current_outParam = ((CellGifDecSubHandle*)subHandle)->outParam; // (TODO: We should use the outParam)
dataOutInfo->status = CELL_GIFDEC_DEC_STATUS_STOP;
ID sub_handle_id_data;
if(!cellGifDec.CheckId(subHandle, sub_handle_id_data))
return CELL_GIFDEC_ERROR_FATAL;
auto subHandle_data = (CellGifDecSubHandle*)sub_handle_id_data.m_data;
const u32& fd = subHandle_data->fd;
const u64& fileSize = subHandle_data->fileSize;
const CellGifDecOutParam& current_outParam = subHandle_data->outParam;
//Copy the GIF file to a buffer
u32 buffer = Memory.Alloc(fileSize,1);
u32 nread = Memory.Alloc(8,1);
u32 pos_addr = Memory.Alloc(8,1);
cellFsLseek(fd, 0, 0, pos_addr);
cellFsRead(fd, buffer, fileSize, nread);
Memory.Free(nread);
Memory.Free(pos_addr);
MemoryAllocator<unsigned char> gif(fileSize);
MemoryAllocator<u64> pos, nread;
cellFsLseek(fd, 0, CELL_SEEK_SET, pos);
cellFsRead(fd, gif.GetAddr(), gif.GetSize(), nread);
//Decode GIF file. (TODO: Is there any faster alternative? Can we do it without external libraries?)
int width, height, actual_components;
unsigned char *gif = (unsigned char*)Memory.VirtualToRealAddr(buffer);
unsigned char *image = stbi_load_from_memory(gif, fileSize, &width, &height, &actual_components, 4);
Memory.Free(buffer);
std::shared_ptr<unsigned char> image(stbi_load_from_memory(gif, fileSize, &width, &height, &actual_components, 4));
if (!image) return CELL_GIFDEC_ERROR_STREAM_FORMAT;
u32 image_size = width * height * 4;
if (current_outParam.outputColorSpace == CELL_GIFDEC_RGBA){
for(u32 i = 0; i < image_size; i+=4){
data += image[i+0];
data += image[i+1];
data += image[i+2];
data += image[i+3];
}
}
if (current_outParam.outputColorSpace == CELL_GIFDEC_ARGB){
for(u32 i = 0; i < image_size; i+=4){
data += image[i+3];
data += image[i+0];
data += image[i+1];
data += image[i+2];
}
}
delete[] image;
uint image_size = width * height * 4;
dataOutInfo += (u32)1; // The output data is an image (dataOutInfo.recordType = 1)
dataOutInfo += (u32)0; // outExtension.label = 0
dataOutInfo += Memory.Alloc(20,1); // outExtension.data allocated (TODO: Is this the best way to avoid exceptions when trying to access this data? Will this produce a memory leak?)
switch(current_outParam.outputColorSpace)
{
case CELL_GIFDEC_RGBA:
memcpy(data, image.get(), image_size);
break;
case CELL_GIFDEC_ARGB:
for(uint i = 0; i < image_size; i+=4)
{
data += image.get()[i+3];
data += image.get()[i+0];
data += image.get()[i+1];
data += image.get()[i+2];
}
break;
default:
return CELL_GIFDEC_ERROR_ARG;
}
dataOutInfo->status = CELL_GIFDEC_DEC_STATUS_FINISH;
dataOutInfo->recordType = CELL_GIFDEC_RECORD_TYPE_IMAGE_DESC;
return CELL_OK;
}
int cellGifDecClose(u32 mainHandle, u32 subHandle)
{
cellFsClose( ((CellGifDecSubHandle*)subHandle)->fd );
delete (CellGifDecSubHandle*)subHandle;
ID sub_handle_id_data;
if(!cellGifDec.CheckId(subHandle, sub_handle_id_data))
return CELL_GIFDEC_ERROR_FATAL;
auto subHandle_data = (CellGifDecSubHandle*)sub_handle_id_data.m_data;
cellFsClose(subHandle_data->fd);
Emu.GetIdManager().RemoveID(subHandle);
return CELL_OK;
}

View File

@ -34,48 +34,72 @@ enum CellJpgDecColorSpace
CELL_JPG_GRAYSCALE_TO_ALPHA_ARGB = 41,
};
enum CellJpgDecDecodeStatus
{
CELL_JPGDEC_DEC_STATUS_FINISH = 0, //Decoding finished
CELL_JPGDEC_DEC_STATUS_STOP = 1, //Decoding halted
};
struct CellJpgDecInfo
{
u32 imageWidth;
u32 imageHeight;
u32 numComponents;
u32 colorSpace; // CellJpgDecColorSpace
be_t<u32> imageWidth;
be_t<u32> imageHeight;
be_t<u32> numComponents;
be_t<u32> colorSpace; // CellJpgDecColorSpace
};
struct CellJpgDecSrc
{
u32 srcSelect; // CellJpgDecStreamSrcSel
u32 fileName; // const char*
u64 fileOffset; // int64_t
u32 fileSize;
u32 streamPtr;
u32 streamSize;
u32 spuThreadEnable; // CellJpgDecSpuThreadEna
be_t<u32> srcSelect; // CellJpgDecStreamSrcSel
be_t<u32> fileName; // const char*
be_t<u64> fileOffset; // int64_t
be_t<u32> fileSize;
be_t<u32> streamPtr;
be_t<u32> streamSize;
be_t<u32> spuThreadEnable; // CellJpgDecSpuThreadEna
};
struct CellJpgDecInParam
{
u32 *commandPtr;
u32 downScale;
u32 method; // CellJpgDecMethod
u32 outputMode; // CellJpgDecOutputMode
u32 outputColorSpace; // CellJpgDecColorSpace
u8 outputColorAlpha;
u8 reserved[3];
be_t<u32> commandPtr;
be_t<u32> downScale;
be_t<u32> method; // CellJpgDecMethod
be_t<u32> outputMode; // CellJpgDecOutputMode
be_t<u32> outputColorSpace; // CellJpgDecColorSpace
be_t<u8> outputColorAlpha;
be_t<u8> reserved[3];
};
struct CellJpgDecOutParam
{
u64 outputWidthByte;
u32 outputWidth;
u32 outputHeight;
u32 outputComponents;
u32 outputMode; // CellJpgDecOutputMode
u32 outputColorSpace; // CellJpgDecColorSpace
u32 downScale;
u32 useMemorySpace;
be_t<u64> outputWidthByte;
be_t<u32> outputWidth;
be_t<u32> outputHeight;
be_t<u32> outputComponents;
be_t<u32> outputMode; // CellJpgDecOutputMode
be_t<u32> outputColorSpace; // CellJpgDecColorSpace
be_t<u32> downScale;
be_t<u32> useMemorySpace;
};
struct CellJpgDecOpnInfo
{
be_t<u32> initSpaceAllocated;
};
struct CellJpgDecDataCtrlParam
{
be_t<u64> outputBytesPerLine;
};
struct CellJpgDecDataOutInfo
{
be_t<float> mean;
be_t<u32> outputLines;
be_t<u32> status;
};
struct CellJpgDecSubHandle //Custom struct
{
u32 fd;
@ -84,7 +108,6 @@ struct CellJpgDecSubHandle //Custom struct
CellJpgDecOutParam outParam;
};
int cellJpgDecCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam)
{
UNIMPLEMENTED_FUNC(cellJpgDec);
@ -103,11 +126,11 @@ int cellJpgDecDestroy(u32 mainHandle)
return CELL_OK;
}
int cellJpgDecOpen(u32 mainHandle, mem32_t subHandle, u32 src_addr, u32 openInfo)
int cellJpgDecOpen(u32 mainHandle, mem32_t subHandle, u32 src_addr, mem_struct_ptr_t<CellJpgDecOpnInfo> openInfo)
{
//u32 srcSelect = Memory.Read32(src_addr);
u32 fileName = Memory.Read32(src_addr+4);
//u64 fileOffset = Memory.Read32(src_addr+8);
//u32 fileOffset = Memory.Read32(src_addr+8);
//u32 fileSize = Memory.Read32(src_addr+12);
//u32 streamPtr = Memory.Read32(src_addr+16);
//u32 streamSize = Memory.Read32(src_addr+20);
@ -116,165 +139,200 @@ int cellJpgDecOpen(u32 mainHandle, mem32_t subHandle, u32 src_addr, u32 openInfo
CellJpgDecSubHandle *current_subHandle = new CellJpgDecSubHandle;
// Get file descriptor
u32 fd_addr = Memory.Alloc(sizeof(u32), 1);
int ret = cellFsOpen(fileName, 0, fd_addr, NULL, 0);
current_subHandle->fd = Memory.Read32(fd_addr);
Memory.Free(fd_addr);
if(ret != 0) return CELL_JPGDEC_ERROR_OPEN_FILE;
MemoryAllocator<be_t<u32>> fd;
int ret = cellFsOpen(fileName, 0, fd, NULL, 0);
current_subHandle->fd = fd->ToLE();
if(ret != CELL_OK) return CELL_JPGDEC_ERROR_OPEN_FILE;
// Get size of file
u32 sb_addr = Memory.Alloc(52,1); // Alloc a CellFsStat struct
cellFsFstat(current_subHandle->fd, sb_addr);
current_subHandle->fileSize = Memory.Read64(sb_addr+36); // Get CellFsStat.st_size
Memory.Free(sb_addr);
MemoryAllocator<CellFsStat> sb; // Alloc a CellFsStat struct
ret = cellFsFstat(current_subHandle->fd, sb);
if(ret != CELL_OK) return ret;
current_subHandle->fileSize = sb->st_size; // Get CellFsStat.st_size
// From now, every u32 subHandle argument is a pointer to a CellPngDecSubHandle struct.
subHandle += (u32)current_subHandle;
subHandle = cellJpgDec.GetNewId(current_subHandle);
return CELL_OK;
}
int cellJpgDecClose(u32 mainHandle, u32 subHandle)
{
cellFsClose( ((CellJpgDecSubHandle*)subHandle)->fd );
delete (CellJpgDecSubHandle*)subHandle;
ID sub_handle_id_data;
if(!cellJpgDec.CheckId(subHandle, sub_handle_id_data))
return CELL_JPGDEC_ERROR_FATAL;
auto subHandle_data = (CellJpgDecSubHandle*)sub_handle_id_data.m_data;
cellFsClose(subHandle_data->fd);
Emu.GetIdManager().RemoveID(subHandle);
return CELL_OK;
}
int cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, mem_class_t info)
int cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, mem_struct_ptr_t<CellJpgDecInfo> info)
{
const u32& fd = ((CellJpgDecSubHandle*)subHandle)->fd;
const u64& fileSize = ((CellJpgDecSubHandle*)subHandle)->fileSize;
CellJpgDecInfo& current_info = ((CellJpgDecSubHandle*)subHandle)->info;
cellJpgDec.Log("cellJpgDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%llx)", mainHandle, subHandle, info.GetAddr());
ID sub_handle_id_data;
if(!cellJpgDec.CheckId(subHandle, sub_handle_id_data))
return CELL_JPGDEC_ERROR_FATAL;
auto subHandle_data = (CellJpgDecSubHandle*)sub_handle_id_data.m_data;
const u32& fd = subHandle_data->fd;
const u64& fileSize = subHandle_data->fileSize;
CellJpgDecInfo& current_info = subHandle_data->info;
//Copy the JPG file to a buffer
u32 buffer = Memory.Alloc(fileSize,1);
u32 nread = Memory.Alloc(8,1);
u32 pos_addr = Memory.Alloc(8,1);
cellFsLseek(fd, 0, 0, pos_addr);
cellFsRead(fd, buffer, fileSize, nread);
Memory.Free(nread);
Memory.Free(pos_addr);
MemoryAllocator<u8> buffer(fileSize);
MemoryAllocator<be_t<u64>> pos, nread;
if (Memory.Read32(buffer) != 0xFFD8FFE0 || // Error: Not a valid SOI header
Memory.Read32(buffer+6) != 0x4A464946) // Error: Not a valid JFIF string
cellFsLseek(fd, 0, CELL_SEEK_SET, pos);
cellFsRead(fd, buffer.GetAddr(), buffer.GetSize(), nread);
if (*buffer.To<u32>(0) != 0xE0FFD8FF || // Error: Not a valid SOI header
*buffer.To<u32>(6) != 0x4649464A) // Error: Not a valid JFIF string
{
Memory.Free(buffer);
return CELL_JPGDEC_ERROR_HEADER;
}
u32 i = 4;
u16 block_length = Memory.Read8(buffer+i)*0xFF + Memory.Read8(buffer+i+1);
while(i < fileSize)
{
i += block_length; // Increase the file index to get to the next block
if (i >= fileSize){
Memory.Free(buffer);
return CELL_JPGDEC_ERROR_HEADER; // Check to protect against segmentation faults
}
if(Memory.Read8(buffer+i) != 0xFF){
Memory.Free(buffer);
return CELL_JPGDEC_ERROR_HEADER; // Check that we are truly at the start of another block
}
if(Memory.Read8(buffer+i+1) == 0xC0){
break; // 0xFFC0 is the "Start of frame" marker which contains the file size
}
i += 2; // Skip the block marker
block_length = Memory.Read8(buffer+i)*0xFF + Memory.Read8(buffer+i+1); // Go to the next block
}
current_info.imageWidth = Memory.Read8(buffer+i+7)*256 + Memory.Read8(buffer+i+8);
current_info.imageHeight = Memory.Read8(buffer+i+5)*256 + Memory.Read8(buffer+i+6);
current_info.numComponents = 3; // Unimplemented
current_info.colorSpace = CELL_JPG_RGB; // Unimplemented
info += current_info.imageWidth;
info += current_info.imageHeight;
info += current_info.numComponents;
info += current_info.colorSpace;
Memory.Free(buffer);
if(i >= fileSize)
return CELL_JPGDEC_ERROR_HEADER;
u16 block_length = buffer[i] * 0xFF + buffer[i+1];
while(true)
{
i += block_length; // Increase the file index to get to the next block
if (i >= fileSize || // Check to protect against segmentation faults
buffer[i] != 0xFF) // Check that we are truly at the start of another block
{
return CELL_JPGDEC_ERROR_HEADER;
}
if(buffer[i+1] == 0xC0)
break; // 0xFFC0 is the "Start of frame" marker which contains the file size
i += 2; // Skip the block marker
block_length = buffer[i] * 0xFF + buffer[i+1]; // Go to the next block
}
current_info.imageWidth = buffer[i+7]*0x100 + buffer[i+8];
current_info.imageHeight = buffer[i+5]*0x100 + buffer[i+6];
current_info.numComponents = 3; // Unimplemented
current_info.colorSpace = CELL_JPG_RGB;
info = current_info;
return CELL_OK;
}
int cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, u32 dataCtrlParam_addr, u32 dataOutInfo_addr)
int cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, const mem_struct_ptr_t<CellJpgDecDataCtrlParam> dataCtrlParam, mem_struct_ptr_t<CellJpgDecDataOutInfo> dataOutInfo)
{
const u32& fd = ((CellJpgDecSubHandle*)subHandle)->fd;
const u64& fileSize = ((CellJpgDecSubHandle*)subHandle)->fileSize;
const CellJpgDecOutParam& current_outParam = ((CellJpgDecSubHandle*)subHandle)->outParam; // (TODO: We should use the outParam)
dataOutInfo->status = CELL_JPGDEC_DEC_STATUS_STOP;
ID sub_handle_id_data;
if(!cellJpgDec.CheckId(subHandle, sub_handle_id_data))
return CELL_JPGDEC_ERROR_FATAL;
auto subHandle_data = (CellJpgDecSubHandle*)sub_handle_id_data.m_data;
const u32& fd = subHandle_data->fd;
const u64& fileSize = subHandle_data->fileSize;
const CellJpgDecOutParam& current_outParam = subHandle_data->outParam;
//Copy the JPG file to a buffer
u32 buffer = Memory.Alloc(fileSize,1);
u32 nread = Memory.Alloc(8,1);
u32 pos_addr = Memory.Alloc(8,1);
cellFsLseek(fd, 0, 0, pos_addr);
cellFsRead(fd, buffer, fileSize, nread);
Memory.Free(nread);
Memory.Free(pos_addr);
MemoryAllocator<unsigned char> jpg(fileSize);
MemoryAllocator<u64> pos, nread;
cellFsLseek(fd, 0, CELL_SEEK_SET, pos);
cellFsRead(fd, jpg.GetAddr(), jpg.GetSize(), nread);
//Decode JPG file. (TODO: Is there any faster alternative? Can we do it without external libraries?)
int width, height, actual_components;
unsigned char *jpg = (unsigned char*)Memory.VirtualToRealAddr(buffer);
unsigned char *image = stbi_load_from_memory(jpg, fileSize, &width, &height, &actual_components, 4);
Memory.Free(buffer);
std::shared_ptr<unsigned char> image(stbi_load_from_memory(jpg, fileSize, &width, &height, &actual_components, 4));
if (!image) return CELL_JPGDEC_ERROR_STREAM_FORMAT;
u32 image_size = width * height * 4;
if (current_outParam.outputColorSpace == CELL_JPG_RGBA){
for(u32 i = 0; i < image_size; i+=4){
data += image[i+0];
data += image[i+1];
data += image[i+2];
data += image[i+3];
uint image_size = width * height;
switch(current_outParam.outputColorSpace)
{
case CELL_JPG_RGBA:
case CELL_JPG_RGB:
image_size *= current_outParam.outputColorSpace == CELL_JPG_RGBA ? 4 : 3;
memcpy(data, image.get(), image_size);
break;
case CELL_JPG_ARGB:
image_size *= 4;
for(u32 i = 0; i < image_size; i+=4)
{
data += image.get()[i+3];
data += image.get()[i+0];
data += image.get()[i+1];
data += image.get()[i+2];
}
break;
case CELL_JPG_GRAYSCALE:
case CELL_JPG_YCbCr:
case CELL_JPG_UPSAMPLE_ONLY:
case CELL_JPG_GRAYSCALE_TO_ALPHA_RGBA:
case CELL_JPG_GRAYSCALE_TO_ALPHA_ARGB:
cellJpgDec.Error("cellJpgDecDecodeData: Unsupported color space (%d)", current_outParam.outputColorSpace.ToLE());
break;
default:
return CELL_JPGDEC_ERROR_ARG;
}
else if (current_outParam.outputColorSpace == CELL_JPG_ARGB){
for(u32 i = 0; i < image_size; i+=4){
data += image[i+3];
data += image[i+0];
data += image[i+1];
data += image[i+2];
}
}
delete[] image;
dataOutInfo->status = CELL_JPGDEC_DEC_STATUS_FINISH;
if(dataCtrlParam->outputBytesPerLine)
dataOutInfo->outputLines = image_size / dataCtrlParam->outputBytesPerLine;
return CELL_OK;
}
int cellJpgDecSetParameter(u32 mainHandle, u32 subHandle, u32 inParam_addr, mem_class_t outParam)
int cellJpgDecSetParameter(u32 mainHandle, u32 subHandle, const mem_struct_ptr_t<CellJpgDecInParam> inParam, mem_struct_ptr_t<CellJpgDecOutParam> outParam)
{
CellJpgDecInfo& current_info = ((CellJpgDecSubHandle*)subHandle)->info;
CellJpgDecOutParam& current_outParam = ((CellJpgDecSubHandle*)subHandle)->outParam;
ID sub_handle_id_data;
if(!cellJpgDec.CheckId(subHandle, sub_handle_id_data))
return CELL_JPGDEC_ERROR_FATAL;
auto subHandle_data = (CellJpgDecSubHandle*)sub_handle_id_data.m_data;
CellJpgDecInfo& current_info = subHandle_data->info;
CellJpgDecOutParam& current_outParam = subHandle_data->outParam;
current_outParam.outputWidthByte = (current_info.imageWidth * current_info.numComponents);
current_outParam.outputWidth = current_info.imageWidth;
current_outParam.outputHeight = current_info.imageHeight;
current_outParam.outputColorSpace = Memory.Read32(inParam_addr+16);
current_outParam.outputColorSpace = inParam->outputColorSpace;
switch (current_outParam.outputColorSpace)
{
case CELL_JPG_GRAYSCALE: current_outParam.outputComponents = 1; break;
case CELL_JPG_RGB: current_outParam.outputComponents = 3; break;
case CELL_JPG_YCbCr: current_outParam.outputComponents = 3; break;
case CELL_JPG_RGBA: current_outParam.outputComponents = 4; break;
case CELL_JPG_UPSAMPLE_ONLY: current_outParam.outputComponents = current_info.numComponents; break;
case CELL_JPG_ARGB: current_outParam.outputComponents = 4; break;
case CELL_JPG_GRAYSCALE_TO_ALPHA_RGBA: current_outParam.outputComponents = 4; break;
case CELL_JPG_GRAYSCALE_TO_ALPHA_ARGB: current_outParam.outputComponents = 4; break;
default: return CELL_JPGDEC_ERROR_ARG; // Not supported color space
}
current_outParam.outputMode = Memory.Read32(inParam_addr+12);
current_outParam.downScale = Memory.Read32(inParam_addr+4);
current_outParam.useMemorySpace = 0; // Unimplemented
outParam += current_outParam.outputWidthByte;
outParam += current_outParam.outputWidth;
outParam += current_outParam.outputHeight;
outParam += current_outParam.outputComponents;
outParam += current_outParam.outputMode;
outParam += current_outParam.outputColorSpace;
outParam += current_outParam.downScale;
outParam += current_outParam.useMemorySpace;
case CELL_JPG_RGB:
case CELL_JPG_YCbCr: current_outParam.outputComponents = 3; break;
case CELL_JPG_UPSAMPLE_ONLY: current_outParam.outputComponents = current_info.numComponents; break;
case CELL_JPG_RGBA:
case CELL_JPG_ARGB:
case CELL_JPG_GRAYSCALE_TO_ALPHA_RGBA:
case CELL_JPG_GRAYSCALE_TO_ALPHA_ARGB: current_outParam.outputComponents = 4; break;
default: return CELL_JPGDEC_ERROR_ARG; // Not supported color space
}
current_outParam.outputMode = inParam->outputMode;
current_outParam.downScale = inParam->downScale;
current_outParam.useMemorySpace = 0; // Unimplemented
outParam = current_outParam;
return CELL_OK;
}

View File

@ -32,49 +32,68 @@ enum CellPngDecColorSpace
CELL_PNGDEC_ARGB = 20,
};
enum CellPngDecDecodeStatus
{
CELL_PNGDEC_DEC_STATUS_FINISH = 0, //Decoding finished
CELL_PNGDEC_DEC_STATUS_STOP = 1, //Decoding halted
};
struct CellPngDecDataOutInfo
{
be_t<u32> chunkInformation;
be_t<u32> numText;
be_t<u32> numUnknownChunk;
be_t<u32> status;
};
struct CellPngDecDataCtrlParam
{
be_t<u64> outputBytesPerLine;
};
struct CellPngDecInfo
{
u32 imageWidth;
u32 imageHeight;
u32 numComponents;
u32 colorSpace; // CellPngDecColorSpace
u32 bitDepth;
u32 interlaceMethod; // CellPngDecInterlaceMode
u32 chunkInformation;
be_t<u32> imageWidth;
be_t<u32> imageHeight;
be_t<u32> numComponents;
be_t<u32> colorSpace; // CellPngDecColorSpace
be_t<u32> bitDepth;
be_t<u32> interlaceMethod; // CellPngDecInterlaceMode
be_t<u32> chunkInformation;
};
struct CellPngDecSrc
{
u32 srcSelect; // CellPngDecStreamSrcSel
u32 fileName; // const char*
u64 fileOffset; // int64_t
u32 fileSize;
u32 streamPtr;
u32 streamSize;
u32 spuThreadEnable; // CellPngDecSpuThreadEna
be_t<u32> srcSelect; // CellPngDecStreamSrcSel
be_t<u32> fileName; // const char*
be_t<u64> fileOffset; // int64_t
be_t<u32> fileSize;
be_t<u32> streamPtr;
be_t<u32> streamSize;
be_t<u32> spuThreadEnable; // CellPngDecSpuThreadEna
};
struct CellPngDecInParam
{
u32 *commandPtr;
u32 outputMode; // CellPngDecOutputMode
u32 outputColorSpace; // CellPngDecColorSpace
u32 outputBitDepth;
u32 outputPackFlag; // CellPngDecPackFlag
u32 outputAlphaSelect; // CellPngDecAlphaSelect
u32 outputColorAlpha;
be_t<u32> commandPtr;
be_t<u32> outputMode; // CellPngDecOutputMode
be_t<u32> outputColorSpace; // CellPngDecColorSpace
be_t<u32> outputBitDepth;
be_t<u32> outputPackFlag; // CellPngDecPackFlag
be_t<u32> outputAlphaSelect; // CellPngDecAlphaSelect
be_t<u32> outputColorAlpha;
};
struct CellPngDecOutParam
{
u64 outputWidthByte;
u32 outputWidth;
u32 outputHeight;
u32 outputComponents;
u32 outputBitDepth;
u32 outputMode; // CellPngDecOutputMode
u32 outputColorSpace; // CellPngDecColorSpace
u32 useMemorySpace;
be_t<u64> outputWidthByte;
be_t<u32> outputWidth;
be_t<u32> outputHeight;
be_t<u32> outputComponents;
be_t<u32> outputBitDepth;
be_t<u32> outputMode; // CellPngDecOutputMode
be_t<u32> outputColorSpace; // CellPngDecColorSpace
be_t<u32> useMemorySpace;
};
struct CellPngDecSubHandle //Custom struct
@ -85,7 +104,6 @@ struct CellPngDecSubHandle //Custom struct
CellPngDecOutParam outParam;
};
int cellPngDecCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam)
{
UNIMPLEMENTED_FUNC(cellPngDec);
@ -102,7 +120,7 @@ int cellPngDecOpen(u32 mainHandle, mem32_t subHandle, u32 src_addr, u32 openInfo
{
//u32 srcSelect = Memory.Read32(src_addr);
u32 fileName = Memory.Read32(src_addr+4);
//u64 fileOffset = Memory.Read32(src_addr+8);
//u32 fileOffset = Memory.Read32(src_addr+8);
//u32 fileSize = Memory.Read32(src_addr+12);
//u32 streamPtr = Memory.Read32(src_addr+16);
//u32 streamSize = Memory.Read32(src_addr+20);
@ -111,160 +129,183 @@ int cellPngDecOpen(u32 mainHandle, mem32_t subHandle, u32 src_addr, u32 openInfo
CellPngDecSubHandle *current_subHandle = new CellPngDecSubHandle;
// Get file descriptor
u32 fd_addr = Memory.Alloc(sizeof(u32), 1);
int ret = cellFsOpen(fileName, 0, fd_addr, NULL, 0);
current_subHandle->fd = Memory.Read32(fd_addr);
Memory.Free(fd_addr);
if(ret != 0) return CELL_PNGDEC_ERROR_OPEN_FILE;
MemoryAllocator<be_t<u32>> fd;
int ret = cellFsOpen(fileName, 0, fd, NULL, 0);
current_subHandle->fd = fd->ToLE();
if(ret != CELL_OK) return CELL_PNGDEC_ERROR_OPEN_FILE;
// Get size of file
u32 sb_addr = Memory.Alloc(52,1); // Alloc a CellFsStat struct
cellFsFstat(current_subHandle->fd, sb_addr);
current_subHandle->fileSize = Memory.Read64(sb_addr+36); // Get CellFsStat.st_size
Memory.Free(sb_addr);
MemoryAllocator<CellFsStat> sb; // Alloc a CellFsStat struct
ret = cellFsFstat(current_subHandle->fd, sb);
if(ret != CELL_OK) return ret;
current_subHandle->fileSize = sb->st_size; // Get CellFsStat.st_size
// From now, every u32 subHandle argument is a pointer to a CellPngDecSubHandle struct.
subHandle += (u32)current_subHandle;
subHandle = cellPngDec.GetNewId(current_subHandle);
return CELL_OK;
}
int cellPngDecClose(u32 mainHandle, u32 subHandle)
{
cellFsClose( ((CellPngDecSubHandle*)subHandle)->fd );
delete (CellPngDecSubHandle*)subHandle;
ID sub_handle_id_data;
if(!cellPngDec.CheckId(subHandle, sub_handle_id_data))
return CELL_PNGDEC_ERROR_FATAL;
auto subHandle_data = (CellPngDecSubHandle*)sub_handle_id_data.m_data;
cellFsClose(subHandle_data->fd);
Emu.GetIdManager().RemoveID(subHandle);
return CELL_OK;
}
int cellPngDecReadHeader(u32 mainHandle, u32 subHandle, mem_class_t info)
int cellPngDecReadHeader(u32 mainHandle, u32 subHandle, mem_struct_ptr_t<CellPngDecInfo> info)
{
const u32& fd = ((CellPngDecSubHandle*)subHandle)->fd;
const u64& fileSize = ((CellPngDecSubHandle*)subHandle)->fileSize;
CellPngDecInfo& current_info = ((CellPngDecSubHandle*)subHandle)->info;
cellPngDec.Log("cellPngDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%llx)", mainHandle, subHandle, info.GetAddr());
ID sub_handle_id_data;
if(!cellPngDec.CheckId(subHandle, sub_handle_id_data))
return CELL_PNGDEC_ERROR_FATAL;
auto subHandle_data = (CellPngDecSubHandle*)sub_handle_id_data.m_data;
const u32& fd = subHandle_data->fd;
const u64& fileSize = subHandle_data->fileSize;
CellPngDecInfo& current_info = subHandle_data->info;
//Check size of file
if(fileSize < 29) return CELL_PNGDEC_ERROR_HEADER; // Error: The file is smaller than the length of a PNG header
//Write the header to buffer
u32 buffer = Memory.Alloc(34,1); // Alloc buffer for PNG header
u32 nread = Memory.Alloc(8,1);
u32 pos_addr = Memory.Alloc(8,1);
cellFsLseek(fd, 0, 0, pos_addr);
cellFsRead(fd, buffer, 34, nread);
Memory.Free(nread);
Memory.Free(pos_addr);
MemoryAllocator<be_t<u32>> buffer(34); // Alloc buffer for PNG header
MemoryAllocator<be_t<u64>> pos, nread;
if (Memory.Read32(buffer) != 0x89504E47 ||
Memory.Read32(buffer+4) != 0x0D0A1A0A || // Error: The first 8 bytes are not a valid PNG signature
Memory.Read32(buffer+12) != 0x49484452) // Error: The PNG file does not start with an IHDR chunk
cellFsLseek(fd, 0, CELL_SEEK_SET, pos);
cellFsRead(fd, buffer.GetAddr(), buffer.GetSize(), nread);
if (buffer[0] != 0x89504E47 ||
buffer[1] != 0x0D0A1A0A || // Error: The first 8 bytes are not a valid PNG signature
buffer[3] != 0x49484452) // Error: The PNG file does not start with an IHDR chunk
{
Memory.Free(buffer);
return CELL_PNGDEC_ERROR_HEADER;
}
current_info.imageWidth = Memory.Read32(buffer+16);
current_info.imageHeight = Memory.Read32(buffer+20);
switch (Memory.Read8(buffer+25))
switch (buffer.To<u8>()[25])
{
case 0: current_info.colorSpace = CELL_PNGDEC_GRAYSCALE; current_info.numComponents = 1; break;
case 2: current_info.colorSpace = CELL_PNGDEC_RGB; current_info.numComponents = 3; break;
case 3: current_info.colorSpace = CELL_PNGDEC_PALETTE; current_info.numComponents = 1; break;
case 4: current_info.colorSpace = CELL_PNGDEC_GRAYSCALE_ALPHA; current_info.numComponents = 2; break;
case 6: current_info.colorSpace = CELL_PNGDEC_RGBA; current_info.numComponents = 4; break;
case 0: current_info.colorSpace = CELL_PNGDEC_GRAYSCALE; current_info.numComponents = 1; break;
case 2: current_info.colorSpace = CELL_PNGDEC_RGB; current_info.numComponents = 3; break;
case 3: current_info.colorSpace = CELL_PNGDEC_PALETTE; current_info.numComponents = 1; break;
case 4: current_info.colorSpace = CELL_PNGDEC_GRAYSCALE_ALPHA; current_info.numComponents = 2; break;
case 6: current_info.colorSpace = CELL_PNGDEC_RGBA; current_info.numComponents = 4; break;
default: return CELL_PNGDEC_ERROR_HEADER; // Not supported color type
}
current_info.bitDepth = Memory.Read8(buffer+24);
current_info.interlaceMethod = Memory.Read8(buffer+28);
current_info.chunkInformation = 0; // Unimplemented
info += current_info.imageWidth;
info += current_info.imageHeight;
info += current_info.numComponents;
info += current_info.colorSpace;
info += current_info.bitDepth;
info += current_info.interlaceMethod;
info += current_info.chunkInformation;
Memory.Free(buffer);
current_info.imageWidth = buffer[4];
current_info.imageHeight = buffer[5];
current_info.bitDepth = buffer.To<u8>()[24];
current_info.interlaceMethod = buffer.To<u8>()[28];
current_info.chunkInformation = 0; // Unimplemented
info = current_info;
return CELL_OK;
}
int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, u32 dataCtrlParam_addr, mem_class_t dataOutInfo)
int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, const mem_struct_ptr_t<CellPngDecDataCtrlParam> dataCtrlParam, mem_struct_ptr_t<CellPngDecDataOutInfo> dataOutInfo)
{
const u32& fd = ((CellPngDecSubHandle*)subHandle)->fd;
const u64& fileSize = ((CellPngDecSubHandle*)subHandle)->fileSize;
const CellPngDecOutParam& current_outParam = ((CellPngDecSubHandle*)subHandle)->outParam;
dataOutInfo->status = CELL_PNGDEC_DEC_STATUS_STOP;
ID sub_handle_id_data;
if(!cellPngDec.CheckId(subHandle, sub_handle_id_data))
return CELL_PNGDEC_ERROR_FATAL;
auto subHandle_data = (CellPngDecSubHandle*)sub_handle_id_data.m_data;
const u32& fd = subHandle_data->fd;
const u64& fileSize = subHandle_data->fileSize;
const CellPngDecOutParam& current_outParam = subHandle_data->outParam;
//Copy the PNG file to a buffer
u32 buffer = Memory.Alloc(fileSize,1);
u32 nread = Memory.Alloc(8,1);
u32 pos_addr = Memory.Alloc(sizeof(u64),1);
cellFsLseek(fd, 0, 0, pos_addr);
cellFsRead(fd, buffer, fileSize, nread);
Memory.Free(nread);
Memory.Free(pos_addr);
MemoryAllocator<unsigned char> png(fileSize);
MemoryAllocator<u64> pos, nread;
cellFsLseek(fd, 0, CELL_SEEK_SET, pos);
cellFsRead(fd, png.GetAddr(), png.GetSize(), nread);
//Decode PNG file. (TODO: Is there any faster alternative? Can we do it without external libraries?)
int width, height, actual_components;
unsigned char *png = (unsigned char*)Memory.VirtualToRealAddr(buffer);
unsigned char *image = stbi_load_from_memory(png, fileSize, &width, &height, &actual_components, 4);
Memory.Free(buffer);
std::shared_ptr<unsigned char> image(stbi_load_from_memory(png, fileSize, &width, &height, &actual_components, 4));
if (!image) return CELL_PNGDEC_ERROR_STREAM_FORMAT;
u32 image_size = width * height * 4;
if (current_outParam.outputColorSpace == CELL_PNGDEC_RGBA){
for(u32 i = 0; i < image_size; i+=4){
data += image[i+0];
data += image[i+1];
data += image[i+2];
data += image[i+3];
uint image_size = width * height;
switch(current_outParam.outputColorSpace)
{
case CELL_PNGDEC_RGB:
case CELL_PNGDEC_RGBA:
image_size *= current_outParam.outputColorSpace == CELL_PNGDEC_RGBA ? 4 : 3;
memcpy(data, image.get(), image_size);
break;
case CELL_PNGDEC_ARGB:
image_size *= 4;
for(uint i = 0; i < image_size; i+=4)
{
data += image.get()[i+3];
data += image.get()[i+0];
data += image.get()[i+1];
data += image.get()[i+2];
}
break;
case CELL_PNGDEC_GRAYSCALE:
case CELL_PNGDEC_PALETTE:
case CELL_PNGDEC_GRAYSCALE_ALPHA:
cellPngDec.Error("cellPngDecDecodeData: Unsupported color space (%d)", current_outParam.outputColorSpace.ToLE());
break;
default:
return CELL_PNGDEC_ERROR_ARG;
}
else if (current_outParam.outputColorSpace == CELL_PNGDEC_ARGB){
for(u32 i = 0; i < image_size; i+=4){
data += image[i+3];
data += image[i+0];
data += image[i+1];
data += image[i+2];
}
}
delete[] image;
dataOutInfo->status = CELL_PNGDEC_DEC_STATUS_FINISH;
return CELL_OK;
}
int cellPngDecSetParameter(u32 mainHandle, u32 subHandle, u32 inParam_addr, mem_class_t outParam)
int cellPngDecSetParameter(u32 mainHandle, u32 subHandle, const mem_struct_ptr_t<CellPngDecInParam> inParam, mem_struct_ptr_t<CellPngDecOutParam> outParam)
{
CellPngDecInfo& current_info = ((CellPngDecSubHandle*)subHandle)->info;
CellPngDecOutParam& current_outParam = ((CellPngDecSubHandle*)subHandle)->outParam;
ID sub_handle_id_data;
if(!cellPngDec.CheckId(subHandle, sub_handle_id_data))
return CELL_PNGDEC_ERROR_FATAL;
current_outParam.outputWidthByte = (current_info.imageWidth * current_info.numComponents * current_info.bitDepth)/8;
auto subHandle_data = (CellPngDecSubHandle*)sub_handle_id_data.m_data;
CellPngDecInfo& current_info = subHandle_data->info;
CellPngDecOutParam& current_outParam = subHandle_data->outParam;
current_outParam.outputWidthByte = (current_info.imageWidth * current_info.numComponents * current_info.bitDepth) / 8;
current_outParam.outputWidth = current_info.imageWidth;
current_outParam.outputHeight = current_info.imageHeight;
current_outParam.outputColorSpace = Memory.Read32(inParam_addr+8);
current_outParam.outputColorSpace = inParam->outputColorSpace;
switch (current_outParam.outputColorSpace)
{
case CELL_PNGDEC_PALETTE:
case CELL_PNGDEC_GRAYSCALE: current_outParam.outputComponents = 1; break;
case CELL_PNGDEC_GRAYSCALE_ALPHA: current_outParam.outputComponents = 2; break;
case CELL_PNGDEC_PALETTE: current_outParam.outputComponents = 1; break;
case CELL_PNGDEC_RGB: current_outParam.outputComponents = 3; break;
case CELL_PNGDEC_RGBA: current_outParam.outputComponents = 4; break;
case CELL_PNGDEC_RGBA:
case CELL_PNGDEC_ARGB: current_outParam.outputComponents = 4; break;
default: return CELL_PNGDEC_ERROR_ARG; // Not supported color space
default: return CELL_PNGDEC_ERROR_ARG; // Not supported color space
}
current_outParam.outputBitDepth = Memory.Read32(inParam_addr+12);
current_outParam.outputMode = Memory.Read32(inParam_addr+4);
current_outParam.outputBitDepth = inParam->outputBitDepth;
current_outParam.outputMode = inParam->outputMode;
current_outParam.useMemorySpace = 0; // Unimplemented
outParam += current_outParam.outputWidthByte;
outParam += current_outParam.outputWidth;
outParam += current_outParam.outputHeight;
outParam += current_outParam.outputComponents;
outParam += current_outParam.outputBitDepth;
outParam += current_outParam.outputMode;
outParam += current_outParam.outputColorSpace;
outParam += current_outParam.useMemorySpace;
outParam = current_outParam;
return CELL_OK;
}

View File

@ -32,7 +32,7 @@ class binder_func_1 : public func_caller
public:
binder_func_1(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_1)); }
virtual void operator()() { declCPU(); RESULT(m_call((T1&)SC_ARG_0)); }
};
template<typename T1>
@ -43,7 +43,7 @@ class binder_func_1<void, T1> : public func_caller
public:
binder_func_1(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); m_call(SC_ARGS_1); }
virtual void operator()() { declCPU(); m_call((T1&)SC_ARG_0); }
};
template<typename TR, typename T1, typename T2>
@ -54,7 +54,7 @@ class binder_func_2 : public func_caller
public:
binder_func_2(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_2)); }
virtual void operator()() { declCPU(); RESULT(m_call((T1&)SC_ARG_0, (T2&)SC_ARG_1)); }
};
template<typename T1, typename T2>
@ -65,7 +65,7 @@ class binder_func_2<void, T1, T2> : public func_caller
public:
binder_func_2(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); m_call(SC_ARGS_2); }
virtual void operator()() { declCPU(); m_call((T1&)SC_ARG_0, (T2&)SC_ARG_1); }
};
template<typename TR, typename T1, typename T2, typename T3>
@ -76,7 +76,7 @@ class binder_func_3 : public func_caller
public:
binder_func_3(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_3)); }
virtual void operator()() { declCPU(); RESULT(m_call((T1&)SC_ARG_0, (T2&)SC_ARG_1, (T3&)SC_ARG_2)); }
};
template<typename T1, typename T2, typename T3>
@ -87,7 +87,7 @@ class binder_func_3<void, T1, T2, T3> : public func_caller
public:
binder_func_3(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); m_call(SC_ARGS_3); }
virtual void operator()() { declCPU(); m_call((T1&)SC_ARG_0, (T2&)SC_ARG_1, (T3&)SC_ARG_2); }
};
template<typename TR, typename T1, typename T2, typename T3, typename T4>
@ -98,7 +98,7 @@ class binder_func_4 : public func_caller
public:
binder_func_4(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_4)); }
virtual void operator()() { declCPU(); RESULT(m_call((T1&)SC_ARG_0, (T2&)SC_ARG_1, (T3&)SC_ARG_2, (T4&)SC_ARG_3)); }
};
template<typename T1, typename T2, typename T3, typename T4>
@ -109,7 +109,7 @@ class binder_func_4<void, T1, T2, T3, T4> : public func_caller
public:
binder_func_4(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); m_call(SC_ARGS_4); }
virtual void operator()() { declCPU(); m_call((T1&)SC_ARG_0, (T2&)SC_ARG_1, (T3&)SC_ARG_2, (T4&)SC_ARG_3); }
};
template<typename TR, typename T1, typename T2, typename T3, typename T4, typename T5>
@ -120,7 +120,7 @@ class binder_func_5 : public func_caller
public:
binder_func_5(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_5)); }
virtual void operator()() { declCPU(); RESULT(m_call((T1&)SC_ARG_0, (T2&)SC_ARG_1, (T3&)SC_ARG_2, (T4&)SC_ARG_3, (T5&)SC_ARG_4)); }
};
template<typename T1, typename T2, typename T3, typename T4, typename T5>
@ -131,7 +131,7 @@ class binder_func_5<void, T1, T2, T3, T4, T5> : public func_caller
public:
binder_func_5(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); m_call(SC_ARGS_5); }
virtual void operator()() { declCPU(); m_call((T1&)SC_ARG_0, (T2&)SC_ARG_1, (T3&)SC_ARG_2, (T4&)SC_ARG_3, (T5&)SC_ARG_4); }
};
template<typename TR, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
@ -142,7 +142,7 @@ class binder_func_6 : public func_caller
public:
binder_func_6(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_6)); }
virtual void operator()() { declCPU(); RESULT(m_call((T1&)SC_ARG_0, (T2&)SC_ARG_1, (T3&)SC_ARG_2, (T4&)SC_ARG_3, (T5&)SC_ARG_4, (T6&)SC_ARG_5)); }
};
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
@ -153,7 +153,7 @@ class binder_func_6<void, T1, T2, T3, T4, T5, T6> : public func_caller
public:
binder_func_6(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); m_call(SC_ARGS_6); }
virtual void operator()() { declCPU(); m_call((T1&)SC_ARG_0, (T2&)SC_ARG_1, (T3&)SC_ARG_2, (T4&)SC_ARG_3, (T5&)SC_ARG_4, (T6&)SC_ARG_5); }
};
template<typename TR, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
@ -164,7 +164,7 @@ class binder_func_7 : public func_caller
public:
binder_func_7(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_7)); }
virtual void operator()() { declCPU(); RESULT(m_call((T1&)SC_ARG_0, (T2&)SC_ARG_1, (T3&)SC_ARG_2, (T4&)SC_ARG_3, (T5&)SC_ARG_4, (T6&)SC_ARG_5, (T7&)SC_ARG_6)); }
};
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
@ -175,7 +175,7 @@ class binder_func_7<void, T1, T2, T3, T4, T5, T6, T7> : public func_caller
public:
binder_func_7(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); m_call(SC_ARGS_7); }
virtual void operator()() { declCPU(); m_call((T1&)SC_ARG_0, (T2&)SC_ARG_1, (T3&)SC_ARG_2, (T4&)SC_ARG_3, (T5&)SC_ARG_4, (T6&)SC_ARG_5, (T7&)SC_ARG_6); }
};
template<typename TR, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
@ -186,7 +186,7 @@ class binder_func_8 : public func_caller
public:
binder_func_8(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_8)); }
virtual void operator()() { declCPU(); RESULT(m_call((T1&)SC_ARG_0, (T2&)SC_ARG_1, (T3&)SC_ARG_2, (T4&)SC_ARG_3, (T5&)SC_ARG_4, (T6&)SC_ARG_5, (T7&)SC_ARG_6, (T8&)SC_ARG_7)); }
};
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
@ -197,7 +197,7 @@ class binder_func_8<void, T1, T2, T3, T4, T5, T6, T7, T8> : public func_caller
public:
binder_func_8(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); m_call(SC_ARGS_8); }
virtual void operator()() { declCPU(); m_call((T1&)SC_ARG_0, (T2&)SC_ARG_1, (T3&)SC_ARG_2, (T4&)SC_ARG_3, (T5&)SC_ARG_4, (T6&)SC_ARG_5, (T7&)SC_ARG_6, (T8&)SC_ARG_7); }
};
template<typename TR, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
@ -208,7 +208,7 @@ class binder_func_9 : public func_caller
public:
binder_func_9(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_9)); }
virtual void operator()() { declCPU(); RESULT(m_call((T1&)SC_ARG_0, (T2&)SC_ARG_1, (T3&)SC_ARG_2, (T4&)SC_ARG_3, (T5&)SC_ARG_4, (T6&)SC_ARG_5, (T7&)SC_ARG_6, (T8&)SC_ARG_7, (T9&)SC_ARG_8)); }
};
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
@ -219,7 +219,7 @@ class binder_func_9<void, T1, T2, T3, T4, T5, T6, T7, T8, T9> : public func_call
public:
binder_func_9(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); m_call(SC_ARGS_9); }
virtual void operator()() { declCPU(); m_call((T1&)SC_ARG_0, (T2&)SC_ARG_1, (T3&)SC_ARG_2, (T4&)SC_ARG_3, (T5&)SC_ARG_4, (T6&)SC_ARG_5, (T7&)SC_ARG_6, (T8&)SC_ARG_7, (T9&)SC_ARG_8); }
};
template<typename TR, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10>
@ -230,7 +230,7 @@ class binder_func_10 : public func_caller
public:
binder_func_10(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_10)); }
virtual void operator()() { declCPU(); RESULT(m_call((T1&)SC_ARG_0, (T2&)SC_ARG_1, (T3&)SC_ARG_2, (T4&)SC_ARG_3, (T5&)SC_ARG_4, (T6&)SC_ARG_5, (T7&)SC_ARG_6, (T8&)SC_ARG_7, (T9&)SC_ARG_8, (T10&)SC_ARG_9)); }
};
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10>
@ -241,7 +241,7 @@ class binder_func_10<void, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : public fun
public:
binder_func_10(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); m_call(SC_ARGS_10); }
virtual void operator()() { declCPU(); m_call((T1&)SC_ARG_0, (T2&)SC_ARG_1, (T3&)SC_ARG_2, (T4&)SC_ARG_3, (T5&)SC_ARG_4, (T6&)SC_ARG_5, (T7&)SC_ARG_6, (T8&)SC_ARG_7, (T9&)SC_ARG_8, (T10&)SC_ARG_9); }
};
template<typename TR, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11>
@ -252,7 +252,7 @@ class binder_func_11 : public func_caller
public:
binder_func_11(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_11)); }
virtual void operator()() { declCPU(); RESULT(m_call((T1&)SC_ARG_0, (T2&)SC_ARG_1, (T3&)SC_ARG_2, (T4&)SC_ARG_3, (T5&)SC_ARG_4, (T6&)SC_ARG_5, (T7&)SC_ARG_6, (T8&)SC_ARG_7, (T9&)SC_ARG_8, (T10&)SC_ARG_9, (T11&)SC_ARG_10)); }
};
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11>
@ -263,7 +263,7 @@ class binder_func_11<void, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> : publi
public:
binder_func_11(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); m_call(SC_ARGS_11); }
virtual void operator()() { declCPU(); m_call((T1&)SC_ARG_0, (T2&)SC_ARG_1, (T3&)SC_ARG_2, (T4&)SC_ARG_3, (T5&)SC_ARG_4, (T6&)SC_ARG_5, (T7&)SC_ARG_6, (T8&)SC_ARG_7, (T9&)SC_ARG_8, (T10&)SC_ARG_9, (T11&)SC_ARG_10); }
};
template<typename TR, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12>
@ -274,7 +274,7 @@ class binder_func_12 : public func_caller
public:
binder_func_12(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_12)); }
virtual void operator()() { declCPU(); RESULT(m_call((T1&)SC_ARG_0, (T2&)SC_ARG_1, (T3&)SC_ARG_2, (T4&)SC_ARG_3, (T5&)SC_ARG_4, (T6&)SC_ARG_5, (T7&)SC_ARG_6, (T8&)SC_ARG_7, (T9&)SC_ARG_8, (T10&)SC_ARG_9, (T11&)SC_ARG_10, (T12&)SC_ARG_11)); }
};
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12>
@ -285,7 +285,7 @@ class binder_func_12<void, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> :
public:
binder_func_12(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); m_call(SC_ARGS_12); }
virtual void operator()() { declCPU(); m_call((T1&)SC_ARG_0, (T2&)SC_ARG_1, (T3&)SC_ARG_2, (T4&)SC_ARG_3, (T5&)SC_ARG_4, (T6&)SC_ARG_5, (T7&)SC_ARG_6, (T8&)SC_ARG_7, (T9&)SC_ARG_8, (T10&)SC_ARG_9, (T11&)SC_ARG_10, (T12&)SC_ARG_11); }
};
template<typename TR>

View File

@ -1,6 +1,6 @@
#pragma once
#include "ErrorCodes.h"
#include "lv2/SC_FileSystem.h"
//#define SYSCALLS_DEBUG
#define declCPU PPUThread& CPU = GetCurrentPPUThread
@ -176,14 +176,14 @@ extern int sys_mmapper_map_memory(u32 start_addr, u32 mem_id, u64 flags);
//cellFs
extern int cellFsOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size);
extern int cellFsRead(u32 fd, u32 buf_addr, u64 nbytes, mem64_t nread_addr);
extern int cellFsWrite(u32 fd, u32 buf_addr, u64 nbytes, mem64_t nwrite_addr);
extern int cellFsRead(u32 fd, u32 buf_addr, u64 nbytes, mem64_t nread);
extern int cellFsWrite(u32 fd, u32 buf_addr, u64 nbytes, mem64_t nwrite);
extern int cellFsClose(u32 fd);
extern int cellFsOpendir(u32 path_addr, mem32_t fd);
extern int cellFsReaddir(u32 fd, u32 dir_addr, mem64_t nread);
extern int cellFsClosedir(u32 fd);
extern int cellFsStat(u32 path_addr, mem_class_t sb);
extern int cellFsFstat(u32 fd, mem_class_t sb);
extern int cellFsStat(u32 path_addr, mem_struct_ptr_t<CellFsStat> sb);
extern int cellFsFstat(u32 fd, mem_struct_ptr_t<CellFsStat> sb);
extern int cellFsMkdir(u32 path_addr, u32 mode);
extern int cellFsRename(u32 from_addr, u32 to_addr);
extern int cellFsRmdir(u32 path_addr);
@ -278,18 +278,31 @@ extern u64 sys_time_get_timebase_frequency();
#define UNIMPLEMENTED_FUNC(module) module.Error("Unimplemented function: "__FUNCTION__)
#define SC_ARGS_1 CPU.GPR[3]
#define SC_ARGS_2 SC_ARGS_1,CPU.GPR[4]
#define SC_ARGS_3 SC_ARGS_2,CPU.GPR[5]
#define SC_ARGS_4 SC_ARGS_3,CPU.GPR[6]
#define SC_ARGS_5 SC_ARGS_4,CPU.GPR[7]
#define SC_ARGS_6 SC_ARGS_5,CPU.GPR[8]
#define SC_ARGS_7 SC_ARGS_6,CPU.GPR[9]
#define SC_ARGS_8 SC_ARGS_7,CPU.GPR[10]
#define SC_ARGS_9 SC_ARGS_8,CPU.GPR[11]
#define SC_ARGS_10 SC_ARGS_9,CPU.GPR[12]
#define SC_ARGS_11 SC_ARGS_10,CPU.GPR[13]
#define SC_ARGS_12 SC_ARGS_11,CPU.GPR[14]
#define SC_ARG_0 CPU.GPR[3]
#define SC_ARG_1 CPU.GPR[4]
#define SC_ARG_2 CPU.GPR[5]
#define SC_ARG_3 CPU.GPR[6]
#define SC_ARG_4 CPU.GPR[7]
#define SC_ARG_5 CPU.GPR[8]
#define SC_ARG_6 CPU.GPR[9]
#define SC_ARG_7 CPU.GPR[10]
#define SC_ARG_8 CPU.GPR[11]
#define SC_ARG_9 CPU.GPR[12]
#define SC_ARG_10 CPU.GPR[13]
#define SC_ARG_11 CPU.GPR[14]
#define SC_ARGS_1 SC_ARG_0
#define SC_ARGS_2 SC_ARGS_1,SC_ARG_1
#define SC_ARGS_3 SC_ARGS_2,SC_ARG_2
#define SC_ARGS_4 SC_ARGS_3,SC_ARG_3
#define SC_ARGS_5 SC_ARGS_4,SC_ARG_4
#define SC_ARGS_6 SC_ARGS_5,SC_ARG_5
#define SC_ARGS_7 SC_ARGS_6,SC_ARG_6
#define SC_ARGS_8 SC_ARGS_7,SC_ARG_7
#define SC_ARGS_9 SC_ARGS_8,SC_ARG_8
#define SC_ARGS_10 SC_ARGS_9,SC_ARG_9
#define SC_ARGS_11 SC_ARGS_10,SC_ARG_10
#define SC_ARGS_12 SC_ARGS_11,SC_ARG_11
extern bool dump_enable;
class PPUThread;

View File

@ -1,87 +1,7 @@
#include "stdafx.h"
#include "SC_FileSystem.h"
#include "Emu/SysCalls/SysCalls.h"
enum CellFsOflag
{
LV2_O_RDONLY = 000000,
LV2_O_WRONLY = 000001,
LV2_O_RDWR = 000002,
LV2_O_ACCMODE = 000003,
LV2_O_CREAT = 000100,
LV2_O_EXCL = 000200,
LV2_O_TRUNC = 001000,
LV2_O_APPEND = 002000,
LV2_O_MSELF = 010000,
};
#define CELL_FS_TYPE_UNKNOWN 0
enum CellFsSeek
{
LV2_SEEK_SET,
LV2_SEEK_CUR,
LV2_SEEK_END,
};
enum CellFsLength
{
LV2_MAX_FS_PATH_LENGTH = 1024,
LV2_MAX_FS_FILE_NAME_LENGTH = 255,
LV2_MAX_FS_MP_LENGTH = 31,
};
enum
{
CELL_FS_S_IFDIR = 0040000, //directory
CELL_FS_S_IFREG = 0100000, //regular
CELL_FS_S_IFLNK = 0120000, //symbolic link
CELL_FS_S_IFWHT = 0160000, //unknown
CELL_FS_S_IRUSR = 0000400, //R for owner
CELL_FS_S_IWUSR = 0000200, //W for owner
CELL_FS_S_IXUSR = 0000100, //X for owner
CELL_FS_S_IRGRP = 0000040, //R for group
CELL_FS_S_IWGRP = 0000020, //W for group
CELL_FS_S_IXGRP = 0000010, //X for group
CELL_FS_S_IROTH = 0000004, //R for other
CELL_FS_S_IWOTH = 0000002, //W for other
CELL_FS_S_IXOTH = 0000001, //X for other
};
struct CellFsStat
{
u32 st_mode;
s32 st_uid;
s32 st_gid;
u64 st_atime;
u64 st_mtime;
u64 st_ctime;
u64 st_size;
u64 st_blksize;
};
struct CellFsUtimbuf
{
u64 actime;
u64 modtime;
};
struct CellFsDirent
{
u8 d_type;
u8 d_namlen;
char d_name[LV2_MAX_FS_FILE_NAME_LENGTH + 1];
};
enum FsDirentType
{
CELL_FS_TYPE_DIRECTORY = 1,
CELL_FS_TYPE_REGULAR = 2,
CELL_FS_TYPE_SYMLINK = 3,
};
extern Module sys_fs;
int cellFsOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size)
@ -94,9 +14,9 @@ int cellFsOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size)
//ConLog.Warning("path: %s [%s]", ppath, path);
s32 _oflags = flags;
if(flags & LV2_O_CREAT)
if(flags & CELL_O_CREAT)
{
_oflags &= ~LV2_O_CREAT;
_oflags &= ~CELL_O_CREAT;
/*
//create path
for(uint p=1;p<ppath.Length();p++)
@ -125,35 +45,35 @@ int cellFsOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size)
vfsOpenMode o_mode;
switch(flags & LV2_O_ACCMODE)
switch(flags & CELL_O_ACCMODE)
{
case LV2_O_RDONLY:
_oflags &= ~LV2_O_RDONLY;
case CELL_O_RDONLY:
_oflags &= ~CELL_O_RDONLY;
o_mode = vfsRead;
break;
case LV2_O_WRONLY:
_oflags &= ~LV2_O_WRONLY;
case CELL_O_WRONLY:
_oflags &= ~CELL_O_WRONLY;
if(flags & LV2_O_APPEND)
if(flags & CELL_O_APPEND)
{
_oflags &= ~LV2_O_APPEND;
_oflags &= ~CELL_O_APPEND;
o_mode = vfsWriteAppend;
}
else if(flags & LV2_O_EXCL)
else if(flags & CELL_O_EXCL)
{
_oflags &= ~LV2_O_EXCL;
_oflags &= ~CELL_O_EXCL;
o_mode = vfsWriteExcl;
}
else //if(flags & LV2_O_TRUNC)
else //if(flags & CELL_O_TRUNC)
{
_oflags &= ~LV2_O_TRUNC;
_oflags &= ~CELL_O_TRUNC;
o_mode = vfsWrite;
}
break;
case LV2_O_RDWR:
_oflags &= ~LV2_O_RDWR;
case CELL_O_RDWR:
_oflags &= ~CELL_O_RDWR;
o_mode = vfsReadWrite;
break;
}
@ -187,7 +107,10 @@ int cellFsRead(u32 fd, u32 buf_addr, u64 nbytes, mem64_t nread)
if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
vfsStream& file = *(vfsStream*)id.m_data;
nread = file.Read(Memory.GetMemFromAddr(buf_addr), nbytes);
const u64 res = nbytes ? file.Read(Memory.GetMemFromAddr(buf_addr), nbytes) : 0;
if(nread.IsGood())
nread = res;
return CELL_OK;
}
@ -205,7 +128,10 @@ int cellFsWrite(u32 fd, u32 buf_addr, u64 nbytes, mem64_t nwrite)
nbytes = block.GetSize() - (buf_addr - block.GetStartAddr());
}
nwrite = nbytes ? file.Write(Memory.GetMemFromAddr(buf_addr), nbytes) : 0;
const u64 res = nbytes ? file.Write(Memory.GetMemFromAddr(buf_addr), nbytes) : 0;
if(nwrite.IsGood())
nwrite = res;
return CELL_OK;
}
@ -242,7 +168,7 @@ int cellFsClosedir(u32 fd)
return CELL_OK;
}
int cellFsStat(const u32 path_addr, mem_class_t sb)
int cellFsStat(const u32 path_addr, mem_struct_ptr_t<CellFsStat> sb)
{
const wxString& path = Memory.ReadString(path_addr);
sys_fs.Log("cellFsFstat(path: %s, sb_addr: 0x%x)", path, sb.GetAddr());
@ -265,63 +191,43 @@ int cellFsStat(const u32 path_addr, mem_class_t sb)
return CELL_ENOENT;
}
CellFsStat stat;
stat.st_mode =
sb->st_mode =
CELL_FS_S_IRUSR | CELL_FS_S_IWUSR | CELL_FS_S_IXUSR |
CELL_FS_S_IRGRP | CELL_FS_S_IWGRP | CELL_FS_S_IXGRP |
CELL_FS_S_IROTH | CELL_FS_S_IWOTH | CELL_FS_S_IXOTH;
stat.st_mode |= CELL_FS_S_IFREG; //TODO: dir CELL_FS_S_IFDIR
stat.st_uid = 0;
stat.st_gid = 0;
stat.st_atime = 0; //TODO
stat.st_mtime = 0; //TODO
stat.st_ctime = 0; //TODO
stat.st_size = f->GetSize();
stat.st_blksize = 4096;
sb += stat.st_mode;
sb += stat.st_uid;
sb += stat.st_gid;
sb += stat.st_atime;
sb += stat.st_mtime;
sb += stat.st_ctime;
sb += stat.st_size;
sb += stat.st_blksize;
sb->st_mode |= CELL_FS_S_IFREG; //TODO: dir CELL_FS_S_IFDIR
sb->st_uid = 0;
sb->st_gid = 0;
sb->st_atime = 0; //TODO
sb->st_mtime = 0; //TODO
sb->st_ctime = 0; //TODO
sb->st_size = f->GetSize();
sb->st_blksize = 4096;
return CELL_OK;
}
int cellFsFstat(u32 fd, mem_class_t sb)
int cellFsFstat(u32 fd, mem_struct_ptr_t<CellFsStat> sb)
{
sys_fs.Log("cellFsFstat(fd: %d, sb_addr: 0x%x)", fd, sb.GetAddr());
ID id;
if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
vfsStream& file = *(vfsStream*)id.m_data;
CellFsStat stat;
stat.st_mode =
sb->st_mode =
CELL_FS_S_IRUSR | CELL_FS_S_IWUSR | CELL_FS_S_IXUSR |
CELL_FS_S_IRGRP | CELL_FS_S_IWGRP | CELL_FS_S_IXGRP |
CELL_FS_S_IROTH | CELL_FS_S_IWOTH | CELL_FS_S_IXOTH;
stat.st_mode |= CELL_FS_S_IFREG; //TODO: dir CELL_FS_S_IFDIR
stat.st_uid = 0;
stat.st_gid = 0;
stat.st_atime = 0; //TODO
stat.st_mtime = 0; //TODO
stat.st_ctime = 0; //TODO
stat.st_size = file.GetSize();
stat.st_blksize = 4096;
sb += stat.st_mode;
sb += stat.st_uid;
sb += stat.st_gid;
sb += stat.st_atime;
sb += stat.st_mtime;
sb += stat.st_ctime;
sb += stat.st_size;
sb += stat.st_blksize;
sb->st_mode |= CELL_FS_S_IFREG; //TODO: dir CELL_FS_S_IFDIR
sb->st_uid = 0;
sb->st_gid = 0;
sb->st_atime = 0; //TODO
sb->st_mtime = 0; //TODO
sb->st_ctime = 0; //TODO
sb->st_size = file.GetSize();
sb->st_blksize = 4096;
return CELL_OK;
}
@ -379,9 +285,9 @@ int cellFsLseek(u32 fd, s64 offset, u32 whence, mem64_t pos)
sys_fs.Log("cellFsLseek(fd: %d, offset: 0x%llx, whence: %d, pos_addr: 0x%x)", fd, offset, whence, pos.GetAddr());
switch(whence)
{
case LV2_SEEK_SET: seek_mode = vfsSeekSet; break;
case LV2_SEEK_CUR: seek_mode = vfsSeekCur; break;
case LV2_SEEK_END: seek_mode = vfsSeekEnd; break;
case CELL_SEEK_SET: seek_mode = vfsSeekSet; break;
case CELL_SEEK_CUR: seek_mode = vfsSeekCur; break;
case CELL_SEEK_END: seek_mode = vfsSeekEnd; break;
default:
sys_fs.Error(fd, "Unknown seek whence! (%d)", whence);
return CELL_EINVAL;

View File

@ -0,0 +1,82 @@
#pragma once
enum CellFsOflag
{
CELL_O_RDONLY = 000000,
CELL_O_WRONLY = 000001,
CELL_O_RDWR = 000002,
CELL_O_ACCMODE = 000003,
CELL_O_CREAT = 000100,
CELL_O_EXCL = 000200,
CELL_O_TRUNC = 001000,
CELL_O_APPEND = 002000,
CELL_O_MSELF = 010000,
};
static const u32 CELL_FS_TYPE_UNKNOWN = 0;
enum CellFsSeek
{
CELL_SEEK_SET,
CELL_SEEK_CUR,
CELL_SEEK_END,
};
enum CellFsLength
{
CELL_MAX_FS_PATH_LENGTH = 1024,
CELL_MAX_FS_FILE_NAME_LENGTH = 255,
CELL_MAX_FS_MP_LENGTH = 31,
};
enum
{
CELL_FS_S_IFDIR = 0040000, //directory
CELL_FS_S_IFREG = 0100000, //regular
CELL_FS_S_IFLNK = 0120000, //symbolic link
CELL_FS_S_IFWHT = 0160000, //unknown
CELL_FS_S_IRUSR = 0000400, //R for owner
CELL_FS_S_IWUSR = 0000200, //W for owner
CELL_FS_S_IXUSR = 0000100, //X for owner
CELL_FS_S_IRGRP = 0000040, //R for group
CELL_FS_S_IWGRP = 0000020, //W for group
CELL_FS_S_IXGRP = 0000010, //X for group
CELL_FS_S_IROTH = 0000004, //R for other
CELL_FS_S_IWOTH = 0000002, //W for other
CELL_FS_S_IXOTH = 0000001, //X for other
};
enum FsDirentType
{
CELL_FS_TYPE_DIRECTORY = 1,
CELL_FS_TYPE_REGULAR = 2,
CELL_FS_TYPE_SYMLINK = 3,
};
struct CellFsStat
{
be_t<u32> st_mode;
be_t<s32> st_uid;
be_t<s32> st_gid;
be_t<u64> st_atime;
be_t<u64> st_mtime;
be_t<u64> st_ctime;
be_t<u64> st_size;
be_t<u64> st_blksize;
};
struct CellFsUtimbuf
{
be_t<u64> actime;
be_t<u64> modtime;
};
struct CellFsDirent
{
u8 d_type;
u8 d_namlen;
char d_name[CELL_MAX_FS_FILE_NAME_LENGTH + 1];
};

View File

@ -99,16 +99,21 @@ void Emulator::Load()
}
ConLog.SkipLn();
const auto f = m_elf_path.Len() ? OpenFile(m_elf_path) : std::shared_ptr<vfsLocalFile>(new vfsLocalFile(m_path));
if(m_elf_path.IsEmpty())
{
GetVFS().GetDeviceLocal(m_path, m_elf_path);
}
if(!f->IsOpened())
vfsFile f(m_elf_path);
if(!f.IsOpened())
{
ConLog.Error("Elf not found! (%s - %s)", m_path, m_elf_path);
return;
}
bool is_error;
Loader l(*f);
Loader l(f);
try
{

View File

@ -206,6 +206,7 @@
<ClCompile Include="Emu\DbgConsole.cpp" />
<ClCompile Include="Emu\FS\VFS.cpp" />
<ClCompile Include="Emu\FS\vfsDevice.cpp" />
<ClCompile Include="Emu\FS\vfsFile.cpp" />
<ClCompile Include="Emu\FS\vfsFileBase.cpp" />
<ClCompile Include="Emu\FS\vfsLocalFile.cpp" />
<ClCompile Include="Emu\FS\vfsStream.cpp" />
@ -291,6 +292,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Utilities\Array.h" />
<ClInclude Include="..\Utilities\BEType.h" />
<ClInclude Include="..\Utilities\IdManager.h" />
<ClInclude Include="..\Utilities\MTProgressDialog.h" />
<ClInclude Include="..\Utilities\Thread.h" />

View File

@ -307,6 +307,9 @@
<ClCompile Include="Emu\SysCalls\lv2\SC_Mouse.cpp">
<Filter>Emu\SysCalls\lv2</Filter>
</ClCompile>
<ClCompile Include="Emu\FS\vfsFile.cpp">
<Filter>Emu\FS</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="rpcs3.rc" />
@ -474,5 +477,8 @@
<ClInclude Include="Emu\Cell\PPUProgramCompiler.h">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\Utilities\BEType.h">
<Filter>Utilities</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -186,6 +186,7 @@ enum Status
Ready,
};
#include "Utilities/BEType.h"
#include "Utilities/Thread.h"
#include "Utilities/Array.h"
#include "Utilities/Timer.h"
@ -202,6 +203,7 @@ enum Status
#include "Emu/FS/vfsFileBase.h"
#include "Emu/FS/vfsLocalFile.h"
#include "Emu/FS/vfsFile.h"
#include "Emu/FS/vfsStream.h"
#include "Emu/FS/vfsStreamMemory.h"
#include "rpcs3.h"