1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 02:32:36 +01:00
This commit is contained in:
O1L 2013-11-13 22:24:24 +04:00
commit 584d4eb9d4
159 changed files with 22082 additions and 6071 deletions

2
.gitignore vendored
View File

@ -22,6 +22,7 @@
*.log
*.exe
*.dll
*.elf
*.lastbuildstate
*.unsuccessfulbuild
@ -39,4 +40,5 @@
/bin/VertexProgram.txt
/bin/BreakPoints.dat
/bin/textures
/bin/data/
rpcs3/git-version.h

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:
(u8&)res = (u8&)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:
(u8&)m_data = (u8&)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

@ -13,7 +13,7 @@ rem // A copy of the GPL 2.0 should have been included with the program.
rem // If not, see http://www.gnu.org/licenses/
rem // Official git repository and contact information can be found at
rem // https://github.com/hrydgard/RPCS3 and http://www.RPCS3.org/.
rem // https://github.com/DHrpcs3/rpcs3 and http://code.google.com/p/rpcs3/.
setlocal ENABLEDELAYEDEXPANSION

4
bin/dev_hdd1/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@ -63,6 +63,38 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "stblib", "stblib", "{9D839D
stblib\stb_image.h = stblib\stb_image.h
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scetool", "scetool", "{AB33A31B-6D15-45E8-B292-D512DEF0A5B1}"
ProjectSection(SolutionItems) = preProject
scetool\aes.c = scetool\aes.c
scetool\aes.h = scetool\aes.h
scetool\aes_omac.h = scetool\aes_omac.h
scetool\bn.cpp = scetool\bn.cpp
scetool\config.h = scetool\config.h
scetool\ecdsa.h = scetool\ecdsa.h
scetool\elf.h = scetool\elf.h
scetool\elf_inlines.h = scetool\elf_inlines.h
scetool\frontend.h = scetool\frontend.h
scetool\getopt.c = scetool\getopt.c
scetool\getopt.h = scetool\getopt.h
scetool\keys.h = scetool\keys.h
scetool\list.h = scetool\list.h
scetool\mt19937.h = scetool\mt19937.h
scetool\np.h = scetool\np.h
scetool\rvk.h = scetool\rvk.h
scetool\sce.h = scetool\sce.h
scetool\sce_inlines.h = scetool\sce_inlines.h
scetool\scetool.cpp = scetool\scetool.cpp
scetool\self.h = scetool\self.h
scetool\sha1.c = scetool\sha1.c
scetool\sha1.h = scetool\sha1.h
scetool\spp.h = scetool\spp.h
scetool\tables.h = scetool\tables.h
scetool\types.h = scetool\types.h
scetool\util.h = scetool\util.h
scetool\zconf.h = scetool\zconf.h
scetool\zlib.h = scetool\zlib.h
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32

View File

@ -0,0 +1,137 @@
#pragma once
#include "Emu/CPU/CPUDecoder.h"
#include "ARMv7Opcodes.h"
class ARMv7Decoder : public CPUDecoder
{
ARMv7Opcodes& m_op;
u8 m_last_instr_size;
public:
ARMv7Decoder(ARMv7Opcodes& op) : m_op(op)
{
}
u32 branchTarget(u32 imm)
{
return imm << 1;
}
virtual u8 DecodeMemory(const u64 address)
{
using namespace ARMv7_opcodes;
const u16 code0 = Memory.Read16(address);
const u16 code1 = Memory.Read16(address + 2);
switch(code0 >> 12) //15 - 12
{
case T1_CBZ:
switch((code0 >> 10) & 0x1)
{
case 0:
switch((code0 >> 8) & 0x1)
{
case 1:
m_op.CBZ((code0 >> 11) & 0x1, branchTarget((((code0 >> 9) & 0x1) << 5) | (code0 >> 3) & 0x1f), code0 & 0x7, 2);
return 2;
}
break;
}
break;
case T1_B:
m_op.B((code0 >> 8) & 0xf, branchTarget(code0 & 0xff), 2);
return 2;
}
switch(code0 >> 11) //15 - 11
{
case T2_B:
m_op.B(0xf, branchTarget(code0 & 0xfff), 2);
return 2;
case T3_B:
{
u8 S = (code0 >> 10) & 0x1;
u8 J1 = (code1 >> 13) & 0x1;
u8 J2 = (code1 >> 11) & 0x1;
u8 I1 = 1 - (J1 ^ S);
u8 I2 = 1 - (J2 ^ S);
u16 imm11 = code1 & 0x7ff;
u32 imm32;
switch(code1 >> 14)
{
case 2: //B
{
u8 cond;
switch((code1 >> 12) & 0x1)
{
case 0:
{
cond = (code0 >> 6) & 0xf;
u32 imm6 = code0 & 0x3f;
imm32 = sign<19, u32>((S << 19) | (I1 << 18) | (I2 << 17) | (imm6 << 11) | imm11);
}
break;
case 1:
cond = 0xf;
u32 imm10 = code0 & 0x7ff;
imm32 = sign<23, u32>((S << 23) | (I1 << 22) | (I2 << 21) | (imm10 << 11) | imm11);
break;
}
m_op.B(cond, branchTarget(imm32), 4);
}
return 4;
case 3: //BL
switch((code1 >> 12) & 0x1)
{
case 0:
break;
case 1:
u32 imm10 = code0 & 0x7ff;
imm32 = sign<23, u32>((S << 23) | (I1 << 22) | (I2 << 21) | (imm10 << 11) | imm11);
m_op.BL(branchTarget(imm32), 4);
return 4;
}
break;
}
}
break;
}
switch(code0 >> 9)
{
case T1_PUSH:
m_op.PUSH((((code0 >> 8) & 0x1) << 14) | (code0 & 0xff));
return 2;
case T1_POP:
m_op.POP((((code0 >> 8) & 0x1) << 15) | (code0 & 0xff));
return 2;
}
switch(code0)
{
case T2_PUSH:
m_op.PUSH(code1);
return 4;
case T2_POP:
m_op.POP(code1);
return 4;
case T1_NOP:
m_op.NOP();
return 2;
}
m_op.UNK(code0, code1);
return 2;
}
};

View File

@ -0,0 +1,96 @@
#pragma once
#include "Emu/ARMv7/ARMv7Opcodes.h"
#include "Emu/CPU/CPUDisAsm.h"
#include "Gui/DisAsmFrame.h"
#include "Emu/Memory/Memory.h"
static const char* g_arm_cond_name[16] =
{
"eq", "ne", "cs", "cc",
"mi", "pl", "vs", "vc",
"hi", "ls", "ge", "lt",
"gt", "le", "al", "al",
};
class ARMv7DisAsm
: public CPUDisAsm
, public ARMv7Opcodes
{
public:
ARMv7DisAsm(CPUDisAsmMode mode) : CPUDisAsm(mode)
{
}
protected:
virtual u32 DisAsmBranchTarget(const s32 imm)
{
return dump_pc + imm;
}
wxString GetRegsListString(u16 regs_list)
{
wxString regs_str;
for(u16 mask=0x1, i=0; mask; mask <<= 1, i++)
{
if(regs_list & mask)
{
if(!regs_str.IsEmpty())
{
regs_str += ", ";
}
regs_str += g_arm_reg_name[i];
}
}
return regs_str;
}
void NULL_OP()
{
Write("null");
}
void PUSH(u16 regs_list)
{
Write(wxString::Format("push {%s}", GetRegsListString(regs_list)));
}
void POP(u16 regs_list)
{
Write(wxString::Format("pop {%s}", GetRegsListString(regs_list)));
}
void NOP()
{
Write("nop");
}
void B(u8 cond, u32 imm, u8 intstr_size)
{
if((cond & 0xe) == 0xe)
{
Write(wxString::Format("b 0x%x", DisAsmBranchTarget(imm) + intstr_size));
}
else
{
Write(wxString::Format("b[%s] 0x%x", g_arm_cond_name[cond], DisAsmBranchTarget(imm) + intstr_size));
}
}
virtual void CBZ(u8 op, u32 imm, u8 rn, u8 intstr_size)
{
Write(wxString::Format("cb%sz 0x%x,%s", (op ? "n" : ""), DisAsmBranchTarget(imm) + intstr_size, g_arm_reg_name[rn]));
}
void BL(u32 imm, u8 intstr_size)
{
Write(wxString::Format("bl 0x%x", DisAsmBranchTarget(imm) + intstr_size));
}
void UNK(const u16 code0, const u16 code1)
{
Write(wxString::Format("Unknown/Illegal opcode! (0x%04x : 0x%04x)", code0, code1));
}
};

View File

@ -0,0 +1,322 @@
#pragma once
#include "Emu/ARMv7/ARMv7Opcodes.h"
class ARMv7Interpreter : public ARMv7Opcodes
{
ARMv7Thread& CPU;
public:
ARMv7Interpreter(ARMv7Thread& cpu) : CPU(cpu)
{
}
enum SRType
{
SRType_None,
SRType_LSL,
SRType_LSR,
SRType_ASR,
SRType_ROR,
SRType_RRX,
};
template<typename T>
bool IsZero(T x)
{
return x == T(0);
}
template<typename T>
bool IsOnes(T x)
{
return x == ~T(0);
}
template<typename T>
u8 IsZeroBit(T x)
{
return IsZero(x) ? 1 : 0;
}
template<typename T>
bool IsOnesBit(T x, u8 len = sizeof(T) * 8)
{
return IsOnes(x) ? 1 : 0;
}
template<typename T>
u8 BitCount(T x, u8 len = sizeof(T) * 8)
{
u8 result = 0;
for(u8 mask=1 << (len - 1); mask; mask >>= 1)
{
if(x & mask) result++;
}
return result;
}
template<typename T>
s8 LowestSetBit(T x, u8 len = sizeof(T) * 8)
{
if(!x) return len;
u8 result = 0;
for(T mask=1, i=0; i<len && (x & mask) == 0; mask <<= 1, i++)
{
result++;
}
return result;
}
template<typename T>
s8 HighestSetBit(T x, u8 len = sizeof(T) * 8)
{
if(!x) return -1;
u8 result = len;
for(T mask=T(1) << (len - 1); (x & mask) == 0; mask >>= 1)
{
result--;
}
return result;
}
template<typename T>
s8 CountLeadingZeroBits(T x, u8 len = sizeof(T) * 8)
{
return len - 1 - HighestSetBit(x, len);
}
SRType DecodeImmShift(u8 type, u8 imm5, uint* shift_n)
{
SRType shift_t;
switch(type)
{
case 0: shift_t = SRType_LSL; if(shift_n) *shift_n = imm5; break;
case 1: shift_t = SRType_LSR; if(shift_n) *shift_n = imm5 == 0 ? 32 : imm5; break;
case 2: shift_t = SRType_ASR; if(shift_n) *shift_n = imm5 == 0 ? 32 : imm5; break;
case 3:
if(imm5 == 0)
{
shift_t = SRType_RRX; if(shift_n) *shift_n = 1;
}
else
{
shift_t = SRType_ROR; if(shift_n) *shift_n = imm5;
}
break;
}
return shift_t;
}
SRType DecodeRegShift(u8 type)
{
SRType shift_t;
switch(type)
{
case 0: shift_t = SRType_LSL; break;
case 1: shift_t = SRType_LSR; break;
case 2: shift_t = SRType_ASR; break;
case 3: shift_t = SRType_ROR; break;
}
return shift_t;
}
u32 LSL_C(u32 x, int shift, bool& carry_out)
{
u32 extended_x = x << shift;
carry_out = (extended_x >> 31) ? 1 : 0;
return extended_x & ~(1 << 31);
}
u32 LSL(u32 x, int shift)
{
if(!shift) return x;
bool carry_out;
return LSL_C(x, shift, carry_out);
}
u32 LSR_C(u32 x, int shift, bool& carry_out)
{
carry_out = (x >> (shift - 1)) & 0x1;
return x >> shift;
}
u32 LSR(u32 x, int shift)
{
if(!shift) return x;
bool carry_out;
return LSR_C(x, shift, carry_out);
}
s32 ASR_C(s32 x, int shift, bool& carry_out)
{
carry_out = (x >> (shift - 1)) & 0x1;
return x >> shift;
}
s32 ASR(s32 x, int shift)
{
if(!shift) return x;
bool carry_out;
return ASR_C(x, shift, carry_out);
}
u32 ROR_C(u32 x, int shift, bool& carry_out)
{
u32 result = LSR(x, shift) | LSL(x, 32 - shift);
carry_out = (result >> 30) & 0x1;
return result;
}
s32 ROR(s32 x, int shift)
{
if(!shift) return x;
bool carry_out;
return ROR_C(x, shift, carry_out);
}
template<typename T> T RRX_C(T x, bool carry_in, bool& carry_out)
{
carry_out = x & 0x1;
return ((u32)carry_in << 31) | (x & 0x7ffffffe);
}
s32 RRX(s32 x, int shift)
{
if(!shift) return x;
bool carry_out;
return RRX_C(x, shift, carry_out);
}
template<typename T> T Shift_C(T value, SRType type, uint amount, bool carry_in, bool& carry_out)
{
if(amount)
{
switch(type)
{
case SRType_LSL: return LSL_C(value, amount, carry_out);
case SRType_LSR: return LSR_C(value, amount, carry_out);
case SRType_ASR: return ASR_C(value, amount, carry_out);
case SRType_ROR: return ROR_C(value, amount, carry_out);
case SRType_RRX: return RRX_C(value, amount, carry_out);
}
}
carry_out = carry_in;
return value;
}
template<typename T> T Shift(T value, SRType type, uint amount, bool carry_in)
{
bool carry_out;
return Shift_C(value, type, amount, carry_in, carry_out);
}
template<typename T> T AddWithCarry(T x, T y, bool carry_in, bool& carry_out, bool& overflow)
{
uint unsigned_sum = (uint)x + (uint)y + (uint)carry_in;
int signed_sum = (int)x + (int)y + (int)carry_in;
T result = unsigned_sum & ~(T(1) << (sizeof(T) - 1));
carry_out = (uint)result != unsigned_sum;
overflow = (int)result != signed_sum;
return result;
}
bool ConditionPassed(u8 cond)
{
bool result;
switch(cond >> 1)
{
case 0: result = CPU.APSR.Z == 1; break;
case 1: result = CPU.APSR.C == 1; break;
case 2: result = CPU.APSR.N == 1; break;
case 3: result = CPU.APSR.V == 1; break;
case 4: result = CPU.APSR.C == 1 && CPU.APSR.Z == 0; break;
case 5: result = CPU.APSR.N == CPU.APSR.V; break;
case 6: result = CPU.APSR.N == CPU.APSR.V && CPU.APSR.Z == 0; break;
case 7: return true;
}
if(cond & 0x1)
{
return !result;
}
return result;
}
protected:
void NULL_OP()
{
ConLog.Error("null");
Emu.Pause();
}
void NOP()
{
}
void PUSH(u16 regs_list)
{
for(u16 mask=0x1, i=0; mask; mask <<= 1, i++)
{
if(regs_list & mask)
{
CPU.SP -= 4;
Memory.Write32(CPU.SP, CPU.read_gpr(i));
}
}
}
void POP(u16 regs_list)
{
for(u16 mask=(0x1 << 15), i=15; mask; mask >>= 1, i--)
{
if(regs_list & mask)
{
CPU.write_gpr(i, Memory.Read32(CPU.SP));
CPU.SP += 4;
}
}
}
void B(u8 cond, u32 imm, u8 intstr_size)
{
if(ConditionPassed(cond))
{
CPU.SetBranch(CPU.PC + intstr_size + imm);
}
}
void CBZ(u8 op, u32 imm, u8 rn, u8 intstr_size)
{
if((CPU.GPR[rn] == 0) ^ op)
{
CPU.SetBranch(CPU.PC + intstr_size + imm);
}
}
void BL(u32 imm, u8 intstr_size)
{
CPU.LR = (CPU.PC + intstr_size) | 1;
CPU.SetBranch(CPU.PC + intstr_size + imm);
}
void UNK(const u16 code0, const u16 code1)
{
ConLog.Error("Unknown/Illegal opcode! (0x%04x : 0x%04x)", code0, code1);
Emu.Pause();
}
};

View File

@ -0,0 +1,49 @@
#pragma once
static const char* g_arm_reg_name[16] =
{
"r0", "r1", "r2", "r3",
"r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11",
"r12", "sp", "lr", "pc",
};
namespace ARMv7_opcodes
{
enum ARMv7_T1Opcodes
{
T1_CBZ = 0xb,
T1_B = 0xd,
T1_PUSH = 0x1d,
T1_POP = 0x5e,
T1_NOP = 0xBF00,
};
enum ARMv7_T2Opcodes
{
T2_B = 0x1c,
T2_PUSH = 0xe92d,
T2_POP = 0xe8bd,
};
enum ARMv7_T3Opcodes
{
T3_B = 0x1e,
};
}
class ARMv7Opcodes
{
public:
virtual void NULL_OP() = 0;
virtual void NOP() = 0;
virtual void PUSH(u16 regs_list) = 0;
virtual void POP(u16 regs_list) = 0;
virtual void B(u8 cond, u32 imm, u8 intstr_size) = 0;
virtual void CBZ(u8 op, u32 imm, u8 rn, u8 intstr_size) = 0;
virtual void BL(u32 imm, u8 intstr_size)=0;
virtual void UNK(const u16 code0, const u16 code1) = 0;
};

View File

@ -0,0 +1,96 @@
#include "stdafx.h"
#include "ARMv7Thread.h"
#include "ARMv7Decoder.h"
#include "ARMv7DisAsm.h"
#include "ARMv7Interpreter.h"
ARMv7Thread::ARMv7Thread() : CPUThread(CPU_THREAD_ARMv7)
{
}
void ARMv7Thread::InitRegs()
{
memset(GPR, 0, sizeof(GPR[0]) * 15);
APSR.APSR = 0;
IPSR.IPSR = 0;
SP = m_stack_point;
}
void ARMv7Thread::InitStack()
{
if(!m_stack_addr)
{
m_stack_size = 0x10000;
m_stack_addr = Memory.Alloc(0x10000, 1);
}
m_stack_point = m_stack_addr + m_stack_size;
}
u64 ARMv7Thread::GetFreeStackSize() const
{
return SP - GetStackAddr();
}
void ARMv7Thread::SetArg(const uint pos, const u64 arg)
{
assert(0);
}
wxString ARMv7Thread::RegsToString()
{
wxString result;
for(int i=0; i<15; ++i)
{
result += wxString::Format("%s\t= 0x%08x\n", g_arm_reg_name[i], GPR[i]);
}
result += wxString::Format("APSR\t= 0x%08x [N: %d, Z: %d, C: %d, V: %d, Q: %d]\n", APSR.APSR, APSR.N, APSR.Z, APSR.C, APSR.V, APSR.Q);
return result;
}
wxString ARMv7Thread::ReadRegString(wxString reg)
{
return wxEmptyString;
}
bool ARMv7Thread::WriteRegString(wxString reg, wxString value)
{
return true;
}
void ARMv7Thread::DoReset()
{
}
void ARMv7Thread::DoRun()
{
switch(Ini.CPUDecoderMode.GetValue())
{
case 0:
//m_dec = new ARMv7Decoder(*new ARMv7DisAsm());
break;
case 1:
case 2:
m_dec = new ARMv7Decoder(*new ARMv7Interpreter(*this));
break;
}
}
void ARMv7Thread::DoPause()
{
}
void ARMv7Thread::DoResume()
{
}
void ARMv7Thread::DoStop()
{
}
void ARMv7Thread::DoCode()
{
}

View File

@ -0,0 +1,99 @@
#pragma once
#include "Emu/CPU/CPUThread.h"
class ARMv7Thread : public CPUThread
{
public:
ARMv7Thread();
union
{
u32 GPR[15];
struct
{
u32 pad[13];
union
{
u32 SP;
struct { u16 SP_main, SP_process; };
};
u32 LR;
};
};
union
{
struct
{
u32 N : 1; //Negative condition code flag
u32 Z : 1; //Zero condition code flag
u32 C : 1; //Carry condition code flag
u32 V : 1; //Overflow condition code flag
u32 Q : 1; //Set to 1 if an SSAT or USAT instruction changes (saturates) the input value for the signed or unsigned range of the result
u32 : 27;
};
u32 APSR;
} APSR;
union
{
struct
{
u32 : 24;
u32 exception : 8;
};
u32 IPSR;
} IPSR;
void write_gpr(u8 n, u32 value)
{
assert(n < 16);
if(n < 15)
{
GPR[n] = value;
}
else
{
SetBranch(value);
}
}
u32 read_gpr(u8 n)
{
assert(n < 16);
if(n < 15)
{
return GPR[n];
}
return PC;
}
public:
virtual void InitRegs();
virtual void InitStack();
virtual u64 GetFreeStackSize() const;
virtual void SetArg(const uint pos, const u64 arg);
public:
virtual wxString RegsToString();
virtual wxString ReadRegString(wxString reg);
virtual bool WriteRegString(wxString reg, wxString value);
protected:
virtual void DoReset();
virtual void DoRun();
virtual void DoPause();
virtual void DoResume();
virtual void DoStop();
virtual void DoCode();
};

879
rpcs3/Emu/CPU/CPUDecoder.h Normal file
View File

@ -0,0 +1,879 @@
#pragma once
#include "CPUInstrTable.h"
#pragma warning( disable : 4800 )
class CPUDecoder
{
public:
virtual u8 DecodeMemory(const u64 address)=0;
};
template<typename TO>
class InstrCaller
{
public:
virtual ~InstrCaller()
{
}
virtual void operator ()(TO* op, u32 code) const = 0;
virtual u32 operator [](u32) const
{
return 0;
}
};
template<typename TO>
class InstrBinder_0 : public InstrCaller<TO>
{
typedef void (TO::*func_t)();
func_t m_func;
public:
InstrBinder_0(func_t func)
: InstrCaller()
, m_func(func)
{
}
virtual void operator ()(TO* op, u32 code) const
{
(op->*m_func)();
}
};
template<typename TO, typename T1>
class InstrBinder_1 : public InstrCaller<TO>
{
typedef void (TO::*func_t)(T1);
func_t m_func;
const CodeFieldBase& m_arg_func_1;
public:
InstrBinder_1(func_t func, const CodeFieldBase& arg_func_1)
: InstrCaller()
, m_func(func)
, m_arg_func_1(arg_func_1)
{
}
virtual void operator ()(TO* op, u32 code) const
{
(op->*m_func)((T1)m_arg_func_1(code));
}
};
template<typename TO, typename T1, typename T2>
class InstrBinder_2 : public InstrCaller<TO>
{
typedef void (TO::*func_t)(T1, T2);
func_t m_func;
const CodeFieldBase& m_arg_func_1;
const CodeFieldBase& m_arg_func_2;
public:
InstrBinder_2(func_t func, const CodeFieldBase& arg_func_1, const CodeFieldBase& arg_func_2)
: InstrCaller()
, m_func(func)
, m_arg_func_1(arg_func_1)
, m_arg_func_2(arg_func_2)
{
}
virtual void operator ()(TO* op, u32 code) const
{
(op->*m_func)(
(T1)m_arg_func_1(code),
(T2)m_arg_func_2(code)
);
}
};
template<typename TO, typename T1, typename T2, typename T3>
class InstrBinder_3 : public InstrCaller<TO>
{
typedef void (TO::*func_t)(T1, T2, T3);
func_t m_func;
const CodeFieldBase& m_arg_func_1;
const CodeFieldBase& m_arg_func_2;
const CodeFieldBase& m_arg_func_3;
public:
InstrBinder_3(func_t func,
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3)
: InstrCaller()
, m_func(func)
, m_arg_func_1(arg_func_1)
, m_arg_func_2(arg_func_2)
, m_arg_func_3(arg_func_3)
{
}
virtual void operator ()(TO* op, u32 code) const
{
(op->*m_func)(
(T1)m_arg_func_1(code),
(T2)m_arg_func_2(code),
(T3)m_arg_func_3(code)
);
}
};
template<typename TO, typename T1, typename T2, typename T3, typename T4>
class InstrBinder_4 : public InstrCaller<TO>
{
typedef void (TO::*func_t)(T1, T2, T3, T4);
func_t m_func;
const CodeFieldBase& m_arg_func_1;
const CodeFieldBase& m_arg_func_2;
const CodeFieldBase& m_arg_func_3;
const CodeFieldBase& m_arg_func_4;
public:
InstrBinder_4(func_t func,
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3,
const CodeFieldBase& arg_func_4)
: InstrCaller()
, m_func(func)
, m_arg_func_1(arg_func_1)
, m_arg_func_2(arg_func_2)
, m_arg_func_3(arg_func_3)
, m_arg_func_4(arg_func_4)
{
}
virtual void operator ()(TO* op, u32 code) const
{
(op->*m_func)(
(T1)m_arg_func_1(code),
(T2)m_arg_func_2(code),
(T3)m_arg_func_3(code),
(T4)m_arg_func_4(code)
);
}
};
template<typename TO, typename T1, typename T2, typename T3, typename T4, typename T5>
class InstrBinder_5 : public InstrCaller<TO>
{
typedef void (TO::*func_t)(T1, T2, T3, T4, T5);
func_t m_func;
const CodeFieldBase& m_arg_func_1;
const CodeFieldBase& m_arg_func_2;
const CodeFieldBase& m_arg_func_3;
const CodeFieldBase& m_arg_func_4;
const CodeFieldBase& m_arg_func_5;
public:
InstrBinder_5(func_t func,
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3,
const CodeFieldBase& arg_func_4,
const CodeFieldBase& arg_func_5)
: InstrCaller()
, m_func(func)
, m_arg_func_1(arg_func_1)
, m_arg_func_2(arg_func_2)
, m_arg_func_3(arg_func_3)
, m_arg_func_4(arg_func_4)
, m_arg_func_5(arg_func_5)
{
}
virtual void operator ()(TO* op, u32 code) const
{
(op->*m_func)(
(T1)m_arg_func_1(code),
(T2)m_arg_func_2(code),
(T3)m_arg_func_3(code),
(T4)m_arg_func_4(code),
(T5)m_arg_func_5(code)
);
}
};
template<typename TO, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
class InstrBinder_6 : public InstrCaller<TO>
{
typedef void (TO::*func_t)(T1, T2, T3, T4, T5, T6);
func_t m_func;
const CodeFieldBase& m_arg_func_1;
const CodeFieldBase& m_arg_func_2;
const CodeFieldBase& m_arg_func_3;
const CodeFieldBase& m_arg_func_4;
const CodeFieldBase& m_arg_func_5;
const CodeFieldBase& m_arg_func_6;
public:
InstrBinder_6(func_t func,
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3,
const CodeFieldBase& arg_func_4,
const CodeFieldBase& arg_func_5,
const CodeFieldBase& arg_func_6)
: InstrCaller()
, m_func(func)
, m_arg_func_1(arg_func_1)
, m_arg_func_2(arg_func_2)
, m_arg_func_3(arg_func_3)
, m_arg_func_4(arg_func_4)
, m_arg_func_5(arg_func_5)
, m_arg_func_6(arg_func_6)
{
}
virtual void operator ()(TO* op, u32 code) const
{
(op->*m_func)(
(T1)m_arg_func_1(code),
(T2)m_arg_func_2(code),
(T3)m_arg_func_3(code),
(T4)m_arg_func_4(code),
(T5)m_arg_func_5(code),
(T6)m_arg_func_6(code)
);
}
};
template<typename TO>
InstrCaller<TO>* instr_bind(void (TO::*func)())
{
return new InstrBinder_0<TO>(func);
}
template<typename TO, typename T1>
InstrCaller<TO>* instr_bind(void (TO::*func)(T1), const CodeFieldBase& arg_func_1)
{
return new InstrBinder_1<TO, T1>(func, arg_func_1);
}
template<typename TO, typename T1, typename T2>
InstrCaller<TO>* instr_bind(void (TO::*func)(T1, T2),
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2)
{
return new InstrBinder_2<TO, T1, T2>(func, arg_func_1, arg_func_2);
}
template<typename TO, typename T1, typename T2, typename T3>
InstrCaller<TO>* instr_bind(void (TO::*func)(T1, T2, T3),
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3)
{
return new InstrBinder_3<TO, T1, T2, T3>(func, arg_func_1, arg_func_2, arg_func_3);
}
template<typename TO, typename T1, typename T2, typename T3, typename T4>
InstrCaller<TO>* instr_bind(void (TO::*func)(T1, T2, T3, T4),
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3,
const CodeFieldBase& arg_func_4)
{
return new InstrBinder_4<TO, T1, T2, T3, T4>(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4);
}
template<typename TO, typename T1, typename T2, typename T3, typename T4, typename T5>
InstrCaller<TO>* instr_bind(void (TO::*func)(T1, T2, T3, T4, T5),
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3,
const CodeFieldBase& arg_func_4,
const CodeFieldBase& arg_func_5)
{
return new InstrBinder_5<TO, T1, T2, T3, T4, T5>(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4, arg_func_5);
}
template<typename TO, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
InstrCaller<TO>* instr_bind(void (TO::*func)(T1, T2, T3, T4, T5, T6),
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3,
const CodeFieldBase& arg_func_4,
const CodeFieldBase& arg_func_5,
const CodeFieldBase& arg_func_6)
{
return new InstrBinder_6<TO, T1, T2, T3, T4, T5, T6>(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4, arg_func_5, arg_func_6);
}
template<typename TO>
class InstrBase : public InstrCaller<TO>
{
protected:
wxString m_name;
const u32 m_opcode;
CodeFieldBase** m_args;
const uint m_args_count;
public:
InstrBase(const wxString& name, int opcode, uint args_count)
: InstrCaller<TO>()
, m_name(name)
, m_opcode(opcode)
, m_args_count(args_count)
, m_args(args_count ? new CodeFieldBase*[args_count] : nullptr)
{
m_name.MakeLower().Replace("_", ".");
}
__forceinline const wxString& GetName() const
{
return m_name;
}
__forceinline const uint GetArgCount() const
{
return m_args_count;
}
__forceinline const CodeFieldBase& GetArg(uint index) const
{
assert(index < m_args_count);
return *m_args[index];
}
void operator ()(TO* op, u32 code) const
{
decode(op, code);
}
u32 operator()(const Array<u32>& args) const
{
return encode(args);
}
virtual void decode(TO* op, u32 code) const=0;
virtual u32 encode(const Array<u32>& args) const=0;
};
template<int _count, typename TO>
class InstrList : public InstrCaller<TO>
{
public:
static const int count = _count;
protected:
const CodeFieldBase& m_func;
InstrCaller<TO>* m_instrs[count];
InstrBase<TO>* m_instrs_info[count];
InstrCaller<TO>* m_error_func;
InstrCaller<TO>* m_parent;
int m_opcode;
public:
InstrList(const CodeFieldBase& func, InstrCaller<TO>* error_func)
: InstrCaller<TO>()
, m_func(func)
, m_error_func(error_func)
, m_parent(nullptr)
, m_opcode(-1)
{
for(int i=0; i<count; ++i)
{
m_instrs[i] = error_func;
}
memset(m_instrs_info, 0, sizeof(InstrBase<TO>*) * count);
}
virtual ~InstrList()
{
for(int i=0; i<count; ++i)
{
delete m_instrs[i];
}
delete m_error_func;
}
void set_parent(InstrCaller<TO>* parent, int opcode)
{
m_opcode = opcode;
m_parent = parent;
}
InstrCaller<TO>* get_parent() const
{
return m_parent;
}
u32 get_opcode() const
{
return m_opcode;
}
void set_error_func(InstrCaller<TO>* error_func)
{
for(int i=0; i<count; ++i)
{
if(m_instrs[i] == m_error_func || !m_instrs[i])
{
m_instrs[i] = error_func;
}
}
m_error_func = error_func;
}
void set_instr(uint pos, InstrCaller<TO>* func, InstrBase<TO>* info = nullptr)
{
assert(pos < count);
m_instrs[pos] = func;
m_instrs_info[pos] = info;
}
InstrCaller<TO>* get_instr(int pos) const
{
assert(pos < count);
return m_instrs[pos];
}
InstrBase<TO>* get_instr_info(int pos) const
{
assert(pos < count);
return m_instrs_info[pos];
}
u32 encode(u32 entry) const
{
return m_func[entry] | (m_parent ? (*m_parent)[m_opcode] : 0);
}
void decode(TO* op, u32 entry, u32 code) const
{
(*m_instrs[entry])(op, code);
}
virtual void operator ()(TO* op, u32 code) const
{
decode(op, m_func(code) & (count - 1), code);
}
virtual u32 operator [](u32 entry) const
{
return encode(entry);
}
};
template<int count1, int count2, typename TO>
static InstrList<count2, TO>* connect_list(InstrList<count1, TO>* parent, InstrList<count2, TO>* child, int opcode)
{
parent->set_instr(opcode, child);
child->set_parent(parent, opcode);
return child;
}
template<int count1, int count2, typename TO>
static InstrList<count2, TO>* connect_list(InstrList<count1, TO>* parent, InstrList<count2, TO>* child)
{
parent->set_error_func(child);
child->set_parent(parent->get_parent(), parent->get_opcode());
return child;
}
template<typename TO, int opcode, int count>
class Instr0 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr0(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)())
: InstrBase(name, opcode, 0)
, m_list(*list)
{
m_list.set_instr(opcode, instr_bind(func), this);
}
virtual void decode(TO* op, u32 code) const
{
m_list.decode(op, opcode, code);
}
virtual u32 encode(const Array<u32>& args) const
{
assert(args.GetCount() == m_args_count);
return m_list.encode(opcode);
}
u32 encode() const
{
return m_list.encode(opcode);
}
u32 operator()() const
{
return encode();
}
};
template<typename TO, int opcode, int count, typename T1>
class Instr1 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr1(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1),
CodeFieldBase& arg_1)
: InstrBase(name, opcode, 1)
, m_list(*list)
{
m_args[0] = &arg_1;
m_list.set_instr(opcode, instr_bind(func, arg_1), this);
}
virtual void decode(TO* op, u32 code) const
{
m_list.decode(op, opcode, code);
}
virtual u32 encode(const Array<u32>& args) const
{
assert(args.GetCount() == m_args_count);
return m_list.encode(opcode) | (*m_args[0])[args[0]];
}
u32 encode(T1 a1) const
{
return m_list.encode(opcode) | (*m_args[0])[a1];
}
u32 operator()(T1 a1) const
{
return encode(a1);
}
};
template<typename TO, int opcode, int count, typename T1, typename T2>
class Instr2 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr2(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2)
: InstrBase(name, opcode, 2)
, m_list(*list)
{
m_args[0] = &arg_1;
m_args[1] = &arg_2;
m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2), this);
}
virtual void decode(TO* op, u32 code) const
{
m_list.decode(op, opcode, code);
}
virtual u32 encode(const Array<u32>& args) const
{
assert(args.GetCount() == m_args_count);
return m_list.encode(opcode) | (*m_args[0])[args[0]] | (*m_args[1])[args[1]];
}
u32 encode(T1 a1, T2 a2) const
{
return m_list.encode(opcode) | (*m_args[0])[a1] | (*m_args[1])[a2];
}
u32 operator()(T1 a1, T2 a2) const
{
return encode(a1, a2);
}
};
template<typename TO, int opcode, int count, typename T1, typename T2, typename T3>
class Instr3 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr3(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3)
: InstrBase(name, opcode, 3)
, m_list(*list)
{
m_args[0] = &arg_1;
m_args[1] = &arg_2;
m_args[2] = &arg_3;
m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2, arg_3), this);
}
virtual void decode(TO* op, u32 code) const
{
m_list.decode(op, opcode, code);
}
virtual u32 encode(const Array<u32>& args) const
{
assert(args.GetCount() == m_args_count);
return m_list.encode(opcode) | (*m_args[0])[args[0]] | (*m_args[1])[args[1]] | (*m_args[2])[args[2]];
}
u32 encode(T1 a1, T2 a2, T3 a3) const
{
return m_list.encode(opcode) | (*m_args[0])[a1] | (*m_args[1])[a2] | (*m_args[2])[a3];
}
u32 operator()(T1 a1, T2 a2, T3 a3) const
{
return encode(a1, a2, a3);
}
};
template<typename TO, int opcode, int count, typename T1, typename T2, typename T3, typename T4>
class Instr4 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr4(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3, T4),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3,
CodeFieldBase& arg_4)
: InstrBase(name, opcode, 4)
, m_list(*list)
{
m_args[0] = &arg_1;
m_args[1] = &arg_2;
m_args[2] = &arg_3;
m_args[3] = &arg_4;
m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2, arg_3, arg_4), this);
}
virtual void decode(TO* op, u32 code) const
{
m_list.decode(op, opcode, code);
}
virtual u32 encode(const Array<u32>& args) const
{
assert(args.GetCount() == m_args_count);
return m_list.encode(opcode) |
(*m_args[0])[args[0]] |
(*m_args[1])[args[1]] |
(*m_args[2])[args[2]] |
(*m_args[3])[args[3]];
}
u32 encode(T1 a1, T2 a2, T3 a3, T4 a4) const
{
return m_list.encode(opcode) |
(*m_args[0])[a1] |
(*m_args[1])[a2] |
(*m_args[2])[a3] |
(*m_args[3])[a4];
}
u32 operator()(T1 a1, T2 a2, T3 a3, T4 a4) const
{
return encode(a1, a2, a3, a4);
}
};
template<typename TO, int opcode, int count, typename T1, typename T2, typename T3, typename T4, typename T5>
class Instr5 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr5(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3, T4, T5),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3,
CodeFieldBase& arg_4,
CodeFieldBase& arg_5)
: InstrBase(name, opcode, 5)
, m_list(*list)
{
m_args[0] = &arg_1;
m_args[1] = &arg_2;
m_args[2] = &arg_3;
m_args[3] = &arg_4;
m_args[4] = &arg_5;
m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2, arg_3, arg_4, arg_5), this);
}
virtual void decode(TO* op, u32 code) const
{
m_list.decode(op, opcode, code);
}
virtual u32 encode(const Array<u32>& args) const
{
assert(args.GetCount() == m_args_count);
return m_list.encode(opcode) |
(*m_args[0])[args[0]] |
(*m_args[1])[args[1]] |
(*m_args[2])[args[2]] |
(*m_args[3])[args[3]] |
(*m_args[4])[args[4]];
}
u32 encode(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) const
{
return m_list.encode(opcode) |
(*m_args[0])[a1] |
(*m_args[1])[a2] |
(*m_args[2])[a3] |
(*m_args[3])[a4] |
(*m_args[4])[a5];
}
u32 operator()(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) const
{
return encode(a1, a2, a3, a4, a5);
}
};
template<typename TO, int opcode, int count, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
class Instr6 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr6(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3, T4, T5, T6),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3,
CodeFieldBase& arg_4,
CodeFieldBase& arg_5,
CodeFieldBase& arg_6)
: InstrBase(name, opcode, 6)
, m_list(*list)
{
m_args[0] = &arg_1;
m_args[1] = &arg_2;
m_args[2] = &arg_3;
m_args[3] = &arg_4;
m_args[4] = &arg_5;
m_args[5] = &arg_6;
m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6), this);
}
virtual void decode(TO* op, u32 code) const
{
m_list.decode(op, opcode, code);
}
virtual u32 encode(const Array<u32>& args) const
{
assert(args.GetCount() == m_args_count);
return m_list.encode(opcode) |
(*m_args[0])[args[0]] |
(*m_args[1])[args[1]] |
(*m_args[2])[args[2]] |
(*m_args[3])[args[3]] |
(*m_args[4])[args[4]] |
(*m_args[5])[args[5]];
}
u32 encode(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T5 a6) const
{
return m_list.encode(opcode) |
(*m_args[0])[a1] |
(*m_args[1])[a2] |
(*m_args[2])[a3] |
(*m_args[3])[a4] |
(*m_args[4])[a5] |
(*m_args[5])[a6];
}
u32 operator()(T1 a1, T2 a2, T3 a3, T4 a4, T4 a5, T4 a6) const
{
return encode(a1, a2, a3, a4, a5, a6);
}
};
template<int opcode, typename TO, int count>
static Instr0<TO, opcode, count>& make_instr(InstrList<count, TO>* list, const wxString& name, void (TO::*func)())
{
return *new Instr0<TO, opcode, count>(list, name, func);
}
template<int opcode, typename TO, int count, typename T1>
static Instr1<TO, opcode, count, T1>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1),
CodeFieldBase& arg_1)
{
return *new Instr1<TO, opcode, count, T1>(list, name, func, arg_1);
}
template<int opcode, typename TO, int count, typename T1, typename T2>
static Instr2<TO, opcode, count, T1, T2>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2)
{
return *new Instr2<TO, opcode, count, T1, T2>(list, name, func, arg_1, arg_2);
}
template<int opcode, typename TO, int count, typename T1, typename T2, typename T3>
static Instr3<TO, opcode, count, T1, T2, T3>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3)
{
return *new Instr3<TO, opcode, count, T1, T2, T3>(list, name, func, arg_1, arg_2, arg_3);
}
template<int opcode, typename TO, int count, typename T1, typename T2, typename T3, typename T4>
static Instr4<TO, opcode, count, T1, T2, T3, T4>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3, T4),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3,
CodeFieldBase& arg_4)
{
return *new Instr4<TO, opcode, count, T1, T2, T3, T4>(list, name, func, arg_1, arg_2, arg_3, arg_4);
}
template<int opcode, typename TO, int count, typename T1, typename T2, typename T3, typename T4, typename T5>
static Instr5<TO, opcode, count, T1, T2, T3, T4, T5>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3, T4, T5),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3,
CodeFieldBase& arg_4,
CodeFieldBase& arg_5)
{
return *new Instr5<TO, opcode, count, T1, T2, T3, T4, T5>(list, name, func, arg_1, arg_2, arg_3, arg_4, arg_5);
}
template<int opcode, typename TO, int count, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
static Instr6<TO, opcode, count, T1, T2, T3, T4, T5, T6>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3, T4, T5, T6),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3,
CodeFieldBase& arg_4,
CodeFieldBase& arg_5,
CodeFieldBase& arg_6)
{
return *new Instr6<TO, opcode, count, T1, T2, T3, T4, T5, T6>(list, name, func, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6);
}

63
rpcs3/Emu/CPU/CPUDisAsm.h Normal file
View File

@ -0,0 +1,63 @@
#pragma once
#include "Emu/Memory/Memory.h"
enum CPUDisAsmMode
{
CPUDisAsm_DumpMode,
CPUDisAsm_InterpreterMode,
//CPUDisAsm_NormalMode,
CPUDisAsm_CompilerElfMode,
};
class CPUDisAsm
{
protected:
const CPUDisAsmMode m_mode;
virtual void Write(const wxString& value)
{
switch(m_mode)
{
case CPUDisAsm_DumpMode:
last_opcode = wxString::Format("\t%08llx:\t%02x %02x %02x %02x\t%s\n", dump_pc,
Memory.Read8(offset + dump_pc),
Memory.Read8(offset + dump_pc + 1),
Memory.Read8(offset + dump_pc + 2),
Memory.Read8(offset + dump_pc + 3), value);
break;
case CPUDisAsm_InterpreterMode:
last_opcode = wxString::Format("[%08llx] %02x %02x %02x %02x: %s", dump_pc,
Memory.Read8(offset + dump_pc),
Memory.Read8(offset + dump_pc + 1),
Memory.Read8(offset + dump_pc + 2),
Memory.Read8(offset + dump_pc + 3), value);
break;
case CPUDisAsm_CompilerElfMode:
last_opcode = value + "\n";
break;
}
}
public:
wxString last_opcode;
u64 dump_pc;
u64 offset;
protected:
CPUDisAsm(CPUDisAsmMode mode)
: m_mode(mode)
, offset(0)
{
}
virtual u32 DisAsmBranchTarget(const s32 imm)=0;
wxString FixOp(wxString op)
{
op.Append(' ', max<int>(8 - op.Len(), 0));
return op;
}
};

View File

@ -0,0 +1,34 @@
#pragma once
template<uint size, typename T> __forceinline static T sign(const T value)
{
static_assert(size > 0 && size < sizeof(T) * 8, "Bad sign size");
if(value & (T(1) << (size - 1)))
{
return value - (T(1) << size);
}
return value;
}
class CodeFieldBase
{
public:
u32 m_type;
public:
CodeFieldBase(u32 type) : m_type(type)
{
}
virtual u32 operator ()(u32 data) const=0;
virtual void operator()(u32& data, u32 value) const=0;
virtual u32 operator[](u32 value) const
{
u32 result = 0;
(*this)(result, value);
return result;
}
};

338
rpcs3/Emu/CPU/CPUThread.cpp Normal file
View File

@ -0,0 +1,338 @@
#include "stdafx.h"
#include "CPUThread.h"
CPUThread* GetCurrentCPUThread()
{
return (CPUThread*)GetCurrentNamedThread();
}
CPUThread::CPUThread(CPUThreadType type)
: ThreadBase(true, "CPUThread")
, m_type(type)
, m_stack_size(0)
, m_stack_addr(0)
, m_offset(0)
, m_prio(0)
, m_sync_wait(false)
, m_wait_thread_id(-1)
, m_free_data(false)
, m_dec(nullptr)
, m_is_step(false)
, m_is_branch(false)
{
}
CPUThread::~CPUThread()
{
Close();
}
void CPUThread::Close()
{
if(IsAlive())
{
m_free_data = true;
}
else
{
delete m_dec;
m_dec = nullptr;
}
Stop();
}
void CPUThread::Reset()
{
CloseStack();
m_sync_wait = 0;
m_wait_thread_id = -1;
SetPc(0);
cycle = 0;
m_is_branch = false;
m_status = Stopped;
m_error = 0;
DoReset();
}
void CPUThread::CloseStack()
{
if(m_stack_addr)
{
Memory.Free(m_stack_addr);
m_stack_addr = 0;
}
m_stack_size = 0;
m_stack_point = 0;
}
void CPUThread::SetId(const u32 id)
{
m_id = id;
}
void CPUThread::SetName(const wxString& name)
{
m_name = name;
}
void CPUThread::Wait(bool wait)
{
wxCriticalSectionLocker lock(m_cs_sync);
m_sync_wait = wait;
}
void CPUThread::Wait(const CPUThread& thr)
{
wxCriticalSectionLocker lock(m_cs_sync);
m_wait_thread_id = thr.GetId();
m_sync_wait = true;
}
bool CPUThread::Sync()
{
wxCriticalSectionLocker lock(m_cs_sync);
return m_sync_wait;
}
int CPUThread::ThreadStatus()
{
if(Emu.IsStopped())
{
return CPUThread_Stopped;
}
if(TestDestroy())
{
return CPUThread_Break;
}
if(m_is_step)
{
return CPUThread_Step;
}
if(Emu.IsPaused() || Sync())
{
return CPUThread_Sleeping;
}
return CPUThread_Running;
}
void CPUThread::SetEntry(const u64 pc)
{
entry = pc;
}
void CPUThread::NextPc(u8 instr_size)
{
if(m_is_branch)
{
m_is_branch = false;
SetPc(nPC);
}
else
{
PC += instr_size;
}
}
void CPUThread::SetBranch(const u64 pc)
{
if(!Memory.IsGoodAddr(m_offset + pc))
{
ConLog.Error("%s branch error: bad address 0x%llx #pc: 0x%llx", GetFName(), m_offset + pc, m_offset + PC);
Emu.Pause();
}
m_is_branch = true;
nPC = pc;
}
void CPUThread::SetPc(const u64 pc)
{
PC = pc;
}
void CPUThread::SetError(const u32 error)
{
if(error == 0)
{
m_error = 0;
}
else
{
m_error |= error;
}
}
wxArrayString CPUThread::ErrorToString(const u32 error)
{
wxArrayString earr;
if(error == 0) return earr;
earr.Add("Unknown error");
return earr;
}
void CPUThread::Run()
{
if(IsRunning()) Stop();
if(IsPaused())
{
Resume();
return;
}
wxGetApp().SendDbgCommand(DID_START_THREAD, this);
m_status = Running;
SetPc(entry);
InitStack();
InitRegs();
DoRun();
Emu.CheckStatus();
wxGetApp().SendDbgCommand(DID_STARTED_THREAD, this);
}
void CPUThread::Resume()
{
if(!IsPaused()) return;
wxGetApp().SendDbgCommand(DID_RESUME_THREAD, this);
m_status = Running;
DoResume();
Emu.CheckStatus();
ThreadBase::Start();
wxGetApp().SendDbgCommand(DID_RESUMED_THREAD, this);
}
void CPUThread::Pause()
{
if(!IsRunning()) return;
wxGetApp().SendDbgCommand(DID_PAUSE_THREAD, this);
m_status = Paused;
DoPause();
Emu.CheckStatus();
ThreadBase::Stop(false);
wxGetApp().SendDbgCommand(DID_PAUSED_THREAD, this);
}
void CPUThread::Stop()
{
if(IsStopped()) return;
wxGetApp().SendDbgCommand(DID_STOP_THREAD, this);
m_status = Stopped;
ThreadBase::Stop(false);
Reset();
DoStop();
Emu.CheckStatus();
wxGetApp().SendDbgCommand(DID_STOPED_THREAD, this);
}
void CPUThread::Exec()
{
m_is_step = false;
wxGetApp().SendDbgCommand(DID_EXEC_THREAD, this);
ThreadBase::Start();
}
void CPUThread::ExecOnce()
{
m_is_step = true;
wxGetApp().SendDbgCommand(DID_EXEC_THREAD, this);
ThreadBase::Start();
if(!ThreadBase::Wait()) while(m_is_step) Sleep(1);
wxGetApp().SendDbgCommand(DID_PAUSE_THREAD, this);
wxGetApp().SendDbgCommand(DID_PAUSED_THREAD, this);
}
void CPUThread::Task()
{
//ConLog.Write("%s enter", CPUThread::GetFName());
const Array<u64>& bp = Emu.GetBreakPoints();
try
{
for(uint i=0; i<bp.GetCount(); ++i)
{
if(bp[i] == m_offset + PC)
{
Emu.Pause();
break;
}
}
while(true)
{
int status = ThreadStatus();
if(status == CPUThread_Stopped || status == CPUThread_Break)
{
break;
}
if(status == CPUThread_Sleeping)
{
Sleep(1);
continue;
}
NextPc(m_dec->DecodeMemory(PC + m_offset));
if(status == CPUThread_Step)
{
m_is_step = false;
break;
}
for(uint i=0; i<bp.GetCount(); ++i)
{
if(bp[i] == m_offset + PC)
{
Emu.Pause();
break;
}
}
}
}
catch(const wxString& e)
{
ConLog.Error("Exception: %s", e);
}
catch(const char* e)
{
ConLog.Error("Exception: %s", e);
}
//ConLog.Write("%s leave", CPUThread::GetFName());
if(m_free_data)
{
delete m_dec;
m_dec = nullptr;
free(this);
}
}

185
rpcs3/Emu/CPU/CPUThread.h Normal file
View File

@ -0,0 +1,185 @@
#pragma once
#include "Emu/Memory/MemoryBlock.h"
#include "Emu/Cell/PPCDecoder.h"
enum CPUThreadType
{
CPU_THREAD_PPU,
CPU_THREAD_SPU,
CPU_THREAD_RAW_SPU,
CPU_THREAD_ARMv7,
};
enum CPUThreadStatus
{
CPUThread_Ready,
CPUThread_Running,
CPUThread_Paused,
CPUThread_Stopped,
CPUThread_Sleeping,
CPUThread_Break,
CPUThread_Step,
};
class CPUThread : public ThreadBase
{
protected:
u32 m_status;
u32 m_error;
u32 m_id;
u64 m_prio;
u64 m_offset;
CPUThreadType m_type;
bool m_joinable;
bool m_joining;
bool m_free_data;
bool m_is_step;
u64 m_stack_addr;
u64 m_stack_size;
u64 m_stack_point;
u32 m_exit_status;
CPUDecoder* m_dec;
public:
virtual void InitRegs()=0;
virtual void InitStack()=0;
virtual void CloseStack();
u64 GetStackAddr() const { return m_stack_addr; }
u64 GetStackSize() const { return m_stack_size; }
virtual u64 GetFreeStackSize() const=0;
void SetStackAddr(u64 stack_addr) { m_stack_addr = stack_addr; }
void SetStackSize(u64 stack_size) { m_stack_size = stack_size; }
virtual void SetArg(const uint pos, const u64 arg) = 0;
void SetId(const u32 id);
void SetName(const wxString& name);
void SetPrio(const u64 prio) { m_prio = prio; }
void SetOffset(const u64 offset) { m_offset = offset; }
void SetExitStatus(const u32 status) { m_exit_status = status; }
u64 GetOffset() const { return m_offset; }
u32 GetExitStatus() const { return m_exit_status; }
u64 GetPrio() const { return m_prio; }
wxString GetName() const { return m_name; }
wxString GetFName() const
{
return
wxString::Format("%s[%d] Thread%s",
GetTypeString(),
m_id,
(GetName().IsEmpty() ? "" : " (" + GetName() + ")")
);
}
static wxString CPUThreadTypeToString(CPUThreadType type)
{
switch(type)
{
case CPU_THREAD_PPU: return "PPU";
case CPU_THREAD_SPU: return "SPU";
case CPU_THREAD_RAW_SPU: return "RawSPU";
case CPU_THREAD_ARMv7: return "ARMv7";
}
return "Unknown";
}
wxString GetTypeString() const { return CPUThreadTypeToString(m_type); }
virtual wxString GetThreadName() const
{
return GetFName() + wxString::Format("[0x%08llx]", PC);
}
public:
u64 entry;
u64 PC;
u64 nPC;
u64 cycle;
bool m_is_branch;
protected:
CPUThread(CPUThreadType type);
public:
~CPUThread();
u32 m_wait_thread_id;
wxCriticalSection m_cs_sync;
bool m_sync_wait;
void Wait(bool wait);
void Wait(const CPUThread& thr);
bool Sync();
template<typename T>
void WaitFor(T func)
{
while(func(ThreadStatus()))
{
Sleep(1);
}
}
int ThreadStatus();
void NextPc(u8 instr_size);
void SetBranch(const u64 pc);
void SetPc(const u64 pc);
void SetEntry(const u64 entry);
void SetError(const u32 error);
static wxArrayString ErrorToString(const u32 error);
wxArrayString ErrorToString() { return ErrorToString(m_error); }
bool IsOk() const { return m_error == 0; }
bool IsRunning() const { return m_status == Running; }
bool IsPaused() const { return m_status == Paused; }
bool IsStopped() const { return m_status == Stopped; }
bool IsJoinable() const { return m_joinable; }
bool IsJoining() const { return m_joining; }
void SetJoinable(bool joinable) { m_joinable = joinable; }
void SetJoining(bool joining) { m_joining = joining; }
u32 GetError() const { return m_error; }
u32 GetId() const { return m_id; }
CPUThreadType GetType() const { return m_type; }
void Reset();
void Close();
void Run();
void Pause();
void Resume();
void Stop();
virtual void AddArgv(const wxString& arg) {}
virtual wxString RegsToString() = 0;
virtual wxString ReadRegString(wxString reg) = 0;
virtual bool WriteRegString(wxString reg, wxString value) = 0;
virtual void Exec();
void ExecOnce();
protected:
virtual void DoReset()=0;
virtual void DoRun()=0;
virtual void DoPause()=0;
virtual void DoResume()=0;
virtual void DoStop()=0;
protected:
virtual void Task();
};
CPUThread* GetCurrentCPUThread();

View File

@ -0,0 +1,111 @@
#include "stdafx.h"
#include "CPUThreadManager.h"
#include "Emu\Cell\PPUThread.h"
#include "Emu\Cell\SPUThread.h"
#include "Emu\Cell\RawSPUThread.h"
#include "Emu\ARMv7\ARMv7Thread.h"
CPUThreadManager::CPUThreadManager()
: m_raw_spu_num(0)
{
}
CPUThreadManager::~CPUThreadManager()
{
Close();
}
void CPUThreadManager::Close()
{
m_raw_spu_num = 0;
while(m_threads.GetCount()) RemoveThread(m_threads[0].GetId());
}
CPUThread& CPUThreadManager::AddThread(CPUThreadType type)
{
std::lock_guard<std::mutex> lock(m_mtx_thread);
CPUThread* new_thread;
switch(type)
{
case CPU_THREAD_PPU: new_thread = new PPUThread(); break;
case CPU_THREAD_SPU: new_thread = new SPUThread(); break;
case CPU_THREAD_RAW_SPU: new_thread = new RawSPUThread(m_raw_spu_num++); break;
case CPU_THREAD_ARMv7: new_thread = new ARMv7Thread(); break;
default: assert(0);
}
new_thread->SetId(Emu.GetIdManager().GetNewID(wxString::Format("%s Thread", new_thread->GetTypeString()), new_thread));
m_threads.Add(new_thread);
wxGetApp().SendDbgCommand(DID_CREATE_THREAD, new_thread);
return *new_thread;
}
void CPUThreadManager::RemoveThread(const u32 id)
{
std::lock_guard<std::mutex> lock(m_mtx_thread);
for(u32 i=0; i<m_threads.GetCount(); ++i)
{
if(m_threads[i].m_wait_thread_id == id)
{
m_threads[i].Wait(false);
m_threads[i].m_wait_thread_id = -1;
}
if(m_threads[i].GetId() != id) continue;
CPUThread* thr = &m_threads[i];
wxGetApp().SendDbgCommand(DID_REMOVE_THREAD, thr);
if(thr->IsAlive())
{
thr->Close();
}
else
{
thr->Close();
delete thr;
}
m_threads.RemoveFAt(i);
i--;
}
Emu.GetIdManager().RemoveID(id, false);
Emu.CheckStatus();
}
s32 CPUThreadManager::GetThreadNumById(CPUThreadType type, u32 id)
{
s32 num = 0;
for(u32 i=0; i<m_threads.GetCount(); ++i)
{
if(m_threads[i].GetId() == id) return num;
if(m_threads[i].GetType() == type) num++;
}
return -1;
}
CPUThread* CPUThreadManager::GetThread(u32 id)
{
for(u32 i=0; i<m_threads.GetCount(); ++i)
{
if(m_threads[i].GetId() == id) return &m_threads[i];
}
return nullptr;
}
void CPUThreadManager::Exec()
{
for(u32 i=0; i<m_threads.GetCount(); ++i)
{
m_threads[i].Exec();
}
}

View File

@ -0,0 +1,27 @@
#pragma once
#include "CPUThread.h"
class CPUThreadManager
{
ArrayF<CPUThread> m_threads;
std::mutex m_mtx_thread;
wxSemaphore m_sem_task;
Stack<u32> m_delete_threads;
u32 m_raw_spu_num;
public:
CPUThreadManager();
~CPUThreadManager();
void Close();
CPUThread& AddThread(CPUThreadType type);
void RemoveThread(const u32 id);
ArrayF<CPUThread>& GetThreads() { return m_threads; }
s32 GetThreadNumById(CPUThreadType type, u32 id);
CPUThread* GetThread(u32 id);
void Exec();
void Task();
};

View File

@ -0,0 +1,9 @@
#include "stdafx.h"
#include "PPCDecoder.h"
u8 PPCDecoder::DecodeMemory(const u64 address)
{
Decode(Memory.Read32(address));
return 4;
}

View File

@ -1,488 +1,15 @@
#pragma once
#include "Emu/CPU/CPUDecoder.h"
#include "PPCInstrTable.h"
#pragma warning( disable : 4800 )
template<typename TO>
class InstrCaller
class PPCDecoder : public CPUDecoder
{
public:
virtual ~InstrCaller()
{
}
virtual void operator ()(TO* op, u32 code) const = 0;
virtual u32 operator [](u32) const
{
return 0;
}
};
class PPC_Decoder
{
protected:
u32 m_code;
public:
u32 GetCode() const { return m_code; }
virtual void Decode(const u32 code)=0;
virtual u8 DecodeMemory(const u64 address);
};
template<typename TO>
class InstrBinder_0 : public InstrCaller<TO>
{
typedef void (TO::*func_t)();
func_t m_func;
public:
InstrBinder_0(func_t func)
: InstrCaller()
, m_func(func)
{
}
virtual void operator ()(TO* op, u32 code) const
{
(op->*m_func)();
}
};
template<typename TO, typename T1>
class InstrBinder_1 : public InstrCaller<TO>
{
typedef void (TO::*func_t)(T1);
func_t m_func;
const CodeFieldBase& m_arg_func_1;
public:
InstrBinder_1(func_t func, const CodeFieldBase& arg_func_1)
: InstrCaller()
, m_func(func)
, m_arg_func_1(arg_func_1)
{
}
virtual void operator ()(TO* op, u32 code) const
{
(op->*m_func)((T1)m_arg_func_1(code));
}
};
template<typename TO, typename T1, typename T2>
class InstrBinder_2 : public InstrCaller<TO>
{
typedef void (TO::*func_t)(T1, T2);
func_t m_func;
const CodeFieldBase& m_arg_func_1;
const CodeFieldBase& m_arg_func_2;
public:
InstrBinder_2(func_t func, const CodeFieldBase& arg_func_1, const CodeFieldBase& arg_func_2)
: InstrCaller()
, m_func(func)
, m_arg_func_1(arg_func_1)
, m_arg_func_2(arg_func_2)
{
}
virtual void operator ()(TO* op, u32 code) const
{
(op->*m_func)(
(T1)m_arg_func_1(code),
(T2)m_arg_func_2(code)
);
}
};
template<typename TO, typename T1, typename T2, typename T3>
class InstrBinder_3 : public InstrCaller<TO>
{
typedef void (TO::*func_t)(T1, T2, T3);
func_t m_func;
const CodeFieldBase& m_arg_func_1;
const CodeFieldBase& m_arg_func_2;
const CodeFieldBase& m_arg_func_3;
public:
InstrBinder_3(func_t func,
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3)
: InstrCaller()
, m_func(func)
, m_arg_func_1(arg_func_1)
, m_arg_func_2(arg_func_2)
, m_arg_func_3(arg_func_3)
{
}
virtual void operator ()(TO* op, u32 code) const
{
(op->*m_func)(
(T1)m_arg_func_1(code),
(T2)m_arg_func_2(code),
(T3)m_arg_func_3(code)
);
}
};
template<typename TO, typename T1, typename T2, typename T3, typename T4>
class InstrBinder_4 : public InstrCaller<TO>
{
typedef void (TO::*func_t)(T1, T2, T3, T4);
func_t m_func;
const CodeFieldBase& m_arg_func_1;
const CodeFieldBase& m_arg_func_2;
const CodeFieldBase& m_arg_func_3;
const CodeFieldBase& m_arg_func_4;
public:
InstrBinder_4(func_t func,
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3,
const CodeFieldBase& arg_func_4)
: InstrCaller()
, m_func(func)
, m_arg_func_1(arg_func_1)
, m_arg_func_2(arg_func_2)
, m_arg_func_3(arg_func_3)
, m_arg_func_4(arg_func_4)
{
}
virtual void operator ()(TO* op, u32 code) const
{
(op->*m_func)(
(T1)m_arg_func_1(code),
(T2)m_arg_func_2(code),
(T3)m_arg_func_3(code),
(T4)m_arg_func_4(code)
);
}
};
template<typename TO, typename T1, typename T2, typename T3, typename T4, typename T5>
class InstrBinder_5 : public InstrCaller<TO>
{
typedef void (TO::*func_t)(T1, T2, T3, T4, T5);
func_t m_func;
const CodeFieldBase& m_arg_func_1;
const CodeFieldBase& m_arg_func_2;
const CodeFieldBase& m_arg_func_3;
const CodeFieldBase& m_arg_func_4;
const CodeFieldBase& m_arg_func_5;
public:
InstrBinder_5(func_t func,
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3,
const CodeFieldBase& arg_func_4,
const CodeFieldBase& arg_func_5)
: InstrCaller()
, m_func(func)
, m_arg_func_1(arg_func_1)
, m_arg_func_2(arg_func_2)
, m_arg_func_3(arg_func_3)
, m_arg_func_4(arg_func_4)
, m_arg_func_5(arg_func_5)
{
}
virtual void operator ()(TO* op, u32 code) const
{
(op->*m_func)(
(T1)m_arg_func_1(code),
(T2)m_arg_func_2(code),
(T3)m_arg_func_3(code),
(T4)m_arg_func_4(code),
(T5)m_arg_func_5(code)
);
}
};
template<typename TO, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
class InstrBinder_6 : public InstrCaller<TO>
{
typedef void (TO::*func_t)(T1, T2, T3, T4, T5, T6);
func_t m_func;
const CodeFieldBase& m_arg_func_1;
const CodeFieldBase& m_arg_func_2;
const CodeFieldBase& m_arg_func_3;
const CodeFieldBase& m_arg_func_4;
const CodeFieldBase& m_arg_func_5;
const CodeFieldBase& m_arg_func_6;
public:
InstrBinder_6(func_t func,
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3,
const CodeFieldBase& arg_func_4,
const CodeFieldBase& arg_func_5,
const CodeFieldBase& arg_func_6)
: InstrCaller()
, m_func(func)
, m_arg_func_1(arg_func_1)
, m_arg_func_2(arg_func_2)
, m_arg_func_3(arg_func_3)
, m_arg_func_4(arg_func_4)
, m_arg_func_5(arg_func_5)
, m_arg_func_6(arg_func_6)
{
}
virtual void operator ()(TO* op, u32 code) const
{
(op->*m_func)(
(T1)m_arg_func_1(code),
(T2)m_arg_func_2(code),
(T3)m_arg_func_3(code),
(T4)m_arg_func_4(code),
(T5)m_arg_func_5(code),
(T6)m_arg_func_6(code)
);
}
};
template<typename TO>
InstrCaller<TO>* instr_bind(void (TO::*func)())
{
return new InstrBinder_0<TO>(func);
}
template<typename TO, typename T1>
InstrCaller<TO>* instr_bind(void (TO::*func)(T1), const CodeFieldBase& arg_func_1)
{
return new InstrBinder_1<TO, T1>(func, arg_func_1);
}
template<typename TO, typename T1, typename T2>
InstrCaller<TO>* instr_bind(void (TO::*func)(T1, T2),
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2)
{
return new InstrBinder_2<TO, T1, T2>(func, arg_func_1, arg_func_2);
}
template<typename TO, typename T1, typename T2, typename T3>
InstrCaller<TO>* instr_bind(void (TO::*func)(T1, T2, T3),
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3)
{
return new InstrBinder_3<TO, T1, T2, T3>(func, arg_func_1, arg_func_2, arg_func_3);
}
template<typename TO, typename T1, typename T2, typename T3, typename T4>
InstrCaller<TO>* instr_bind(void (TO::*func)(T1, T2, T3, T4),
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3,
const CodeFieldBase& arg_func_4)
{
return new InstrBinder_4<TO, T1, T2, T3, T4>(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4);
}
template<typename TO, typename T1, typename T2, typename T3, typename T4, typename T5>
InstrCaller<TO>* instr_bind(void (TO::*func)(T1, T2, T3, T4, T5),
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3,
const CodeFieldBase& arg_func_4,
const CodeFieldBase& arg_func_5)
{
return new InstrBinder_5<TO, T1, T2, T3, T4, T5>(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4, arg_func_5);
}
template<typename TO, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
InstrCaller<TO>* instr_bind(void (TO::*func)(T1, T2, T3, T4, T5, T6),
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3,
const CodeFieldBase& arg_func_4,
const CodeFieldBase& arg_func_5,
const CodeFieldBase& arg_func_6)
{
return new InstrBinder_6<TO, T1, T2, T3, T4, T5, T6>(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4, arg_func_5, arg_func_6);
}
template<typename TO>
class InstrBase : public InstrCaller<TO>
{
protected:
wxString m_name;
const u32 m_opcode;
CodeFieldBase** m_args;
const uint m_args_count;
public:
InstrBase(const wxString& name, int opcode, uint args_count)
: InstrCaller<TO>()
, m_name(name)
, m_opcode(opcode)
, m_args_count(args_count)
, m_args(args_count ? new CodeFieldBase*[args_count] : nullptr)
{
m_name.MakeLower().Replace("_", ".");
}
__forceinline const wxString& GetName() const
{
return m_name;
}
__forceinline const uint GetArgCount() const
{
return m_args_count;
}
__forceinline const CodeFieldBase& GetArg(uint index) const
{
assert(index < m_args_count);
return *m_args[index];
}
void operator ()(TO* op, u32 code) const
{
decode(op, code);
}
u32 operator()(const Array<u32>& args) const
{
return encode(args);
}
virtual void decode(TO* op, u32 code) const=0;
virtual u32 encode(const Array<u32>& args) const=0;
};
template<int _count, typename TO>
class InstrList : public InstrCaller<TO>
{
public:
static const int count = _count;
protected:
const CodeFieldBase& m_func;
InstrCaller<TO>* m_instrs[count];
InstrBase<TO>* m_instrs_info[count];
InstrCaller<TO>* m_error_func;
InstrCaller<TO>* m_parent;
int m_opcode;
public:
InstrList(const CodeFieldBase& func, InstrCaller<TO>* error_func)
: InstrCaller<TO>()
, m_func(func)
, m_error_func(error_func)
, m_parent(nullptr)
, m_opcode(-1)
{
for(int i=0; i<count; ++i)
{
m_instrs[i] = error_func;
}
memset(m_instrs_info, 0, sizeof(InstrBase<TO>*) * count);
}
virtual ~InstrList()
{
for(int i=0; i<count; ++i)
{
delete m_instrs[i];
}
delete m_error_func;
}
void set_parent(InstrCaller<TO>* parent, int opcode)
{
m_opcode = opcode;
m_parent = parent;
}
InstrCaller<TO>* get_parent() const
{
return m_parent;
}
u32 get_opcode() const
{
return m_opcode;
}
void set_error_func(InstrCaller<TO>* error_func)
{
for(int i=0; i<count; ++i)
{
if(m_instrs[i] == m_error_func || !m_instrs[i])
{
m_instrs[i] = error_func;
}
}
m_error_func = error_func;
}
void set_instr(uint pos, InstrCaller<TO>* func, InstrBase<TO>* info = nullptr)
{
assert(pos < count);
m_instrs[pos] = func;
m_instrs_info[pos] = info;
}
InstrCaller<TO>* get_instr(int pos) const
{
assert(pos < count);
return m_instrs[pos];
}
InstrBase<TO>* get_instr_info(int pos) const
{
assert(pos < count);
return m_instrs_info[pos];
}
u32 encode(u32 entry) const
{
return m_func[entry] | (m_parent ? (*m_parent)[m_opcode] : 0);
}
void decode(TO* op, u32 entry, u32 code) const
{
(*m_instrs[entry])(op, code);
}
virtual void operator ()(TO* op, u32 code) const
{
decode(op, m_func(code) & (count - 1), code);
}
virtual u32 operator [](u32 entry) const
{
return encode(entry);
}
};
template<int count1, int count2, typename TO>
static InstrList<count2, TO>* connect_list(InstrList<count1, TO>* parent, InstrList<count2, TO>* child, int opcode)
{
parent->set_instr(opcode, child);
child->set_parent(parent, opcode);
return child;
}
template<int count1, int count2, typename TO>
static InstrList<count2, TO>* connect_list(InstrList<count1, TO>* parent, InstrList<count2, TO>* child)
{
parent->set_error_func(child);
child->set_parent(parent->get_parent(), parent->get_opcode());
return child;
}
template<typename TO, uint from, uint to>
static InstrList<1 << CodeField<from, to>::size, TO>* new_list(const CodeField<from, to>& func, InstrCaller<TO>* error_func = nullptr)
@ -500,403 +27,4 @@ template<int count, typename TO, uint from, uint to>
static InstrList<1 << CodeField<from, to>::size, TO>* new_list(InstrList<count, TO>* parent, const CodeField<from, to>& func, InstrCaller<TO>* error_func = nullptr)
{
return connect_list(parent, new InstrList<1 << CodeField<from, to>::size, TO>(func, error_func));
}
template<typename TO, int opcode, int count>
class Instr0 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr0(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)())
: InstrBase(name, opcode, 0)
, m_list(*list)
{
m_list.set_instr(opcode, instr_bind(func), this);
}
virtual void decode(TO* op, u32 code) const
{
m_list.decode(op, opcode, code);
}
virtual u32 encode(const Array<u32>& args) const
{
assert(args.GetCount() == m_args_count);
return m_list.encode(opcode);
}
u32 encode() const
{
return m_list.encode(opcode);
}
u32 operator()() const
{
return encode();
}
};
template<typename TO, int opcode, int count, typename T1>
class Instr1 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr1(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1),
CodeFieldBase& arg_1)
: InstrBase(name, opcode, 1)
, m_list(*list)
{
m_args[0] = &arg_1;
m_list.set_instr(opcode, instr_bind(func, arg_1), this);
}
virtual void decode(TO* op, u32 code) const
{
m_list.decode(op, opcode, code);
}
virtual u32 encode(const Array<u32>& args) const
{
assert(args.GetCount() == m_args_count);
return m_list.encode(opcode) | (*m_args[0])[args[0]];
}
u32 encode(T1 a1) const
{
return m_list.encode(opcode) | (*m_args[0])[a1];
}
u32 operator()(T1 a1) const
{
return encode(a1);
}
};
template<typename TO, int opcode, int count, typename T1, typename T2>
class Instr2 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr2(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2)
: InstrBase(name, opcode, 2)
, m_list(*list)
{
m_args[0] = &arg_1;
m_args[1] = &arg_2;
m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2), this);
}
virtual void decode(TO* op, u32 code) const
{
m_list.decode(op, opcode, code);
}
virtual u32 encode(const Array<u32>& args) const
{
assert(args.GetCount() == m_args_count);
return m_list.encode(opcode) | (*m_args[0])[args[0]] | (*m_args[1])[args[1]];
}
u32 encode(T1 a1, T2 a2) const
{
return m_list.encode(opcode) | (*m_args[0])[a1] | (*m_args[1])[a2];
}
u32 operator()(T1 a1, T2 a2) const
{
return encode(a1, a2);
}
};
template<typename TO, int opcode, int count, typename T1, typename T2, typename T3>
class Instr3 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr3(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3)
: InstrBase(name, opcode, 3)
, m_list(*list)
{
m_args[0] = &arg_1;
m_args[1] = &arg_2;
m_args[2] = &arg_3;
m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2, arg_3), this);
}
virtual void decode(TO* op, u32 code) const
{
m_list.decode(op, opcode, code);
}
virtual u32 encode(const Array<u32>& args) const
{
assert(args.GetCount() == m_args_count);
return m_list.encode(opcode) | (*m_args[0])[args[0]] | (*m_args[1])[args[1]] | (*m_args[2])[args[2]];
}
u32 encode(T1 a1, T2 a2, T3 a3) const
{
return m_list.encode(opcode) | (*m_args[0])[a1] | (*m_args[1])[a2] | (*m_args[2])[a3];
}
u32 operator()(T1 a1, T2 a2, T3 a3) const
{
return encode(a1, a2, a3);
}
};
template<typename TO, int opcode, int count, typename T1, typename T2, typename T3, typename T4>
class Instr4 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr4(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3, T4),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3,
CodeFieldBase& arg_4)
: InstrBase(name, opcode, 4)
, m_list(*list)
{
m_args[0] = &arg_1;
m_args[1] = &arg_2;
m_args[2] = &arg_3;
m_args[3] = &arg_4;
m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2, arg_3, arg_4), this);
}
virtual void decode(TO* op, u32 code) const
{
m_list.decode(op, opcode, code);
}
virtual u32 encode(const Array<u32>& args) const
{
assert(args.GetCount() == m_args_count);
return m_list.encode(opcode) |
(*m_args[0])[args[0]] |
(*m_args[1])[args[1]] |
(*m_args[2])[args[2]] |
(*m_args[3])[args[3]];
}
u32 encode(T1 a1, T2 a2, T3 a3, T4 a4) const
{
return m_list.encode(opcode) |
(*m_args[0])[a1] |
(*m_args[1])[a2] |
(*m_args[2])[a3] |
(*m_args[3])[a4];
}
u32 operator()(T1 a1, T2 a2, T3 a3, T4 a4) const
{
return encode(a1, a2, a3, a4);
}
};
template<typename TO, int opcode, int count, typename T1, typename T2, typename T3, typename T4, typename T5>
class Instr5 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr5(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3, T4, T5),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3,
CodeFieldBase& arg_4,
CodeFieldBase& arg_5)
: InstrBase(name, opcode, 5)
, m_list(*list)
{
m_args[0] = &arg_1;
m_args[1] = &arg_2;
m_args[2] = &arg_3;
m_args[3] = &arg_4;
m_args[4] = &arg_5;
m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2, arg_3, arg_4, arg_5), this);
}
virtual void decode(TO* op, u32 code) const
{
m_list.decode(op, opcode, code);
}
virtual u32 encode(const Array<u32>& args) const
{
assert(args.GetCount() == m_args_count);
return m_list.encode(opcode) |
(*m_args[0])[args[0]] |
(*m_args[1])[args[1]] |
(*m_args[2])[args[2]] |
(*m_args[3])[args[3]] |
(*m_args[4])[args[4]];
}
u32 encode(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) const
{
return m_list.encode(opcode) |
(*m_args[0])[a1] |
(*m_args[1])[a2] |
(*m_args[2])[a3] |
(*m_args[3])[a4] |
(*m_args[4])[a5];
}
u32 operator()(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) const
{
return encode(a1, a2, a3, a4, a5);
}
};
template<typename TO, int opcode, int count, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
class Instr6 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr6(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3, T4, T5, T6),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3,
CodeFieldBase& arg_4,
CodeFieldBase& arg_5,
CodeFieldBase& arg_6)
: InstrBase(name, opcode, 6)
, m_list(*list)
{
m_args[0] = &arg_1;
m_args[1] = &arg_2;
m_args[2] = &arg_3;
m_args[3] = &arg_4;
m_args[4] = &arg_5;
m_args[5] = &arg_6;
m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6), this);
}
virtual void decode(TO* op, u32 code) const
{
m_list.decode(op, opcode, code);
}
virtual u32 encode(const Array<u32>& args) const
{
assert(args.GetCount() == m_args_count);
return m_list.encode(opcode) |
(*m_args[0])[args[0]] |
(*m_args[1])[args[1]] |
(*m_args[2])[args[2]] |
(*m_args[3])[args[3]] |
(*m_args[4])[args[4]] |
(*m_args[5])[args[5]];
}
u32 encode(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T5 a6) const
{
return m_list.encode(opcode) |
(*m_args[0])[a1] |
(*m_args[1])[a2] |
(*m_args[2])[a3] |
(*m_args[3])[a4] |
(*m_args[4])[a5] |
(*m_args[5])[a6];
}
u32 operator()(T1 a1, T2 a2, T3 a3, T4 a4, T4 a5, T4 a6) const
{
return encode(a1, a2, a3, a4, a5, a6);
}
};
template<int opcode, typename TO, int count>
static Instr0<TO, opcode, count>& make_instr(InstrList<count, TO>* list, const wxString& name, void (TO::*func)())
{
return *new Instr0<TO, opcode, count>(list, name, func);
}
template<int opcode, typename TO, int count, typename T1>
static Instr1<TO, opcode, count, T1>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1),
CodeFieldBase& arg_1)
{
return *new Instr1<TO, opcode, count, T1>(list, name, func, arg_1);
}
template<int opcode, typename TO, int count, typename T1, typename T2>
static Instr2<TO, opcode, count, T1, T2>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2)
{
return *new Instr2<TO, opcode, count, T1, T2>(list, name, func, arg_1, arg_2);
}
template<int opcode, typename TO, int count, typename T1, typename T2, typename T3>
static Instr3<TO, opcode, count, T1, T2, T3>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3)
{
return *new Instr3<TO, opcode, count, T1, T2, T3>(list, name, func, arg_1, arg_2, arg_3);
}
template<int opcode, typename TO, int count, typename T1, typename T2, typename T3, typename T4>
static Instr4<TO, opcode, count, T1, T2, T3, T4>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3, T4),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3,
CodeFieldBase& arg_4)
{
return *new Instr4<TO, opcode, count, T1, T2, T3, T4>(list, name, func, arg_1, arg_2, arg_3, arg_4);
}
template<int opcode, typename TO, int count, typename T1, typename T2, typename T3, typename T4, typename T5>
static Instr5<TO, opcode, count, T1, T2, T3, T4, T5>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3, T4, T5),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3,
CodeFieldBase& arg_4,
CodeFieldBase& arg_5)
{
return *new Instr5<TO, opcode, count, T1, T2, T3, T4, T5>(list, name, func, arg_1, arg_2, arg_3, arg_4, arg_5);
}
template<int opcode, typename TO, int count, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
static Instr6<TO, opcode, count, T1, T2, T3, T4, T5, T6>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3, T4, T5, T6),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3,
CodeFieldBase& arg_4,
CodeFieldBase& arg_5,
CodeFieldBase& arg_6)
{
return *new Instr6<TO, opcode, count, T1, T2, T3, T4, T5, T6>(list, name, func, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6);
}

View File

@ -1,80 +1,18 @@
#pragma once
#include "Emu/CPU/CPUDisAsm.h"
#include "Gui/DisAsmFrame.h"
#include "Emu/Memory/Memory.h"
enum DisAsmModes
{
DumpMode,
InterpreterMode,
NormalMode,
CompilerElfMode,
};
class PPC_DisAsm
class PPCDisAsm : public CPUDisAsm
{
protected:
DisAsmFrame* disasm_frame;
const DisAsmModes m_mode;
virtual void Write(const wxString value)
PPCDisAsm(CPUDisAsmMode mode) : CPUDisAsm(mode)
{
switch(m_mode)
{
case DumpMode:
{
wxString mem = wxString::Format("\t%08llx:\t", dump_pc);
for(u8 i=0; i < 4; ++i)
{
mem += wxString::Format("%02x", Memory.Read8(dump_pc + i));
if(i < 3) mem += " ";
}
last_opcode = mem + "\t" + value + "\n";
}
break;
case InterpreterMode:
{
last_opcode = wxString::Format("[%08llx] %02x %02x %02x %02x: %s", dump_pc,
Memory.Read8(offset + dump_pc),
Memory.Read8(offset + dump_pc + 1),
Memory.Read8(offset + dump_pc + 2),
Memory.Read8(offset + dump_pc + 3), value);
}
break;
case CompilerElfMode: last_opcode = value + "\n"; break;
default: if(disasm_frame) disasm_frame->AddLine(value); break;
}
}
public:
wxString last_opcode;
u64 dump_pc;
u64 offset;
protected:
PPC_DisAsm(PPCThread& cpu, DisAsmModes mode = NormalMode)
: m_mode(mode)
, disasm_frame(NULL)
, offset(0)
{
if(m_mode != NormalMode) return;
disasm_frame = new DisAsmFrame(cpu);
disasm_frame->Show();
}
virtual u32 DisAsmBranchTarget(const s32 imm)=0;
wxString FixOp(wxString op)
{
op.Append(' ', max<int>(8 - op.Len(), 0));
return op;
}
void DisAsm_V4(const wxString& op, u32 v0, u32 v1, u32 v2, u32 v3)
{
Write(wxString::Format("%s v%d,v%d,v%d,v%d", FixOp(op), v0, v1, v2, v3));
@ -153,7 +91,7 @@ protected:
}
void DisAsm_F1_R2(const wxString& op, u32 f0, u32 r0, u32 r1)
{
if(m_mode == CompilerElfMode)
if(m_mode == CPUDisAsm_CompilerElfMode)
{
Write(wxString::Format("%s f%d,r%d,r%d", FixOp(op), f0, r0, r1));
return;
@ -163,7 +101,7 @@ protected:
}
void DisAsm_F1_IMM_R1_RC(const wxString& op, u32 f0, s32 imm0, u32 r0, bool rc)
{
if(m_mode == CompilerElfMode)
if(m_mode == CPUDisAsm_CompilerElfMode)
{
Write(wxString::Format("%s%s f%d,r%d,%d #%x", FixOp(op), rc ? "." : "", f0, r0, imm0, imm0));
return;
@ -241,7 +179,7 @@ protected:
}
void DisAsm_R2_IMM(const wxString& op, u32 r0, u32 r1, s32 imm0)
{
if(m_mode == CompilerElfMode)
if(m_mode == CPUDisAsm_CompilerElfMode)
{
Write(wxString::Format("%s r%d,r%d,%d #%x", FixOp(op), r0, r1, imm0, imm0));
return;

View File

@ -1,16 +1,5 @@
#pragma once
template<uint size, typename T> __forceinline static T sign(const T value)
{
static_assert(size > 0 && size < sizeof(T) * 8, "Bad size");
static const T sub_value = T(1) << size;
if(value & (T(1) << (size - 1)))
{
return value - sub_value;
}
return value;
}
#include "Emu/CPU/CPUInstrTable.h"
enum CodeFieldType
{
@ -22,27 +11,6 @@ enum CodeFieldType
FIELD_BRANCH,
};
class CodeFieldBase
{
public:
CodeFieldType m_type;
public:
CodeFieldBase(CodeFieldType type = FIELD_IMM) : m_type(type)
{
}
virtual u32 operator ()(u32 data) const=0;
virtual void operator()(u32& data, u32 value) const=0;
virtual u32 operator[](u32 value) const
{
u32 result = 0;
(*this)(result, value);
return result;
}
};
template<uint from, uint to=from>
class CodeField : public CodeFieldBase
{

View File

@ -4,21 +4,17 @@
PPCThread* GetCurrentPPCThread()
{
return (PPCThread*)GetCurrentNamedThread();
CPUThread* thread = GetCurrentCPUThread();
if(!thread || (thread->GetType() != CPU_THREAD_PPU && thread->GetType() != CPU_THREAD_SPU && thread->GetType() != CPU_THREAD_RAW_SPU))
{
throw wxString("GetCurrentPPCThread: bad thread");
}
return (PPCThread*)thread;
}
PPCThread::PPCThread(PPCThreadType type)
: ThreadBase(true, "PPCThread")
, m_type(type)
, DisAsmFrame(nullptr)
, m_dec(nullptr)
, stack_size(0)
, stack_addr(0)
, m_prio(0)
, m_offset(0)
, m_sync_wait(false)
, m_wait_thread_id(-1)
, m_free_data(false)
PPCThread::PPCThread(CPUThreadType type) : CPUThread(type)
{
}
@ -27,323 +23,24 @@ PPCThread::~PPCThread()
Close();
}
void PPCThread::Close()
void PPCThread::DoReset()
{
if(IsAlive())
{
m_free_data = true;
}
if(DisAsmFrame)
{
DisAsmFrame->Close();
DisAsmFrame = nullptr;
}
Stop();
}
void PPCThread::Reset()
{
CloseStack();
m_sync_wait = 0;
m_wait_thread_id = -1;
memset(m_args, 0, sizeof(u64) * 4);
SetPc(0);
cycle = 0;
isBranch = false;
m_status = Stopped;
m_error = 0;
DoReset();
}
void PPCThread::InitStack()
{
if(stack_addr) return;
if(stack_size == 0) stack_size = 0x10000;
stack_addr = Memory.StackMem.Alloc(Memory.AlignAddr(stack_size, 0x100));
if(m_stack_addr) return;
if(m_stack_size == 0) m_stack_size = 0x10000;
m_stack_addr = Memory.StackMem.Alloc(Memory.AlignAddr(m_stack_size, 0x100));
stack_point = stack_addr + stack_size;
m_stack_point = m_stack_addr + m_stack_size;
/*
stack_point += stack_size - 0x10;
stack_point &= -0x10;
Memory.Write64(stack_point, 0);
stack_point -= 0x60;
Memory.Write64(stack_point, stack_point + 0x60);
m_stack_point += m_stack_size - 0x10;
m_stack_point &= -0x10;
Memory.Write64(m_stack_point, 0);
m_stack_point -= 0x60;
Memory.Write64(m_stack_point, m_stack_point + 0x60);
*/
if(wxFileExists("stack.dat"))
{
ConLog.Warning("loading stack.dat...");
wxFile stack("stack.dat");
stack.Read(Memory.GetMemFromAddr(stack_addr), 0x10000);
stack.Close();
}
}
void PPCThread::CloseStack()
{
Memory.Free(stack_addr);
stack_addr = 0;
stack_size = 0;
}
void PPCThread::SetId(const u32 id)
{
m_id = id;
}
void PPCThread::SetName(const wxString& name)
{
m_name = name;
}
void PPCThread::Wait(bool wait)
{
wxCriticalSectionLocker lock(m_cs_sync);
m_sync_wait = wait;
}
void PPCThread::Wait(const PPCThread& thr)
{
wxCriticalSectionLocker lock(m_cs_sync);
m_wait_thread_id = thr.GetId();
m_sync_wait = true;
}
bool PPCThread::Sync()
{
wxCriticalSectionLocker lock(m_cs_sync);
return m_sync_wait;
}
int PPCThread::ThreadStatus()
{
if(Emu.IsStopped())
{
return PPCThread_Stopped;
}
if(TestDestroy())
{
return PPCThread_Break;
}
if(Emu.IsPaused() || Sync())
{
return PPCThread_Sleeping;
}
return PPCThread_Running;
}
void PPCThread::NextBranchPc()
{
SetPc(nPC);
}
void PPCThread::NextPc()
{
if(isBranch)
{
NextBranchPc();
isBranch = false;
return;
}
SetPc(PC + 4);
}
void PPCThread::PrevPc()
{
SetPc(PC - 4);
}
void PPCThread::SetPc(const u64 pc)
{
PC = pc;
nPC = PC + 4;
}
void PPCThread::SetEntry(const u64 pc)
{
entry = pc;
}
void PPCThread::SetBranch(const u64 pc)
{
if(!Memory.IsGoodAddr(m_offset + pc))
{
ConLog.Error("%s branch error: bad address 0x%llx #pc: 0x%llx", GetFName(), m_offset+ pc, m_offset + PC);
Emu.Pause();
}
nPC = pc;
isBranch = true;
}
void PPCThread::SetError(const u32 error)
{
if(error == 0)
{
m_error = 0;
}
else
{
m_error |= error;
}
}
wxArrayString PPCThread::ErrorToString(const u32 error)
{
wxArrayString earr;
if(error == 0) return earr;
earr.Add("Unknown error");
return earr;
}
void PPCThread::Run()
{
if(IsRunning()) Stop();
if(IsPaused())
{
Resume();
return;
}
wxGetApp().SendDbgCommand(DID_START_THREAD, this);
m_status = Running;
SetPc(entry);
InitStack();
InitRegs();
DoRun();
Emu.CheckStatus();
wxGetApp().SendDbgCommand(DID_STARTED_THREAD, this);
}
void PPCThread::Resume()
{
if(!IsPaused()) return;
wxGetApp().SendDbgCommand(DID_RESUME_THREAD, this);
m_status = Running;
DoResume();
Emu.CheckStatus();
ThreadBase::Start();
wxGetApp().SendDbgCommand(DID_RESUMED_THREAD, this);
}
void PPCThread::Pause()
{
if(!IsRunning()) return;
wxGetApp().SendDbgCommand(DID_PAUSE_THREAD, this);
m_status = Paused;
DoPause();
Emu.CheckStatus();
ThreadBase::Stop(false);
wxGetApp().SendDbgCommand(DID_PAUSED_THREAD, this);
}
void PPCThread::Stop()
{
if(IsStopped()) return;
wxGetApp().SendDbgCommand(DID_STOP_THREAD, this);
m_status = Stopped;
ThreadBase::Stop(false);
Reset();
DoStop();
Emu.CheckStatus();
wxGetApp().SendDbgCommand(DID_STOPED_THREAD, this);
}
void PPCThread::Exec()
{
wxGetApp().SendDbgCommand(DID_EXEC_THREAD, this);
ThreadBase::Start();
//std::thread thr(std::bind(std::mem_fn(&PPCThread::Task), this));
}
void PPCThread::ExecOnce()
{
DoCode(Memory.Read32(m_offset + PC));
NextPc();
}
void PPCThread::Task()
{
//ConLog.Write("%s enter", PPCThread::GetFName());
const Array<u64>& bp = Emu.GetBreakPoints();
try
{
for(uint i=0; i<bp.GetCount(); ++i)
{
if(bp[i] == m_offset + PC)
{
Emu.Pause();
break;
}
}
while(true)
{
int status = ThreadStatus();
if(status == PPCThread_Stopped || status == PPCThread_Break)
{
break;
}
if(status == PPCThread_Sleeping)
{
Sleep(1);
continue;
}
DoCode(Memory.Read32(m_offset + PC));
NextPc();
for(uint i=0; i<bp.GetCount(); ++i)
{
if(bp[i] == m_offset + PC)
{
Emu.Pause();
break;
}
}
}
}
catch(const wxString& e)
{
ConLog.Error("Exception: %s", e);
}
catch(const char* e)
{
ConLog.Error("Exception: %s", e);
}
//ConLog.Write("%s leave", PPCThread::GetFName());
if(m_free_data)
free(this);
}

View File

@ -1,184 +1,33 @@
#pragma once
#include "Emu/Memory/MemoryBlock.h"
#include "Emu/CPU/CPUThread.h"
#include "Emu/Cell/PPCDecoder.h"
enum PPCThreadType
{
PPC_THREAD_PPU,
PPC_THREAD_SPU,
PPC_THREAD_RAW_SPU,
};
enum PPCThreadStatus
{
PPCThread_Ready,
PPCThread_Running,
PPCThread_Paused,
PPCThread_Stopped,
PPCThread_Sleeping,
PPCThread_Break,
};
class PPCThread : public ThreadBase
class PPCThread : public CPUThread
{
protected:
u32 m_status;
u32 m_error;
PPC_Decoder* m_dec;
wxWindow* DisAsmFrame;
u32 m_id;
PPCThreadType m_type;
u64 m_args[4];
u64 m_prio;
bool m_joinable;
bool m_joining;
Array<u64> argv_addr;
u64 m_offset;
u32 m_exit_status;
bool m_free_data;
Array<u64> m_argv_addr;
public:
u64 stack_size;
u64 stack_addr;
u64 stack_point;
virtual void InitRegs()=0;
virtual void InitStack();
virtual void CloseStack();
virtual u64 GetStackAddr() const { return stack_addr; }
virtual u64 GetStackSize() const { return stack_size; }
virtual u64 GetFreeStackSize() const=0;
void SetArg(const uint pos, const u64 arg) { assert(pos < 4); m_args[pos] = arg; }
void SetId(const u32 id);
void SetName(const wxString& name);
void SetPrio(const u64 prio) { m_prio = prio; }
void SetOffset(const u64 offset) { m_offset = offset; }
void SetExitStatus(const u32 status) { m_exit_status = status; }
u64 GetOffset() const { return m_offset; }
u32 GetExitStatus() const { return m_exit_status; }
u64 GetPrio() const { return m_prio; }
wxString GetName() const { return m_name; }
wxString GetFName() const
{
return
wxString::Format("%s[%d] Thread%s",
GetTypeString(),
m_id,
(GetName().IsEmpty() ? "" : " (" + GetName() + ")")
);
}
static wxString PPCThreadTypeToString(PPCThreadType type)
{
switch(type)
{
case PPC_THREAD_PPU: return "PPU";
case PPC_THREAD_SPU: return "SPU";
case PPC_THREAD_RAW_SPU: return "RawSPU";
}
return "Unknown";
}
wxString GetTypeString() const { return PPCThreadTypeToString(m_type); }
virtual void SetArg(const uint pos, const u64 arg) { assert(pos < 4); m_args[pos] = arg; }
virtual wxString GetThreadName() const
{
return GetFName() + wxString::Format("[0x%08llx]", PC);
}
public:
bool isBranch;
u64 entry;
u64 PC;
u64 nPC;
u64 cycle;
protected:
PPCThread(PPCThreadType type);
PPCThread(CPUThreadType type);
public:
~PPCThread();
u32 m_wait_thread_id;
wxCriticalSection m_cs_sync;
bool m_sync_wait;
void Wait(bool wait);
void Wait(const PPCThread& thr);
bool Sync();
template<typename T>
void WaitFor(T func)
{
while(func(ThreadStatus()))
{
Sleep(1);
}
}
int ThreadStatus();
void NextPc();
void NextBranchPc();
void PrevPc();
void SetBranch(const u64 pc);
void SetPc(const u64 pc);
void SetEntry(const u64 entry);
void SetError(const u32 error);
static wxArrayString ErrorToString(const u32 error);
wxArrayString ErrorToString() { return ErrorToString(m_error); }
bool IsOk() const { return m_error == 0; }
bool IsRunning() const { return m_status == Running; }
bool IsPaused() const { return m_status == Paused; }
bool IsStopped() const { return m_status == Stopped; }
bool IsJoinable() const { return m_joinable; }
bool IsJoining() const { return m_joining; }
void SetJoinable(bool joinable) { m_joinable = joinable; }
void SetJoining(bool joining) { m_joining = joining; }
u32 GetError() const { return m_error; }
u32 GetId() const { return m_id; }
PPCThreadType GetType() const { return m_type; }
void Reset();
void Close();
void Run();
void Pause();
void Resume();
void Stop();
virtual wxString RegsToString() { return wxEmptyString; }
virtual wxString ReadRegString(wxString reg) { return wxEmptyString; }
virtual bool WriteRegString(wxString reg, wxString value) { return false; }
virtual void Exec();
void ExecOnce();
virtual void AddArgv(const wxString& arg) {}
protected:
virtual void DoReset()=0;
virtual void DoRun()=0;
virtual void DoPause()=0;
virtual void DoResume()=0;
virtual void DoStop()=0;
public:
virtual void Task();
private:
virtual void DoCode(const s32 code)=0;
virtual void DoReset() override;
};
PPCThread* GetCurrentPPCThread();

View File

@ -4,18 +4,17 @@
#include "Emu/Cell/PPCDecoder.h"
#include "PPUInstrTable.h"
class PPU_Decoder : public PPC_Decoder
class PPUDecoder : public PPCDecoder
{
PPU_Opcodes* m_op;
PPUOpcodes* m_op;
public:
PPU_Decoder(PPU_Opcodes& op) : m_op(&op)
PPUDecoder(PPUOpcodes& op) : m_op(&op)
{
}
~PPU_Decoder()
~PPUDecoder()
{
m_op->Exit();
delete m_op;
}

View File

@ -6,41 +6,243 @@
#include "Gui/DisAsmFrame.h"
#include "Emu/Memory/Memory.h"
class PPU_DisAsm
: public PPU_Opcodes
, public PPC_DisAsm
class PPUDisAsm
: public PPUOpcodes
, public PPCDisAsm
{
public:
PPCThread& CPU;
PPU_DisAsm()
: PPC_DisAsm(*(PPCThread*)NULL, DumpMode)
, CPU(*(PPCThread*)NULL)
{
}
PPU_DisAsm(PPCThread& cpu, DisAsmModes mode = NormalMode)
: PPC_DisAsm(cpu, mode)
, CPU(cpu)
{
}
~PPU_DisAsm()
PPUDisAsm(CPUDisAsmMode mode) : PPCDisAsm(mode)
{
}
private:
void Exit()
{
if(m_mode == NormalMode && !disasm_frame->exit)
{
disasm_frame->Close();
}
}
u32 DisAsmBranchTarget(const s32 imm)
{
return branchTarget(m_mode == NormalMode ? CPU.PC : dump_pc, imm);
return branchTarget(dump_pc, imm);
}
private:
void DisAsm_V4(const wxString& op, u32 v0, u32 v1, u32 v2, u32 v3)
{
Write(wxString::Format("%s v%d,v%d,v%d,v%d", FixOp(op), v0, v1, v2, v3));
}
void DisAsm_V3_UIMM(const wxString& op, u32 v0, u32 v1, u32 v2, u32 uimm)
{
Write(wxString::Format("%s v%d,v%d,v%d,%u #%x", FixOp(op), v0, v1, v2, uimm, uimm));
}
void DisAsm_V3(const wxString& op, u32 v0, u32 v1, u32 v2)
{
Write(wxString::Format("%s v%d,v%d,v%d", FixOp(op), v0, v1, v2));
}
void DisAsm_V2_UIMM(const wxString& op, u32 v0, u32 v1, u32 uimm)
{
Write(wxString::Format("%s v%d,v%d,%u #%x", FixOp(op), v0, v1, uimm, uimm));
}
void DisAsm_V2(const wxString& op, u32 v0, u32 v1)
{
Write(wxString::Format("%s v%d,v%d", FixOp(op), v0, v1));
}
void DisAsm_V1_SIMM(const wxString& op, u32 v0, s32 simm)
{
Write(wxString::Format("%s v%d,%d #%x", FixOp(op), v0, simm, simm));
}
void DisAsm_V1(const wxString& op, u32 v0)
{
Write(wxString::Format("%s v%d", FixOp(op), v0));
}
void DisAsm_V1_R2(const wxString& op, u32 v0, u32 r1, u32 r2)
{
Write(wxString::Format("%s v%d,r%d,r%d", FixOp(op), v0, r1, r2));
}
void DisAsm_CR1_F2_RC(const wxString& op, u32 cr0, u32 f0, u32 f1, bool rc)
{
Write(wxString::Format("%s%s cr%d,f%d,f%d", FixOp(op), rc ? "." : "", cr0, f0, f1));
}
void DisAsm_CR1_F2(const wxString& op, u32 cr0, u32 f0, u32 f1)
{
DisAsm_CR1_F2_RC(op, cr0, f0, f1, false);
}
void DisAsm_INT1_R2(const wxString& op, u32 i0, u32 r0, u32 r1)
{
Write(wxString::Format("%s %d,r%d,r%d", FixOp(op), i0, r0, r1));
}
void DisAsm_INT1_R1_IMM(const wxString& op, u32 i0, u32 r0, s32 imm0)
{
Write(wxString::Format("%s %d,r%d,%d #%x", FixOp(op), i0, r0, imm0, imm0));
}
void DisAsm_INT1_R1_RC(const wxString& op, u32 i0, u32 r0, bool rc)
{
Write(wxString::Format("%s%s %d,r%d", FixOp(op), rc ? "." : "", i0, r0));
}
void DisAsm_INT1_R1(const wxString& op, u32 i0, u32 r0)
{
DisAsm_INT1_R1_RC(op, i0, r0, false);
}
void DisAsm_F4_RC(const wxString& op, u32 f0, u32 f1, u32 f2, u32 f3, bool rc)
{
Write(wxString::Format("%s%s f%d,f%d,f%d,f%d", FixOp(op), rc ? "." : "", f0, f1, f2, f3));
}
void DisAsm_F3_RC(const wxString& op, u32 f0, u32 f1, u32 f2, bool rc)
{
Write(wxString::Format("%s%s f%d,f%d,f%d", FixOp(op), rc ? "." : "", f0, f1, f2));
}
void DisAsm_F3(const wxString& op, u32 f0, u32 f1, u32 f2)
{
DisAsm_F3_RC(op, f0, f1, f2, false);
}
void DisAsm_F2_RC(const wxString& op, u32 f0, u32 f1, bool rc)
{
Write(wxString::Format("%s%s f%d,f%d", FixOp(op), rc ? "." : "", f0, f1));
}
void DisAsm_F2(const wxString& op, u32 f0, u32 f1)
{
DisAsm_F2_RC(op, f0, f1, false);
}
void DisAsm_F1_R2(const wxString& op, u32 f0, u32 r0, u32 r1)
{
if(m_mode == CPUDisAsm_CompilerElfMode)
{
Write(wxString::Format("%s f%d,r%d,r%d", FixOp(op), f0, r0, r1));
return;
}
Write(wxString::Format("%s f%d,r%d(r%d)", FixOp(op), f0, r0, r1));
}
void DisAsm_F1_IMM_R1_RC(const wxString& op, u32 f0, s32 imm0, u32 r0, bool rc)
{
if(m_mode == CPUDisAsm_CompilerElfMode)
{
Write(wxString::Format("%s%s f%d,r%d,%d #%x", FixOp(op), rc ? "." : "", f0, r0, imm0, imm0));
return;
}
Write(wxString::Format("%s%s f%d,%d(r%d) #%x", FixOp(op), rc ? "." : "", f0, imm0, r0, imm0));
}
void DisAsm_F1_IMM_R1(const wxString& op, u32 f0, s32 imm0, u32 r0)
{
DisAsm_F1_IMM_R1_RC(op, f0, imm0, r0, false);
}
void DisAsm_F1_RC(const wxString& op, u32 f0, bool rc)
{
Write(wxString::Format("%s%s f%d", FixOp(op), rc ? "." : "", f0));
}
void DisAsm_R1_RC(const wxString& op, u32 r0, bool rc)
{
Write(wxString::Format("%s%s r%d", FixOp(op), rc ? "." : "", r0));
}
void DisAsm_R1(const wxString& op, u32 r0)
{
DisAsm_R1_RC(op, r0, false);
}
void DisAsm_R2_OE_RC(const wxString& op, u32 r0, u32 r1, u32 oe, bool rc)
{
Write(wxString::Format("%s%s%s r%d,r%d", FixOp(op), oe ? "o" : "", rc ? "." : "", r0, r1));
}
void DisAsm_R2_RC(const wxString& op, u32 r0, u32 r1, bool rc)
{
DisAsm_R2_OE_RC(op, r0, r1, false, rc);
}
void DisAsm_R2(const wxString& op, u32 r0, u32 r1)
{
DisAsm_R2_RC(op, r0, r1, false);
}
void DisAsm_R3_OE_RC(const wxString& op, u32 r0, u32 r1, u32 r2, u32 oe, bool rc)
{
Write(wxString::Format("%s%s%s r%d,r%d,r%d", FixOp(op), oe ? "o" : "", rc ? "." : "", r0, r1, r2));
}
void DisAsm_R3_INT2_RC(const wxString& op, u32 r0, u32 r1, u32 r2, s32 i0, s32 i1, bool rc)
{
Write(wxString::Format("%s%s r%d,r%d,r%d,%d,%d", FixOp(op), rc ? "." : "", r0, r1, r2, i0, i1));
}
void DisAsm_R3_RC(const wxString& op, u32 r0, u32 r1, u32 r2, bool rc)
{
DisAsm_R3_OE_RC(op, r0, r1, r2, false, rc);
}
void DisAsm_R3(const wxString& op, u32 r0, u32 r1, u32 r2)
{
DisAsm_R3_RC(op, r0, r1, r2, false);
}
void DisAsm_R2_INT3_RC(const wxString& op, u32 r0, u32 r1, s32 i0, s32 i1, s32 i2, bool rc)
{
Write(wxString::Format("%s%s r%d,r%d,%d,%d,%d", FixOp(op), rc ? "." : "", r0, r1, i0, i1, i2));
}
void DisAsm_R2_INT3(const wxString& op, u32 r0, u32 r1, s32 i0, s32 i1, s32 i2)
{
DisAsm_R2_INT3_RC(op, r0, r1, i0, i1, i2, false);
}
void DisAsm_R2_INT2_RC(const wxString& op, u32 r0, u32 r1, s32 i0, s32 i1, bool rc)
{
Write(wxString::Format("%s%s r%d,r%d,%d,%d", FixOp(op), rc ? "." : "", r0, r1, i0, i1));
}
void DisAsm_R2_INT2(const wxString& op, u32 r0, u32 r1, s32 i0, s32 i1)
{
DisAsm_R2_INT2_RC(op, r0, r1, i0, i1, false);
}
void DisAsm_R2_INT1_RC(const wxString& op, u32 r0, u32 r1, s32 i0, bool rc)
{
Write(wxString::Format("%s%s r%d,r%d,%d", FixOp(op), rc ? "." : "", r0, r1, i0));
}
void DisAsm_R2_INT1(const wxString& op, u32 r0, u32 r1, s32 i0)
{
DisAsm_R2_INT1_RC(op, r0, r1, i0, false);
}
void DisAsm_R2_IMM(const wxString& op, u32 r0, u32 r1, s32 imm0)
{
if(m_mode == CPUDisAsm_CompilerElfMode)
{
Write(wxString::Format("%s r%d,r%d,%d #%x", FixOp(op), r0, r1, imm0, imm0));
return;
}
Write(wxString::Format("%s r%d,%d(r%d) #%x", FixOp(op), r0, imm0, r1, imm0));
}
void DisAsm_R1_IMM(const wxString& op, u32 r0, s32 imm0)
{
Write(wxString::Format("%s r%d,%d #%x", FixOp(op), r0, imm0, imm0));
}
void DisAsm_IMM_R1(const wxString& op, s32 imm0, u32 r0)
{
Write(wxString::Format("%s %d,r%d #%x", FixOp(op), imm0, r0, imm0));
}
void DisAsm_CR1_R1_IMM(const wxString& op, u32 cr0, u32 r0, s32 imm0)
{
Write(wxString::Format("%s cr%d,r%d,%d #%x", FixOp(op), cr0, r0, imm0, imm0));
}
void DisAsm_CR1_R2_RC(const wxString& op, u32 cr0, u32 r0, u32 r1, bool rc)
{
Write(wxString::Format("%s%s cr%d,r%d,r%d", FixOp(op), rc ? "." : "", cr0, r0, r1));
}
void DisAsm_CR1_R2(const wxString& op, u32 cr0, u32 r0, u32 r1)
{
DisAsm_CR1_R2_RC(op, cr0, r0, r1, false);
}
void DisAsm_CR2(const wxString& op, u32 cr0, u32 cr1)
{
Write(wxString::Format("%s cr%d,cr%d", FixOp(op), cr0, cr1));
}
void DisAsm_INT3(const wxString& op, const int i0, const int i1, const int i2)
{
Write(wxString::Format("%s %d,%d,%d", FixOp(op), i0, i1, i2));
}
void DisAsm_INT1(const wxString& op, const int i0)
{
Write(wxString::Format("%s %d", FixOp(op), i0));
}
void DisAsm_BRANCH(const wxString& op, const int pc)
{
Write(wxString::Format("%s 0x%x", FixOp(op), DisAsmBranchTarget(pc)));
}
void DisAsm_BRANCH_A(const wxString& op, const int pc)
{
Write(wxString::Format("%s 0x%x", FixOp(op), pc));
}
void DisAsm_B2_BRANCH(const wxString& op, u32 b0, u32 b1, const int pc)
{
Write(wxString::Format("%s %d,%d,0x%x ", FixOp(op), b0, b1, DisAsmBranchTarget(pc)));
}
void DisAsm_CR_BRANCH(const wxString& op, u32 cr, const int pc)
{
Write(wxString::Format("%s cr%d,0x%x ", FixOp(op), cr, DisAsmBranchTarget(pc)));
}
private:
@ -738,7 +940,7 @@ private:
}
void BC(u32 bo, u32 bi, s32 bd, u32 aa, u32 lk)
{
if(m_mode == CompilerElfMode)
if(m_mode == CPUDisAsm_CompilerElfMode)
{
Write(wxString::Format("bc 0x%x, 0x%x, 0x%x, %d, %d", bo, bi, bd, aa, lk));
return;
@ -844,7 +1046,7 @@ private:
}
void B(s32 ll, u32 aa, u32 lk)
{
if(m_mode == CompilerElfMode)
if(m_mode == CPUDisAsm_CompilerElfMode)
{
Write(wxString::Format("b 0x%x, %d, %d", ll, aa, lk));
return;

View File

@ -203,20 +203,20 @@ namespace PPU_instr
static CodeField<9, 10> STRM;
static auto main_list = new_list(OPCD, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, OPCD));
static auto main_list = new_list(OPCD, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, OPCD));
static auto g04_list = new_list(main_list, PPU_opcodes::G_04, GD_04);
static auto g04_0_list = new_list(g04_list, GD_04_0, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_04_0));
static auto g13_list = new_list(main_list, PPU_opcodes::G_13, GD_13, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_13));
static auto g1e_list = new_list(main_list, PPU_opcodes::G_1e, GD_1e, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_1e));
static auto g1f_list = new_list(main_list, PPU_opcodes::G_1f, GD_1f, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_1f));
static auto g3a_list = new_list(main_list, PPU_opcodes::G_3a, GD_3a, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_3a));
static auto g3b_list = new_list(main_list, PPU_opcodes::G_3b, GD_3b, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_3b));
static auto g3e_list = new_list(main_list, PPU_opcodes::G_3e, GD_3e, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_3e));
static auto g04_0_list = new_list(g04_list, GD_04_0, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_04_0));
static auto g13_list = new_list(main_list, PPU_opcodes::G_13, GD_13, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_13));
static auto g1e_list = new_list(main_list, PPU_opcodes::G_1e, GD_1e, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_1e));
static auto g1f_list = new_list(main_list, PPU_opcodes::G_1f, GD_1f, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_1f));
static auto g3a_list = new_list(main_list, PPU_opcodes::G_3a, GD_3a, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_3a));
static auto g3b_list = new_list(main_list, PPU_opcodes::G_3b, GD_3b, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_3b));
static auto g3e_list = new_list(main_list, PPU_opcodes::G_3e, GD_3e, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_3e));
static auto g3f_list = new_list(main_list, PPU_opcodes::G_3f, GD_3f);
static auto g3f_0_list = new_list(g3f_list, GD_3f_0, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_3f_0));
static auto g3f_0_list = new_list(g3f_list, GD_3f_0, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_3f_0));
#define bind_instr(list, name, ...) \
static const auto& name = make_instr<PPU_opcodes::name>(list, #name, &PPU_Opcodes::name, ##__VA_ARGS__)
static const auto& name = make_instr<PPU_opcodes::name>(list, #name, &PPUOpcodes::name, ##__VA_ARGS__)
bind_instr(main_list, TDI, TO, RA, simm16);
bind_instr(main_list, TWI, TO, RA, simm16);

View File

@ -45,13 +45,13 @@ u64 rotr64(const u64 x, const u8 n) { return (x >> n) | (x << (64 - n)); }
#define rotl64 _rotl64
#define rotr64 _rotr64
class PPU_Interpreter : public PPU_Opcodes
class PPUInterpreter : public PPUOpcodes
{
private:
PPUThread& CPU;
public:
PPU_Interpreter(PPUThread& cpu) : CPU(cpu)
PPUInterpreter(PPUThread& cpu) : CPU(cpu)
{
InitRotateMask();
}
@ -61,7 +61,7 @@ private:
void SysCall()
{
CPU.DoSyscall(CPU.GPR[11]);
SysCalls::DoSyscall(CPU.GPR[11]);
if(enable_log)
ConLog.Warning("SysCall[%lld] done with code [0x%llx]! #pc: 0x%llx", CPU.GPR[11], CPU.GPR[3], CPU.PC);

View File

@ -428,11 +428,9 @@ namespace PPU_opcodes
};
}
class PPU_Opcodes
class PPUOpcodes
{
public:
virtual void Exit()=0;
static u64 branchTarget(const u64 pc, const u64 imm)
{
return pc + (imm & ~0x3ULL);

View File

@ -362,7 +362,7 @@ void CompilePPUProgram::DetectArgInfo(Arg& arg)
return;
}
if(GetInstruction<PPU_Opcodes>(str))
if(GetInstruction<PPUOpcodes>(str))
{
arg.type = ARG_INSTR;
return;
@ -1397,17 +1397,9 @@ void CompilePPUProgram::Compile()
LoadArgs();
auto instr = GetInstruction<PPU_Opcodes>(op);
auto instr = GetInstruction<PPUOpcodes>(op);
if(instr)
{
/*
FIELD_IMM,
FIELD_R_GPR,
FIELD_R_FPR,
FIELD_R_VPR,
FIELD_R_CR,
FIELD_BRANCH,
*/
uint type[] =
{
ARG_IMM,

View File

@ -10,14 +10,12 @@ PPUThread& GetCurrentPPUThread()
{
PPCThread* thread = GetCurrentPPCThread();
if(!thread || thread->GetType() != PPC_THREAD_PPU) throw wxString("GetCurrentPPUThread: bad thread");
if(!thread || thread->GetType() != CPU_THREAD_PPU) throw wxString("GetCurrentPPUThread: bad thread");
return *(PPUThread*)thread;
}
PPUThread::PPUThread()
: PPCThread(PPC_THREAD_PPU)
, SysCalls(*this)
PPUThread::PPUThread() : PPCThread(CPU_THREAD_PPU)
{
Reset();
}
@ -29,6 +27,8 @@ PPUThread::~PPUThread()
void PPUThread::DoReset()
{
PPCThread::DoReset();
//reset regs
memset(VPR, 0, sizeof(VPR));
memset(FPR, 0, sizeof(FPR));
@ -52,10 +52,10 @@ void PPUThread::DoReset()
void PPUThread::AddArgv(const wxString& arg)
{
stack_point -= arg.Len() + 1;
stack_point = Memory.AlignAddr(stack_point, 0x10) - 0x10;
argv_addr.AddCpy(stack_point);
Memory.WriteString(stack_point, arg);
m_stack_point -= arg.Len() + 1;
m_stack_point = Memory.AlignAddr(m_stack_point, 0x10) - 0x10;
m_argv_addr.AddCpy(m_stack_point);
Memory.WriteString(m_stack_point, arg);
}
void PPUThread::InitRegs()
@ -88,9 +88,9 @@ void PPUThread::InitRegs()
}
*/
stack_point = Memory.AlignAddr(stack_point, 0x200) - 0x200;
m_stack_point = Memory.AlignAddr(m_stack_point, 0x200) - 0x200;
GPR[1] = stack_point;
GPR[1] = m_stack_point;
GPR[2] = rtoc;
for(int i=4; i<32; ++i)
@ -99,14 +99,14 @@ void PPUThread::InitRegs()
GPR[i] = (i+1) * 0x10000;
}
if(argv_addr.GetCount())
if(m_argv_addr.GetCount())
{
u64 argc = argv_addr.GetCount();
stack_point -= 0xc + 4 * argc;
u64 argv = stack_point;
u64 argc = m_argv_addr.GetCount();
m_stack_point -= 0xc + 4 * argc;
u64 argv = m_stack_point;
mem64_ptr_t argv_list(argv);
for(int i=0; i<argc; ++i) argv_list += argv_addr[i];
for(int i=0; i<argc; ++i) argv_list += m_argv_addr[i];
GPR[3] = argc;
GPR[4] = argv;
@ -149,12 +149,12 @@ void PPUThread::DoRun()
switch(Ini.CPUDecoderMode.GetValue())
{
case 0:
m_dec = new PPU_Decoder(*new PPU_DisAsm(*this));
//m_dec = new PPUDecoder(*new PPUDisAsm());
break;
case 1:
case 2:
m_dec = new PPU_Decoder(*new PPU_Interpreter(*this));
m_dec = new PPUDecoder(*new PPUInterpreter(*this));
break;
}
}
@ -178,43 +178,6 @@ void PPUThread::DoStop()
bool dump_enable = false;
void PPUThread::DoCode(const s32 code)
{
#ifdef _DEBUG
static bool is_last_enabled = false;
if(dump_enable)
{
static wxFile f("dump.txt", wxFile::write);
static PPU_DisAsm disasm(*this, DumpMode);
static PPU_Decoder decoder(disasm);
if(!is_last_enabled)
{
f.Write(RegsToString() + "\n");
}
disasm.dump_pc = PC;
decoder.Decode(code);
f.Write(disasm.last_opcode);
is_last_enabled = true;
}
else
{
is_last_enabled = false;
}
#endif
if(++cycle > 220)
{
cycle = 0;
TB++;
}
m_dec->Decode(code);
}
bool FPRdouble::IsINF(PPCdouble d)
{
return ((u64&)d & 0x7FFFFFFFFFFFFFFFULL) == 0x7FF0000000000000ULL;

View File

@ -511,9 +511,7 @@ union VPR_reg
static const s32 MAX_INT_VALUE = 0x7fffffff;
class PPUThread
: public PPCThread
, public SysCalls
class PPUThread : public PPCThread
{
public:
PPCdouble FPR[32]; //Floating Point Register
@ -727,7 +725,7 @@ public:
virtual wxString RegsToString()
{
wxString ret = PPCThread::RegsToString();
wxString ret;
for(uint i=0; i<32; ++i) ret += wxString::Format("GPR[%d] = 0x%llx\n", i, GPR[i]);
for(uint i=0; i<32; ++i) ret += wxString::Format("FPR[%d] = %.6G\n", i, FPR[i]);
@ -768,6 +766,7 @@ public:
if (reg == "CTR") return wxString::Format("%016llx", CTR);
if (reg == "XER") return wxString::Format("%016llx", XER);
if (reg == "FPSCR") return wxString::Format("%08x", FPSCR);
return wxEmptyString;
}
@ -828,9 +827,6 @@ protected:
virtual void DoPause();
virtual void DoResume();
virtual void DoStop();
public:
virtual void DoCode(const s32 code);
};
PPUThread& GetCurrentPPUThread();

View File

@ -1,51 +1,259 @@
#include "stdafx.h"
#include "Emu/Cell/RawSPUThread.h"
RawSPUThread::RawSPUThread(PPCThreadType type) : SPUThread(type)
RawSPUThread::RawSPUThread(u32 index, CPUThreadType type)
: SPUThread(type)
, m_index(index)
{
Memory.MemoryBlocks.Add(MemoryBlock::SetRange(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index, RAW_SPU_OFFSET));
Reset();
}
RawSPUThread::~RawSPUThread()
{
MemoryBlock::Delete();
}
bool RawSPUThread::Read8(const u64 addr, u8* value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Read8(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
ConLog.Error("RawSPUThread[%d]: Read8(0x%x)", m_index, offset);
Emu.Pause();
return false;
}
bool RawSPUThread::Read16(const u64 addr, u16* value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Read16(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
ConLog.Error("RawSPUThread[%d]: Read16(0x%x)", m_index, offset);
Emu.Pause();
return false;
}
bool RawSPUThread::Read32(const u64 addr, u32* value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Read32(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
switch(offset)
{
case MFC_LSA_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_LSA)", m_index); *value = MFC.LSA.GetValue(); break;
case MFC_EAH_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_EAH)", m_index); *value = MFC.EAH.GetValue(); break;
case MFC_EAL_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_EAL)", m_index); *value = MFC.EAL.GetValue(); break;
case MFC_Size_Tag_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_Size_Tag)", m_index); *value = MFC.Size_Tag.GetValue(); break;
case MFC_CMDStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_CMDStatus)", m_index); *value = MFC.CMDStatus.GetValue(); break;
case MFC_QStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_QStatus)", m_index); *value = MFC.QStatus.GetValue(); break;
case Prxy_QueryType_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_QueryType)", m_index); *value = Prxy.QueryType.GetValue(); break;
case Prxy_QueryMask_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_QueryMask)", m_index); *value = Prxy.QueryMask.GetValue(); break;
case Prxy_TagStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_TagStatus)", m_index); *value = Prxy.TagStatus.GetValue(); break;
case SPU_Out_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Out_MBox)", m_index); *value = SPU.Out_MBox.GetValue(); break;
case SPU_In_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_In_MBox)", m_index); *value = SPU.In_MBox.GetValue(); break;
case SPU_MBox_Status_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_MBox_Status)", m_index); *value = SPU.MBox_Status.GetValue(); break;
case SPU_RunCntl_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RunCntl)", m_index); *value = SPU.RunCntl.GetValue(); break;
case SPU_Status_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Status)", m_index); *value = SPU.Status.GetValue(); break;
case SPU_NPC_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_NPC)", m_index); *value = SPU.NPC.GetValue(); break;
case SPU_RdSigNotify1_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RdSigNotify1)", m_index); *value = SPU.RdSigNotify1.GetValue(); break;
case SPU_RdSigNotify2_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RdSigNotify2)", m_index); *value = SPU.RdSigNotify2.GetValue(); break;
default:
ConLog.Error("RawSPUThread[%d]: Read32(0x%x)", m_index, offset);
Emu.Pause();
break;
}
return true;
}
bool RawSPUThread::Read64(const u64 addr, u64* value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Read64(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
ConLog.Error("RawSPUThread[%d]: Read64(0x%x)", m_index, offset);
Emu.Pause();
return false;
}
bool RawSPUThread::Read128(const u64 addr, u128* value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Read128(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
ConLog.Error("RawSPUThread[%d]: Read128(0x%x)", m_index, offset);
Emu.Pause();
return false;
}
bool RawSPUThread::Write8(const u64 addr, const u8 value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Write8(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
ConLog.Error("RawSPUThread[%d]: Write8(0x%x, 0x%x)", m_index, offset, value);
Emu.Pause();
return false;
}
bool RawSPUThread::Write16(const u64 addr, const u16 value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Write16(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
ConLog.Error("RawSPUThread[%d]: Write16(0x%x, 0x%x)", m_index, offset, value);
Emu.Pause();
return false;
}
bool RawSPUThread::Write32(const u64 addr, const u32 value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Write32(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
switch(offset)
{
case MFC_LSA_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_LSA, 0x%x)", m_index, value); MFC.LSA.SetValue(value); break;
case MFC_EAH_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_EAH, 0x%x)", m_index, value); MFC.EAH.SetValue(value); break;
case MFC_EAL_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_EAL, 0x%x)", m_index, value); MFC.EAL.SetValue(value); break;
case MFC_Size_Tag_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_Size_Tag, 0x%x)", m_index, value); MFC.Size_Tag.SetValue(value); break;
case MFC_CMDStatus_offs:
{
ConLog.Warning("RawSPUThread[%d]: Write32(MFC_CMDStatus, 0x%x)", m_index, value);
MFC.CMDStatus.SetValue(value);
u16 op = value & MFC_MASK_CMD;
switch(op)
{
case MFC_PUT_CMD:
case MFC_GET_CMD:
{
u32 lsa = MFC.LSA.GetValue();
u64 ea = (u64)MFC.EAL.GetValue() | ((u64)MFC.EAH.GetValue() << 32);
u32 size_tag = MFC.Size_Tag.GetValue();
u16 tag = (u16)size_tag;
u16 size = size_tag >> 16;
ConLog.Warning("RawSPUThread[%d]: DMA %s:", m_index, op == MFC_PUT_CMD ? "PUT" : "GET");
ConLog.Warning("*** lsa = 0x%x", lsa);
ConLog.Warning("*** ea = 0x%llx", ea);
ConLog.Warning("*** tag = 0x%x", tag);
ConLog.Warning("*** size = 0x%x", size);
ConLog.SkipLn();
MFC.CMDStatus.SetValue(dmac.Cmd(value, tag, lsa, ea, size));
}
break;
default:
ConLog.Error("RawSPUThread[%d]: Unknown MFC cmd. (opcode=0x%x, cmd=0x%x)", m_index, op, value);
break;
}
}
break;
case MFC_QStatus_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_QStatus, 0x%x)", m_index, value); MFC.QStatus.SetValue(value); break;
case Prxy_QueryType_offs:
{
ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_QueryType, 0x%x)", m_index, value);
Prxy.QueryType.SetValue(value);
switch(value)
{
case 2:
ConLog.Warning("RawSPUThread[%d]: Prxy Query Immediate.", m_index);
break;
default:
ConLog.Error("RawSPUThread[%d]: Unknown Prxy Query Type. (prxy_query=0x%x)", m_index, value);
break;
}
Prxy.QueryType.SetValue(0);
MFC.QStatus.SetValue(Prxy.QueryMask.GetValue());
}
break;
case Prxy_QueryMask_offs: ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_QueryMask, 0x%x)", m_index, value); Prxy.QueryMask.SetValue(value); break;
case Prxy_TagStatus_offs: ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_TagStatus, 0x%x)", m_index, value); Prxy.TagStatus.SetValue(value); break;
case SPU_Out_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_Out_MBox, 0x%x)", m_index, value); SPU.Out_MBox.SetValue(value); break;
case SPU_In_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_In_MBox, 0x%x)", m_index, value); SPU.In_MBox.SetValue(value); break;
case SPU_MBox_Status_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_MBox_Status, 0x%x)", m_index, value); SPU.MBox_Status.SetValue(value); break;
case SPU_RunCntl_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_RunCntl, 0x%x)", m_index, value); SPU.RunCntl.SetValue(value); break;
case SPU_Status_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_Status, 0x%x)", m_index, value); SPU.Status.SetValue(value); break;
case SPU_NPC_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_NPC, 0x%x)", m_index, value); SPU.NPC.SetValue(value); break;
case SPU_RdSigNotify1_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_RdSigNotify1, 0x%x)", m_index, value); SPU.RdSigNotify1.SetValue(value); break;
case SPU_RdSigNotify2_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_RdSigNotify2, 0x%x)", m_index, value); SPU.RdSigNotify2.SetValue(value); break;
default:
ConLog.Error("RawSPUThread[%d]: Write32(0x%x, 0x%x)", m_index, offset, value);
Emu.Pause();
break;
}
return true;
}
bool RawSPUThread::Write64(const u64 addr, const u64 value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Write64(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
ConLog.Error("RawSPUThread[%d]: Write64(0x%x, 0x%llx)", m_index, offset, value);
Emu.Pause();
return false;
}
bool RawSPUThread::Write128(const u64 addr, const u128 value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Write128(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
ConLog.Error("RawSPUThread[%d]: Write128(0x%x, 0x%llx_%llx)", m_index, offset, value._u64[1], value._u64[0]);
Emu.Pause();
return false;
}
void RawSPUThread::InitRegs()
{
GPR[3]._u64[1] = m_args[0];
GPR[4]._u64[1] = m_args[1];
GPR[5]._u64[1] = m_args[2];
GPR[6]._u64[1] = m_args[3];
m_offset = GetStartAddr() + RAW_SPU_LS_OFFSET;
SPUThread::InitRegs();
}
u32 num = Emu.GetCPU().GetThreadNumById(GetType(), GetId());
m_offset = RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * num + RAW_SPU_LS_OFFSET;
mfc.dmac.ls_offset = m_offset;
mfc.dmac.proxy_pos = 0;
mfc.dmac.queue_pos = 0;
mfc.MFC_LSA.SetAddr(GetRawSPURegAddrByNum(num, MFC_LSA_offs));
mfc.MFC_EAH.SetAddr(GetRawSPURegAddrByNum(num, MFC_EAH_offs));
mfc.MFC_EAL.SetAddr(GetRawSPURegAddrByNum(num, MFC_EAL_offs));
mfc.MFC_Size_Tag.SetAddr(GetRawSPURegAddrByNum(num, MFC_Size_Tag_offs));
mfc.MFC_CMDStatus.SetAddr(GetRawSPURegAddrByNum(num, MFC_CMDStatus_offs));
mfc.MFC_QStatus.SetAddr(GetRawSPURegAddrByNum(num, MFC_QStatus_offs));
mfc.Prxy_QueryType.SetAddr(GetRawSPURegAddrByNum(num, Prxy_QueryType_offs));
mfc.Prxy_QueryMask.SetAddr(GetRawSPURegAddrByNum(num, Prxy_QueryMask_offs));
mfc.Prxy_TagStatus.SetAddr(GetRawSPURegAddrByNum(num, Prxy_TagStatus_offs));
mfc.SPU_Out_MBox.SetAddr(GetRawSPURegAddrByNum(num, SPU_Out_MBox_offs));
mfc.SPU_In_MBox.SetAddr(GetRawSPURegAddrByNum(num, SPU_In_MBox_offs));
mfc.SPU_MBox_Status.SetAddr(GetRawSPURegAddrByNum(num, SPU_MBox_Status_offs));
mfc.SPU_RunCntl.SetAddr(GetRawSPURegAddrByNum(num, SPU_RunCntl_offs));
mfc.SPU_Status.SetAddr(GetRawSPURegAddrByNum(num, SPU_Status_offs));
mfc.SPU_NPC.SetAddr(GetRawSPURegAddrByNum(num, SPU_NPC_offs));
mfc.SPU_RdSigNotify1.SetAddr(GetRawSPURegAddrByNum(num, SPU_RdSigNotify1_offs));
mfc.SPU_RdSigNotify2.SetAddr(GetRawSPURegAddrByNum(num, SPU_RdSigNotify2_offs));
mfc.SPU_RunCntl.SetValue(SPU_RUNCNTL_STOP);
mfc.SPU_Status.SetValue(SPU_STATUS_RUNNING);
mfc.Prxy_QueryType.SetValue(0);
mfc.MFC_CMDStatus.SetValue(0);
PC = mfc.SPU_NPC.GetValue();
u32 RawSPUThread::GetIndex() const
{
return m_index;
}
void RawSPUThread::Task()
@ -70,27 +278,25 @@ void RawSPUThread::Task()
{
int status = ThreadStatus();
if(status == PPCThread_Stopped || status == PPCThread_Break)
if(status == CPUThread_Stopped || status == CPUThread_Break)
{
break;
}
if(status == PPCThread_Sleeping)
if(status == CPUThread_Sleeping)
{
Sleep(1);
continue;
}
mfc.Handle();
if(mfc.SPU_RunCntl.GetValue() != SPU_RUNCNTL_RUNNABLE)
if(SPU.RunCntl.GetValue() != SPU_RUNCNTL_RUNNABLE)
{
if(!is_last_paused)
{
if(is_last_paused = mfc.SPU_RunCntl.GetValue() != SPU_RUNCNTL_RUNNABLE)
if(is_last_paused = SPU.RunCntl.GetValue() != SPU_RUNCNTL_RUNNABLE)
{
mfc.SPU_NPC.SetValue(PC);
mfc.SPU_Status.SetValue(SPU_STATUS_WAITING_FOR_CHANNEL);
SPU.NPC.SetValue(PC);
SPU.Status.SetValue(SPU_STATUS_WAITING_FOR_CHANNEL);
}
}
@ -101,12 +307,11 @@ void RawSPUThread::Task()
if(is_last_paused)
{
is_last_paused = false;
PC = mfc.SPU_NPC.GetValue();
mfc.SPU_Status.SetValue(SPU_STATUS_RUNNING);
PC = SPU.NPC.GetValue();
SPU.Status.SetValue(SPU_STATUS_RUNNING);
}
DoCode(Memory.Read32(m_offset + PC));
NextPc();
NextPc(m_dec->DecodeMemory(PC + m_offset));
for(uint i=0; i<bp.GetCount(); ++i)
{
@ -128,4 +333,4 @@ void RawSPUThread::Task()
}
ConLog.Write("%s leave", PPCThread::GetFName());
}
}

View File

@ -39,30 +39,34 @@ __forceinline static u32 GetRawSPURegAddrByNum(int num, int offset)
__forceinline static u32 GetRawSPURegAddrById(int id, int offset)
{
return GetRawSPURegAddrByNum(Emu.GetCPU().GetThreadNumById(PPC_THREAD_RAW_SPU, id), offset);
return GetRawSPURegAddrByNum(Emu.GetCPU().GetThreadNumById(CPU_THREAD_RAW_SPU, id), offset);
}
class RawSPUThread : public SPUThread
class RawSPUThread
: public SPUThread
, public MemoryBlock
{
u32 m_index;
public:
RawSPUThread(PPCThreadType type = PPC_THREAD_RAW_SPU);
RawSPUThread(u32 index, CPUThreadType type = CPU_THREAD_RAW_SPU);
~RawSPUThread();
virtual u8 ReadLS8 (const u32 lsa) const { return Memory.Read8 (lsa + (m_offset & 0x3fffc)); }
virtual u16 ReadLS16 (const u32 lsa) const { return Memory.Read16 (lsa + m_offset); }
virtual u32 ReadLS32 (const u32 lsa) const { return Memory.Read32 (lsa + m_offset); }
virtual u64 ReadLS64 (const u32 lsa) const { return Memory.Read64 (lsa + m_offset); }
virtual u128 ReadLS128(const u32 lsa) const { return Memory.Read128(lsa + m_offset); }
virtual bool Read8(const u64 addr, u8* value) override;
virtual bool Read16(const u64 addr, u16* value) override;
virtual bool Read32(const u64 addr, u32* value) override;
virtual bool Read64(const u64 addr, u64* value) override;
virtual bool Read128(const u64 addr, u128* value) override;
virtual void WriteLS8 (const u32 lsa, const u8& data) const { Memory.Write8 (lsa + m_offset, data); }
virtual void WriteLS16 (const u32 lsa, const u16& data) const { Memory.Write16 (lsa + m_offset, data); }
virtual void WriteLS32 (const u32 lsa, const u32& data) const { Memory.Write32 (lsa + m_offset, data); }
virtual void WriteLS64 (const u32 lsa, const u64& data) const { Memory.Write64 (lsa + m_offset, data); }
virtual void WriteLS128(const u32 lsa, const u128& data) const { Memory.Write128(lsa + m_offset, data); }
virtual bool Write8(const u64 addr, const u8 value) override;
virtual bool Write16(const u64 addr, const u16 value) override;
virtual bool Write32(const u64 addr, const u32 value) override;
virtual bool Write64(const u64 addr, const u64 value) override;
virtual bool Write128(const u64 addr, const u128 value) override;
public:
virtual void InitRegs();
u32 GetIndex() const;
private:
virtual void Task();

View File

@ -4,18 +4,17 @@
#include "Emu/Cell/PPCDecoder.h"
#include "Emu/Cell/SPUInstrtable.h"
class SPU_Decoder : public PPC_Decoder
class SPUDecoder : public PPCDecoder
{
SPU_Opcodes* m_op;
SPUOpcodes* m_op;
public:
SPU_Decoder(SPU_Opcodes& op) : m_op(&op)
SPUDecoder(SPUOpcodes& op) : m_op(&op)
{
}
~SPU_Decoder()
~SPUDecoder()
{
m_op->Exit();
delete m_op;
}

View File

@ -6,43 +6,23 @@
#include "Gui/DisAsmFrame.h"
#include "Emu/Memory/Memory.h"
class SPU_DisAsm
: public SPU_Opcodes
, public PPC_DisAsm
class SPUDisAsm
: public SPUOpcodes
, public PPCDisAsm
{
public:
PPCThread& CPU;
SPU_DisAsm()
: PPC_DisAsm(*(PPCThread*)NULL, DumpMode)
, CPU(*(PPCThread*)NULL)
SPUDisAsm(CPUDisAsmMode mode) : PPCDisAsm(mode)
{
}
SPU_DisAsm(PPCThread& cpu, DisAsmModes mode = NormalMode)
: PPC_DisAsm(cpu, mode)
, CPU(cpu)
{
}
~SPU_DisAsm()
~SPUDisAsm()
{
}
private:
void Exit()
{
if(m_mode == NormalMode && !disasm_frame->exit)
{
disasm_frame->Close();
}
this->~SPU_DisAsm();
}
virtual u32 DisAsmBranchTarget(const s32 imm)
{
return branchTarget(m_mode == NormalMode ? CPU.PC : dump_pc, imm);
return branchTarget(dump_pc, imm);
}
private:
@ -114,7 +94,7 @@ private:
}
void MFSPR(u32 rt, u32 sa)
{
DisAsm("mfspr", spu_reg_name[rt], spu_reg_name[sa]); // Are SPR mapped on the GPR or are there 128 additional registers ?
DisAsm("mfspr", spu_reg_name[rt], spu_reg_name[sa]); // Are SPR mapped on the GPR or are there 128 additional registers ? Yes, there are also 128 SPR making 256 registers total
}
void RDCH(u32 rt, u32 ra)
{
@ -448,7 +428,7 @@ private:
{
DisAsm("sumb", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb]);
}
void HGT(u32 rt, u32 ra, u32 rb)
void HGT(u32 rt, s32 ra, s32 rb)
{
DisAsm("hgt", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb]);
}

View File

@ -39,15 +39,15 @@ namespace SPU_instr
static CodeField<18, 31> L_18_31;
static CodeField<11> L_11;
static auto rrr_list = new_list<SPU_Opcodes>(RRR);
static auto rrr_list = new_list<SPUOpcodes>(RRR);
static auto ri18_list = new_list(rrr_list, RI18);
static auto ri10_list = new_list(ri18_list, RI10);
static auto ri16_list = new_list(ri10_list, RI16);
static auto ri8_list = new_list(ri16_list, RI8);
static auto ri7_list = new_list(ri8_list, RI7, instr_bind(&SPU_Opcodes::UNK, GetCode, RRR, RI7));
static auto ri7_list = new_list(ri8_list, RI7, instr_bind(&SPUOpcodes::UNK, GetCode, RRR, RI7));
#define bind_instr(list, name, ...) \
static const auto& name = make_instr<SPU_opcodes::name>(list, #name, &SPU_Opcodes::name, ##__VA_ARGS__)
static const auto& name = make_instr<SPU_opcodes::name>(list, #name, &SPUOpcodes::name, ##__VA_ARGS__)
bind_instr(ri7_list, STOP, L_18_31);
bind_instr(ri7_list, LNOP);

View File

@ -7,19 +7,17 @@
#define UNIMPLEMENTED() UNK(__FUNCTION__)
class SPU_Interpreter : public SPU_Opcodes
class SPUInterpreter : public SPUOpcodes
{
private:
SPUThread& CPU;
public:
SPU_Interpreter(SPUThread& cpu) : CPU(cpu)
SPUInterpreter(SPUThread& cpu) : CPU(cpu)
{
}
private:
void Exit(){}
void SysCall()
{
}
@ -46,7 +44,17 @@ private:
}
void MFSPR(u32 rt, u32 sa)
{
UNIMPLEMENTED();
//If register is a dummy register (register labeled 0x0)
if(sa == 0x0)
{
CPU.GPR[rt]._u128.hi = 0x0;
CPU.GPR[rt]._u128.lo = 0x0;
}
else
{
CPU.GPR[rt]._u128.hi = CPU.SPR[sa]._u128.hi;
CPU.GPR[rt]._u128.lo = CPU.SPR[sa]._u128.lo;
}
}
void RDCH(u32 rt, u32 ra)
{
@ -252,7 +260,11 @@ private:
}
void MTSPR(u32 rt, u32 sa)
{
UNIMPLEMENTED();
if(sa != 0)
{
CPU.SPR[sa]._u128.hi = CPU.GPR[rt]._u128.hi;
CPU.SPR[sa]._u128.lo = CPU.GPR[rt]._u128.lo;
}
}
void WRCH(u32 ra, u32 rt)
{
@ -299,7 +311,7 @@ private:
void IRET(u32 ra)
{
UNIMPLEMENTED();
// SetBranch(SRR0);
//SetBranch(SRR0);
}
void BISLED(u32 rt, u32 ra)
{
@ -620,9 +632,13 @@ private:
CPU.GPR[rt]._u16[w*2 + 1] = CPU.GPR[rb]._u8[w*4] + CPU.GPR[rb]._u8[w*4 + 1] + CPU.GPR[rb]._u8[w*4 + 2] + CPU.GPR[rb]._u8[w*4 + 3];
}
}
void HGT(u32 rt, u32 ra, u32 rb)
//HGT uses signed values. HLGT uses unsigned values
void HGT(u32 rt, s32 ra, s32 rb)
{
UNIMPLEMENTED();
if(CPU.GPR[ra]._i32[0] > CPU.GPR[rb]._i32[0])
{
CPU.Stop();
}
}
void CLZ(u32 rt, u32 ra)
{
@ -749,7 +765,10 @@ private:
}
void HLGT(u32 rt, u32 ra, u32 rb)
{
UNIMPLEMENTED();
if(CPU.GPR[ra]._u32[0] > CPU.GPR[rb]._u32[0])
{
CPU.Stop();
}
}
void DFMA(u32 rt, u32 ra, u32 rb)
{
@ -816,8 +835,13 @@ private:
for (int w = 0; w < 4; w++)
CPU.GPR[rt]._u32[w] += CPU.GPR[ra]._u16[w*2] * CPU.GPR[rb]._u16[w*2];
}
//Forced bits to 0, hence the shift:
void FSCRRD(u32 rt)
{
/*CPU.GPR[rt]._u128.lo =
CPU.FPSCR.Exception0 << 20 &
CPU.FPSCR.*/
UNIMPLEMENTED();
}
void FESD(u32 rt, u32 ra)
@ -892,7 +916,7 @@ private:
void MPYU(u32 rt, u32 ra, u32 rb)
{
for (int w = 0; w < 4; w++)
CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._u16[w*2 + 1] * CPU.GPR[rb]._u16[w*2 + 1];
CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._u16[w*2] * CPU.GPR[rb]._u16[w*2];
}
void CEQB(u32 rt, u32 ra, u32 rb)
{

View File

@ -226,15 +226,13 @@ namespace SPU_opcodes
};
};
class SPU_Opcodes
class SPUOpcodes
{
public:
static u32 branchTarget(const u64 pc, const s32 imm)
{
return (pc + (imm << 2)) & 0x3fffc;
}
virtual void Exit()=0;
//0 - 10
virtual void STOP(u32 code) = 0;
@ -325,7 +323,7 @@ public:
virtual void EQV(u32 rt, u32 ra, u32 rb) = 0;
virtual void CGTB(u32 rt, u32 ra, u32 rb) = 0;
virtual void SUMB(u32 rt, u32 ra, u32 rb) = 0;
virtual void HGT(u32 rt, u32 ra, u32 rb) = 0;
virtual void HGT(u32 rt, s32 ra, s32 rb) = 0;
virtual void CLZ(u32 rt, u32 ra) = 0;
virtual void XSWD(u32 rt, u32 ra) = 0;
virtual void XSHW(u32 rt, u32 ra) = 0;

View File

@ -8,13 +8,18 @@ SPUThread& GetCurrentSPUThread()
{
PPCThread* thread = GetCurrentPPCThread();
if(!thread || thread->GetType() == PPC_THREAD_PPU) throw wxString("GetCurrentSPUThread: bad thread");
if(!thread || (thread->GetType() != CPU_THREAD_SPU && thread->GetType() != CPU_THREAD_RAW_SPU))
{
throw wxString("GetCurrentSPUThread: bad thread");
}
return *(SPUThread*)thread;
}
SPUThread::SPUThread(PPCThreadType type) : PPCThread(type)
SPUThread::SPUThread(CPUThreadType type) : PPCThread(type)
{
assert(type == CPU_THREAD_SPU || type == CPU_THREAD_RAW_SPU);
Reset();
}
@ -24,8 +29,10 @@ SPUThread::~SPUThread()
void SPUThread::DoReset()
{
PPCThread::DoReset();
//reset regs
for(u32 i=0; i<128; ++i) GPR[i].Reset();
memset(GPR, 0, sizeof(SPU_GPR_hdr) * 128);
}
void SPUThread::InitRegs()
@ -35,6 +42,16 @@ void SPUThread::InitRegs()
GPR[4]._u64[1] = m_args[1];
GPR[5]._u64[1] = m_args[2];
GPR[6]._u64[1] = m_args[3];
dmac.ls_offset = m_offset;
dmac.proxy_pos = 0;
dmac.queue_pos = 0;
SPU.RunCntl.SetValue(SPU_RUNCNTL_STOP);
SPU.Status.SetValue(SPU_STATUS_RUNNING);
Prxy.QueryType.SetValue(0);
MFC.CMDStatus.SetValue(0);
PC = SPU.NPC.GetValue();
}
u64 SPUThread::GetFreeStackSize() const
@ -47,12 +64,12 @@ void SPUThread::DoRun()
switch(Ini.CPUDecoderMode.GetValue())
{
case 0:
m_dec = new SPU_Decoder(*new SPU_DisAsm(*this));
//m_dec = new SPUDecoder(*new SPUDisAsm());
break;
case 1:
case 2:
m_dec = new SPU_Decoder(*new SPU_Interpreter(*this));
m_dec = new SPUDecoder(*new SPUInterpreter(*this));
break;
}
}
@ -70,8 +87,3 @@ void SPUThread::DoStop()
delete m_dec;
m_dec = 0;
}
void SPUThread::DoCode(const s32 code)
{
m_dec->Decode(code);
}

View File

@ -22,6 +22,25 @@ static const wxString spu_reg_name[128] =
"$112", "$113", "$114", "$115", "$116", "$117", "$118", "$119",
"$120", "$121", "$122", "$123", "$124", "$125", "$126", "$127",
};
//SPU reg $0 is a dummy reg, and is used for certain instructions.
static const wxString spu_specialreg_name[128] = {
"$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
"$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
"$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
"$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31",
"$32", "$33", "$34", "$35", "$36", "$37", "$38", "$39",
"$40", "$41", "$42", "$43", "$44", "$45", "$46", "$47",
"$48", "$49", "$50", "$51", "$52", "$53", "$54", "$55",
"$56", "$57", "$58", "$59", "$60", "$61", "$62", "$63",
"$64", "$65", "$66", "$67", "$68", "$69", "$70", "$71",
"$72", "$73", "$74", "$75", "$76", "$77", "$78", "$79",
"$80", "$81", "$82", "$83", "$84", "$85", "$86", "$87",
"$88", "$89", "$90", "$91", "$92", "$93", "$94", "$95",
"$96", "$97", "$98", "$99", "$100", "$101", "$102", "$103",
"$104", "$105", "$106", "$107", "$108", "$109", "$110", "$111",
"$112", "$113", "$114", "$115", "$116", "$117", "$118", "$119",
"$120", "$121", "$122", "$123", "$124", "$125", "$126", "$127",
};
static const wxString spu_ch_name[128] =
{
@ -98,6 +117,89 @@ enum
SPU_STATUS_SINGLE_STEP = 0x10,
};
//Floating point status and control register. Unsure if this is one of the GPRs or SPRs
//Is 128 bits, but bits 0-19, 24-28, 32-49, 56-60, 64-81, 88-92, 96-115, 120-124 are unused
class FPSCR
{
public:
u64 low;
u64 hi;
FPSCR() {}
wxString ToString() const
{
return "FPSCR writer not yet implemented"; //wxString::Format("%08x%08x%08x%08x", _u32[3], _u32[2], _u32[1], _u32[0]);
}
void Reset()
{
memset(this, 0, sizeof(*this));
}
//slice -> 0 - 1 (4 slices total, only two have rounding)
//0 -> round even
//1 -> round towards zero (truncate)
//2 -> round towards positive inf
//3 -> round towards neg inf
void setSliceRounding(u8 slice, u8 roundTo)
{
u64 mask = roundTo;
switch(slice)
{
case 0:
mask = mask << 20;
break;
case 1:
mask = mask << 22;
break;
}
//rounding is located in the low end of the FPSCR
this->low = this->low & mask;
}
//Slice 0 or 1
u8 checkSliceRounding(u8 slice)
{
switch(slice)
{
case 0:
return this->low >> 20 & 0x3;
case 1:
return this->low >> 22 & 0x3;
}
}
//Single Precision Exception Flags (all 3 slices)
//slice -> slice number (0-3)
//exception: 1 -> Overflow 2 -> Underflow 4-> Diff (could be IE^3 non compliant)
void setSinglePrecisionExceptionFlags(u8 slice, u8 exception)
{
u64 mask = exception;
switch(slice)
{
case 0:
mask = mask << 29;
this->low = this->low & mask;
break;
case 1:
mask = mask << 61;
this->low = this->low & mask;
break;
case 2:
mask = mask << 29;
this->hi = this->hi & mask;
break;
case 3:
mask = mask << 61;
this->hi = this->hi & mask;
break;
}
}
};
union SPU_GPR_hdr
{
u128 _u128;
@ -126,32 +228,120 @@ union SPU_GPR_hdr
}
};
union SPU_SPR_hdr
{
u128 _u128;
s128 _i128;
SPU_SPR_hdr() {}
wxString ToString() const
{
return wxString::Format("%16%16", _u128.hi, _u128.lo);
}
void Reset()
{
memset(this, 0, sizeof(*this));
}
};
class SPUThread : public PPCThread
{
public:
SPU_GPR_hdr GPR[128]; //General-Purpose Register
/*
SPUReg<1> MFC_LSA;
SPUReg<1> MFC_EAH;
SPUReg<1> MFC_EAL;
SPUReg<1> MFC_Size_Tag;
SPUReg<1> MFC_CMDStatus;
SPUReg<1> MFC_QStatus;
SPUReg<1> Prxy_QueryType;
SPUReg<1> Prxy_QueryMask;
SPUReg<1> Prxy_TagStatus;
SPUReg<1> SPU_Out_MBox;
SPUReg<4> SPU_In_MBox;
SPUReg<1> SPU_MBox_Status;
SPUReg<1> SPU_RunCntl;
SPUReg<1> SPU_Status;
SPUReg<1> SPU_NPC;
SPUReg<1> SPU_RdSigNotify1;
SPUReg<1> SPU_RdSigNotify2;
*/
SizedStack<u32, 1> SPU_OutIntr_Mbox;
SPU_SPR_hdr SPR[128]; //Special-Purpose Registers
FPSCR FPSCR;
template<size_t _max_count>
class Channel
{
public:
static const size_t max_count = _max_count;
private:
u32 m_value[max_count];
u32 m_index;
public:
Channel()
{
Init();
}
void Init()
{
m_index = 0;
}
__forceinline bool Pop(u32& res)
{
if(!m_index) return false;
res = m_value[--m_index];
return true;
}
__forceinline bool Push(u32 value)
{
if(m_index >= max_count) return false;
m_value[m_index++] = value;
return true;
}
u32 GetCount() const
{
return m_index;
}
u32 GetFreeCount() const
{
return max_count - m_index;
}
void SetValue(u32 value)
{
m_value[0] = value;
}
u32 GetValue() const
{
return m_value[0];
}
};
struct
{
Channel<1> LSA;
Channel<1> EAH;
Channel<1> EAL;
Channel<1> Size_Tag;
Channel<1> CMDStatus;
Channel<1> QStatus;
} MFC;
struct
{
Channel<1> QueryType;
Channel<1> QueryMask;
Channel<1> TagStatus;
} Prxy;
struct
{
Channel<1> Out_MBox;
Channel<1> OutIntr_Mbox;
Channel<4> In_MBox;
Channel<1> MBox_Status;
Channel<1> RunCntl;
Channel<1> Status;
Channel<1> NPC;
Channel<1> RdSigNotify1;
Channel<1> RdSigNotify2;
} SPU;
u32 LSA;
MFC mfc;
union
{
@ -159,18 +349,20 @@ public:
struct { u32 EAH, EAL; };
};
DMAC dmac;
u32 GetChannelCount(u32 ch)
{
switch(ch)
{
case SPU_WrOutMbox:
return mfc.SPU_Out_MBox.GetFreeCount();
return SPU.Out_MBox.GetFreeCount();
case SPU_RdInMbox:
return mfc.SPU_In_MBox.GetCount();
return SPU.In_MBox.GetFreeCount();
case SPU_WrOutIntrMbox:
return 0;//return SPU_OutIntr_Mbox.GetFreeCount();
return 0;//return SPU.OutIntr_Mbox.GetFreeCount();
default:
ConLog.Error("%s error: unknown/illegal channel (%d).", __FUNCTION__, ch);
@ -188,7 +380,7 @@ public:
{
case SPU_WrOutIntrMbox:
ConLog.Warning("SPU_WrOutIntrMbox = 0x%x", v);
if(!SPU_OutIntr_Mbox.Push(v))
if(!SPU.OutIntr_Mbox.Push(v))
{
ConLog.Warning("Not enought free rooms.");
}
@ -196,11 +388,11 @@ public:
case SPU_WrOutMbox:
ConLog.Warning("SPU_WrOutMbox = 0x%x", v);
if(!mfc.SPU_Out_MBox.Push(v))
if(!SPU.Out_MBox.Push(v))
{
ConLog.Warning("Not enought free rooms.");
}
mfc.SPU_Status.SetValue((mfc.SPU_Status.GetValue() & ~0xff) | 1);
SPU.Status.SetValue((SPU.Status.GetValue() & ~0xff) | 1);
break;
default:
@ -217,8 +409,8 @@ public:
switch(ch)
{
case SPU_RdInMbox:
if(!mfc.SPU_In_MBox.Pop(v)) v = 0;
mfc.SPU_Status.SetValue((mfc.SPU_Status.GetValue() & ~0xff00) | (mfc.SPU_In_MBox.GetCount() << 8));
if(!SPU.In_MBox.Pop(v)) v = 0;
SPU.Status.SetValue((SPU.Status.GetValue() & ~0xff00) | (SPU.In_MBox.GetCount() << 8));
break;
default:
@ -241,13 +433,15 @@ public:
virtual void WriteLS128(const u32 lsa, const u128& data) const { Memory.Write128(lsa + m_offset, data); }
public:
SPUThread(PPCThreadType type = PPC_THREAD_SPU);
SPUThread(CPUThreadType type = CPU_THREAD_SPU);
~SPUThread();
virtual wxString RegsToString()
{
wxString ret = PPCThread::RegsToString();
wxString ret;
for(uint i=0; i<128; ++i) ret += wxString::Format("GPR[%d] = 0x%s\n", i, GPR[i].ToString());
return ret;
}
@ -262,7 +456,8 @@ public:
return wxEmptyString;
}
bool WriteRegString(wxString reg, wxString value) {
bool WriteRegString(wxString reg, wxString value)
{
while (value.Len() < 32) value = "0"+value;
if (reg.Contains("["))
{
@ -292,9 +487,6 @@ protected:
virtual void DoPause();
virtual void DoResume();
virtual void DoStop();
protected:
virtual void DoCode(const s32 code);
};
SPUThread& GetCurrentSPUThread();

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;
@ -148,7 +170,12 @@ void VFS::SaveLoadDevices(Array<VFSManagerEntry>& res, bool is_load)
res[idx].path = "$(EmulatorDir)\\dev_hdd0\\";
res[idx].mount = "/dev_hdd0/";
res[idx].device = vfsDevice_LocalFile;
idx = res.Move(new VFSManagerEntry());
res[idx].path = "$(EmulatorDir)\\dev_hdd1\\";
res[idx].mount = "/dev_hdd1/";
res[idx].device = vfsDevice_LocalFile;
/*
idx = res.Move(new VFSManagerEntry());
res[idx].path = "$(GameDir)";
res[idx].mount = "";
@ -158,6 +185,7 @@ void VFS::SaveLoadDevices(Array<VFSManagerEntry>& res, bool is_load)
res[idx].path = "$(GameDir)";
res[idx].mount = "/";
res[idx].device = vfsDevice_LocalFile;
*/
idx = res.Move(new VFSManagerEntry());
res[idx].path = "$(GameDir)";

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

@ -1,4 +1,5 @@
#pragma once
#include "rpcs3.h"
enum
{
@ -39,6 +40,104 @@ struct gcmInfo
u32 control_addr;
};
struct CellGcmSurface
{
u8 type;
u8 antialias;
u8 color_format;
u8 color_target;
u8 color_location[4];
u32 color_offset[4];
u32 color_pitch[4];
u8 depth_format;
u8 depth_location;
u16 pad;
u32 depth_offset;
u32 depth_pitch;
u16 width;
u16 height;
u16 x;
u16 y;
};
struct CellGcmReportData
{
u64 timer;
u32 value;
u32 pad;
};
struct CellGcmZcullInfo
{
u32 region;
u32 size;
u32 start;
u32 offset;
u32 status0;
u32 status1;
};
struct CellGcmTileInfo
{
u32 tile;
u32 limit;
u32 pitch;
u32 format;
};
struct GcmZcullInfo
{
u32 m_offset;
u32 m_width;
u32 m_height;
u32 m_cullStart;
u32 m_zFormat;
u32 m_aaFormat;
u32 m_zCullDir;
u32 m_zCullFormat;
u32 m_sFunc;
u32 m_sRef;
u32 m_sMask;
bool m_binded;
GcmZcullInfo()
{
memset(this, 0, sizeof(*this));
}
};
struct GcmTileInfo
{
u8 m_location;
u32 m_offset;
u32 m_size;
u32 m_pitch;
u8 m_comp;
u16 m_base;
u8 m_bank;
bool m_binded;
GcmTileInfo()
{
memset(this, 0, sizeof(*this));
}
CellGcmTileInfo Pack()
{
CellGcmTileInfo ret;
re(ret.tile, (m_location + 1) | (m_bank << 4) | ((m_offset / 0x10000) << 16) | (m_location << 31));
re(ret.limit, ((m_offset + m_size - 1) / 0x10000) << 16 | (m_location << 31));
re(ret.pitch, (m_pitch / 0x100) << 8);
re(ret.format, m_base | ((m_base + ((m_size - 1) / 0x10000)) << 13) | (m_comp << 26) | (1 << 30));
return ret;
}
};
enum
{
CELL_GCM_LOCATION_LOCAL,

View File

@ -135,11 +135,13 @@ GLrbo::~GLrbo()
void GLrbo::Create(u32 count)
{
if(m_id.GetCount())
if(m_id.GetCount() == count)
{
return;
}
Delete();
m_id.SetCount(count);
glGenRenderbuffers(count, m_id.GetPtr());
}
@ -163,6 +165,11 @@ void GLrbo::Unbind()
void GLrbo::Delete()
{
if(!IsCreated())
{
return;
}
glDeleteRenderbuffers(m_id.GetCount(), m_id.GetPtr());
m_id.Clear();
}
@ -198,11 +205,15 @@ void GLfbo::Create()
void GLfbo::Bind(u32 type, int id)
{
if(id != -1)
assert(m_id);
glBindFramebuffer(type, id);
}
void GLfbo::Bind(u32 type)
{
assert(IsCreated());
m_type = type;
glBindFramebuffer(m_type, id == -1 ? m_id : id);
Bind(type, m_id);
}
void GLfbo::Texture1D(u32 attachment, u32 texture, int level)
@ -242,6 +253,11 @@ void GLfbo::Unbind(u32 type)
void GLfbo::Delete()
{
if(!IsCreated())
{
return;
}
glDeleteFramebuffers(1, &m_id);
m_id = 0;
}

View File

@ -77,12 +77,13 @@ public:
~GLfbo();
void Create();
void Bind(u32 type = GL_FRAMEBUFFER, int id = -1);
static void Bind(u32 type, int id);
void Bind(u32 type = GL_FRAMEBUFFER);
void Texture1D(u32 attachment, u32 texture, int level = 0);
void Texture2D(u32 attachment, u32 texture, int level = 0);
void Texture3D(u32 attachment, u32 texture, int zoffset = 0, int level = 0);
void Renderbuffer(u32 attachment, u32 renderbuffer);
void Blit(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, u32 mask, u32 filter);
static void Blit(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, u32 mask, u32 filter);
void Unbind();
static void Unbind(u32 type);
void Delete();

View File

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "FragmentProgram.h"
#include "GLFragmentProgram.h"
void FragmentDecompilerThread::AddCode(wxString code, bool append_mask)
void GLFragmentDecompilerThread::AddCode(wxString code, bool append_mask)
{
if(!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt) return;
@ -72,13 +72,14 @@ void FragmentDecompilerThread::AddCode(wxString code, bool append_mask)
code = "clamp(" + code + ", 0.0, 1.0)";
}
code = cond + (dst.set_cond ? AddCond(dst.fp16) : AddReg(dst.dest_reg, dst.fp16)) + mask
code = cond + (dst.set_cond ? m_parr.AddParam(PARAM_NONE , "vec4", wxString::Format(dst.fp16 ? "hc%d" : "rc%d", src0.cond_reg_index))
: AddReg(dst.dest_reg, dst.fp16)) + mask
+ " = " + code + (append_mask ? mask : wxEmptyString);
main += "\t" + code + ";\n";
}
wxString FragmentDecompilerThread::GetMask()
wxString GLFragmentDecompilerThread::GetMask()
{
wxString ret = wxEmptyString;
@ -95,25 +96,32 @@ wxString FragmentDecompilerThread::GetMask()
return ret.IsEmpty() || strncmp(ret, dst_mask, 4) == 0 ? wxEmptyString : ("." + ret);
}
wxString FragmentDecompilerThread::AddReg(u32 index, int fp16)
wxString GLFragmentDecompilerThread::AddReg(u32 index, int fp16)
{
//if(!index && !fp16) return "gl_FragColor";
return m_parr.AddParam((index || fp16) ? PARAM_NONE : PARAM_OUT, "vec4",
wxString::Format((fp16 ? "h%u" : "r%u"), index), (index || fp16) ? -1 : 0);
/*
if(HasReg(index, fp16))
{
return wxString::Format((fp16 ? "h%u" : "r%u"), index);
}
*/
//ConLog.Warning("%c%d: %d %d", (fp16 ? 'h' : 'r'), index, dst.tex_num, src2.use_index_reg);
return m_parr.AddParam(fp16 ? PARAM_NONE : PARAM_OUT, "vec4",
wxString::Format((fp16 ? "h%u" : "r%u"), index), fp16 ? -1 : index);
}
bool FragmentDecompilerThread::HasReg(u32 index, int fp16)
bool GLFragmentDecompilerThread::HasReg(u32 index, int fp16)
{
return m_parr.HasParam((index || fp16) ? PARAM_NONE : PARAM_OUT, "vec4",
return m_parr.HasParam(PARAM_OUT, "vec4",
wxString::Format((fp16 ? "h%u" : "r%u"), index));
}
wxString FragmentDecompilerThread::AddCond(int fp16)
wxString GLFragmentDecompilerThread::AddCond(int fp16)
{
return m_parr.AddParam(PARAM_NONE , "vec4", (fp16 ? "hc" : "rc"), -1);
return m_parr.AddParam(PARAM_NONE , "vec4", wxString::Format(fp16 ? "hc%d" : "rc%d", src0.cond_mod_reg_index));
}
wxString FragmentDecompilerThread::AddConst()
wxString GLFragmentDecompilerThread::AddConst()
{
mem32_ptr_t data(m_addr + m_size + m_offset);
@ -126,12 +134,12 @@ wxString FragmentDecompilerThread::AddConst()
wxString::Format("vec4(%f, %f, %f, %f)", (float&)x, (float&)y, (float&)z, (float&)w));
}
wxString FragmentDecompilerThread::AddTex()
wxString GLFragmentDecompilerThread::AddTex()
{
return m_parr.AddParam(PARAM_UNIFORM, "sampler2D", wxString::Format("tex%d", dst.tex_num));
}
template<typename T> wxString FragmentDecompilerThread::GetSRC(T src)
template<typename T> wxString GLFragmentDecompilerThread::GetSRC(T src)
{
wxString ret = wxEmptyString;
@ -196,15 +204,10 @@ template<typename T> wxString FragmentDecompilerThread::GetSRC(T src)
return ret;
}
wxString FragmentDecompilerThread::BuildCode()
wxString GLFragmentDecompilerThread::BuildCode()
{
wxString p = wxEmptyString;
if(!m_parr.HasParam(PARAM_OUT, "vec4", "r0") && m_parr.HasParam(PARAM_NONE, "vec4", "h0"))
{
main += "\t" + m_parr.AddParam(PARAM_OUT, "vec4", "r0", 0) + " = " + "h0;\n";
}
for(u32 i=0; i<m_parr.params.GetCount(); ++i)
{
p += m_parr.params[i].Format();
@ -219,7 +222,7 @@ wxString FragmentDecompilerThread::BuildCode()
return wxString::Format(prot, p, main);
}
void FragmentDecompilerThread::Task()
void GLFragmentDecompilerThread::Task()
{
mem32_ptr_t data(m_addr);
m_size = 0;
@ -233,16 +236,18 @@ void FragmentDecompilerThread::Task()
m_offset = 4 * 4;
switch(dst.opcode | (src1.opcode_is_branch << 6))
const u32 opcode = dst.opcode | (src1.opcode_is_branch << 6);
switch(opcode)
{
case 0x00: break; //NOP
case 0x01: AddCode(GetSRC(src0)); break; //MOV
case 0x02: AddCode("(" + GetSRC(src0) + " * " + GetSRC(src1) + ")"); break; //MUL
case 0x03: AddCode("(" + GetSRC(src0) + " + " + GetSRC(src1) + ")"); break; //ADD
case 0x04: AddCode("(" + GetSRC(src0) + " * " + GetSRC(src1) + " + " + GetSRC(src2) + ")"); break; //MAD
case 0x05: AddCode("vec4(dot(" + GetSRC(src0) + ".xyz, " + GetSRC(src1) + ".xyz)).xxxx"); break; // DP3
case 0x06: AddCode("vec4(dot(" + GetSRC(src0) + ", " + GetSRC(src1) + ")).xxxx"); break; // DP4
case 0x07: AddCode("vec4(distance(" + GetSRC(src0) + ", " + GetSRC(src1) + ")).xxxx"); break; // DST
case 0x05: AddCode("vec2(dot(" + GetSRC(src0) + ".xyz, " + GetSRC(src1) + ".xyz), 0).xxxx"); break; // DP3
case 0x06: AddCode("vec2(dot(" + GetSRC(src0) + ", " + GetSRC(src1) + "), 0).xxxx"); break; // DP4
case 0x07: AddCode("vec2(distance(" + GetSRC(src0) + ", " + GetSRC(src1) + "), 0).xxxx"); break; // DST
case 0x08: AddCode("min(" + GetSRC(src0) + ", " + GetSRC(src1) + ")"); break; // MIN
case 0x09: AddCode("max(" + GetSRC(src0) + ", " + GetSRC(src1) + ")"); break; // MAX
case 0x0a: AddCode("vec4(lessThan(" + GetSRC(src0) + ", " + GetSRC(src1) + "))"); break; // SLT
@ -292,7 +297,7 @@ void FragmentDecompilerThread::Task()
//case 0x35: break; // BEMLUM
//case 0x36: break; // REFL
//case 0x37: break; // TIMESWTEX
case 0x38: AddCode("vec4(dot(" + GetSRC(src0) + ".xy, " + GetSRC(src1) + ".xy)).xxxx"); break; // DP2
case 0x38: AddCode("vec2(dot(" + GetSRC(src0) + ".xy, " + GetSRC(src1) + ".xy)).xxxx"); break; // DP2
case 0x39: AddCode("normalize(" + GetSRC(src0) + ".xyz)"); break; // NRM
case 0x3a: AddCode("(" + GetSRC(src0) + " / " + GetSRC(src1) + ")"); break; // DIV
case 0x3b: AddCode("(" + GetSRC(src0) + " / sqrt(" + GetSRC(src1) + "))"); break; // DIVSQ
@ -301,7 +306,7 @@ void FragmentDecompilerThread::Task()
case 0x3e: break; // FENCB
default:
ConLog.Error("Unknown opcode 0x%x (inst %d)", dst.opcode, m_size / (4 * 4));
ConLog.Error("Unknown opcode 0x%x (inst %d)", opcode, m_size / (4 * 4));
Emu.Pause();
break;
}
@ -310,20 +315,20 @@ void FragmentDecompilerThread::Task()
if(dst.end) break;
data.SetOffset(m_offset);
data.Skip(m_offset);
}
m_shader = BuildCode();
main.Clear();
}
ShaderProgram::ShaderProgram()
GLShaderProgram::GLShaderProgram()
: m_decompiler_thread(nullptr)
, id(0)
{
}
ShaderProgram::~ShaderProgram()
GLShaderProgram::~GLShaderProgram()
{
if(m_decompiler_thread)
{
@ -340,7 +345,7 @@ ShaderProgram::~ShaderProgram()
Delete();
}
void ShaderProgram::Decompile()
void GLShaderProgram::Decompile(RSXShaderProgram& prog)
{
#if 0
FragmentDecompilerThread(shader, parr, addr).Entry();
@ -357,12 +362,12 @@ void ShaderProgram::Decompile()
m_decompiler_thread = nullptr;
}
m_decompiler_thread = new FragmentDecompilerThread(shader, parr, addr, size);
m_decompiler_thread = new GLFragmentDecompilerThread(shader, parr, prog.addr, prog.size);
m_decompiler_thread->Start();
#endif
}
void ShaderProgram::Compile()
void GLShaderProgram::Compile()
{
if(id) glDeleteShader(id);
@ -396,7 +401,7 @@ void ShaderProgram::Compile()
//else ConLog.Write("Shader compiled successfully!");
}
void ShaderProgram::Delete()
void GLShaderProgram::Delete()
{
for(u32 i=0; i<parr.params.GetCount(); ++i)
{

View File

@ -1,7 +1,8 @@
#pragma once
#include "ShaderParam.h"
#include "GLShaderParam.h"
#include "Emu/GS/RSXFragmentProgram.h"
struct FragmentDecompilerThread : public ThreadBase
struct GLFragmentDecompilerThread : public ThreadBase
{
union OPDEST
{
@ -99,19 +100,21 @@ struct FragmentDecompilerThread : public ThreadBase
wxString main;
wxString& m_shader;
ParamArray& m_parr;
GLParamArray& m_parr;
u32 m_addr;
u32& m_size;
u32 m_const_index;
u32 m_offset;
u32 m_location;
FragmentDecompilerThread(wxString& shader, ParamArray& parr, u32 addr, u32& size)
GLFragmentDecompilerThread(wxString& shader, GLParamArray& parr, u32 addr, u32& size)
: ThreadBase(false, "Fragment Shader Decompiler Thread")
, m_shader(shader)
, m_parr(parr)
, m_addr(addr)
, m_size(size)
, m_const_index(0)
, m_location(0)
{
m_size = 0;
}
@ -133,18 +136,15 @@ struct FragmentDecompilerThread : public ThreadBase
u32 GetData(const u32 d) const { return d << 16 | d >> 16; }
};
struct ShaderProgram
struct GLShaderProgram
{
ShaderProgram();
~ShaderProgram();
GLShaderProgram();
~GLShaderProgram();
FragmentDecompilerThread* m_decompiler_thread;
GLFragmentDecompilerThread* m_decompiler_thread;
ParamArray parr;
GLParamArray parr;
u32 size;
u32 addr;
u32 offset;
wxString shader;
u32 id;
@ -156,7 +156,7 @@ struct ShaderProgram
m_decompiler_thread->Wait();
}
}
void Decompile();
void Decompile(RSXShaderProgram& prog);
void Compile();
void Delete();

File diff suppressed because it is too large Load Diff

View File

@ -3,9 +3,9 @@
#include "Emu/GS/RSXThread.h"
#include "wx/glcanvas.h"
#include "GLBuffers.h"
#include "Program.h"
#include "GLProgram.h"
#include "OpenGL.h"
#include "ProgramBuffer.h"
#include "GLProgramBuffer.h"
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "gl.lib")
@ -15,57 +15,10 @@ void checkForGlError(const char* situation);
class GLTexture
{
u32 m_width, m_height;
u32 m_id;
u32 m_offset;
bool m_enabled;
bool m_cubemap;
u8 m_dimension;
u32 m_format;
u16 m_mipmap;
u32 m_pitch;
u16 m_depth;
u16 m_minlod;
u16 m_maxlod;
u8 m_maxaniso;
u8 m_wraps;
u8 m_wrapt;
u8 m_wrapr;
u8 m_unsigned_remap;
u8 m_zfunc;
u8 m_gamma;
u8 m_aniso_bias;
u8 m_signed_remap;
u16 m_bias;
u8 m_min_filter;
u8 m_mag_filter;
u8 m_conv;
u8 m_a_signed;
u8 m_r_signed;
u8 m_g_signed;
u8 m_b_signed;
u32 m_remap;
public:
GLTexture()
: m_width(0), m_height(0)
, m_id(0)
, m_offset(0)
, m_enabled(false)
, m_cubemap(false)
, m_dimension(0)
, m_format(0)
, m_mipmap(0)
, m_minlod(0)
, m_maxlod(1000)
, m_maxaniso(0)
GLTexture() : m_id(0)
{
}
@ -81,85 +34,9 @@ public:
glGenTextures(1, &m_id);
checkForGlError("GLTexture::Init() -> glGenTextures");
Bind();
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
}
}
void SetRect(const u32 width, const u32 height)
{
m_width = width;
m_height = height;
}
u32 GetOffset() const { return m_offset; }
void SetFormat(const bool cubemap, const u8 dimension, const u32 format, const u16 mipmap)
{
m_cubemap = cubemap;
m_dimension = dimension;
m_format = format;
m_mipmap = mipmap;
}
void SetAddress(u8 wraps, u8 wrapt, u8 wrapr, u8 unsigned_remap, u8 zfunc, u8 gamma, u8 aniso_bias, u8 signed_remap)
{
m_wraps = wraps;
m_wrapt = wrapt;
m_wrapr = wrapr;
m_unsigned_remap = unsigned_remap;
m_zfunc = zfunc;
m_gamma = gamma;
m_aniso_bias = aniso_bias;
m_signed_remap = signed_remap;
}
void SetControl0(const bool enable, const u16 minlod, const u16 maxlod, const u8 maxaniso)
{
m_enabled = enable;
m_minlod = minlod;
m_maxlod = maxlod;
m_maxaniso = maxaniso;
}
void SetControl1(u32 remap)
{
m_remap = remap;
}
void SetControl3(u16 depth, u32 pitch)
{
m_depth = depth;
m_pitch = pitch;
}
void SetFilter(u16 bias, u8 min, u8 mag, u8 conv, u8 a_signed, u8 r_signed, u8 g_signed, u8 b_signed)
{
m_bias = bias;
m_min_filter = min;
m_mag_filter = mag;
m_conv = conv;
m_a_signed = a_signed;
m_r_signed = r_signed;
m_g_signed = g_signed;
m_b_signed = b_signed;
}
u32 GetFormat() const { return m_format; }
void SetOffset(const u32 offset)
{
m_offset = offset;
}
wxSize GetRect() const
{
return wxSize(m_width, m_height);
}
int GetGlWrap(int wrap)
{
switch(wrap)
@ -176,12 +53,12 @@ public:
return GL_REPEAT;
}
void Init()
void Init(RSXTexture& tex)
{
Bind();
if(!Memory.IsGoodAddr(m_offset))
if(!Memory.IsGoodAddr(tex.GetOffset()))
{
ConLog.Error("Bad texture address=0x%x", m_offset);
ConLog.Error("Bad texture address=0x%x", tex.GetOffset());
return;
}
//ConLog.Warning("texture addr = 0x%x, width = %d, height = %d, max_aniso=%d, mipmap=%d, remap=0x%x, zfunc=0x%x, wraps=0x%x, wrapt=0x%x, wrapr=0x%x, minlod=0x%x, maxlod=0x%x",
@ -189,17 +66,16 @@ public:
//TODO: safe init
checkForGlError("GLTexture::Init() -> glBindTexture");
glPixelStorei(GL_PACK_ROW_LENGTH, m_pitch);
int format = tex.GetFormat() & ~(0x20 | 0x40);
bool is_swizzled = (tex.GetFormat() & 0x20) == 0;
int format = m_format & ~(0x20 | 0x40);
bool is_swizzled = (m_format & 0x20) == 0;
char* pixels = (char*)Memory.GetMemFromAddr(m_offset);
glPixelStorei(GL_PACK_ALIGNMENT, tex.m_pitch);
char* pixels = (char*)Memory.GetMemFromAddr(tex.GetOffset());
switch(format)
{
case 0x81:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_BLUE, GL_UNSIGNED_BYTE, pixels);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.m_width, tex.m_height, 0, GL_BLUE, GL_UNSIGNED_BYTE, pixels);
checkForGlError("GLTexture::Init() -> glTexImage2D");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
@ -211,39 +87,39 @@ public:
break;
case 0x85:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, pixels);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.m_width, tex.m_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, pixels);
checkForGlError("GLTexture::Init() -> glTexImage2D");
break;
case 0x86:
{
u32 size = ((m_width + 3) / 4) * ((m_height + 3) / 4) * 8;
u32 size = ((tex.m_width + 3) / 4) * ((tex.m_height + 3) / 4) * 8;
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, m_width, m_height, 0, size, pixels);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, tex.m_width, tex.m_height, 0, size, pixels);
checkForGlError("GLTexture::Init() -> glCompressedTexImage2D");
}
break;
case 0x87:
{
u32 size = ((m_width + 3) / 4) * ((m_height + 3) / 4) * 16;
u32 size = ((tex.m_width + 3) / 4) * ((tex.m_height + 3) / 4) * 16;
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, m_width, m_height, 0, size, pixels);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, tex.m_width, tex.m_height, 0, size, pixels);
checkForGlError("GLTexture::Init() -> glCompressedTexImage2D");
}
break;
case 0x88:
{
u32 size = ((m_width + 3) / 4) * ((m_height + 3) / 4) * 16;
u32 size = ((tex.m_width + 3) / 4) * ((tex.m_height + 3) / 4) * 16;
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, m_width, m_height, 0, size, pixels);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, tex.m_width, tex.m_height, 0, size, pixels);
checkForGlError("GLTexture::Init() -> glCompressedTexImage2D");
}
break;
case 0x94:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RED, GL_SHORT, pixels);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.m_width, tex.m_height, 0, GL_RED, GL_SHORT, pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_ONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_ONE);
@ -252,32 +128,30 @@ public:
break;
case 0x9a:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_BGRA, GL_HALF_FLOAT, pixels);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.m_width, tex.m_height, 0, GL_BGRA, GL_HALF_FLOAT, pixels);
checkForGlError("GLTexture::Init() -> glTexImage2D");
break;
case 0x9e:
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, pixels);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.m_width, tex.m_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, pixels);
checkForGlError("GLTexture::Init() -> glTexImage2D");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE);
}
break;
default: ConLog.Error("Init tex error: Bad tex format (0x%x | 0x%x | 0x%x)", format, m_format & 0x20, m_format & 0x40); break;
default: ConLog.Error("Init tex error: Bad tex format (0x%x | 0x%x | 0x%x)", format, tex.GetFormat() & 0x20, tex.GetFormat() & 0x40); break;
}
if(m_mipmap > 1)
{
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, tex.m_mipmap - 1);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, tex.m_mipmap > 1);
if(format != 0x81 && format != 0x94)
{
u8 remap_a = m_remap & 0x3;
u8 remap_r = (m_remap >> 2) & 0x3;
u8 remap_g = (m_remap >> 4) & 0x3;
u8 remap_b = (m_remap >> 6) & 0x3;
u8 remap_a = tex.m_remap & 0x3;
u8 remap_r = (tex.m_remap >> 2) & 0x3;
u8 remap_g = (tex.m_remap >> 4) & 0x3;
u8 remap_b = (tex.m_remap >> 6) & 0x3;
static const int gl_remap[] =
{
@ -292,7 +166,7 @@ public:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, gl_remap[remap_g]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, gl_remap[remap_b]);
}
static const int gl_tex_zfunc[] =
{
GL_NEVER,
@ -304,17 +178,16 @@ public:
GL_GEQUAL,
GL_ALWAYS,
};
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GetGlWrap(m_wraps));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GetGlWrap(m_wrapt));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GetGlWrap(m_wrapr));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, gl_tex_zfunc[m_zfunc]);
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, m_bias);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, m_minlod);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, m_maxlod);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, m_maxaniso);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GetGlWrap(tex.m_wraps));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GetGlWrap(tex.m_wrapt));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GetGlWrap(tex.m_wrapr));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, gl_tex_zfunc[tex.m_zfunc]);
glTexEnvi(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, tex.m_bias);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, tex.m_minlod);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, tex.m_maxlod);
static const int gl_tex_filter[] =
{
GL_NEAREST,
@ -327,20 +200,20 @@ public:
GL_NEAREST,
};
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_tex_filter[m_min_filter]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_tex_filter[m_mag_filter]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_tex_filter[tex.m_min_filter]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_tex_filter[tex.m_mag_filter]);
//Unbind();
}
void Save(const wxString& name)
void Save(RSXTexture& tex, const wxString& name)
{
if(!m_id || !m_offset || !m_width || !m_height) return;
if(!m_id || !tex.m_offset || !tex.m_width || !tex.m_height) return;
u32* alldata = new u32[m_width * m_height];
u32* alldata = new u32[tex.m_width * tex.m_height];
Bind();
switch(m_format & ~(0x20 | 0x40))
switch(tex.m_format & ~(0x20 | 0x40))
{
case 0x81:
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, alldata);
@ -357,15 +230,15 @@ public:
{
wxFile f(name + ".raw", wxFile::write);
f.Write(alldata, m_width * m_height * 4);
f.Write(alldata, tex.m_width * tex.m_height * 4);
}
u8* data = new u8[m_width * m_height * 3];
u8* alpha = new u8[m_width * m_height];
u8* data = new u8[tex.m_width * tex.m_height * 3];
u8* alpha = new u8[tex.m_width * tex.m_height];
u8* src = (u8*)alldata;
u8* dst_d = data;
u8* dst_a = alpha;
for(u32 i=0; i<m_width*m_height;i++)
for(u32 i=0; i<tex.m_width*tex.m_height;i++)
{
*dst_d++ = *src++;
*dst_d++ = *src++;
@ -374,7 +247,7 @@ public:
}
wxImage out;
out.Create(m_width, m_height, data, alpha);
out.Create(tex.m_width, tex.m_height, data, alpha);
out.SaveFile(name, wxBITMAP_TYPE_PNG);
free(alldata);
@ -382,7 +255,7 @@ public:
//free(alpha);
}
void Save()
void Save(RSXTexture& tex)
{
static const wxString& dir_path = "textures";
static const wxString& file_fmt = dir_path + "\\" + "tex[%d].png";
@ -391,7 +264,7 @@ public:
u32 count = 0;
while(wxFileExists(wxString::Format(file_fmt, count))) count++;
Save(wxString::Format(file_fmt, count));
Save(tex, wxString::Format(file_fmt, count));
}
void Bind()
@ -412,64 +285,11 @@ public:
m_id = 0;
}
}
bool IsEnabled() const { return m_enabled; }
};
struct TransformConstant
{
u32 id;
float x, y, z, w;
TransformConstant()
: x(0.0f)
, y(0.0f)
, z(0.0f)
, w(0.0f)
{
}
TransformConstant(u32 id, float x, float y, float z, float w)
: id(id)
, x(x)
, y(y)
, z(z)
, w(w)
{
}
};
struct IndexArrayData
{
Array<u8> m_data;
int m_type;
u32 m_first;
u32 m_count;
u32 m_addr;
u32 index_max;
u32 index_min;
IndexArrayData()
{
Reset();
}
void Reset()
{
m_type = 0;
m_first = ~0;
m_count = 0;
m_addr = 0;
index_min = ~0;
index_max = 0;
m_data.Clear();
}
};
struct GLGSFrame : public GSFrame
{
wxGLCanvas* canvas;
GLTexture m_textures[16];
u32 m_frames;
GLGSFrame();
@ -478,7 +298,6 @@ struct GLGSFrame : public GSFrame
void Flip();
wxGLCanvas* GetCanvas() const { return canvas; }
GLTexture& GetTexture(const u32 index) { return m_textures[index]; }
virtual void SetViewport(int x, int y, u32 w, u32 h);
@ -486,63 +305,137 @@ private:
virtual void OnSize(wxSizeEvent& event);
};
struct GLRSXThread : public ThreadBase
class PostDrawObj
{
wxWindow* m_parent;
Stack<u32> call_stack;
protected:
GLShaderProgram m_fp;
GLVertexProgram m_vp;
GLProgram m_program;
GLfbo m_fbo;
GLrbo m_rbo;
GLRSXThread(wxWindow* parent);
public:
virtual void Draw()
{
static bool s_is_initialized = false;
virtual void Task();
if(!s_is_initialized)
{
s_is_initialized = true;
Initialize();
}
}
virtual void InitializeShaders() = 0;
virtual void InitializeLocations() = 0;
void Initialize()
{
InitializeShaders();
m_fp.Compile();
m_vp.Compile();
m_program.Create(m_vp.id, m_fp.id);
m_program.Use();
InitializeLocations();
}
};
class DrawCursorObj : PostDrawObj
{
u32 m_tex_id;
public:
DrawCursorObj() : m_tex_id(0)
{
}
virtual void Draw()
{
PostDrawObj::Draw();
}
virtual void InitializeShaders()
{
m_vp.shader =
"layout (location = 0) in vec4 in_pos;\n"
"layout (location = 1) in vec2 in_tc;\n"
"out vec2 tc;\n"
"\n"
"void main()\n"
"{\n"
" tc = in_tc;\n"
" gl_Position = in_pos;\n"
"}\n";
m_fp.shader =
"#version 330\n"
"\n"
"in vec2 tc;\n"
"uniform sampler2D tex;\n"
"layout (location = 0) out vec4 res;\n"
"\n"
"void main()\n"
"{\n"
" res = texture(tex, tc);\n"
"}\n";
}
void SetTexture(void* pixels, int width, int hight)
{
glUniform2i(1, width, hight);
if(!m_tex_id)
{
glGenTextures(1, &m_tex_id);
}
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_tex_id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, hight, 0, GL_BLUE, GL_UNSIGNED_BYTE, pixels);
m_program.SetTex(0);
}
void SetPosition(float x, float y, float z = 0.0f)
{
glUniform4f(0, x, y, z, 1.0f);
}
void InitializeLocations()
{
}
};
class GLGSRender
: public wxWindow
, public GSRender
, public ExecRSXCMDdata
{
public:
static const uint m_vertex_count = 16;
static const uint m_fragment_count = 16;
static const uint m_textures_count = 16;
private:
GLRSXThread* m_rsx_thread;
IndexArrayData m_indexed_array;
ShaderProgram m_shader_progs[m_fragment_count];
ShaderProgram* m_cur_shader_prog;
int m_cur_shader_prog_num;
VertexData m_vertex_data[m_vertex_count];
Array<u8> m_vdata;
VertexProgram m_vertex_progs[m_vertex_count];
VertexProgram* m_cur_vertex_prog;
Array<TransformConstant> m_transform_constants;
Array<TransformConstant> m_fragment_constants;
ArrayF<PostDrawObj> m_post_draw_objs;
Program m_program;
GLProgram m_program;
int m_fp_buf_num;
int m_vp_buf_num;
int m_draw_array_count;
int m_draw_mode;
ProgramBuffer m_prog_buffer;
GLProgramBuffer m_prog_buffer;
u32 m_width;
u32 m_height;
GLShaderProgram m_shader_prog;
GLVertexProgram m_vertex_prog;
GLTexture m_gl_textures[m_textures_count];
GLvao m_vao;
GLvbo m_vbo;
GLrbo m_rbo;
GLfbo m_fbo;
wxGLContext* m_context;
public:
GLGSFrame* m_frame;
u32 m_draw_frames;
u32 m_skip_frames;
GLGSRender();
~GLGSRender();
virtual ~GLGSRender();
private:
void EnableVertexData(bool indexed_draw=false);
@ -552,16 +445,22 @@ private:
void InitFragmentData();
void Enable(bool enable, const u32 cap);
virtual void Init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress);
virtual void Draw();
virtual void Close();
bool LoadProgram();
void WriteDepthBuffer();
void WriteColourBufferA();
void WriteColourBufferB();
void WriteColourBufferC();
void WriteColourBufferD();
void WriteBuffers();
public:
void DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u32 count);
void CloseOpenGL();
void DrawObjects();
protected:
virtual void OnInit();
virtual void OnInitThread();
virtual void OnExitThread();
virtual void OnReset();
virtual void ExecCMD();
virtual void Reset();
void Init();
virtual void Flip();
};

View File

@ -25,7 +25,7 @@ OPENGL_PROC(PFNGLDELETEPROGRAMPROC, DeleteProgram);
OPENGL_PROC(PFNGLATTACHSHADERPROC, AttachShader);
OPENGL_PROC(PFNGLGETATTRIBLOCATIONPROC, GetAttribLocation);
OPENGL_PROC(PFNGLLINKPROGRAMPROC, LinkProgram);
OPENGL_PROC(PFNGLBINDFRAGDATALOCATIONPROC, BindFragDataLocation);
//OPENGL_PROC(PFNGLBINDFRAGDATALOCATIONPROC, BindFragDataLocation);
OPENGL_PROC(PFNGLBINDATTRIBLOCATIONPROC, BindAttribLocation);
OPENGL_PROC(PFNGLGETUNIFORMLOCATIONPROC, GetUniformLocation);
OPENGL_PROC(PFNGLGETPROGRAMIVPROC, GetProgramiv);
@ -38,6 +38,9 @@ OPENGL_PROC(PFNGLVERTEXATTRIB3SVPROC, VertexAttrib3sv);
OPENGL_PROC(PFNGLVERTEXATTRIB4SVPROC, VertexAttrib4sv);
OPENGL_PROC(PFNGLVERTEXATTRIB4IVPROC, VertexAttrib4iv);
OPENGL_PROC(PFNGLVERTEXATTRIB1FPROC, VertexAttrib1f);
OPENGL_PROC(PFNGLVERTEXATTRIB2FPROC, VertexAttrib2f);
OPENGL_PROC(PFNGLVERTEXATTRIB3FPROC, VertexAttrib3f);
OPENGL_PROC(PFNGLVERTEXATTRIB4FPROC, VertexAttrib4f);
OPENGL_PROC(PFNGLVERTEXATTRIB2FVPROC, VertexAttrib2fv);
OPENGL_PROC(PFNGLVERTEXATTRIB3FVPROC, VertexAttrib3fv);
OPENGL_PROC(PFNGLVERTEXATTRIB4FVPROC, VertexAttrib4fv);
@ -95,4 +98,5 @@ OPENGL_PROC(PFNGLFRAMEBUFFERTEXTURE1DPROC, FramebufferTexture1D);
OPENGL_PROC(PFNGLFRAMEBUFFERTEXTURE2DPROC, FramebufferTexture2D);
OPENGL_PROC(PFNGLFRAMEBUFFERTEXTURE3DPROC, FramebufferTexture3D);
OPENGL_PROC(PFNGLFRAMEBUFFERRENDERBUFFERPROC, FramebufferRenderbuffer);
OPENGL_PROC(PFNGLBLITFRAMEBUFFERPROC, BlitFramebuffer);
OPENGL_PROC(PFNGLBLITFRAMEBUFFERPROC, BlitFramebuffer);
OPENGL_PROC(PFNGLDRAWBUFFERSPROC, DrawBuffers);

View File

@ -1,12 +1,12 @@
#include "stdafx.h"
#include "Program.h"
#include "GLProgram.h"
#include "GLGSRender.h"
Program::Program() : id(0)
GLProgram::GLProgram() : id(0)
{
}
int Program::GetLocation(const wxString& name)
int GLProgram::GetLocation(const wxString& name)
{
for(u32 i=0; i<m_locations.GetCount(); ++i)
{
@ -24,12 +24,12 @@ int Program::GetLocation(const wxString& name)
return m_locations[pos].loc;
}
bool Program::IsCreated() const
bool GLProgram::IsCreated() const
{
return id > 0;
}
void Program::Create(const u32 vp, const u32 fp)
void GLProgram::Create(const u32 vp, const u32 fp)
{
if(IsCreated()) Delete();
id = glCreateProgram();
@ -74,19 +74,19 @@ void Program::Create(const u32 vp, const u32 fp)
}
}
void Program::UnUse()
void GLProgram::UnUse()
{
id = 0;
m_locations.Clear();
}
void Program::Use()
void GLProgram::Use()
{
glUseProgram(id);
checkForGlError("glUseProgram");
}
void Program::SetTex(u32 index)
void GLProgram::SetTex(u32 index)
{
int loc = GetLocation(wxString::Format("tex%u", index));
checkForGlError(wxString::Format("GetLocation(tex%u)", index));
@ -94,7 +94,7 @@ void Program::SetTex(u32 index)
checkForGlError(wxString::Format("SetTex(%u - %d - %d)", id, index, loc));
}
void Program::Delete()
void GLProgram::Delete()
{
if(!IsCreated()) return;
glDeleteProgram(id);

View File

@ -1,8 +1,8 @@
#pragma once
#include "VertexProgram.h"
#include "FragmentProgram.h"
#include "GLVertexProgram.h"
#include "GLFragmentProgram.h"
struct Program
struct GLProgram
{
private:
struct Location
@ -16,7 +16,7 @@ private:
public:
u32 id;
Program();
GLProgram();
int GetLocation(const wxString& name);
bool IsCreated() const;

View File

@ -1,14 +1,14 @@
#include "stdafx.h"
#include "ProgramBuffer.h"
#include "GLProgramBuffer.h"
int ProgramBuffer::SearchFp(ShaderProgram& fp)
int GLProgramBuffer::SearchFp(const RSXShaderProgram& rsx_fp, GLShaderProgram& gl_fp)
{
for(u32 i=0; i<m_buf.GetCount(); ++i)
{
if(memcmp(&m_buf[i].fp_data[0], &Memory[fp.addr], m_buf[i].fp_data.GetCount()) != 0) continue;
if(memcmp(&m_buf[i].fp_data[0], &Memory[rsx_fp.addr], m_buf[i].fp_data.GetCount()) != 0) continue;
fp.id = m_buf[i].fp_id;
fp.shader = m_buf[i].fp_shader.GetPtr();
gl_fp.id = m_buf[i].fp_id;
gl_fp.shader = m_buf[i].fp_shader.GetPtr();
return i;
}
@ -16,15 +16,15 @@ int ProgramBuffer::SearchFp(ShaderProgram& fp)
return -1;
}
int ProgramBuffer::SearchVp(VertexProgram& vp)
int GLProgramBuffer::SearchVp(const RSXVertexProgram& rsx_vp, GLVertexProgram& gl_vp)
{
for(u32 i=0; i<m_buf.GetCount(); ++i)
{
if(m_buf[i].vp_data.GetCount() != vp.data.GetCount()) continue;
if(memcmp(m_buf[i].vp_data.GetPtr(), vp.data.GetPtr(), vp.data.GetCount() * 4) != 0) continue;
if(m_buf[i].vp_data.GetCount() != rsx_vp.data.GetCount()) continue;
if(memcmp(m_buf[i].vp_data.GetPtr(), rsx_vp.data.GetPtr(), rsx_vp.data.GetCount() * 4) != 0) continue;
vp.id = m_buf[i].vp_id;
vp.shader = m_buf[i].vp_shader.GetPtr();
gl_vp.id = m_buf[i].vp_id;
gl_vp.shader = m_buf[i].vp_shader.GetPtr();
return i;
}
@ -32,19 +32,19 @@ int ProgramBuffer::SearchVp(VertexProgram& vp)
return -1;
}
bool ProgramBuffer::CmpVP(const u32 a, const u32 b) const
bool GLProgramBuffer::CmpVP(const u32 a, const u32 b) const
{
if(m_buf[a].vp_data.GetCount() != m_buf[b].vp_data.GetCount()) return false;
return memcmp(m_buf[a].vp_data.GetPtr(), m_buf[b].vp_data.GetPtr(), m_buf[a].vp_data.GetCount() * 4) == 0;
}
bool ProgramBuffer::CmpFP(const u32 a, const u32 b) const
bool GLProgramBuffer::CmpFP(const u32 a, const u32 b) const
{
if(m_buf[a].fp_data.GetCount() != m_buf[b].fp_data.GetCount()) return false;
return memcmp(m_buf[a].fp_data.GetPtr(), m_buf[b].fp_data.GetPtr(), m_buf[a].fp_data.GetCount()) == 0;
}
u32 ProgramBuffer::GetProg(u32 fp, u32 vp) const
u32 GLProgramBuffer::GetProg(u32 fp, u32 vp) const
{
if(fp == vp)
{
@ -82,34 +82,34 @@ u32 ProgramBuffer::GetProg(u32 fp, u32 vp) const
return 0;
}
void ProgramBuffer::Add(Program& prog, ShaderProgram& fp, VertexProgram& vp)
void GLProgramBuffer::Add(GLProgram& prog, GLShaderProgram& gl_fp, RSXShaderProgram& rsx_fp, GLVertexProgram& gl_vp, RSXVertexProgram& rsx_vp)
{
BufferInfo& new_buf = *new BufferInfo();
GLBufferInfo& new_buf = *new GLBufferInfo();
ConLog.Write("Add program (%d):", m_buf.GetCount());
ConLog.Write("*** prog id = %d", prog.id);
ConLog.Write("*** vp id = %d", vp.id);
ConLog.Write("*** fp id = %d", fp.id);
ConLog.Write("*** vp data size = %d", vp.data.GetCount() * 4);
ConLog.Write("*** fp data size = %d", fp.size);
ConLog.Write("*** vp id = %d", gl_vp.id);
ConLog.Write("*** fp id = %d", gl_fp.id);
ConLog.Write("*** vp data size = %d", rsx_vp.data.GetCount() * 4);
ConLog.Write("*** fp data size = %d", rsx_fp.size);
ConLog.Write("*** vp shader = \n%s", vp.shader);
ConLog.Write("*** fp shader = \n%s", fp.shader);
ConLog.Write("*** vp shader = \n%s", gl_vp.shader);
ConLog.Write("*** fp shader = \n%s", gl_fp.shader);
new_buf.prog_id = prog.id;
new_buf.vp_id = vp.id;
new_buf.fp_id = fp.id;
new_buf.vp_id = gl_vp.id;
new_buf.fp_id = gl_fp.id;
new_buf.fp_data.AddCpy(&Memory[fp.addr], fp.size);
new_buf.vp_data.CopyFrom(vp.data);
new_buf.fp_data.AddCpy(&Memory[rsx_fp.addr], rsx_fp.size);
new_buf.vp_data.CopyFrom(rsx_vp.data);
new_buf.vp_shader = vp.shader;
new_buf.fp_shader = fp.shader;
new_buf.vp_shader = gl_vp.shader;
new_buf.fp_shader = gl_fp.shader;
m_buf.Move(&new_buf);
}
void ProgramBuffer::Clear()
void GLProgramBuffer::Clear()
{
for(u32 i=0; i<m_buf.GetCount(); ++i)
{

View File

@ -0,0 +1,29 @@
#pragma once
#include "GLProgram.h"
struct GLBufferInfo
{
u32 prog_id;
u32 fp_id;
u32 vp_id;
Array<u8> fp_data;
Array<u32> vp_data;
ArrayString fp_shader;
ArrayString vp_shader;
};
struct GLProgramBuffer
{
Array<GLBufferInfo> m_buf;
int SearchFp(const RSXShaderProgram& rsx_fp, GLShaderProgram& gl_fp);
int SearchVp(const RSXVertexProgram& rsx_vp, GLVertexProgram& gl_vp);
bool CmpVP(const u32 a, const u32 b) const;
bool CmpFP(const u32 a, const u32 b) const;
u32 GetProg(u32 fp, u32 vp) const;
void Add(GLProgram& prog, GLShaderProgram& gl_fp, RSXShaderProgram& rsx_fp, GLVertexProgram& gl_vp, RSXVertexProgram& rsx_vp);
void Clear();
};

View File

@ -1,7 +1,7 @@
#pragma once
#include "OpenGL.h"
enum ParamFlag
enum GLParamFlag
{
PARAM_IN,
PARAM_OUT,
@ -10,13 +10,13 @@ enum ParamFlag
PARAM_NONE,
};
struct ParamItem
struct GLParamItem
{
ArrayString name;
ArrayString location;
ArrayString value;
ParamItem(const wxString& _name, int _location, const wxString& _value = wxEmptyString)
GLParamItem(const wxString& _name, int _location, const wxString& _value = wxEmptyString)
: name(_name)
, location(_location > -1 ? wxString::Format("layout (location = %d) ", _location) : "")
, value(_value)
@ -24,13 +24,13 @@ struct ParamItem
}
};
struct ParamType
struct GLParamType
{
const ParamFlag flag;
const GLParamFlag flag;
ArrayString type;
Array<ParamItem> items;
Array<GLParamItem> items;
ParamType(const ParamFlag _flag, const wxString& _type)
GLParamType(const GLParamFlag _flag, const wxString& _type)
: type(_type)
, flag(_flag)
{
@ -68,11 +68,11 @@ struct ParamType
}
};
struct ParamArray
struct GLParamArray
{
Array<ParamType> params;
Array<GLParamType> params;
ParamType* SearchParam(const wxString& type)
GLParamType* SearchParam(const wxString& type)
{
for(u32 i=0; i<params.GetCount(); ++i)
{
@ -82,7 +82,7 @@ struct ParamArray
return nullptr;
}
wxString GetParamFlag(const ParamFlag flag)
wxString GetParamFlag(const GLParamFlag flag)
{
switch(flag)
{
@ -95,46 +95,46 @@ struct ParamArray
return wxEmptyString;
}
bool HasParam(const ParamFlag flag, wxString type, const wxString& name)
bool HasParam(const GLParamFlag flag, wxString type, const wxString& name)
{
type = GetParamFlag(flag) + type;
ParamType* t = SearchParam(type);
GLParamType* t = SearchParam(type);
return t && t->SearchName(name);
}
wxString AddParam(const ParamFlag flag, wxString type, const wxString& name, const wxString& value)
wxString AddParam(const GLParamFlag flag, wxString type, const wxString& name, const wxString& value)
{
type = GetParamFlag(flag) + type;
ParamType* t = SearchParam(type);
GLParamType* t = SearchParam(type);
if(t)
{
if(!t->SearchName(name)) t->items.Move(new ParamItem(name, -1, value));
if(!t->SearchName(name)) t->items.Move(new GLParamItem(name, -1, value));
}
else
{
const u32 num = params.GetCount();
params.Move(new ParamType(flag, type));
params[num].items.Move(new ParamItem(name, -1, value));
params.Move(new GLParamType(flag, type));
params[num].items.Move(new GLParamItem(name, -1, value));
}
return name;
}
wxString AddParam(const ParamFlag flag, wxString type, const wxString& name, int location = -1)
wxString AddParam(const GLParamFlag flag, wxString type, const wxString& name, int location = -1)
{
type = GetParamFlag(flag) + type;
ParamType* t = SearchParam(type);
GLParamType* t = SearchParam(type);
if(t)
{
if(!t->SearchName(name)) t->items.Move(new ParamItem(name, location));
if(!t->SearchName(name)) t->items.Move(new GLParamItem(name, location));
}
else
{
const u32 num = params.GetCount();
params.Move(new ParamType(flag, type));
params[num].items.Move(new ParamItem(name, location));
params.Move(new GLParamType(flag, type));
params[num].items.Move(new GLParamItem(name, location));
}
return name;

View File

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "VertexProgram.h"
#include "GLVertexProgram.h"
wxString VertexDecompilerThread::GetMask(bool is_sca)
wxString GLVertexDecompilerThread::GetMask(bool is_sca)
{
wxString ret = wxEmptyString;
@ -23,17 +23,17 @@ wxString VertexDecompilerThread::GetMask(bool is_sca)
return ret.IsEmpty() || ret == "xyzw" ? wxEmptyString : ("." + ret);
}
wxString VertexDecompilerThread::GetVecMask()
wxString GLVertexDecompilerThread::GetVecMask()
{
return GetMask(false);
}
wxString VertexDecompilerThread::GetScaMask()
wxString GLVertexDecompilerThread::GetScaMask()
{
return GetMask(true);
}
wxString VertexDecompilerThread::GetDST(bool isSca)
wxString GLVertexDecompilerThread::GetDST(bool isSca)
{
static const wxString reg_table[] =
{
@ -73,7 +73,7 @@ wxString VertexDecompilerThread::GetDST(bool isSca)
return ret;
}
wxString VertexDecompilerThread::GetSRC(const u32 n, bool isSca)
wxString GLVertexDecompilerThread::GetSRC(const u32 n, bool isSca)
{
static const wxString reg_table[] =
{
@ -151,7 +151,7 @@ wxString VertexDecompilerThread::GetSRC(const u32 n, bool isSca)
return ret;
}
void VertexDecompilerThread::AddCode(bool is_sca, wxString code, bool src_mask)
void GLVertexDecompilerThread::AddCode(bool is_sca, wxString code, bool src_mask)
{
if(d0.cond == 0) return;
enum
@ -215,17 +215,17 @@ void VertexDecompilerThread::AddCode(bool is_sca, wxString code, bool src_mask)
main += "\t" + code + ";\n";
}
void VertexDecompilerThread::AddVecCode(const wxString& code, bool src_mask)
void GLVertexDecompilerThread::AddVecCode(const wxString& code, bool src_mask)
{
AddCode(false, code, src_mask);
}
void VertexDecompilerThread::AddScaCode(const wxString& code)
void GLVertexDecompilerThread::AddScaCode(const wxString& code)
{
AddCode(true, code, false);
}
wxString VertexDecompilerThread::BuildCode()
wxString GLVertexDecompilerThread::BuildCode()
{
wxString p = wxEmptyString;
@ -243,7 +243,7 @@ wxString VertexDecompilerThread::BuildCode()
return wxString::Format(prot, p, main);
}
void VertexDecompilerThread::Task()
void GLVertexDecompilerThread::Task()
{
for(u32 i=0;;)
{
@ -295,10 +295,10 @@ void VertexDecompilerThread::Task()
case 0x02: AddVecCode("(" + GetSRC(0) + " * " + GetSRC(1) + ")"); break; //MUL
case 0x03: AddVecCode("(" + GetSRC(0) + " + " + GetSRC(2) + ")"); break; //ADD
case 0x04: AddVecCode("(" + GetSRC(0) + " * " + GetSRC(1) + " + " + GetSRC(2) + ")"); break; //MAD
case 0x05: AddVecCode("vec4(dot(" + GetSRC(0) + ".xyz, " + GetSRC(1) + ".xyz)).xxxx"); break; //DP3
case 0x06: AddVecCode("vec4(dot(vec4(" + GetSRC(0) + ".xyz, 1), " + GetSRC(1) + ")).xxxx"); break; //DPH
case 0x07: AddVecCode("vec4(dot(" + GetSRC(0) + ", " + GetSRC(1) + ")).xxxx"); break; //DP4
case 0x08: AddVecCode("vec4(distance(" + GetSRC(0) + ", " + GetSRC(1) + ")).xxxx"); break; //DST
case 0x05: AddVecCode("vec2(dot(" + GetSRC(0) + ".xyz, " + GetSRC(1) + ".xyz), 0).xxxx"); break; //DP3
case 0x06: AddVecCode("vec2(dot(vec4(" + GetSRC(0) + ".xyz, 1), " + GetSRC(1) + "), 0).xxxx"); break; //DPH
case 0x07: AddVecCode("vec2(dot(" + GetSRC(0) + ", " + GetSRC(1) + "), 0).xxxx"); break; //DP4
case 0x08: AddVecCode("vec2(distance(" + GetSRC(0) + ", " + GetSRC(1) + "), 0).xxxx"); break; //DST
case 0x09: AddVecCode("min(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //MIN
case 0x0a: AddVecCode("max(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //MAX
case 0x0b: AddVecCode("vec4(lessThan(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SLT
@ -306,11 +306,11 @@ void VertexDecompilerThread::Task()
case 0x0e: AddVecCode("fract(" + GetSRC(0) + ")"); break; //FRC
case 0x0f: AddVecCode("floor(" + GetSRC(0) + ")"); break; //FLR
case 0x10: AddVecCode("vec4(equal(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SEQ
//case 0x11: AddVecCode("vec4(0.0f, 0.0f, 0.0f, 0.0f)"); break; //SFL
//case 0x11: AddVecCode("vec4(equal(" + GetSRC(0) + ", vec4(0, 0, 0, 0)))"); break; //SFL
case 0x12: AddVecCode("vec4(greaterThan(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SGT
case 0x13: AddVecCode("vec4(lessThanEqual(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SLE
case 0x14: AddVecCode("vec4(notEqual(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SNE
//case 0x15: AddVecCode("vec4(1.0f, 1.0f, 1.0f, 1.0f)"); break; //STR
//case 0x15: AddVecCode("vec4(notEqual(" + GetSRC(0) + ", vec4(0, 0, 0, 0)))"); break; //STR
case 0x16: AddVecCode("sign(" + GetSRC(0) + ")"); break; //SSG
default:
@ -327,13 +327,13 @@ void VertexDecompilerThread::Task()
main = wxEmptyString;
}
VertexProgram::VertexProgram()
GLVertexProgram::GLVertexProgram()
: m_decompiler_thread(nullptr)
, id(0)
{
}
VertexProgram::~VertexProgram()
GLVertexProgram::~GLVertexProgram()
{
if(m_decompiler_thread)
{
@ -350,10 +350,10 @@ VertexProgram::~VertexProgram()
Delete();
}
void VertexProgram::Decompile()
void GLVertexProgram::Decompile(RSXVertexProgram& prog)
{
#if 0
VertexDecompilerThread(data, shader, parr).Entry();
GLVertexDecompilerThread(data, shader, parr).Entry();
#else
if(m_decompiler_thread)
{
@ -367,12 +367,12 @@ void VertexProgram::Decompile()
m_decompiler_thread = nullptr;
}
m_decompiler_thread = new VertexDecompilerThread(data, shader, parr);
m_decompiler_thread = new GLVertexDecompilerThread(prog.data, shader, parr);
m_decompiler_thread->Start();
#endif
}
void VertexProgram::Compile()
void GLVertexProgram::Compile()
{
if(id) glDeleteShader(id);
@ -407,9 +407,8 @@ void VertexProgram::Compile()
}
void VertexProgram::Delete()
void GLVertexProgram::Delete()
{
data.Clear();
parr.params.Clear();
shader.Clear();
@ -419,79 +418,3 @@ void VertexProgram::Delete()
id = 0;
}
}
VertexData::VertexData()
: frequency(0)
, stride(0)
, size(0)
, type(0)
, addr(0)
, data()
{
}
void VertexData::Reset()
{
frequency = 0;
stride = 0;
size = 0;
type = 0;
addr = 0;
data.ClearF();
}
void VertexData::Load(u32 start, u32 count)
{
if(!addr) return;
const u32 tsize = GetTypeSize();
data.SetCount((start + count) * tsize * size);
for(u32 i=start; i<start + count; ++i)
{
const u8* src = Memory.GetMemFromAddr(addr) + stride * i;
u8* dst = &data[i * tsize * size];
switch(tsize)
{
case 1:
{
memcpy(dst, src, size);
}
break;
case 2:
{
const u16* c_src = (const u16*)src;
u16* c_dst = (u16*)dst;
for(u32 j=0; j<size; ++j) *c_dst++ = re(*c_src++);
}
break;
case 4:
{
const u32* c_src = (const u32*)src;
u32* c_dst = (u32*)dst;
for(u32 j=0; j<size; ++j) *c_dst++ = re(*c_src++);
}
break;
}
}
}
u32 VertexData::GetTypeSize()
{
switch (type)
{
case 1: return 2;
case 2: return 4;
case 3: return 2;
case 4: return 1;
case 5: return 2;
case 7: return 1;
}
ConLog.Error("Bad vertex data type! %d", type);
return 1;
}

View File

@ -1,7 +1,8 @@
#pragma once
#include "ShaderParam.h"
#include "GLShaderParam.h"
#include "Emu/GS/RSXVertexProgram.h"
struct VertexDecompilerThread : public ThreadBase
struct GLVertexDecompilerThread : public ThreadBase
{
union D0
{
@ -129,9 +130,9 @@ struct VertexDecompilerThread : public ThreadBase
wxString main;
wxString& m_shader;
Array<u32>& m_data;
ParamArray& m_parr;
GLParamArray& m_parr;
VertexDecompilerThread(Array<u32>& data, wxString& shader, ParamArray& parr)
GLVertexDecompilerThread(Array<u32>& data, wxString& shader, GLParamArray& parr)
: ThreadBase(false, "Vertex Shader Decompiler Thread")
, m_data(data)
, m_shader(shader)
@ -152,17 +153,16 @@ struct VertexDecompilerThread : public ThreadBase
virtual void Task();
};
struct VertexProgram
{
wxString shader;
struct GLVertexProgram
{
GLVertexDecompilerThread* m_decompiler_thread;
GLVertexProgram();
~GLVertexProgram();
GLParamArray parr;
u32 id;
VertexDecompilerThread* m_decompiler_thread;
VertexProgram();
~VertexProgram();
Array<u32> data;
ParamArray parr;
wxString shader;
void Wait()
{
@ -171,27 +171,8 @@ struct VertexProgram
m_decompiler_thread->Wait();
}
}
void Decompile();
void Decompile(RSXVertexProgram& prog);
void Compile();
void Delete();
};
struct VertexData
{
u32 frequency;
u32 stride;
u32 size;
u32 type;
u32 addr;
u32 constant_count;
Array<u8> data;
VertexData();
void Reset();
bool IsEnabled() { return size > 0; }
void Load(u32 start, u32 count);
u32 GetTypeSize();
};

View File

@ -1,29 +0,0 @@
#pragma once
#include "Program.h"
struct BufferInfo
{
u32 prog_id;
u32 fp_id;
u32 vp_id;
Array<u8> fp_data;
Array<u32> vp_data;
ArrayString fp_shader;
ArrayString vp_shader;
};
struct ProgramBuffer
{
Array<BufferInfo> m_buf;
int SearchFp(ShaderProgram& fp);
int SearchVp(VertexProgram& vp);
bool CmpVP(const u32 a, const u32 b) const;
bool CmpFP(const u32 a, const u32 b) const;
u32 GetProg(u32 fp, u32 vp) const;
void Add(Program& prog, ShaderProgram& fp, VertexProgram& vp);
void Clear();
};

View File

@ -32,6 +32,7 @@ void GSManager::Close()
if(m_render)
{
m_render->Close();
delete m_render;
m_render = nullptr;
}
}

View File

@ -76,28 +76,6 @@ void GSFrame::SetSize(int width, int height)
}
*/
GSRender::GSRender()
: m_ctrl(nullptr)
, m_flip_status(0)
, m_flip_mode(CELL_GCM_DISPLAY_VSYNC)
, m_main_mem_addr(0)
{
}
u32 GSRender::GetAddress(u32 offset, u8 location)
{
switch(location)
{
case CELL_GCM_LOCATION_LOCAL: return m_local_mem_addr + offset;
case CELL_GCM_LOCATION_MAIN: return m_main_mem_addr + offset;
}
ConLog.Error("GetAddress(offset=0x%x, location=0x%x", location);
assert(0);
return 0;
}
GSLockCurrent::GSLockCurrent(GSLockType type) : GSLock(Emu.GetGSManager().GetRender(), type)
{
}

View File

@ -1,16 +1,6 @@
#pragma once
#include "Emu/GS/GCM.h"
#include "Emu/SysCalls/Callback.h"
#include "rpcs3.h"
enum Method
{
CELL_GCM_METHOD_FLAG_NON_INCREMENT = 0x40000000,
CELL_GCM_METHOD_FLAG_JUMP = 0x20000000,
CELL_GCM_METHOD_FLAG_CALL = 0x00000002,
CELL_GCM_METHOD_FLAG_RETURN = 0x00020000,
};
#include "Emu/GS/RSXThread.h"
wxSize AspectRatio(wxSize rs, const wxSize as);
@ -40,138 +30,13 @@ private:
DECLARE_EVENT_TABLE();
};
struct CellGcmSurface
struct GSRender : public RSXThread
{
u8 type;
u8 antialias;
u8 color_format;
u8 color_target;
u8 color_location[4];
u32 color_offset[4];
u32 color_pitch[4];
u8 depth_format;
u8 depth_location;
u16 pad;
u32 depth_offset;
u32 depth_pitch;
u16 width;
u16 height;
u16 x;
u16 y;
};
struct CellGcmReportData
{
u64 timer;
u32 value;
u32 pad;
};
struct CellGcmZcullInfo
{
u32 region;
u32 size;
u32 start;
u32 offset;
u32 status0;
u32 status1;
};
struct CellGcmTileInfo
{
u32 tile;
u32 limit;
u32 pitch;
u32 format;
};
struct GcmZcullInfo
{
u32 m_offset;
u32 m_width;
u32 m_height;
u32 m_cullStart;
u32 m_zFormat;
u32 m_aaFormat;
u32 m_zCullDir;
u32 m_zCullFormat;
u32 m_sFunc;
u32 m_sRef;
u32 m_sMask;
bool m_binded;
GcmZcullInfo()
virtual ~GSRender()
{
memset(this, 0, sizeof(*this));
}
};
struct GcmTileInfo
{
u8 m_location;
u32 m_offset;
u32 m_size;
u32 m_pitch;
u8 m_comp;
u16 m_base;
u8 m_bank;
bool m_binded;
GcmTileInfo()
{
memset(this, 0, sizeof(*this));
}
CellGcmTileInfo Pack()
{
CellGcmTileInfo ret;
re(ret.tile, (m_location + 1) | (m_bank << 4) | ((m_offset / 0x10000) << 16) | (m_location << 31));
re(ret.limit, ((m_offset + m_size - 1) / 0x10000) << 16 | (m_location << 31));
re(ret.pitch, (m_pitch / 0x100) << 8);
re(ret.format, m_base | ((m_base + ((m_size - 1) / 0x10000)) << 13) | (m_comp << 26) | (1 << 30));
return ret;
}
};
static const int g_tiles_count = 15;
struct GSRender
{
u32 m_ioAddress, m_ioSize, m_ctrlAddress;
CellGcmControl* m_ctrl;
wxCriticalSection m_cs_main;
wxSemaphore m_sem_flush;
wxSemaphore m_sem_flip;
int m_flip_status;
int m_flip_mode;
volatile bool m_draw;
Callback m_flip_handler;
GcmTileInfo m_tiles[g_tiles_count];
u32 m_tiles_addr;
u32 m_zculls_addr;
u32 m_gcm_buffers_addr;
u32 m_gcm_buffers_count;
u32 m_gcm_current_buffer;
u32 m_ctxt_addr;
u32 m_report_main_addr;
u32 m_local_mem_addr, m_main_mem_addr;
Array<MemInfo> m_main_mem_info;
GSRender();
virtual void Init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress)=0;
virtual void Draw()=0;
virtual void Close()=0;
u32 GetAddress(u32 offset, u8 location);
};
enum GSLockType

View File

@ -24,168 +24,53 @@ private:
}
};
struct NullRSXThread : public wxThread
{
wxWindow* m_parent;
Stack<u32> call_stack;
NullRSXThread(wxWindow* parent);
virtual void OnExit();
void Start();
ExitCode Entry();
};
class NullGSRender
: public wxWindow
, public GSRender
{
private:
NullRSXThread* m_rsx_thread;
public:
NullGSFrame* m_frame;
NullGSRender()
: m_frame(nullptr)
, m_rsx_thread(nullptr)
NullGSRender() : m_frame(nullptr)
{
m_draw = false;
m_frame = new NullGSFrame();
}
~NullGSRender()
virtual ~NullGSRender()
{
Close();
m_frame->Close();
}
private:
virtual void Init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress)
virtual void OnInit()
{
if(m_frame->IsShown()) return;
m_frame->SetSize(740, 480);
m_frame->Show();
m_ioAddress = ioAddress;
m_ctrlAddress = ctrlAddress;
m_ioSize = ioSize;
m_local_mem_addr = localAddress;
m_ctrl = (CellGcmControl*)Memory.GetMemFromAddr(m_ctrlAddress);
(m_rsx_thread = new NullRSXThread(this))->Start();
}
public:
void DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u32 count)
virtual void OnInitThread()
{
switch(cmd)
{
case NV406E_SET_REFERENCE:
m_ctrl->ref = re32(args[0]);
break;
}
}
virtual void Draw()
virtual void OnExitThread()
{
}
virtual void OnReset()
{
}
virtual void ExecCMD()
{
}
virtual void Flip()
{
//if(m_frame && !m_frame->IsBeingDeleted()) m_frame->Draw();
m_draw = true;
}
virtual void Close()
{
if(m_rsx_thread) m_rsx_thread->Delete();
if(IsAlive()) Stop();
if(m_frame->IsShown()) m_frame->Hide();
m_ctrl = NULL;
}
};
NullRSXThread::NullRSXThread(wxWindow* parent)
: wxThread(wxTHREAD_DETACHED)
, m_parent(parent)
{
}
void NullRSXThread::OnExit()
{
call_stack.Clear();
}
void NullRSXThread::Start()
{
Create();
Run();
}
wxThread::ExitCode NullRSXThread::Entry()
{
ConLog.Write("Null RSX thread entry");
NullGSRender& p = *(NullGSRender*)m_parent;
while(!TestDestroy() && p.m_frame && !p.m_frame->IsBeingDeleted())
{
wxCriticalSectionLocker lock(p.m_cs_main);
if(p.m_ctrl->get == p.m_ctrl->put || !Emu.IsRunning())
{
SemaphorePostAndWait(p.m_sem_flush);
if(p.m_draw)
{
p.m_draw = false;
p.m_flip_status = 0;
if(SemaphorePostAndWait(p.m_sem_flip)) continue;
}
Sleep(1);
continue;
}
const u32 get = re(p.m_ctrl->get);
const u32 cmd = Memory.Read32(p.m_ioAddress + get);
const u32 count = (cmd >> 18) & 0x7ff;
if(cmd & CELL_GCM_METHOD_FLAG_JUMP)
{
p.m_ctrl->get = re32(cmd & ~(CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_NON_INCREMENT));
ConLog.Warning("rsx jump!");
continue;
}
if(cmd & CELL_GCM_METHOD_FLAG_CALL)
{
call_stack.Push(get + 4);
p.m_ctrl->get = re32(cmd & ~CELL_GCM_METHOD_FLAG_CALL);
ConLog.Warning("rsx call!");
continue;
}
if(cmd & CELL_GCM_METHOD_FLAG_RETURN)
{
p.m_ctrl->get = re32(call_stack.Pop());
ConLog.Warning("rsx return!");
continue;
}
if(cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT)
{
//ConLog.Warning("non increment cmd! 0x%x", cmd);
}
if(cmd == 0)
{
ConLog.Warning("null cmd: addr=0x%x, put=0x%x, get=0x%x", p.m_ioAddress + get, re(p.m_ctrl->put), get);
Emu.Pause();
continue;
}
p.DoCmd(cmd, cmd & 0x3ffff, mem32_ptr_t(p.m_ioAddress + get + 4), count);
re(p.m_ctrl->get, get + (count + 1) * 4);
}
ConLog.Write("Null RSX thread exit...");
call_stack.Clear();
return (ExitCode)0;
}

View File

@ -0,0 +1,15 @@
#pragma once
struct RSXShaderProgram
{
u32 size;
u32 addr;
u32 offset;
RSXShaderProgram()
: size(0)
, addr(0)
, offset(0)
{
}
};

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,281 @@
#pragma once
#include "GCM.h"
#include "RSXVertexProgram.h"
#include "RSXFragmentProgram.h"
#include "Emu/SysCalls/Callback.h"
class ExecRSXCMDdata
enum Method
{
CELL_GCM_METHOD_FLAG_NON_INCREMENT = 0x40000000,
CELL_GCM_METHOD_FLAG_JUMP = 0x20000000,
CELL_GCM_METHOD_FLAG_CALL = 0x00000002,
CELL_GCM_METHOD_FLAG_RETURN = 0x00020000,
};
class RSXTexture
{
public:
bool m_enabled;
u32 m_width, m_height;
u32 m_offset;
bool m_cubemap;
u8 m_dimension;
u32 m_format;
u16 m_mipmap;
u32 m_pitch;
u16 m_depth;
u16 m_minlod;
u16 m_maxlod;
u8 m_maxaniso;
u8 m_wraps;
u8 m_wrapt;
u8 m_wrapr;
u8 m_unsigned_remap;
u8 m_zfunc;
u8 m_gamma;
u8 m_aniso_bias;
u8 m_signed_remap;
u16 m_bias;
u8 m_min_filter;
u8 m_mag_filter;
u8 m_conv;
u8 m_a_signed;
u8 m_r_signed;
u8 m_g_signed;
u8 m_b_signed;
u32 m_remap;
public:
RSXTexture()
: m_width(0), m_height(0)
, m_offset(0)
, m_enabled(false)
, m_cubemap(false)
, m_dimension(0)
, m_format(0)
, m_mipmap(0)
, m_minlod(0)
, m_maxlod(1000)
, m_maxaniso(0)
{
}
void SetRect(const u32 width, const u32 height)
{
m_width = width;
m_height = height;
}
void SetFormat(const bool cubemap, const u8 dimension, const u32 format, const u16 mipmap)
{
m_cubemap = cubemap;
m_dimension = dimension;
m_format = format;
m_mipmap = mipmap;
}
void SetAddress(u8 wraps, u8 wrapt, u8 wrapr, u8 unsigned_remap, u8 zfunc, u8 gamma, u8 aniso_bias, u8 signed_remap)
{
m_wraps = wraps;
m_wrapt = wrapt;
m_wrapr = wrapr;
m_unsigned_remap = unsigned_remap;
m_zfunc = zfunc;
m_gamma = gamma;
m_aniso_bias = aniso_bias;
m_signed_remap = signed_remap;
}
void SetControl0(const bool enable, const u16 minlod, const u16 maxlod, const u8 maxaniso)
{
m_enabled = enable;
m_minlod = minlod;
m_maxlod = maxlod;
m_maxaniso = maxaniso;
}
void SetControl1(u32 remap)
{
m_remap = remap;
}
void SetControl3(u16 depth, u32 pitch)
{
m_depth = depth;
m_pitch = pitch;
}
void SetFilter(u16 bias, u8 min, u8 mag, u8 conv, u8 a_signed, u8 r_signed, u8 g_signed, u8 b_signed)
{
m_bias = bias;
m_min_filter = min;
m_mag_filter = mag;
m_conv = conv;
m_a_signed = a_signed;
m_r_signed = r_signed;
m_g_signed = g_signed;
m_b_signed = b_signed;
}
u32 GetFormat() const
{
return m_format;
}
void SetOffset(const u32 offset)
{
m_offset = offset;
}
wxSize GetRect() const
{
return wxSize(m_width, m_height);
}
bool IsEnabled() const
{
return m_enabled;
}
u32 GetOffset() const
{
return m_offset;
}
};
struct RSXVertexData
{
u32 frequency;
u32 stride;
u32 size;
u32 type;
u32 addr;
u32 constant_count;
Array<u8> data;
RSXVertexData();
void Reset();
bool IsEnabled() { return size > 0; }
void Load(u32 start, u32 count);
u32 GetTypeSize();
};
struct RSXIndexArrayData
{
Array<u8> m_data;
int m_type;
u32 m_first;
u32 m_count;
u32 m_addr;
u32 index_max;
u32 index_min;
RSXIndexArrayData()
{
Reset();
}
void Reset()
{
m_type = 0;
m_first = ~0;
m_count = 0;
m_addr = 0;
index_min = ~0;
index_max = 0;
m_data.Clear();
}
};
struct RSXTransformConstant
{
u32 id;
float x, y, z, w;
RSXTransformConstant()
: x(0.0f)
, y(0.0f)
, z(0.0f)
, w(0.0f)
{
}
RSXTransformConstant(u32 id, float x, float y, float z, float w)
: id(id)
, x(x)
, y(y)
, z(z)
, w(w)
{
}
};
class RSXThread : public ThreadBase
{
public:
static const uint m_textures_count = 16;
static const uint m_vertex_count = 16;
static const uint m_fragment_count = 16;
static const uint m_tiles_count = 15;
protected:
Stack<u32> m_call_stack;
CellGcmControl* m_ctrl;
public:
GcmTileInfo m_tiles[m_tiles_count];
RSXTexture m_textures[m_textures_count];
RSXVertexData m_vertex_data[m_vertex_count];
RSXIndexArrayData m_indexed_array;
Array<RSXTransformConstant> m_fragment_constants;
Array<RSXTransformConstant> m_transform_constants;
u32 m_cur_shader_prog_num;
RSXShaderProgram m_shader_progs[m_fragment_count];
RSXShaderProgram* m_cur_shader_prog;
RSXVertexProgram m_vertex_progs[m_vertex_count];
RSXVertexProgram* m_cur_vertex_prog;
public:
u32 m_ioAddress, m_ioSize, m_ctrlAddress;
int m_flip_status;
int m_flip_mode;
u32 m_tiles_addr;
u32 m_zculls_addr;
u32 m_gcm_buffers_addr;
u32 m_gcm_buffers_count;
u32 m_gcm_current_buffer;
u32 m_ctxt_addr;
u32 m_report_main_addr;
u32 m_local_mem_addr, m_main_mem_addr;
Array<MemInfo> m_main_mem_info;
protected:
uint m_draw_mode;
u32 m_width, m_height;
u32 m_draw_array_count;
public:
wxCriticalSection m_cs_main;
wxSemaphore m_sem_flush;
wxSemaphore m_sem_flip;
Callback m_flip_handler;
public:
bool m_set_color_mask;
bool m_color_mask_r;
@ -45,8 +318,13 @@ public:
bool m_set_front_polygon_mode;
u32 m_front_polygon_mode;
bool m_set_clear_surface;
u32 m_clear_surface_mask;
u32 m_clear_surface_z;
u8 m_clear_surface_s;
u8 m_clear_surface_color_r;
u8 m_clear_surface_color_g;
u8 m_clear_surface_color_b;
u8 m_clear_surface_color_a;
bool m_set_blend_sfactor;
u16 m_blend_sfactor_rgb;
@ -119,11 +397,12 @@ public:
u8 m_blend_color_b;
u8 m_blend_color_a;
bool m_set_clear_color;
u8 m_clear_color_r;
u8 m_clear_color_g;
u8 m_clear_color_b;
u8 m_clear_color_a;
u8 m_clear_s;
u32 m_clear_z;
u32 m_context_dma_img_src;
u32 m_context_dma_img_dst;
@ -171,11 +450,6 @@ public:
u8 m_surface_antialias;
u8 m_surface_width;
u8 m_surface_height;
u32 m_surface_pitch_a;
u32 m_surface_offset_a;
u32 m_surface_offset_z;
u32 m_surface_offset_b;
u32 m_surface_pitch_b;
bool m_set_context_dma_color_a;
u32 m_context_dma_color_a;
@ -186,6 +460,9 @@ public:
bool m_set_context_dma_color_c;
u32 m_context_dma_color_c;
bool m_set_context_dma_color_d;
u32 m_context_dma_color_d;
bool m_set_context_dma_z;
u32 m_context_dma_z;
@ -205,35 +482,74 @@ public:
bool m_set_alpha_ref;
u32 m_alpha_ref;
u32 m_surface_pitch_a;
u32 m_surface_pitch_b;
u32 m_surface_pitch_c;
u32 m_surface_pitch_d;
u32 m_surface_pitch_z;
u32 m_surface_offset_a;
u32 m_surface_offset_b;
u32 m_surface_offset_c;
u32 m_surface_offset_d;
u32 m_surface_offset_z;
u16 m_shader_window_height;
u8 m_shader_window_origin;
u16 m_shader_window_pixel_centers;
u32 m_surface_colour_target;
u8 m_begin_end;
public:
ExecRSXCMDdata()
protected:
RSXThread()
: ThreadBase(false, "RSXThread")
, m_ctrl(nullptr)
, m_flip_status(0)
, m_flip_mode(CELL_GCM_DISPLAY_VSYNC)
, m_main_mem_addr(0)
, m_local_mem_addr(0)
, m_draw_mode(0)
, m_draw_array_count(0)
{
Reset();
}
virtual void Reset()
{
m_set_color_mask = false;
m_set_alpha_test = false;
m_set_blend = false;
m_set_depth_bounds_test = false;
m_depth_test_enable = false;
m_set_logic_op = false;
m_set_cull_face_enable = false;
m_set_dither = false;
m_set_stencil_test = false;
m_set_line_smooth = false;
m_set_poly_smooth = false;
m_set_two_sided_stencil_test_enable = false;
m_set_surface_clip_horizontal = false;
m_set_surface_clip_vertical = false;
m_clear_color_r = 0;
m_clear_color_g = 0;
m_clear_color_b = 0;
m_clear_color_a = 0;
m_clear_z = 0xffffff;
m_clear_s = 0;
Reset();
}
void Reset()
{
m_set_color_mask = false;
m_set_clip = false;
m_set_depth_func = false;
m_depth_test_enable = false;
m_set_viewport_horizontal = false;
m_set_viewport_vertical = false;
m_set_scissor_horizontal = false;
m_set_scissor_vertical = false;
m_set_front_polygon_mode = false;
m_set_clear_surface = false;
m_clear_surface_mask = 0;
m_set_blend_sfactor = false;
m_set_blend_dfactor = false;
m_set_logic_op = false;
m_set_cull_face_enable = false;
m_set_dither = false;
m_set_stencil_test = false;
m_set_stencil_mask = false;
m_set_stencil_func = false;
m_set_stencil_func_ref = false;
@ -241,7 +557,6 @@ public:
m_set_stencil_fail = false;
m_set_stencil_zfail = false;
m_set_stencil_zpass = false;
m_set_two_sided_stencil_test_enable = false;
m_set_back_stencil_mask = false;
m_set_back_stencil_func = false;
m_set_back_stencil_func_ref = false;
@ -251,12 +566,9 @@ public:
m_set_back_stencil_zpass = false;
m_set_blend_equation = false;
m_set_depth_mask = false;
m_set_line_smooth = false;
m_set_poly_smooth = false;
m_set_line_width = false;
m_set_shade_mode = false;
m_set_blend_color = false;
m_set_clear_color = false;
m_set_semaphore_offset = false;
m_set_fog_mode = false;
m_set_fog_params = false;
@ -265,28 +577,67 @@ public:
m_set_context_dma_color_a = false;
m_set_context_dma_color_b = false;
m_set_context_dma_color_c = false;
m_set_context_dma_color_d = false;
m_set_context_dma_z = false;
m_set_surface_clip_horizontal = false;
m_set_surface_clip_vertical = false;
m_set_cull_face = false;
m_set_alpha_func = false;
m_set_alpha_ref = false;
m_clear_surface_mask = 0;
m_begin_end = 0;
}
virtual void ExecCMD()=0;
};
void Begin(u32 draw_mode);
void End();
class RSXThread : public ThreadBase
{
Array<u32> call_stack;
CellGcmControl& m_ctrl;
u32 m_ioAddress;
void DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u32 count);
protected:
RSXThread(CellGcmControl* ctrl, u32 ioAddress);
virtual void OnInit() = 0;
virtual void OnInitThread() = 0;
virtual void OnExitThread() = 0;
virtual void OnReset() = 0;
virtual void ExecCMD() = 0;
virtual void Flip() = 0;
u32 GetAddress(u32 offset, u8 location)
{
switch(location)
{
case CELL_GCM_LOCATION_LOCAL: return m_local_mem_addr + offset;
case CELL_GCM_LOCATION_MAIN: return m_main_mem_addr + offset;
}
ConLog.Error("GetAddress(offset=0x%x, location=0x%x)", location);
assert(0);
return 0;
}
void LoadVertexData(u32 first, u32 count)
{
for(u32 i=0; i<m_vertex_count; ++i)
{
if(!m_vertex_data[i].IsEnabled()) continue;
m_vertex_data[i].Load(first, count);
}
}
private:
virtual void Task();
virtual void OnExit();
};
public:
void Init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress)
{
m_ctrl = (CellGcmControl*)&Memory[ctrlAddress];
m_ioAddress = ioAddress;
m_ioSize = ioSize;
m_ctrlAddress = ctrlAddress;
m_local_mem_addr = localAddress;
m_cur_vertex_prog = nullptr;
m_cur_shader_prog = nullptr;
m_cur_shader_prog_num = 0;
OnInit();
ThreadBase::Start();
}
};

View File

@ -0,0 +1,6 @@
#pragma once
struct RSXVertexProgram
{
Array<u32> data;
};

View File

@ -0,0 +1,160 @@
//DynamicMemoryBlockBase
template<typename PT>
DynamicMemoryBlockBase<PT>::DynamicMemoryBlockBase() : m_max_size(0)
{
}
template<typename PT>
const u32 DynamicMemoryBlockBase<PT>::GetUsedSize() const
{
u32 size = 0;
for(u32 i=0; i<m_used_mem.GetCount(); ++i)
{
size += m_used_mem[i].size;
}
return size;
}
template<typename PT>
bool DynamicMemoryBlockBase<PT>::IsInMyRange(const u64 addr)
{
return addr >= GetStartAddr() && addr < GetStartAddr() + GetSize();
}
template<typename PT>
bool DynamicMemoryBlockBase<PT>::IsInMyRange(const u64 addr, const u32 size)
{
return IsInMyRange(addr) && IsInMyRange(addr + size - 1);
}
template<typename PT>
bool DynamicMemoryBlockBase<PT>::IsMyAddress(const u64 addr)
{
for(u32 i=0; i<m_used_mem.GetCount(); ++i)
{
if(addr >= m_used_mem[i].addr && addr < m_used_mem[i].addr + m_used_mem[i].size)
{
return true;
}
}
return false;
}
template<typename PT>
MemoryBlock* DynamicMemoryBlockBase<PT>::SetRange(const u64 start, const u32 size)
{
m_max_size = size;
MemoryBlock::SetRange(start, 0);
return this;
}
template<typename PT>
void DynamicMemoryBlockBase<PT>::Delete()
{
m_used_mem.Clear();
m_max_size = 0;
MemoryBlock::Delete();
}
template<typename PT>
bool DynamicMemoryBlockBase<PT>::Alloc(u64 addr, u32 size)
{
if(!IsInMyRange(addr, size))
{
assert(0);
return false;
}
if(IsMyAddress(addr) || IsMyAddress(addr + size - 1))
{
return false;
}
for(u32 i=0; i<m_used_mem.GetCount(); ++i)
{
if(addr >= m_used_mem[i].addr && addr < m_used_mem[i].addr + m_used_mem[i].size) return false;
}
AppendUsedMem(addr, size);
return true;
}
template<typename PT>
void DynamicMemoryBlockBase<PT>::AppendUsedMem(u64 addr, u32 size)
{
m_used_mem.Move(new MemBlockInfo(addr, size));
}
template<typename PT>
u64 DynamicMemoryBlockBase<PT>::Alloc(u32 size)
{
for(u64 addr=GetStartAddr(); addr <= GetEndAddr() - size;)
{
bool is_good_addr = true;
for(u32 i=0; i<m_used_mem.GetCount(); ++i)
{
if((addr >= m_used_mem[i].addr && addr < m_used_mem[i].addr + m_used_mem[i].size) ||
(m_used_mem[i].addr >= addr && m_used_mem[i].addr < addr + size))
{
is_good_addr = false;
addr = m_used_mem[i].addr + m_used_mem[i].size;
break;
}
}
if(!is_good_addr) continue;
AppendUsedMem(addr, size);
return addr;
}
return 0;
}
template<typename PT>
bool DynamicMemoryBlockBase<PT>::Alloc()
{
return Alloc(GetSize() - GetUsedSize()) != 0;
}
template<typename PT>
bool DynamicMemoryBlockBase<PT>::Free(u64 addr)
{
for(u32 i=0; i<m_used_mem.GetCount(); ++i)
{
if(addr == m_used_mem[i].addr)
{
m_used_mem.RemoveAt(i);
return true;
}
}
return false;
}
template<typename PT>
u8* DynamicMemoryBlockBase<PT>::GetMem(u64 addr) const
{
for(u32 i=0; i<m_used_mem.GetCount(); ++i)
{
u64 _addr = FixAddr(m_used_mem[i].addr);
if(addr >= _addr && addr < _addr + m_used_mem[i].size)
{
return (u8*)m_used_mem[i].mem + addr - _addr;
}
}
ConLog.Error("GetMem(%llx) from not allocated address.", addr);
assert(0);
return nullptr;
}

View File

@ -248,6 +248,86 @@ bool MemoryBlock::Write128(const u64 addr, const u128 value)
return true;
}
bool MemoryBlockLE::Read8(const u64 addr, u8* value)
{
if(!IsMyAddress(addr)) return false;
*value = *(u8*)GetMem(FixAddr(addr));
return true;
}
bool MemoryBlockLE::Read16(const u64 addr, u16* value)
{
if(!IsMyAddress(addr)) return false;
*value = *(u16*)GetMem(FixAddr(addr));
return true;
}
bool MemoryBlockLE::Read32(const u64 addr, u32* value)
{
if(!IsMyAddress(addr)) return false;
*value = *(u32*)GetMem(FixAddr(addr));
return true;
}
bool MemoryBlockLE::Read64(const u64 addr, u64* value)
{
if(!IsMyAddress(addr)) return false;
*value = *(u64*)GetMem(FixAddr(addr));
return true;
}
bool MemoryBlockLE::Read128(const u64 addr, u128* value)
{
if(!IsMyAddress(addr)) return false;
*value = *(u128*)GetMem(FixAddr(addr));
return true;
}
bool MemoryBlockLE::Write8(const u64 addr, const u8 value)
{
if(!IsMyAddress(addr)) return false;
*(u8*)GetMem(FixAddr(addr)) = value;
return true;
}
bool MemoryBlockLE::Write16(const u64 addr, const u16 value)
{
if(!IsMyAddress(addr)) return false;
*(u16*)GetMem(FixAddr(addr)) = value;
return true;
}
bool MemoryBlockLE::Write32(const u64 addr, const u32 value)
{
if(!IsMyAddress(addr)) return false;
*(u32*)GetMem(FixAddr(addr)) = value;
return true;
}
bool MemoryBlockLE::Write64(const u64 addr, const u64 value)
{
if(!IsMyAddress(addr)) return false;
*(u64*)GetMem(FixAddr(addr)) = value;
return true;
}
bool MemoryBlockLE::Write128(const u64 addr, const u128 value)
{
if(!IsMyAddress(addr)) return false;
*(u128*)GetMem(FixAddr(addr)) = value;
return true;
}
//NullMemoryBlock
bool NullMemoryBlock::Read8(const u64 addr, u8* WXUNUSED(value))
{
@ -319,199 +399,24 @@ bool NullMemoryBlock::Write128(const u64 addr, const u128 value)
return false;
}
//DynamicMemoryBlock
DynamicMemoryBlock::DynamicMemoryBlock() : m_max_size(0)
{
}
const u32 DynamicMemoryBlock::GetUsedSize() const
{
u32 size = 0;
for(u32 i=0; i<m_used_mem.GetCount(); ++i)
{
size += m_used_mem[i].size;
}
return size;
}
bool DynamicMemoryBlock::IsInMyRange(const u64 addr)
{
return addr >= GetStartAddr() && addr < GetStartAddr() + GetSize();
}
bool DynamicMemoryBlock::IsInMyRange(const u64 addr, const u32 size)
{
return IsInMyRange(addr) && IsInMyRange(addr + size - 1);
}
bool DynamicMemoryBlock::IsMyAddress(const u64 addr)
{
for(u32 i=0; i<m_used_mem.GetCount(); ++i)
{
if(addr >= m_used_mem[i].addr && addr < m_used_mem[i].addr + m_used_mem[i].size)
{
return true;
}
}
return false;
}
MemoryBlock* DynamicMemoryBlock::SetRange(const u64 start, const u32 size)
{
m_max_size = size;
MemoryBlock::SetRange(start, 0);
return this;
}
void DynamicMemoryBlock::Delete()
{
m_used_mem.Clear();
m_max_size = 0;
MemoryBlock::Delete();
}
bool DynamicMemoryBlock::Alloc(u64 addr, u32 size)
{
if(!IsInMyRange(addr, size))
{
assert(0);
return false;
}
if(IsMyAddress(addr) || IsMyAddress(addr + size - 1))
{
return false;
}
for(u32 i=0; i<m_used_mem.GetCount(); ++i)
{
if(addr >= m_used_mem[i].addr && addr < m_used_mem[i].addr + m_used_mem[i].size) return false;
}
AppendUsedMem(addr, size);
return true;
}
void DynamicMemoryBlock::AppendUsedMem(u64 addr, u32 size)
{
m_used_mem.Move(new MemBlockInfo(addr, size));
}
u64 DynamicMemoryBlock::Alloc(u32 size)
{
for(u64 addr=GetStartAddr(); addr <= GetEndAddr() - size;)
{
bool is_good_addr = true;
for(u32 i=0; i<m_used_mem.GetCount(); ++i)
{
if((addr >= m_used_mem[i].addr && addr < m_used_mem[i].addr + m_used_mem[i].size) ||
(m_used_mem[i].addr >= addr && m_used_mem[i].addr < addr + size))
{
is_good_addr = false;
addr = m_used_mem[i].addr + m_used_mem[i].size;
break;
}
}
if(!is_good_addr) continue;
AppendUsedMem(addr, size);
return addr;
}
return 0;
}
bool DynamicMemoryBlock::Alloc()
{
return Alloc(GetSize() - GetUsedSize()) != 0;
}
bool DynamicMemoryBlock::Free(u64 addr)
{
for(u32 i=0; i<m_used_mem.GetCount(); ++i)
{
if(addr == m_used_mem[i].addr)
{
m_used_mem.RemoveAt(i);
return true;
}
}
return false;
}
u8* DynamicMemoryBlock::GetMem(u64 addr) const
{
for(u32 i=0; i<m_used_mem.GetCount(); ++i)
{
u64 _addr = FixAddr(m_used_mem[i].addr);
if(addr >= _addr && addr < _addr + m_used_mem[i].size)
{
return (u8*)m_used_mem[i].mem + addr - _addr;
}
}
ConLog.Error("GetMem(%llx) from not allocated address.", addr);
assert(0);
return nullptr;
}
#define DEBUG_RAWSPU_MEM 1
//MemoryBase
void MemoryBase::Write8(u64 addr, const u8 data)
{
#if DEBUG_RAWSPU_MEM
if(SpuRawMem.IsMyAddress(addr))
{
ConLog.Warning("Write8(addr=0x%llx,data=0x%x)", addr, data);
}
#endif
GetMemByAddr(addr).Write8(addr, data);
}
void MemoryBase::Write16(u64 addr, const u16 data)
{
#if DEBUG_RAWSPU_MEM
if(SpuRawMem.IsMyAddress(addr))
{
ConLog.Warning("Write16(addr=0x%llx,data=0x%x)", addr, data);
}
#endif
GetMemByAddr(addr).Write16(addr, data);
}
void MemoryBase::Write32(u64 addr, const u32 data)
{
#if DEBUG_RAWSPU_MEM
if(SpuRawMem.IsMyAddress(addr))
{
ConLog.Warning("Write32(addr=0x%llx,data=0x%x)", addr, data);
}
#endif
GetMemByAddr(addr).Write32(addr, data);
}
void MemoryBase::Write64(u64 addr, const u64 data)
{
#if DEBUG_RAWSPU_MEM
if(SpuRawMem.IsMyAddress(addr))
{
ConLog.Warning("Write64(addr=0x%llx,data=0x%llx)", addr, data);
}
#endif
GetMemByAddr(addr).Write64(addr, data);
}
@ -557,83 +462,35 @@ bool MemoryBase::Write128NN(u64 addr, const u128 data)
u8 MemoryBase::Read8(u64 addr)
{
#if DEBUG_RAWSPU_MEM
if(SpuRawMem.IsMyAddress(addr))
{
ConLog.Warning("Read8(addr=0x%llx)", addr);
}
#endif
MemoryBlock& mem = GetMemByAddr(addr);
if(mem.IsNULL())
{
mem.Read8(addr, NULL);
return 0;
}
return mem.FastRead8(mem.FixAddr(addr));
u8 res;
GetMemByAddr(addr).Read8(addr, &res);
return res;
}
u16 MemoryBase::Read16(u64 addr)
{
#if DEBUG_RAWSPU_MEM
if(SpuRawMem.IsMyAddress(addr))
{
ConLog.Warning("Read16(addr=0x%llx)", addr);
}
#endif
MemoryBlock& mem = GetMemByAddr(addr);
if(mem.IsNULL())
{
mem.Read16(addr, NULL);
return 0;
}
return mem.FastRead16(mem.FixAddr(addr));
u16 res;
GetMemByAddr(addr).Read16(addr, &res);
return res;
}
u32 MemoryBase::Read32(u64 addr)
{
#if DEBUG_RAWSPU_MEM
if(SpuRawMem.IsMyAddress(addr) && !(GetCurrentPPCThread() && GetCurrentPPCThread()->GetType() == PPC_THREAD_RAW_SPU))
{
ConLog.Warning("Read32(addr=0x%llx)", addr);
}
#endif
MemoryBlock& mem = GetMemByAddr(addr);
if(mem.IsNULL())
{
mem.Read32(addr, NULL);
return 0;
}
return mem.FastRead32(mem.FixAddr(addr));
u32 res;
GetMemByAddr(addr).Read32(addr, &res);
return res;
}
u64 MemoryBase::Read64(u64 addr)
{
#if DEBUG_RAWSPU_MEM
if(SpuRawMem.IsMyAddress(addr))
{
ConLog.Warning("Read64(addr=0x%llx)", addr);
}
#endif
MemoryBlock& mem = GetMemByAddr(addr);
if(mem.IsNULL())
{
mem.Read64(addr, NULL);
return 0;
}
return mem.FastRead64(mem.FixAddr(addr));
u64 res;
GetMemByAddr(addr).Read64(addr, &res);
return res;
}
u128 MemoryBase::Read128(u64 addr)
{
MemoryBlock& mem = GetMemByAddr(addr);
if(mem.IsNULL())
{
mem.Read128(addr, NULL);
return u128::From32(0);
}
return mem.FastRead128(mem.FixAddr(addr));
u128 res;
GetMemByAddr(addr).Read128(addr, &res);
return res;
}

View File

@ -1,12 +1,20 @@
#pragma once
#include "MemoryBlock.h"
enum MemoryType
{
Memory_PS3,
Memory_PSV,
Memory_PSP,
};
class MemoryBase
{
NullMemoryBlock NullMem;
public:
ArrayF<MemoryBlock> MemoryBlocks;
MemoryBlock* UserMemory;
DynamicMemoryBlock MainMem;
DynamicMemoryBlock PRXMem;
@ -17,6 +25,21 @@ public:
MemoryBlock SpuRawMem;
MemoryBlock SpuThrMem;
struct
{
DynamicMemoryBlockLE RAM;
DynamicMemoryBlockLE Userspace;
} PSVMemory;
struct
{
DynamicMemoryBlockLE Scratchpad;
DynamicMemoryBlockLE VRAM;
DynamicMemoryBlockLE RAM;
DynamicMemoryBlockLE Kernel;
DynamicMemoryBlockLE Userspace;
} PSPMemory;
bool m_inited;
MemoryBase()
@ -126,21 +149,39 @@ public:
return true;
}
void Init()
void Init(MemoryType type)
{
if(m_inited) return;
m_inited = true;
ConLog.Write("Initing memory...");
MemoryBlocks.Add(MainMem.SetRange(0x00010000, 0x2FFF0000));
MemoryBlocks.Add(PRXMem.SetRange(0x30000000, 0x10000000));
MemoryBlocks.Add(RSXCMDMem.SetRange(0x40000000, 0x10000000));
MemoryBlocks.Add(MmaperMem.SetRange(0xB0000000, 0x10000000));
MemoryBlocks.Add(RSXFBMem.SetRange(0xC0000000, 0x10000000));
MemoryBlocks.Add(StackMem.SetRange(0xD0000000, 0x10000000));
//MemoryBlocks.Add(SpuRawMem.SetRange(0xE0000000, 0x10000000));
//MemoryBlocks.Add(SpuThrMem.SetRange(0xF0000000, 0x10000000));
switch(type)
{
case Memory_PS3:
MemoryBlocks.Add(MainMem.SetRange(0x00010000, 0x2FFF0000));
MemoryBlocks.Add(UserMemory = PRXMem.SetRange(0x30000000, 0x10000000));
MemoryBlocks.Add(RSXCMDMem.SetRange(0x40000000, 0x10000000));
MemoryBlocks.Add(MmaperMem.SetRange(0xB0000000, 0x10000000));
MemoryBlocks.Add(RSXFBMem.SetRange(0xC0000000, 0x10000000));
MemoryBlocks.Add(StackMem.SetRange(0xD0000000, 0x10000000));
//MemoryBlocks.Add(SpuRawMem.SetRange(0xE0000000, 0x10000000));
//MemoryBlocks.Add(SpuThrMem.SetRange(0xF0000000, 0x10000000));
break;
case Memory_PSV:
MemoryBlocks.Add(PSVMemory.RAM.SetRange(0x81000000, 0x10000000));
MemoryBlocks.Add(UserMemory = PSVMemory.Userspace.SetRange(0x91000000, 0x10000000));
break;
case Memory_PSP:
MemoryBlocks.Add(PSPMemory.Scratchpad.SetRange(0x00010000, 0x00004000));
MemoryBlocks.Add(PSPMemory.VRAM.SetRange(0x04000000, 0x00200000));
MemoryBlocks.Add(PSPMemory.RAM.SetRange(0x08000000, 0x02000000));
MemoryBlocks.Add(PSPMemory.Kernel.SetRange(0x88000000, 0x00800000));
MemoryBlocks.Add(UserMemory = PSPMemory.Userspace.SetRange(0x08800000, 0x01800000));
break;
}
ConLog.Write("Memory initialized.");
}
@ -178,16 +219,7 @@ public:
MemoryBlocks[i].Delete();
}
MemoryBlocks.Clear();
}
void Reset()
{
if(!m_inited) return;
ConLog.Write("Resetting memory...");
Close();
Init();
MemoryBlocks.ClearF();
}
void Write8(const u64 addr, const u8 data);
@ -310,22 +342,22 @@ public:
u32 GetUserMemTotalSize()
{
return PRXMem.GetSize();
return UserMemory->GetSize();
}
u32 GetUserMemAvailSize()
{
return PRXMem.GetSize() - PRXMem.GetUsedSize();
return UserMemory->GetSize() - UserMemory->GetUsedSize();
}
u64 Alloc(const u32 size, const u32 align)
{
return PRXMem.Alloc(AlignAddr(size, align));
return UserMemory->Alloc(AlignAddr(size, align));
}
bool Free(const u64 addr)
{
return PRXMem.Free(addr);
return UserMemory->Free(addr);
}
bool Map(const u64 dst_addr, const u64 src_addr, const u32 size)
@ -348,7 +380,7 @@ public:
{
if(MemoryBlocks[i].GetStartAddr() == addr)
{
MemoryBlocks.RemoveFAt(i);
MemoryBlocks.RemoveAt(i);
}
}
}
@ -369,24 +401,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 +459,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 +486,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 +496,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

@ -98,8 +98,30 @@ public:
const u64 GetStartAddr() const { return range_start; }
const u64 GetEndAddr() const { return GetStartAddr() + GetSize() - 1; }
virtual const u32 GetSize() const { return range_size; }
virtual const u32 GetUsedSize() const { return GetSize(); }
u8* GetMem() const { return mem; }
virtual u8* GetMem(u64 addr) const { return mem + addr; }
virtual bool Alloc(u64 addr, u32 size) { return false; }
virtual u64 Alloc(u32 size) { return 0; }
virtual bool Alloc() { return false; }
virtual bool Free(u64 addr) { return false; }
};
class MemoryBlockLE : public MemoryBlock
{
public:
virtual bool Read8(const u64 addr, u8* value) override;
virtual bool Read16(const u64 addr, u16* value) override;
virtual bool Read32(const u64 addr, u32* value) override;
virtual bool Read64(const u64 addr, u64* value) override;
virtual bool Read128(const u64 addr, u128* value) override;
virtual bool Write8(const u64 addr, const u8 value) override;
virtual bool Write16(const u64 addr, const u16 value) override;
virtual bool Write32(const u64 addr, const u32 value) override;
virtual bool Write64(const u64 addr, const u64 value) override;
virtual bool Write128(const u64 addr, const u128 value) override;
};
class MemoryMirror : public MemoryBlock
@ -145,32 +167,38 @@ class NullMemoryBlock : public MemoryBlock
virtual bool Write128(const u64 addr, const u128 value);
};
class DynamicMemoryBlock : public MemoryBlock
template<typename PT>
class DynamicMemoryBlockBase : public PT
{
Array<MemBlockInfo> m_used_mem;
u32 m_max_size;
public:
DynamicMemoryBlock();
DynamicMemoryBlockBase();
const u32 GetSize() const { return m_max_size; }
const u32 GetUsedSize() const;
bool IsInMyRange(const u64 addr);
bool IsInMyRange(const u64 addr, const u32 size);
bool IsMyAddress(const u64 addr);
virtual bool IsInMyRange(const u64 addr);
virtual bool IsInMyRange(const u64 addr, const u32 size);
virtual bool IsMyAddress(const u64 addr);
MemoryBlock* SetRange(const u64 start, const u32 size);
virtual MemoryBlock* SetRange(const u64 start, const u32 size);
virtual void Delete();
bool Alloc(u64 addr, u32 size);
u64 Alloc(u32 size);
bool Alloc();
bool Free(u64 addr);
virtual bool Alloc(u64 addr, u32 size);
virtual u64 Alloc(u32 size);
virtual bool Alloc();
virtual bool Free(u64 addr);
virtual u8* GetMem(u64 addr) const;
private:
void AppendUsedMem(u64 addr, u32 size);
};
#include "DynamicMemoryBlockBase.inl"
typedef DynamicMemoryBlockBase<MemoryBlock> DynamicMemoryBlock;
typedef DynamicMemoryBlockBase<MemoryBlockLE> DynamicMemoryBlockLE;

View File

@ -50,11 +50,11 @@ void Callback::Branch(bool wait)
{
m_has_data = false;
PPCThread& new_thread = Emu.GetCPU().AddThread(PPC_THREAD_PPU);
CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU);
new_thread.SetEntry(m_addr);
new_thread.SetPrio(1001);
new_thread.stack_size = 0x10000;
new_thread.SetStackSize(0x10000);
new_thread.SetName("Callback");
new_thread.SetArg(0, a1);

View File

@ -356,8 +356,8 @@ s64 SysCalls::DoFunc(const u32 id)
case 0xc8f3bd09: FUNC_LOG_ERROR("TODO: cellGcmGetCurrentField");
case 0xcaabd992: FUNC_LOG_ERROR("TODO: cellGcmInitDefaultFifoMode");
case 0xd01b570d: FUNC_LOG_ERROR("TODO: cellGcmSetGraphicsHandler");
case 0xd0b1d189: ConLog.Error("TODO: cellGcmSetTile"); return SC_ARGS_1;
case 0xd34a420d: ConLog.Error("TODO: cellGcmSetZcull"); return SC_ARGS_1;
case 0xd0b1d189: FUNC_LOG_ERROR("TODO: cellGcmSetTile");
case 0xd34a420d: FUNC_LOG_ERROR("TODO: cellGcmSetZcull");
case 0xd8f88e1a: FUNC_LOG_ERROR("TODO: _cellGcmSetFlipCommandWithWaitLabel");
case 0xd9a0a879: FUNC_LOG_ERROR("TODO: cellGcmGetZcullInfo");
case 0xd9b7653e: FUNC_LOG_ERROR("TODO: cellGcmUnbindTile");
@ -817,9 +817,9 @@ s64 SysCalls::DoFunc(const u32 id)
case 0x516ee89e: FUNC_LOG_ERROR("TODO: cellRescInit");
case 0x5a338cdb: FUNC_LOG_ERROR("TODO: cellRescGetBufferSize");
case 0x66f5e388: FUNC_LOG_ERROR("TODO: cellRescGetLastFlipTime");
case 0x6cd0f95f: return cellRescSetSrc(SC_ARGS_2);//FUNC_LOG_ERROR("TODO: cellRescSetSrc");
case 0x6cd0f95f: FUNC_LOG_ERROR("TODO: cellRescSetSrc");
case 0x7af8a37f: FUNC_LOG_ERROR("TODO: cellRescSetRegisterCount");
case 0x8107277c: return cellRescSetBufferAddress(SC_ARGS_3); //FUNC_LOG_ERROR("TODO: cellRescSetBufferAddress");
case 0x8107277c: FUNC_LOG_ERROR("TODO: cellRescSetBufferAddress");
case 0xc47c5c22: FUNC_LOG_ERROR("TODO: cellRescGetFlipStatus");
case 0xd1ca0503: FUNC_LOG_ERROR("TODO: cellRescVideoOutResolutionId2RescBufferMode");
case 0xd3758645: FUNC_LOG_ERROR("TODO: cellRescSetVBlankHandler");
@ -1410,19 +1410,19 @@ s64 SysCalls::DoFunc(const u32 id)
case 0xa193143c: FUNC_LOG_ERROR("TODO: cellSysmoduleSetMemcontainer");
case 0x018a1381: FUNC_LOG_ERROR("TODO: cellSysutilAvcSetLayoutMode");
case 0x01f04d94: FUNC_LOG_ERROR("TODO: cellSysutilGamePowerOff_I");
case 0x02ff3c1b: return cellSysutilUnregisterCallback(SC_ARGS_1); //FUNC_LOG_ERROR("TODO: cellSysutilUnregisterCallback");
case 0x02ff3c1b: FUNC_LOG_ERROR("TODO: cellSysutilUnregisterCallback");
case 0x073b89d5: FUNC_LOG_ERROR("TODO: cellSysutilAvcGetSpeakerVolumeLevel");
case 0x08269f37: FUNC_LOG_ERROR("TODO: cellSysutilAvcGetShowStatus");
case 0x0bae8772: return cellVideoOutConfigure(SC_ARGS_4); //FUNC_LOG_ERROR("TODO: cellVideoOutConfigure");
case 0x0bae8772: FUNC_LOG_ERROR("TODO: cellVideoOutConfigure");
case 0x0c316b87: FUNC_LOG_ERROR("TODO: cellWebBrowserConfigGetHeapSize2");
case 0x0e091c36: FUNC_LOG_ERROR("TODO: cellSaveDataUserListAutoSave");
case 0x0f03cfb0: FUNC_LOG_ERROR("TODO: cellSaveDataUserListSave");
case 0x0f8a3b6b: FUNC_LOG_ERROR("TODO: cellWebBrowserConfigSetMimeSet");
case 0x10cabeff: FUNC_LOG_ERROR("TODO: cellWebBrowserGetUsrdataOnGameExit");
case 0x15b0b0cd: return cellVideoOutGetConfiguration(SC_ARGS_3); //FUNC_LOG_ERROR("TODO: cellVideoOutGetConfiguration");
case 0x15b0b0cd: FUNC_LOG_ERROR("TODO: cellVideoOutGetConfiguration");
case 0x15df71ed: FUNC_LOG_ERROR("TODO: cellSysutilAvcLoadAsync");
case 0x17dbe8b3: FUNC_LOG_ERROR("TODO: cellSysutilAvcJoinRequest");
case 0x189a74da: return cellSysutilCheckCallback(); //FUNC_LOG_ERROR("TODO: cellSysutilCheckCallback");
case 0x189a74da: FUNC_LOG_ERROR("TODO: cellSysutilCheckCallback");
case 0x1a91874b: FUNC_LOG_ERROR("TODO: cellWebBrowserConfigSetFullScreen2");
case 0x1d99c3ee: FUNC_LOG_ERROR("TODO: cellOskDialogGetInputText");
case 0x1dfbfdd6: FUNC_LOG_ERROR("TODO: cellSaveDataListLoad2");
@ -1484,8 +1484,8 @@ s64 SysCalls::DoFunc(const u32 id)
case 0x71acb8d3: FUNC_LOG_ERROR("TODO: cellSysutilAvcSetVideoMuting");
case 0x744c1544: FUNC_LOG_ERROR("TODO: cellSysCacheClear");
case 0x749c9b5f: FUNC_LOG_ERROR("TODO: cellWebBrowserInitialize");
case 0x75bbb672: return cellVideoOutGetNumberOfDevice(SC_ARGS_1); //FUNC_LOG_ERROR("TODO: cellVideoOutGetNumberOfDevice");
case 0x7603d3db: return cellMsgDialogOpen2(SC_ARGS_5); //FUNC_LOG_ERROR("TODO: cellMsgDialogOpen2");
case 0x75bbb672: FUNC_LOG_ERROR("TODO: cellVideoOutGetNumberOfDevice");
case 0x7603d3db: FUNC_LOG_ERROR("TODO: cellMsgDialogOpen2");
case 0x7663e368: FUNC_LOG_ERROR("TODO: cellAudioOutGetDeviceInfo");
case 0x76948bfc: FUNC_LOG_ERROR("TODO: cellSysconfAbort");
case 0x76fc8fb1: FUNC_LOG_ERROR("TODO: cellWebBrowserConfigSetHeapSize");
@ -1498,7 +1498,7 @@ s64 SysCalls::DoFunc(const u32 id)
case 0x7fb3c6a5: FUNC_LOG_ERROR("TODO: cellWebBrowserConfig2");
case 0x7fcfc915: FUNC_LOG_ERROR("TODO: cellOskDialogLoadAsync");
case 0x83668b8e: FUNC_LOG_ERROR("TODO: cellWebBrowserConfig");
case 0x887572d5: return cellVideoOutGetState(SC_ARGS_3);//FUNC_LOG_ERROR("TODO: cellVideoOutGetState");
case 0x887572d5: FUNC_LOG_ERROR("TODO: cellVideoOutGetState");
case 0x8a4cb646: FUNC_LOG_ERROR("TODO: cellWebBrowserCreateWithConfig");
case 0x8a5dbb58: FUNC_LOG_ERROR("TODO: cellWebComponentCreate");
case 0x8b7ed64b: FUNC_LOG_ERROR("TODO: cellSaveDataAutoSave2");
@ -1515,11 +1515,11 @@ s64 SysCalls::DoFunc(const u32 id)
case 0x9c9fe6a4: FUNC_LOG_ERROR("TODO: cellWebBrowserConfigSetFunction");
case 0x9ca9ffa7: FUNC_LOG_ERROR("TODO: cellHddGameSetSystemVer");
case 0x9d6af72a: FUNC_LOG_ERROR("TODO: cellMsgDialogProgressBarSetMsg");
case 0x9d98afa0: return cellSysutilRegisterCallback(SC_ARGS_3); //FUNC_LOG_ERROR("TODO: cellSysutilRegisterCallback");
case 0x9d98afa0: FUNC_LOG_ERROR("TODO: cellSysutilRegisterCallback");
case 0x9dfdad46: FUNC_LOG_ERROR("TODO: cellAudioOutUnregisterCallback");
case 0x9fb97b10: FUNC_LOG_ERROR("TODO: cellWebBrowserNavigate2");
case 0xa11552f6: FUNC_LOG_ERROR("TODO: cellSysutilGetBgmPlaybackStatus");
case 0xa322db75: return cellVideoOutGetResolutionAvailability(SC_ARGS_4); //FUNC_LOG_ERROR("TODO: cellVideoOutGetResolutionAvailability");
case 0xa322db75: FUNC_LOG_ERROR("TODO: cellVideoOutGetResolutionAvailability");
case 0xa36335a5: FUNC_LOG_ERROR("TODO: cellSysutilDisableBgmPlaybackEx");
case 0xa4dd11cc: FUNC_LOG_ERROR("TODO: cellWebBrowserConfigGetHeapSize");
case 0xa4ed7dfe: FUNC_LOG_ERROR("TODO: cellSaveDataDelete");
@ -1556,7 +1556,7 @@ s64 SysCalls::DoFunc(const u32 id)
case 0xdce51399: FUNC_LOG_ERROR("TODO: cellWebComponentDestroy");
case 0xdfdd302e: FUNC_LOG_ERROR("TODO: cellDiscGameRegisterDiscChangeCallback");
case 0xe22ed55d: FUNC_LOG_ERROR("TODO: cellWebBrowserConfigSetFunction2");
case 0xe558748d: return cellVideoOutGetResolution(SC_ARGS_2); //FUNC_LOG_ERROR("TODO: cellVideoOutGetResolution");
case 0xe558748d: FUNC_LOG_ERROR("TODO: cellVideoOutGetResolution");
case 0xe5e2b09d: FUNC_LOG_ERROR("TODO: cellAudioOutGetNumberOfDevice");
case 0xe7951dee: FUNC_LOG_ERROR("TODO: cellGameDataCheckCreate");
case 0xe7fa820b: FUNC_LOG_ERROR("TODO: cellSaveDataEnableOverlay");
@ -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");
@ -3563,28 +3563,25 @@ s64 SysCalls::DoFunc(const u32 id)
case 0x05c65656: FUNC_LOG_ERROR("TODO: sys_mempool_try_allocate_block");
case 0x0618936b: FUNC_LOG_ERROR("TODO: _sys_vsnprintf");
case 0x06574237: FUNC_LOG_ERROR("TODO: _sys_snprintf");
case 0x1573dc3f: return sys_lwmutex_lock(SC_ARGS_2);//FUNC_LOG_ERROR("TODO: sys_lwmutex_lock");
case 0x1573dc3f: FUNC_LOG_ERROR("TODO: sys_lwmutex_lock");
case 0x191f0c4a: FUNC_LOG_ERROR("TODO: _sys_strrchr");
case 0x1ae10b92: FUNC_LOG_ERROR("TODO: _sys_spu_printf_attach_thread");
case 0x1bc200f4: return sys_lwmutex_unlock(SC_ARGS_1);//FUNC_LOG_ERROR("TODO: sys_lwmutex_unlock");
case 0x1bc200f4: FUNC_LOG_ERROR("TODO: sys_lwmutex_unlock");
case 0x1c9a942c: FUNC_LOG_ERROR("TODO: sys_lwcond_destroy");
case 0x1ca525a2: FUNC_LOG_ERROR("TODO: _sys_strncasecmp");
case 0x1ed454ce: FUNC_LOG_ERROR("TODO: sys_spu_elf_get_information");
case 0x24a1ea07: return sys_ppu_thread_create(SC_ARGS_7);//FUNC_LOG_ERROR("TODO: sys_ppu_thread_create");
case 0x24a1ea07: FUNC_LOG_ERROR("TODO: sys_ppu_thread_create");
case 0x25596f51: FUNC_LOG_ERROR("TODO: sys_mempool_get_count");
case 0x26090058: FUNC_LOG_ERROR("TODO: sys_prx_load_module");
case 0x27427742: FUNC_LOG_ERROR("TODO: _sys_memmove");
case 0x2a6d9d51: FUNC_LOG_ERROR("TODO: sys_lwcond_wait");
case 0x2c847572: FUNC_LOG_ERROR("TODO: _sys_process_atexitspawn");
case 0x2d36462b:
//FUNC_LOG_ERROR("TODO: _sys_strlen");
ConLog.Write("sys_strlen(addr=0x%x(%s))", SC_ARGS_1, Memory.ReadString(SC_ARGS_1));
return strlen((const char*)&Memory[SC_ARGS_1]);
case 0x2f85c0ef: return sys_lwmutex_create(SC_ARGS_2);//FUNC_LOG_ERROR("TODO: sys_lwmutex_create");
case 0x2d36462b: FUNC_LOG_ERROR("TODO: _sys_strlen");
case 0x2f85c0ef: FUNC_LOG_ERROR("TODO: sys_lwmutex_create");
case 0x3172759d: FUNC_LOG_ERROR("TODO: sys_game_get_temperature");
case 0x318f17e1: FUNC_LOG_ERROR("TODO: _sys_memalign");
case 0x350d454e: return sys_ppu_thread_get_id(SC_ARGS_1);//FUNC_LOG_ERROR("TODO: sys_ppu_thread_get_id");
case 0x35168520: return sys_heap_malloc(SC_ARGS_2); //FUNC_LOG_ERROR("TODO: _sys_heap_malloc");
case 0x350d454e: FUNC_LOG_ERROR("TODO: sys_ppu_thread_get_id");
case 0x35168520: FUNC_LOG_ERROR("TODO: _sys_heap_malloc");
case 0x3bd53c7b: FUNC_LOG_ERROR("TODO: _sys_memchr");
case 0x3dd4a957: FUNC_LOG_ERROR("TODO: sys_ppu_thread_register_atexit");
case 0x409ad939: FUNC_LOG_ERROR("TODO: sys_mmapper_free_memory");
@ -3602,28 +3599,18 @@ s64 SysCalls::DoFunc(const u32 id)
case 0x608212fc: FUNC_LOG_ERROR("TODO: sys_mempool_free_block");
case 0x620e35a7: FUNC_LOG_ERROR("TODO: sys_game_get_system_sw_version");
case 0x67f9fedb: FUNC_LOG_ERROR("TODO: sys_game_process_exitspawn2");
case 0x68b9b011:
ConLog.Warning("_sys_memset(0x%llx, 0x%lld, 0x%lld)", SC_ARGS_3);
return
(u32)memset(Memory.GetMemFromAddr(CPU.GPR[3]), CPU.GPR[4], CPU.GPR[5])
- Memory.GetMemByAddr(CPU.GPR[3]).GetStartAddr();
FUNC_LOG_ERROR("TODO: _sys_memset");
case 0x68b9b011: FUNC_LOG_ERROR("TODO: _sys_memset");
case 0x6bf66ea7: FUNC_LOG_ERROR("TODO: _sys_memcpy");
case 0x6e05231d: FUNC_LOG_ERROR("TODO: sys_game_watchdog_stop");
case 0x70258515: FUNC_LOG_ERROR("TODO: sys_mmapper_allocate_memory_from_container");
case 0x71a8472a: FUNC_LOG_ERROR("TODO: sys_get_random_number");
case 0x722a0254: FUNC_LOG_ERROR("TODO: sys_spinlock_trylock");
case 0x74311398: FUNC_LOG_ERROR("TODO: sys_prx_get_my_module_id");
case 0x744680a2:
// FUNC_LOG_ERROR("TODO: sys_initialize_tls");
ConLog.Warning("sys_initialize_tls()");
//CPU.GPR[4] = Emu.GetTLSFilesz();
//CPU.GPR[5] = Emu.GetTLSMemsz();
return 0;//Memory.MainMem.Alloc(Emu.GetTLSMemsz());//Emu.GetTLSAddr();
case 0x744680a2: FUNC_LOG_ERROR("TODO: sys_initialize_tls");
case 0x7498887b: FUNC_LOG_ERROR("TODO: _sys_strchr");
case 0x791b9219: FUNC_LOG_ERROR("TODO: _sys_vsprintf");
case 0x80fb0c19: FUNC_LOG_ERROR("TODO: sys_prx_stop_module");
case 0x8461e528: return sys_time_get_system_time();//FUNC_LOG_ERROR("TODO: sys_time_get_system_time");
case 0x8461e528: FUNC_LOG_ERROR("TODO: sys_time_get_system_time");
case 0x84bb6774: FUNC_LOG_ERROR("TODO: sys_prx_get_module_info");
case 0x893305fa: FUNC_LOG_ERROR("TODO: sys_raw_spu_load");
case 0x8985b5b6: FUNC_LOG_ERROR("TODO: _sys_heap_stats");
@ -3640,33 +3627,27 @@ s64 SysCalls::DoFunc(const u32 id)
case 0x9f18429d: FUNC_LOG_ERROR("TODO: sys_prx_start_module");
case 0x9f950780: FUNC_LOG_ERROR("TODO: sys_game_get_rtc_status");
case 0xa146a143: FUNC_LOG_ERROR("TODO: sys_mempool_allocate_block");
case 0xa1f9eafe:
ConLog.Warning("_sys_sprintf(0x%llx, 0x%llx(%s), 0x%llx)", CPU.GPR[3], CPU.GPR[4], Memory.ReadString(CPU.GPR[4]), CPU.GPR[5]);
return vsprintf((char*)Memory.GetMemFromAddr(CPU.GPR[3]), Memory.ReadString(CPU.GPR[4]), (char*)Memory.GetMemFromAddr(CPU.GPR[5]));
FUNC_LOG_ERROR("TODO: _sys_sprintf");
case 0xa1f9eafe: FUNC_LOG_ERROR("TODO: _sys_sprintf");
case 0xa285139d: FUNC_LOG_ERROR("TODO: sys_spinlock_lock");
case 0xa2c7ba64: FUNC_LOG_ERROR("TODO: sys_prx_exitspawn_with_level");
case 0xa330ad84: FUNC_LOG_ERROR("TODO: sys_prx_load_module_on_memcontainer_by_fd");
case 0xa3e3be68: sys_ppu_thread_once(SC_ARGS_2); return SC_ARGS_1;//FUNC_LOG_ERROR("TODO: sys_ppu_thread_once");
case 0xa3e3be68: FUNC_LOG_ERROR("TODO: sys_ppu_thread_once");
case 0xa5d06bf0: FUNC_LOG_ERROR("TODO: sys_prx_get_module_list");
case 0xaa6d9bff: FUNC_LOG_ERROR("TODO: sys_prx_load_module_on_memcontainer");
case 0xac6fc404: FUNC_LOG_ERROR("TODO: sys_ppu_thread_unregister_atexit");
case 0xacad8fb6: FUNC_LOG_ERROR("TODO: sys_game_watchdog_clear");
case 0xaeb78725: return sys_lwmutex_trylock(SC_ARGS_1);//FUNC_LOG_ERROR("TODO: sys_lwmutex_trylock");
case 0xaeb78725: FUNC_LOG_ERROR("TODO: sys_lwmutex_trylock");
case 0xaede4b03: FUNC_LOG_ERROR("TODO: _sys_heap_delete_heap");
case 0xaff080a4: return sys_ppu_thread_exit(SC_ARGS_1);//FUNC_LOG_ERROR("TODO: sys_ppu_thread_exit");
case 0xb257540b: return sys_mmapper_allocate_memory(SC_ARGS_3); //FUNC_LOG_ERROR("TODO: sys_mmapper_allocate_memory");
case 0xaff080a4: FUNC_LOG_ERROR("TODO: sys_ppu_thread_exit");
case 0xb257540b: FUNC_LOG_ERROR("TODO: sys_mmapper_allocate_memory");
case 0xb27c8ae7: FUNC_LOG_ERROR("TODO: sys_prx_load_module_list");
case 0xb2fcf2c8: return sys_heap_create_heap(SC_ARGS_3);//FUNC_LOG_ERROR("TODO: _sys_heap_create_heap");
case 0xb2fcf2c8: FUNC_LOG_ERROR("TODO: _sys_heap_create_heap");
case 0xb3bbcf2a: FUNC_LOG_ERROR("TODO: _sys_spu_printf_detach_thread");
case 0xb6369393: FUNC_LOG_ERROR("TODO: _sys_heap_get_total_free_size");
case 0xb995662e: FUNC_LOG_ERROR("TODO: sys_raw_spu_image_load");
case 0xb9bf1078: FUNC_LOG_ERROR("TODO: _sys_heap_alloc_heap_memory");
case 0xbdb18f83:
ConLog.Warning("_sys_malloc(0x%llx)", SC_ARGS_1);
return Memory.Alloc(CPU.GPR[3], Emu.GetMallocPageSize());
FUNC_LOG_ERROR("TODO: _sys_malloc");
case 0xc3476d0c: return sys_lwmutex_destroy(SC_ARGS_1);////FUNC_LOG_ERROR("TODO: sys_lwmutex_destroy");
case 0xbdb18f83: FUNC_LOG_ERROR("TODO: _sys_malloc");
case 0xc3476d0c: FUNC_LOG_ERROR("TODO: sys_lwmutex_destroy");
case 0xc4fd6121: FUNC_LOG_ERROR("TODO: _sys_qsort");
case 0xca9a60bf: FUNC_LOG_ERROR("TODO: sys_mempool_create");
case 0xd0ea47a7: FUNC_LOG_ERROR("TODO: sys_prx_unregister_library");
@ -3674,13 +3655,13 @@ s64 SysCalls::DoFunc(const u32 id)
case 0xd3039d4d: FUNC_LOG_ERROR("TODO: _sys_strncpy");
case 0xda0eb71a: FUNC_LOG_ERROR("TODO: sys_lwcond_create");
case 0xdb6b3250: FUNC_LOG_ERROR("TODO: sys_spu_elf_get_segments");
case 0xdc578057: return sys_mmapper_map_memory(SC_ARGS_3); //FUNC_LOG_ERROR("TODO: sys_mmapper_map_memory");
case 0xdc578057: FUNC_LOG_ERROR("TODO: sys_mmapper_map_memory");
case 0xdd0c1e09: FUNC_LOG_ERROR("TODO: _sys_spu_printf_attach_group");
case 0xdd3b27ac: FUNC_LOG_ERROR("TODO: _sys_spu_printf_finalize");
case 0xe0998dbf: FUNC_LOG_ERROR("TODO: sys_prx_get_module_id_by_name");
case 0xe0da8efd: FUNC_LOG_ERROR("TODO: sys_spu_image_close");
case 0xe66bac36: FUNC_LOG_ERROR("TODO: console_putc");
case 0xe6f2c1e7: return sys_process_exit(SC_ARGS_1);///FUNC_LOG_ERROR("TODO: sys_process_exit");
case 0xe6f2c1e7: FUNC_LOG_ERROR("TODO: sys_process_exit");
case 0xe76964f5: FUNC_LOG_ERROR("TODO: sys_game_board_storage_read");
case 0xe7ef3a80: FUNC_LOG_ERROR("TODO: sys_prx_load_module_list_on_memcontainer");
case 0xe9a1bd84: FUNC_LOG_ERROR("TODO: sys_lwcond_signal_all");
@ -3693,7 +3674,7 @@ s64 SysCalls::DoFunc(const u32 id)
case 0xf7f7fb20: FUNC_LOG_ERROR("TODO: _sys_free");
case 0xfa7f693d: FUNC_LOG_ERROR("TODO: _sys_vprintf");
case 0xfb5db080: FUNC_LOG_ERROR("TODO: _sys_memcmp");
case 0xfc52a7a9: return sys_game_process_exitspawn(SC_ARGS_7); FUNC_LOG_ERROR("TODO: sys_game_process_exitspawn");
case 0xfc52a7a9: FUNC_LOG_ERROR("TODO: sys_game_process_exitspawn");
}
ConLog.Error("Unknown func id: 0x%08x", id);

File diff suppressed because it is too large Load Diff

View File

@ -433,7 +433,7 @@ int cellGcmSetTileInfo(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u
cellGcmSys.Warning("cellGcmSetTileInfo(index=%d, location=%d, offset=%d, size=%d, pitch=%d, comp=%d, base=%d, bank=%d)",
index, location, offset, size, pitch, comp, base, bank);
if(index >= g_tiles_count || base >= 800 || bank >= 4)
if(index >= RSXThread::m_tiles_count || base >= 800 || bank >= 4)
{
return CELL_GCM_ERROR_INVALID_VALUE;
}
@ -470,7 +470,7 @@ int cellGcmBindTile(u8 index)
{
cellGcmSys.Warning("cellGcmBindTile(index=%d)", index);
if(index >= g_tiles_count)
if(index >= RSXThread::m_tiles_count)
{
return CELL_GCM_ERROR_INVALID_VALUE;
}
@ -485,7 +485,7 @@ int cellGcmUnbindTile(u8 index)
{
cellGcmSys.Warning("cellGcmUnbindTile(index=%d)", index);
if(index >= g_tiles_count)
if(index >= RSXThread::m_tiles_count)
{
return CELL_GCM_ERROR_INVALID_VALUE;
}

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

@ -18,6 +18,21 @@ enum
CELL_PHOTO_DECODE_ERROR_DECODE = 0x8002c906,
};
// Datatypes
struct CellPhotoDecodeSetParam
{
u32 dstBuffer_addr;
u16 width;
u16 height;
};
struct CellPhotoDecodeReturnParam
{
u16 width;
u16 height;
};
// Functions
int cellPhotoDecodeInitialize()
{
UNIMPLEMENTED_FUNC(cellPhotoDecode);

View File

@ -18,6 +18,30 @@ enum
CELL_PHOTO_IMPORT_ERROR_INITIALIZE = 0x8002c706,
};
// Datatypes
struct CellPhotoImportFileDataSub
{
int width;
int height;
//CellPhotoImportFormatType format;
//CellPhotoImportTexRot rotate;
};
struct CellPhotoImportFileData
{
char dstFileName; //[CELL_FS_MAX_FS_FILE_NAME_LENGTH];
char photo_title; //[CELL_PHOTO_IMPORT_PHOTO_TITLE_MAX_LENGTH*3];
char game_title; //[CELL_PHOTO_IMPORT_GAME_TITLE_MAX_SIZE];
char game_comment; //[CELL_PHOTO_IMPORT_GAME_COMMENT_MAX_SIZE];
CellPhotoImportFileDataSub* data_sub;
};
struct CellPhotoImportSetParam
{
unsigned int fileSizeMax;
};
// Functions
int _cellPhotoImport()
{
UNIMPLEMENTED_FUNC(cellPhotoImport);

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

@ -9,7 +9,6 @@ Module cellRecs(0x001f, cellRecs_init);
int cellRescSetConvertAndFlip(s32 indx)
{
cellRecs.Log("cellRescSetConvertAndFlip(indx=0x%x)", indx);
Emu.GetGSManager().GetRender().Draw();
return CELL_OK;
}

View File

@ -1,267 +1,609 @@
#include "stdafx.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/SC_FUNC.h"
void cellRtc_init();
Module cellRtc(0x0009, cellRtc_init);
// Return Codes
enum
{
CELL_RTC_ERROR_NOT_INITIALIZED = 0x80010601,
CELL_RTC_ERROR_INVALID_POINTER = 0x80010602,
CELL_RTC_ERROR_INVALID_VALUE = 0x80010603,
CELL_RTC_ERROR_INVALID_ARG = 0x80010604,
CELL_RTC_ERROR_NOT_SUPPORTED = 0x80010605,
CELL_RTC_ERROR_NO_CLOCK = 0x80010606,
CELL_RTC_ERROR_BAD_PARSE = 0x80010607,
CELL_RTC_ERROR_INVALID_YEAR = 0x80010621,
CELL_RTC_ERROR_INVALID_MONTH = 0x80010622,
CELL_RTC_ERROR_INVALID_DAY = 0x80010623,
CELL_RTC_ERROR_INVALID_HOUR = 0x80010624,
CELL_RTC_ERROR_INVALID_MINUTE = 0x80010625,
CELL_RTC_ERROR_INVALID_SECOND = 0x80010626,
CELL_RTC_ERROR_INVALID_MICROSECOND = 0x80010627,
};
int cellRtcGetCurrentTick()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcGetCurrentClock()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcGetCurrentClockLocalTime()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcFormatRfc2822()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcFormatRfc2822LocalTime()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcFormatRfc3339()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcFormatRfc3339LocalTime()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcParseDateTime()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcParseRfc3339()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcGetTick()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcSetTick()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcTickAddTicks()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcTickAddMicroseconds()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcTickAddSeconds()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcTickAddMinutes()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcTickAddHours()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcTickAddDays()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcTickAddWeeks()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcTickAddMonths()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcTickAddYears()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcConvertUtcToLocalTime()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcConvertLocalTimeToUtc()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcGetDosTime()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcGetTime_t()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcGetWin32FileTime()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcSetDosTime()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcSetTime_t()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcSetWin32FileTime()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcIsLeapYear()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcGetDaysInMonth()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcGetDayOfWeek()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcCheckValid()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
int cellRtcCompareTick()
{
UNIMPLEMENTED_FUNC(cellRtc);
return CELL_OK;
}
void cellRtc_init()
{
cellRtc.AddFunc(0x9dafc0d9, cellRtcGetCurrentTick);
cellRtc.AddFunc(0x32c941cf, cellRtcGetCurrentClock);
cellRtc.AddFunc(0x2cce9cf5, cellRtcGetCurrentClockLocalTime);
cellRtc.AddFunc(0x5491b9d5, cellRtcFormatRfc2822);
cellRtc.AddFunc(0xa07c3d2f, cellRtcFormatRfc2822LocalTime);
cellRtc.AddFunc(0xd9c0b463, cellRtcFormatRfc3339);
cellRtc.AddFunc(0x1324948a, cellRtcFormatRfc3339LocalTime);
cellRtc.AddFunc(0xc5bc0fac, cellRtcParseDateTime);
cellRtc.AddFunc(0xcf11c3d6, cellRtcParseRfc3339);
cellRtc.AddFunc(0xc7bdb7eb, cellRtcGetTick);
cellRtc.AddFunc(0x99b13034, cellRtcSetTick);
cellRtc.AddFunc(0x269a1882, cellRtcTickAddTicks);
cellRtc.AddFunc(0xf8509925, cellRtcTickAddMicroseconds);
cellRtc.AddFunc(0xccce71bd, cellRtcTickAddSeconds);
cellRtc.AddFunc(0x2f010bfa, cellRtcTickAddMinutes);
cellRtc.AddFunc(0xd41d3bd2, cellRtcTickAddHours);
cellRtc.AddFunc(0x75744e2a, cellRtcTickAddDays);
cellRtc.AddFunc(0x64c63fd5, cellRtcTickAddWeeks);
cellRtc.AddFunc(0xe0ecbb45, cellRtcTickAddMonths);
cellRtc.AddFunc(0x332a74dd, cellRtcTickAddYears);
cellRtc.AddFunc(0xc48d5002, cellRtcConvertUtcToLocalTime);
cellRtc.AddFunc(0x46ca7fe0, cellRtcConvertLocalTimeToUtc);
// (TODO: Time Information Manipulation Functions missing)
cellRtc.AddFunc(0xdfff32cf, cellRtcGetDosTime);
cellRtc.AddFunc(0xcb90c761, cellRtcGetTime_t);
cellRtc.AddFunc(0xe7086f05, cellRtcGetWin32FileTime);
cellRtc.AddFunc(0x9598d4b3, cellRtcSetDosTime);
cellRtc.AddFunc(0xbb543189, cellRtcSetTime_t);
cellRtc.AddFunc(0x5f68c268, cellRtcSetWin32FileTime);
cellRtc.AddFunc(0x5316b4a8, cellRtcIsLeapYear);
cellRtc.AddFunc(0x5b6a0a1d, cellRtcGetDaysInMonth);
cellRtc.AddFunc(0xc2d8cf95, cellRtcGetDayOfWeek);
cellRtc.AddFunc(0x7f1086e6, cellRtcCheckValid);
cellRtc.AddFunc(0xfb51fc61, cellRtcCompareTick);
#include "stdafx.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/SC_FUNC.h"
void cellRtc_init();
Module cellRtc(0x0009, cellRtc_init);
// Return Codes
enum
{
CELL_RTC_ERROR_NOT_INITIALIZED = 0x80010601,
CELL_RTC_ERROR_INVALID_POINTER = 0x80010602,
CELL_RTC_ERROR_INVALID_VALUE = 0x80010603,
CELL_RTC_ERROR_INVALID_ARG = 0x80010604,
CELL_RTC_ERROR_NOT_SUPPORTED = 0x80010605,
CELL_RTC_ERROR_NO_CLOCK = 0x80010606,
CELL_RTC_ERROR_BAD_PARSE = 0x80010607,
CELL_RTC_ERROR_INVALID_YEAR = 0x80010621,
CELL_RTC_ERROR_INVALID_MONTH = 0x80010622,
CELL_RTC_ERROR_INVALID_DAY = 0x80010623,
CELL_RTC_ERROR_INVALID_HOUR = 0x80010624,
CELL_RTC_ERROR_INVALID_MINUTE = 0x80010625,
CELL_RTC_ERROR_INVALID_SECOND = 0x80010626,
CELL_RTC_ERROR_INVALID_MICROSECOND = 0x80010627,
};
struct CellRtcTick
{
u64 tick;
};
struct CellRtcDateTime
{
u16 year;
u16 month;
u16 day;
u16 hour;
u16 minute;
u16 second;
u32 microsecond;
};
long convertToUNIXTime(u16 seconds, u16 minutes, u16 hours, u16 days, int years)
{
return (seconds + minutes*60 + hours*3600 + days*86400 + (years-70)*31536000 + ((years-69)/4)*86400 - ((years-1)/100)*86400 + ((years+299)/400)*86400);
}
u64 convertToWin32FILETIME(u16 seconds, u16 minutes, u16 hours, u16 days, int years)
{
long unixtime = convertToUNIXTime(seconds, minutes, hours, days, years);
LONGLONG win32time = Int32x32To64(unixtime, 10000000) + 116444736000000000;
u64 win32filetime = (u64) win32time | win32time >> 32;
return win32filetime;
}
int cellRtcGetCurrentTick(mem64_t tick)
{
cellRtc.Log("cellRtcGetCurrentTick(tick_addr=0x%x)", tick.GetAddr());
wxDateTime unow = wxDateTime::UNow();
tick = unow.GetTicks();
return CELL_OK;
}
int cellRtcGetCurrentClock(u32 clock_addr, int time_zone)
{
cellRtc.Log("cellRtcGetCurrentClock(clock_addr=0x%x, time_zone=%d)", clock_addr, time_zone);
wxDateTime unow = wxDateTime::UNow();
// Add time_zone as offset in minutes.
wxTimeSpan tz = wxTimeSpan::wxTimeSpan(0, (long) time_zone, 0, 0);
unow.Add(tz);
Memory.Write16(clock_addr, unow.GetYear(wxDateTime::TZ::UTC));
Memory.Write16(clock_addr + 2, unow.GetMonth(wxDateTime::TZ::UTC));
Memory.Write16(clock_addr + 4, unow.GetDay(wxDateTime::TZ::UTC));
Memory.Write16(clock_addr + 6, unow.GetHour(wxDateTime::TZ::UTC));
Memory.Write16(clock_addr + 8, unow.GetMinute(wxDateTime::TZ::UTC));
Memory.Write16(clock_addr + 10, unow.GetSecond(wxDateTime::TZ::UTC));
Memory.Write32(clock_addr + 12, unow.GetMillisecond(wxDateTime::TZ::UTC) * 1000);
return CELL_OK;
}
int cellRtcGetCurrentClockLocalTime(u32 clock_addr)
{
cellRtc.Log("cellRtcGetCurrentClockLocalTime(clock_addr=0x%x)", clock_addr);
wxDateTime unow = wxDateTime::UNow();
Memory.Write16(clock_addr, unow.GetYear(wxDateTime::TZ::Local));
Memory.Write16(clock_addr + 2, unow.GetMonth(wxDateTime::TZ::Local));
Memory.Write16(clock_addr + 4, unow.GetDay(wxDateTime::TZ::Local));
Memory.Write16(clock_addr + 6, unow.GetHour(wxDateTime::TZ::Local));
Memory.Write16(clock_addr + 8, unow.GetMinute(wxDateTime::TZ::Local));
Memory.Write16(clock_addr + 10, unow.GetSecond(wxDateTime::TZ::Local));
Memory.Write32(clock_addr + 12, unow.GetMillisecond(wxDateTime::TZ::Local) * 1000);
return CELL_OK;
}
int cellRtcFormatRfc2822(u32 rfc_addr, u32 tick_addr, int time_zone)
{
cellRtc.Log("cellRtcFormatRfc2822(rfc_addr=0x%x, tick_addr=0x%x, time_zone=%d)", rfc_addr, tick_addr, time_zone);
CellRtcTick current_tick;
current_tick.tick = Memory.Read64(tick_addr);
// Add time_zone as offset in minutes.
wxTimeSpan tz = wxTimeSpan::wxTimeSpan(0, (long) time_zone, 0, 0);
// Get date from ticks + tz.
wxDateTime date = wxDateTime::wxDateTime((time_t)current_tick.tick);
date.Add(tz);
// Format date string in RFC2822 format (e.g.: Mon, 01 Jan 1990 12:00:00 +0000).
const wxString& str = date.Format("%a, %d %b %Y %T %z", wxDateTime::TZ::UTC);
Memory.WriteString(rfc_addr, str);
return CELL_OK;
}
int cellRtcFormatRfc2822LocalTime(u32 rfc_addr, u32 tick_addr)
{
cellRtc.Log("cellRtcFormatRfc2822LocalTime(rfc_addr=0x%x, tick_addr=0x%x)", rfc_addr, tick_addr);
CellRtcTick current_tick;
current_tick.tick = Memory.Read64(tick_addr);
// Get date from ticks.
wxDateTime date = wxDateTime::wxDateTime((time_t)current_tick.tick);
// Format date string in RFC2822 format (e.g.: Mon, 01 Jan 1990 12:00:00 +0000).
const wxString& str = date.Format("%a, %d %b %Y %T %z", wxDateTime::TZ::Local);
Memory.WriteString(rfc_addr, str);
return CELL_OK;
}
int cellRtcFormatRfc3339(u32 rfc_addr, u32 tick_addr, int time_zone)
{
cellRtc.Log("cellRtcFormatRfc3339(rfc_addr=0x%x, tick_addr=0x%x, time_zone=%d)", rfc_addr, tick_addr, time_zone);
CellRtcTick current_tick;
current_tick.tick = Memory.Read64(tick_addr);
// Add time_zone as offset in minutes.
wxTimeSpan tz = wxTimeSpan::wxTimeSpan(0, (long) time_zone, 0, 0);
// Get date from ticks + tz.
wxDateTime date = wxDateTime::wxDateTime((time_t)current_tick.tick);
date.Add(tz);
// Format date string in RFC3339 format (e.g.: 1990-01-01T12:00:00.00Z).
const wxString& str = date.Format("%FT%T.%zZ", wxDateTime::TZ::UTC);
Memory.WriteString(rfc_addr, str);
return CELL_OK;
}
int cellRtcFormatRfc3339LocalTime(u32 rfc_addr, u32 tick_addr)
{
cellRtc.Log("cellRtcFormatRfc3339LocalTime(rfc_addr=0x%x, tick_addr=0x%x)", rfc_addr, tick_addr);
CellRtcTick current_tick;
current_tick.tick = Memory.Read64(tick_addr);
// Get date from ticks.
wxDateTime date = wxDateTime::wxDateTime((time_t)current_tick.tick);
// Format date string in RFC3339 format (e.g.: 1990-01-01T12:00:00.00Z).
const wxString& str = date.Format("%FT%T.%zZ", wxDateTime::TZ::Local);
Memory.WriteString(rfc_addr, str);
return CELL_OK;
}
int cellRtcParseDateTime(mem64_t tick, u32 datetime_addr)
{
cellRtc.Log("cellRtcParseDateTime(tick_addr=0x%x, datetime_addr=0x%x)", tick.GetAddr(), datetime_addr);
const wxString& format = Memory.ReadString(datetime_addr);
// Get date from formatted string.
wxDateTime date;
date.ParseDateTime(format);
tick = date.GetTicks();
return CELL_OK;
}
int cellRtcParseRfc3339(mem64_t tick, u32 datetime_addr)
{
cellRtc.Log("cellRtcParseRfc3339(tick_addr=0x%x, datetime_addr=0x%x)", tick.GetAddr(), datetime_addr);
const wxString& format = Memory.ReadString(datetime_addr);
// Get date from RFC3339 formatted string.
wxDateTime date;
date.ParseDateTime(format);
tick = date.GetTicks();
return CELL_OK;
}
int cellRtcGetTick(u32 clock_addr, mem64_t tick)
{
cellRtc.Log("cellRtcGetTick(clock_addr=0x%x, tick_addr=0x%x)", clock_addr, tick.GetAddr());
CellRtcDateTime clock;
clock.year = Memory.Read16(clock_addr);
clock.month = Memory.Read16(clock_addr + 2);
clock.day = Memory.Read16(clock_addr + 4);
clock.hour = Memory.Read16(clock_addr + 6);
clock.minute = Memory.Read16(clock_addr + 8);
clock.second = Memory.Read16(clock_addr + 10);
clock.microsecond = Memory.Read32(clock_addr + 12);
wxDateTime datetime = wxDateTime::wxDateTime(clock.day, (wxDateTime::Month)clock.month, clock.year, clock.hour, clock.minute, clock.second, (clock.microsecond / 1000));
tick = datetime.GetTicks();
return CELL_OK;
}
int cellRtcSetTick(u32 clock_addr, u32 tick_addr)
{
cellRtc.Log("cellRtcSetTick(clock_addr=0x%x, tick_addr=0x%x)", clock_addr, tick_addr);
CellRtcTick current_tick;
current_tick.tick = Memory.Read64(tick_addr);
wxDateTime date = wxDateTime::wxDateTime((time_t)current_tick.tick);
CellRtcDateTime clock;
clock.year = date.GetYear(wxDateTime::TZ::UTC);
clock.month = date.GetMonth(wxDateTime::TZ::UTC);
clock.day = date.GetDay(wxDateTime::TZ::UTC);
clock.hour = date.GetHour(wxDateTime::TZ::UTC);
clock.minute = date.GetMinute(wxDateTime::TZ::UTC);
clock.second = date.GetSecond(wxDateTime::TZ::UTC);
clock.microsecond = date.GetMillisecond(wxDateTime::TZ::UTC) * 1000;
Memory.Write16(clock_addr, clock.year);
Memory.Write16(clock_addr + 2, clock.month);
Memory.Write16(clock_addr + 4, clock.day);
Memory.Write16(clock_addr + 6, clock.hour);
Memory.Write16(clock_addr + 8, clock.minute);
Memory.Write16(clock_addr + 10, clock.second);
Memory.Write32(clock_addr + 12, clock.microsecond);
return CELL_OK;
}
int cellRtcTickAddTicks(mem64_t tick, u32 tick_add_addr, long add)
{
cellRtc.Log("cellRtcTickAddTicks(tick_addr=0x%x, tick_add_addr=0x%x, add=%l)", tick.GetAddr(), tick_add_addr, add);
tick = Memory.Read64(tick_add_addr) + add;
return CELL_OK;
}
int cellRtcTickAddMicroseconds(mem64_t tick, u32 tick_add_addr, long add)
{
cellRtc.Log("cellRtcTickAddMicroseconds(tick_addr=0x%x, tick_add_addr=0x%x, add=%l)", tick.GetAddr(), tick_add_addr, add);
wxDateTime date = wxDateTime::wxDateTime((time_t)Memory.Read64(tick_add_addr));
wxTimeSpan microseconds = wxTimeSpan::wxTimeSpan(0, 0, 0, add / 1000);
date.Add(microseconds);
tick = date.GetTicks();
return CELL_OK;
}
int cellRtcTickAddSeconds(mem64_t tick, u32 tick_add_addr, long add)
{
cellRtc.Log("cellRtcTickAddSeconds(tick_addr=0x%x, tick_add_addr=0x%x, add=%l)", tick.GetAddr(), tick_add_addr, add);
wxDateTime date = wxDateTime::wxDateTime((time_t)Memory.Read64(tick_add_addr));
wxTimeSpan seconds = wxTimeSpan::wxTimeSpan(0, 0, add, 0);
date.Add(seconds);
tick = date.GetTicks();
return CELL_OK;
}
int cellRtcTickAddMinutes(mem64_t tick, u32 tick_add_addr, long add)
{
cellRtc.Log("cellRtcTickAddMinutes(tick_addr=0x%x, tick_add_addr=0x%x, add=%l)", tick.GetAddr(), tick_add_addr, add);
wxDateTime date = wxDateTime::wxDateTime((time_t)Memory.Read64(tick_add_addr));
wxTimeSpan minutes = wxTimeSpan::wxTimeSpan(0, add, 0, 0);
date.Add(minutes);
tick = date.GetTicks();
return CELL_OK;
}
int cellRtcTickAddHours(mem64_t tick, u32 tick_add_addr, int add)
{
cellRtc.Log("cellRtcTickAddHours(tick_addr=0x%x, tick_add_addr=0x%x, add=%l)", tick.GetAddr(), tick_add_addr, add);
wxDateTime date = wxDateTime::wxDateTime((time_t)Memory.Read64(tick_add_addr));
wxTimeSpan hours = wxTimeSpan::wxTimeSpan(add, 0, 0, 0);
date.Add(hours);
tick = date.GetTicks();
return CELL_OK;
}
int cellRtcTickAddDays(mem64_t tick, u32 tick_add_addr, int add)
{
cellRtc.Log("cellRtcTickAddDays(tick_addr=0x%x, tick_add_addr=0x%x, add=%l)", tick.GetAddr(), tick_add_addr, add);
wxDateTime date = wxDateTime::wxDateTime((time_t)Memory.Read64(tick_add_addr));
wxDateSpan days = wxDateSpan::wxDateSpan(0, 0, 0, add);
date.Add(days);
tick = date.GetTicks();
return CELL_OK;
}
int cellRtcTickAddWeeks(mem64_t tick, u32 tick_add_addr, int add)
{
cellRtc.Log("cellRtcTickAddWeeks(tick_addr=0x%x, tick_add_addr=0x%x, add=%l)", tick.GetAddr(), tick_add_addr, add);
wxDateTime date = wxDateTime::wxDateTime((time_t)Memory.Read64(tick_add_addr));
wxDateSpan weeks = wxDateSpan::wxDateSpan(0, 0, add, 0);
date.Add(weeks);
tick = date.GetTicks();
return CELL_OK;
}
int cellRtcTickAddMonths(mem64_t tick, u32 tick_add_addr, int add)
{
cellRtc.Log("cellRtcTickAddMonths(tick_addr=0x%x, tick_add_addr=0x%x, add=%l)", tick.GetAddr(), tick_add_addr, add);
wxDateTime date = wxDateTime::wxDateTime((time_t)Memory.Read64(tick_add_addr));
wxDateSpan months = wxDateSpan::wxDateSpan(0, add, 0, 0);
date.Add(months);
tick = date.GetTicks();
return CELL_OK;
}
int cellRtcTickAddYears(mem64_t tick, u32 tick_add_addr, int add)
{
cellRtc.Log("cellRtcTickAddYears(tick_addr=0x%x, tick_add_addr=0x%x, add=%l)", tick.GetAddr(), tick_add_addr, add);
wxDateTime date = wxDateTime::wxDateTime((time_t)Memory.Read64(tick_add_addr));
wxDateSpan years = wxDateSpan::wxDateSpan(add, 0, 0, 0);
date.Add(years);
tick = date.GetTicks();
return CELL_OK;
}
int cellRtcConvertUtcToLocalTime(u32 tick_utc_addr, mem64_t tick_local)
{
cellRtc.Log("cellRtcConvertUtcToLocalTime(tick_utc_addr=0x%x, tick_local_addr=0x%x)", tick_utc_addr, tick_local.GetAddr());
wxDateTime time = wxDateTime::wxDateTime((time_t)Memory.Read64(tick_utc_addr));
wxDateTime local_time = time.FromUTC(false);
tick_local = local_time.GetTicks();
return CELL_OK;
}
int cellRtcConvertLocalTimeToUtc(u32 tick_local_addr, mem64_t tick_utc)
{
cellRtc.Log("cellRtcConvertLocalTimeToUtc(tick_local_addr=0x%x, tick_utc_addr=0x%x)", tick_local_addr, tick_utc.GetAddr());
wxDateTime time = wxDateTime::wxDateTime((time_t)Memory.Read64(tick_local_addr));
wxDateTime utc_time = time.ToUTC(false);
tick_utc = utc_time.GetTicks();
return CELL_OK;
}
int cellRtcGetDosTime(u32 datetime_addr, mem64_t dos_time)
{
cellRtc.Log("cellRtcGetDosTime(datetime_addr=0x%x, dos_time_addr=0x%x)", datetime_addr, dos_time.GetAddr());
CellRtcDateTime datetime;
datetime.year = Memory.Read16(datetime_addr);
datetime.month = Memory.Read16(datetime_addr + 2);
datetime.day = Memory.Read16(datetime_addr + 4);
datetime.hour = Memory.Read16(datetime_addr + 6);
datetime.minute = Memory.Read16(datetime_addr + 8);
datetime.second = Memory.Read16(datetime_addr + 10);
datetime.microsecond = Memory.Read32(datetime_addr + 12);
// Convert to DOS time.
wxDateTime date_time = wxDateTime::wxDateTime(datetime.day, (wxDateTime::Month)datetime.month, datetime.year, datetime.hour, datetime.minute, datetime.second, (datetime.microsecond / 1000));
dos_time = date_time.GetAsDOS();
return CELL_OK;
}
int cellRtcGetTime_t(u32 datetime_addr, mem64_t posix_time)
{
cellRtc.Log("cellRtcGetTime_t(datetime_addr=0x%x, posix_time_addr=0x%x)", datetime_addr, posix_time.GetAddr());
CellRtcDateTime datetime;
datetime.year = Memory.Read16(datetime_addr);
datetime.month = Memory.Read16(datetime_addr + 2);
datetime.day = Memory.Read16(datetime_addr + 4);
datetime.hour = Memory.Read16(datetime_addr + 6);
datetime.minute = Memory.Read16(datetime_addr + 8);
datetime.second = Memory.Read16(datetime_addr + 10);
datetime.microsecond = Memory.Read32(datetime_addr + 12);
// Convert to POSIX time_t.
wxDateTime date_time = wxDateTime::wxDateTime(datetime.day, (wxDateTime::Month)datetime.month, datetime.year, datetime.hour, datetime.minute, datetime.second, (datetime.microsecond / 1000));
posix_time = convertToUNIXTime(date_time.GetSecond(wxDateTime::TZ::UTC), date_time.GetMinute(wxDateTime::TZ::UTC),
date_time.GetHour(wxDateTime::TZ::UTC), date_time.GetDay(wxDateTime::TZ::UTC), date_time.GetYear(wxDateTime::TZ::UTC));
return CELL_OK;
}
int cellRtcGetWin32FileTime(u32 datetime_addr, mem64_t win32_time)
{
cellRtc.Log("cellRtcGetWin32FileTime(datetime_addr=0x%x, win32_time_addr=0x%x)", datetime_addr, win32_time.GetAddr());
CellRtcDateTime datetime;
datetime.year = Memory.Read16(datetime_addr);
datetime.month = Memory.Read16(datetime_addr + 2);
datetime.day = Memory.Read16(datetime_addr + 4);
datetime.hour = Memory.Read16(datetime_addr + 6);
datetime.minute = Memory.Read16(datetime_addr + 8);
datetime.second = Memory.Read16(datetime_addr + 10);
datetime.microsecond = Memory.Read32(datetime_addr + 12);
// Convert to WIN32 FILETIME.
wxDateTime date_time = wxDateTime::wxDateTime(datetime.day, (wxDateTime::Month)datetime.month, datetime.year, datetime.hour, datetime.minute, datetime.second, (datetime.microsecond / 1000));
win32_time = convertToWin32FILETIME(date_time.GetSecond(wxDateTime::TZ::UTC), date_time.GetMinute(wxDateTime::TZ::UTC),
date_time.GetHour(wxDateTime::TZ::UTC), date_time.GetDay(wxDateTime::TZ::UTC), date_time.GetYear(wxDateTime::TZ::UTC));
return CELL_OK;
}
int cellRtcSetDosTime(u32 datetime_addr, u32 dos_time_addr)
{
cellRtc.Log("cellRtcSetDosTime(datetime_addr=0x%x, dos_time_addr=0x%x)", datetime_addr, dos_time_addr);
wxDateTime date_time;
wxDateTime dos_time = date_time.SetFromDOS(Memory.Read32(dos_time_addr));
CellRtcDateTime datetime;
datetime.year = dos_time.GetYear(wxDateTime::TZ::UTC);
datetime.month = dos_time.GetMonth(wxDateTime::TZ::UTC);
datetime.day = dos_time.GetDay(wxDateTime::TZ::UTC);
datetime.hour = dos_time.GetHour(wxDateTime::TZ::UTC);
datetime.minute = dos_time.GetMinute(wxDateTime::TZ::UTC);
datetime.second = dos_time.GetSecond(wxDateTime::TZ::UTC);
datetime.microsecond = dos_time.GetMillisecond(wxDateTime::TZ::UTC) * 1000;
Memory.Write16(datetime_addr, datetime.year);
Memory.Write16(datetime_addr + 2, datetime.month);
Memory.Write16(datetime_addr + 4, datetime.day);
Memory.Write16(datetime_addr + 6, datetime.hour);
Memory.Write16(datetime_addr + 8, datetime.minute);
Memory.Write16(datetime_addr + 10, datetime.second);
Memory.Write32(datetime_addr + 12, datetime.microsecond);
return CELL_OK;
}
int cellRtcSetTime_t(u32 datetime_addr, u32 posix_time_addr)
{
cellRtc.Log("cellRtcSetTime_t(datetime_addr=0x%x, posix_time_addr=0x%x)", datetime_addr, posix_time_addr);
wxDateTime date_time = wxDateTime::wxDateTime((time_t)Memory.Read64(posix_time_addr));
CellRtcDateTime datetime;
datetime.year = date_time.GetYear(wxDateTime::TZ::UTC);
datetime.month = date_time.GetMonth(wxDateTime::TZ::UTC);
datetime.day = date_time.GetDay(wxDateTime::TZ::UTC);
datetime.hour = date_time.GetHour(wxDateTime::TZ::UTC);
datetime.minute = date_time.GetMinute(wxDateTime::TZ::UTC);
datetime.second = date_time.GetSecond(wxDateTime::TZ::UTC);
datetime.microsecond = date_time.GetMillisecond(wxDateTime::TZ::UTC) * 1000;
Memory.Write16(datetime_addr, datetime.year);
Memory.Write16(datetime_addr + 2, datetime.month);
Memory.Write16(datetime_addr + 4, datetime.day);
Memory.Write16(datetime_addr + 6, datetime.hour);
Memory.Write16(datetime_addr + 8, datetime.minute);
Memory.Write16(datetime_addr + 10, datetime.second);
Memory.Write32(datetime_addr + 12, datetime.microsecond);
return CELL_OK;
}
int cellRtcSetWin32FileTime(u32 datetime_addr, u32 win32_time_addr)
{
cellRtc.Log("cellRtcSetWin32FileTime(datetime_addr=0x%x, win32_time_addr=0x%x)", datetime_addr, win32_time_addr);
wxDateTime date_time = wxDateTime::wxDateTime((time_t)Memory.Read64(win32_time_addr));
CellRtcDateTime datetime;
datetime.year = date_time.GetYear(wxDateTime::TZ::UTC);
datetime.month = date_time.GetMonth(wxDateTime::TZ::UTC);
datetime.day = date_time.GetDay(wxDateTime::TZ::UTC);
datetime.hour = date_time.GetHour(wxDateTime::TZ::UTC);
datetime.minute = date_time.GetMinute(wxDateTime::TZ::UTC);
datetime.second = date_time.GetSecond(wxDateTime::TZ::UTC);
datetime.microsecond = date_time.GetMillisecond(wxDateTime::TZ::UTC) * 1000;
Memory.Write16(datetime_addr, datetime.year);
Memory.Write16(datetime_addr + 2, datetime.month);
Memory.Write16(datetime_addr + 4, datetime.day);
Memory.Write16(datetime_addr + 6, datetime.hour);
Memory.Write16(datetime_addr + 8, datetime.minute);
Memory.Write16(datetime_addr + 10, datetime.second);
Memory.Write32(datetime_addr + 12, datetime.microsecond);
return CELL_OK;
}
int cellRtcIsLeapYear(int year)
{
cellRtc.Log("cellRtcIsLeapYear(year=%d)", year);
wxDateTime datetime;
return datetime.IsLeapYear(year, wxDateTime::Gregorian);
}
int cellRtcGetDaysInMonth(int year, int month)
{
cellRtc.Log("cellRtcGetDaysInMonth(year=%d, month=%d)", year, month);
wxDateTime datetime;
return datetime.GetNumberOfDays((wxDateTime::Month) month, year, wxDateTime::Gregorian);
}
int cellRtcGetDayOfWeek(int year, int month, int day)
{
cellRtc.Log("cellRtcGetDayOfWeek(year=%d, month=%d, day=%d)", year, month, day);
wxDateTime datetime;
datetime.SetToWeekDay((wxDateTime::WeekDay) day, 1, (wxDateTime::Month) month, year);
return datetime.GetWeekDay();
}
int cellRtcCheckValid(u32 datetime_addr)
{
cellRtc.Log("cellRtcCheckValid(datetime_addr=0x%x)", datetime_addr);
CellRtcDateTime datetime;
datetime.year = Memory.Read16(datetime_addr);
datetime.month = Memory.Read16(datetime_addr + 2);
datetime.day = Memory.Read16(datetime_addr + 4);
datetime.hour = Memory.Read16(datetime_addr + 6);
datetime.minute = Memory.Read16(datetime_addr + 8);
datetime.second = Memory.Read16(datetime_addr + 10);
datetime.microsecond = Memory.Read32(datetime_addr + 12);
if((datetime.year < 1) || (datetime.year > 9999)) return CELL_RTC_ERROR_INVALID_YEAR;
else if((datetime.month < 1) || (datetime.month > 12)) return CELL_RTC_ERROR_INVALID_MONTH;
else if((datetime.day < 1) || (datetime.day > 31)) return CELL_RTC_ERROR_INVALID_DAY;
else if((datetime.hour < 0) || (datetime.hour > 23)) return CELL_RTC_ERROR_INVALID_HOUR;
else if((datetime.minute < 0) || (datetime.minute > 59)) return CELL_RTC_ERROR_INVALID_MINUTE;
else if((datetime.second < 0) || (datetime.second > 59)) return CELL_RTC_ERROR_INVALID_SECOND;
else if((datetime.microsecond < 0) || (datetime.microsecond > 999999)) return CELL_RTC_ERROR_INVALID_MICROSECOND;
else return CELL_OK;
}
int cellRtcCompareTick(u32 tick_addr_1, u32 tick_addr_2)
{
cellRtc.Log("cellRtcCompareTick(tick_addr_1=0x%x, tick_addr_2=0x%x)", tick_addr_1, tick_addr_2);
u64 tick1 = Memory.Read64(tick_addr_1);
u64 tick2 = Memory.Read64(tick_addr_2);
if(tick1 < tick2) return -1;
else if(tick1 > tick2) return 1;
else return CELL_OK;
}
void cellRtc_init()
{
cellRtc.AddFunc(0x9dafc0d9, cellRtcGetCurrentTick);
cellRtc.AddFunc(0x32c941cf, cellRtcGetCurrentClock);
cellRtc.AddFunc(0x2cce9cf5, cellRtcGetCurrentClockLocalTime);
cellRtc.AddFunc(0x5491b9d5, cellRtcFormatRfc2822);
cellRtc.AddFunc(0xa07c3d2f, cellRtcFormatRfc2822LocalTime);
cellRtc.AddFunc(0xd9c0b463, cellRtcFormatRfc3339);
cellRtc.AddFunc(0x1324948a, cellRtcFormatRfc3339LocalTime);
cellRtc.AddFunc(0xc5bc0fac, cellRtcParseDateTime);
cellRtc.AddFunc(0xcf11c3d6, cellRtcParseRfc3339);
cellRtc.AddFunc(0xc7bdb7eb, cellRtcGetTick);
cellRtc.AddFunc(0x99b13034, cellRtcSetTick);
cellRtc.AddFunc(0x269a1882, cellRtcTickAddTicks);
cellRtc.AddFunc(0xf8509925, cellRtcTickAddMicroseconds);
cellRtc.AddFunc(0xccce71bd, cellRtcTickAddSeconds);
cellRtc.AddFunc(0x2f010bfa, cellRtcTickAddMinutes);
cellRtc.AddFunc(0xd41d3bd2, cellRtcTickAddHours);
cellRtc.AddFunc(0x75744e2a, cellRtcTickAddDays);
cellRtc.AddFunc(0x64c63fd5, cellRtcTickAddWeeks);
cellRtc.AddFunc(0xe0ecbb45, cellRtcTickAddMonths);
cellRtc.AddFunc(0x332a74dd, cellRtcTickAddYears);
cellRtc.AddFunc(0xc48d5002, cellRtcConvertUtcToLocalTime);
cellRtc.AddFunc(0x46ca7fe0, cellRtcConvertLocalTimeToUtc);
// (TODO: Time Information Manipulation Functions missing)
cellRtc.AddFunc(0xdfff32cf, cellRtcGetDosTime);
cellRtc.AddFunc(0xcb90c761, cellRtcGetTime_t);
cellRtc.AddFunc(0xe7086f05, cellRtcGetWin32FileTime);
cellRtc.AddFunc(0x9598d4b3, cellRtcSetDosTime);
cellRtc.AddFunc(0xbb543189, cellRtcSetTime_t);
cellRtc.AddFunc(0x5f68c268, cellRtcSetWin32FileTime);
cellRtc.AddFunc(0x5316b4a8, cellRtcIsLeapYear);
cellRtc.AddFunc(0x5b6a0a1d, cellRtcGetDaysInMonth);
cellRtc.AddFunc(0xc2d8cf95, cellRtcGetDayOfWeek);
cellRtc.AddFunc(0x7f1086e6, cellRtcCheckValid);
cellRtc.AddFunc(0xfb51fc61, cellRtcCompareTick);
}

View File

@ -2,11 +2,18 @@
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/SC_FUNC.h"
<<<<<<< HEAD
void cellSaveData_init ();
Module cellSaveData ("cellSaveData", cellSaveData_init);
//Error codes
=======
void cellSaveData_init();
Module cellSaveData("cellSaveData", cellSaveData_init);
// Error codes
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
enum
{
CELL_SAVEDATA_RET_OK = 0,
@ -22,6 +29,7 @@ enum
CELL_SAVEDATA_ERROR_NOUSER,
};
<<<<<<< HEAD
//datatyps
struct CellSaveDataSetList
@ -30,67 +38,121 @@ unsigned int sortType;
unsigned int sortOrder;
char *dirNamePrefix;
void *reserved;
=======
// Datatypes
struct CellSaveDataSetList
{
unsigned int sortType;
unsigned int sortOrder;
char *dirNamePrefix;
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
};
struct CellSaveDataSetBuf
{
<<<<<<< HEAD
unsigned int dirListMax;
unsigned int fileListMax;
unsigned int reserved[6];
unsigned int bufSize;
void *buf;
=======
unsigned int dirListMax;
unsigned int fileListMax;
unsigned int reserved[6];
unsigned int bufSize;
void *buf;
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
};
struct CellSaveDataNewDataIcon
{
<<<<<<< HEAD
char *title;
unsigned int iconBufSize;
void *iconBuf;
void *reserved;
=======
char *title;
unsigned int iconBufSize;
void *iconBuf;
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
};
struct CellSaveDataListNewData
{
<<<<<<< HEAD
unsigned int iconPosition;
char *dirName;
CellSaveDataNewDataIcon *icon;
void *reserved;
=======
unsigned int iconPosition;
char *dirName;
CellSaveDataNewDataIcon *icon;
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
};
struct CellSaveDataDirList
{
<<<<<<< HEAD
char dirName; //[CELL_SAVEDATA_DIRNAME_SIZE];
char listParam; //[CELL_SAVEDATA_SYSP_LPARAM_SIZE];
char reserved[8];
=======
char dirName; //[CELL_SAVEDATA_DIRNAME_SIZE];
char listParam; //[CELL_SAVEDATA_SYSP_LPARAM_SIZE];
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
};
struct CellSaveDataListGet
{
<<<<<<< HEAD
unsigned int dirNum;
unsigned int dirListNum;
CellSaveDataDirList *dirList;
char reserved[64];
=======
unsigned int dirNum;
unsigned int dirListNum;
CellSaveDataDirList *dirList;
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
};
struct CellSaveDataListSet
{
<<<<<<< HEAD
unsigned int focusPosition;
char *focusDirName;
unsigned int fixedListNum;
CellSaveDataDirList *fixedList;
CellSaveDataListNewData *newData;
void *reserved;
=======
unsigned int focusPosition;
char *focusDirName;
unsigned int fixedListNum;
CellSaveDataDirList *fixedList;
CellSaveDataListNewData *newData;
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
};
struct CellSaveDataFixedSet
{
<<<<<<< HEAD
char *dirName;
CellSaveDataNewDataIcon *newIcon;
unsigned int option;
=======
char *dirName;
CellSaveDataNewDataIcon *newIcon;
unsigned int option;
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
};
struct CellSaveDataSystemFileParam
{
<<<<<<< HEAD
char title; //[CELL_SAVEDATA_SYSP_TITLE_SIZE];
char subTitle; //[CELL_SAVEDATA_SYSP_SUBTITLE_SIZE];
char detail; //[CELL_SAVEDATA_SYSP_DETAIL_SIZE];
@ -98,18 +160,35 @@ unsigned int attribute;
char reserved2[4];
char listParam; //[CELL_SAVEDATA_SYSP_LPARAM_SIZE];
char reserved[256];
=======
char title; //[CELL_SAVEDATA_SYSP_TITLE_SIZE];
char subTitle; //[CELL_SAVEDATA_SYSP_SUBTITLE_SIZE];
char detail; //[CELL_SAVEDATA_SYSP_DETAIL_SIZE];
unsigned int attribute;
char reserved2[4];
char listParam; //[CELL_SAVEDATA_SYSP_LPARAM_SIZE];
char reserved[256];
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
};
struct CellSaveDataDirStat
{
<<<<<<< HEAD
s64 st_atime;
s64 st_mtime;
s64 st_ctime;
char dirName; //[CELL_SAVEDATA_DIRNAME_SIZE];
=======
s64 st_atime;
s64 st_mtime;
s64 st_ctime;
char dirName; //[CELL_SAVEDATA_DIRNAME_SIZE];
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
};
struct CellSaveDataFileStat
{
<<<<<<< HEAD
unsigned int fileType;
char reserved1[4];
u64 st_size;
@ -118,10 +197,21 @@ s64 st_mtime;
s64 st_ctime;
char fileName; //[CELL_SAVEDATA_FILENAME_SIZE];
char reserved2[3];
=======
unsigned int fileType;
char reserved1[4];
u64 st_size;
s64 st_atime;
s64 st_mtime;
s64 st_ctime;
char fileName; //[CELL_SAVEDATA_FILENAME_SIZE];
char reserved2[3];
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
};
struct CellSaveDataStatGet
{
<<<<<<< HEAD
int hddFreeSizeKB;
unsigned int isNewData;
CellSaveDataDirStat dir;
@ -133,33 +223,64 @@ unsigned int fileNum;
unsigned int fileListNum;
CellSaveDataFileStat *fileList;
char reserved[64];
=======
int hddFreeSizeKB;
unsigned int isNewData;
CellSaveDataDirStat dir;
CellSaveDataSystemFileParam getParam;
unsigned int bind;
int sizeKB;
int sysSizeKB;
unsigned int fileNum;
unsigned int fileListNum;
CellSaveDataFileStat *fileList;
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
};
struct CellSaveDataAutoIndicator
{
<<<<<<< HEAD
unsigned int dispPosition;
unsigned int dispMode;
char *dispMsg;
unsigned int picBufSize;
void *picBuf;
void *reserved;
=======
unsigned int dispPosition;
unsigned int dispMode;
char *dispMsg;
unsigned int picBufSize;
void *picBuf;
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
};
struct CellSaveDataStatSet
{
<<<<<<< HEAD
CellSaveDataSystemFileParam *setParam;
unsigned int reCreateMode;
CellSaveDataAutoIndicator *indicator;
=======
CellSaveDataSystemFileParam *setParam;
unsigned int reCreateMode;
CellSaveDataAutoIndicator *indicator;
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
};
struct CellSaveDataFileGet
{
<<<<<<< HEAD
unsigned int excSize;
char reserved[64];
=======
unsigned int excSize;
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
};
struct CellSaveDataFileSet
{
<<<<<<< HEAD
unsigned int fileOperation;
void *reserved;
unsigned int fileType;
@ -169,19 +290,39 @@ unsigned int fileOffset;
unsigned int fileSize;
unsigned int fileBufSize;
void *fileBuf;
=======
unsigned int fileOperation;
void *reserved;
unsigned int fileType;
unsigned char secureFileId; //[CELL_SAVEDATA_SECUREFILEID_SIZE];
char *fileName;
unsigned int fileOffset;
unsigned int fileSize;
unsigned int fileBufSize;
void *fileBuf;
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
};
struct CellSaveDataCBResult
{
<<<<<<< HEAD
int result;
unsigned int progressBarInc;
int errNeedSizeKB;
char *invalidMsg;
void *userdata;
=======
int result;
unsigned int progressBarInc;
int errNeedSizeKB;
char *invalidMsg;
void *userdata;
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
};
struct CellSaveDataDoneGet
{
<<<<<<< HEAD
int excResult;
char dirName; //[CELL_SAVEDATA_DIRNAME_SIZE];
int sizeKB;
@ -192,196 +333,331 @@ char reserved[64];
//functions
int cellSaveDataListSave2 () //unsigned int version, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataListCallback funcList, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
=======
int excResult;
char dirName; //[CELL_SAVEDATA_DIRNAME_SIZE];
int sizeKB;
int hddFreeSizeKB;
};
// Functions
int cellSaveDataListSave2() //unsigned int version, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataListCallback funcList, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataListLoad2 () //unsigned int version, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataListCallback funcList, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
=======
int cellSaveDataListLoad2() //unsigned int version, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataListCallback funcList, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataFixedSave2 () //unsigned int version, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataFixedCallback funcFixed, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile,sys_memory_container_t container, void *userdata
=======
int cellSaveDataFixedSave2() //unsigned int version, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataFixedCallback funcFixed, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile,sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataFixedLoad2 () //unsigned int version, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataFixedCallback funcFixed, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
=======
int cellSaveDataFixedLoad2() //unsigned int version, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataFixedCallback funcFixed, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataAutoSave2 () //unsigned int version, const char *dirName, unsigned int errDialog, CellSaveDataSetBuf *setBuf, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
=======
int cellSaveDataAutoSave2() //unsigned int version, const char *dirName, unsigned int errDialog, CellSaveDataSetBuf *setBuf, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataAutoLoad2 () //unsigned int version, const char *dirName, unsigned int errDialog, CellSaveDataSetBuf *setBuf, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
=======
int cellSaveDataAutoLoad2() //unsigned int version, const char *dirName, unsigned int errDialog, CellSaveDataSetBuf *setBuf, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataListAutoSave () //unsigned int version, unsigned int errDialog, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataFixedCallback funcFixed, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile,sys_memory_container_t container, void *userdata
=======
int cellSaveDataListAutoSave() //unsigned int version, unsigned int errDialog, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataFixedCallback funcFixed, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile,sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataListAutoLoad () //unsigned int version, unsigned int errDialog, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataFixedCallback funcFixed, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
=======
int cellSaveDataListAutoLoad() //unsigned int version, unsigned int errDialog, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataFixedCallback funcFixed, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataDelete2 () //sys_memory_container_t container
=======
int cellSaveDataDelete2() //sys_memory_container_t container
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_CANCEL;
}
<<<<<<< HEAD
int cellSaveDataFixedDelete () //CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataFixedCallback funcFixed, CellSaveDataDoneCallback funcDone, sys_memory_container_t container, void *userdata
=======
int cellSaveDataFixedDelete() //CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataFixedCallback funcFixed, CellSaveDataDoneCallback funcDone, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataUserListSave () //unsigned int version, CellSysutilUserId userId, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataListCallback funcList, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
=======
int cellSaveDataUserListSave() //unsigned int version, CellSysutilUserId userId, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataListCallback funcList, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataUserListLoad () //unsigned int version, CellSysutilUserId userId, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataListCallback funcList, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
=======
int cellSaveDataUserListLoad() //unsigned int version, CellSysutilUserId userId, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataListCallback funcList, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataUserFixedSave () //unsigned int version, CellSysutilUserId userId, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataFixedCallback funcFixed, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
=======
int cellSaveDataUserFixedSave() //unsigned int version, CellSysutilUserId userId, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataFixedCallback funcFixed, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataUserFixedLoad () //unsigned int version, CellSysutilUserId userId, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataFixedCallback funcFixed, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
=======
int cellSaveDataUserFixedLoad() //unsigned int version, CellSysutilUserId userId, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataFixedCallback funcFixed, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataUserAutoSave () //unsigned int version, CellSysutilUserId userId, const char *dirName, unsigned int errDialog, CellSaveDataSetBuf *setBuf, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
=======
int cellSaveDataUserAutoSave() //unsigned int version, CellSysutilUserId userId, const char *dirName, unsigned int errDialog, CellSaveDataSetBuf *setBuf, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataUserAutoLoad () //unsigned int version, CellSysutilUserId userId, const char *dirName, unsigned int errDialog, CellSaveDataSetBuf *setBuf, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
=======
int cellSaveDataUserAutoLoad() //unsigned int version, CellSysutilUserId userId, const char *dirName, unsigned int errDialog, CellSaveDataSetBuf *setBuf, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataUserListAutoSave () //unsigned int version, CellSysutilUserId userId, unsigned int errDialog, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataFixedCallback funcFixed, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
=======
int cellSaveDataUserListAutoSave() //unsigned int version, CellSysutilUserId userId, unsigned int errDialog, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataFixedCallback funcFixed, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataUserListAutoLoad () //unsigned int version, CellSysutilUserId userId, unsigned int errDialog, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataFixedCallback funcFixed, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
=======
int cellSaveDataUserListAutoLoad() //unsigned int version, CellSysutilUserId userId, unsigned int errDialog, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataFixedCallback funcFixed, CellSaveDataStatCallback funcStat, CellSaveDataFileCallback funcFile, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataUserFixedDelete () //CellSysutilUserId userId, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataFixedCallback funcFixed, CellSaveDataDoneCallback funcDone, sys_memory_container_t container, void *userdata
=======
int cellSaveDataUserFixedDelete() //CellSysutilUserId userId, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataFixedCallback funcFixed, CellSaveDataDoneCallback funcDone, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
//void cellSaveDataEnableOverlay (); //int enable
//Functions (Extensions)
int cellSaveDataListDelete () //CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataListCallback funcList, CellSaveDataDoneCallback funcDone, sys_memory_container_t container, void *userdata
=======
//void cellSaveDataEnableOverlay(); //int enable
// Functions (Extensions)
int cellSaveDataListDelete() //CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataListCallback funcList, CellSaveDataDoneCallback funcDone, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataListImport () //CellSaveDataSetList *setList, unsigned int maxSizeKB, CellSaveDataDoneCallback funcDone, sys_memory_container_t container, void *userdata
=======
int cellSaveDataListImport() //CellSaveDataSetList *setList, unsigned int maxSizeKB, CellSaveDataDoneCallback funcDone, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataListExport () //CellSaveDataSetList *setList, unsigned int maxSizeKB, CellSaveDataDoneCallback funcDone, sys_memory_container_t container, void *userdata
=======
int cellSaveDataListExport() //CellSaveDataSetList *setList, unsigned int maxSizeKB, CellSaveDataDoneCallback funcDone, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataFixedImport () //const char *dirName, unsigned int maxSizeKB, CellSaveDataDoneCallback funcDone, sys_memory_container_t container, void *userdata
=======
int cellSaveDataFixedImport() //const char *dirName, unsigned int maxSizeKB, CellSaveDataDoneCallback funcDone, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataFixedExport () //const char *dirName, unsigned int maxSizeKB, CellSaveDataDoneCallback funcDone, sys_memory_container_t container, void *userdata
=======
int cellSaveDataFixedExport() //const char *dirName, unsigned int maxSizeKB, CellSaveDataDoneCallback funcDone, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataGetListItem () //const char *dirName, CellSaveDataDirStat *dir, CellSaveDataSystemFileParam *sysFileParam, unsigned int *bind, int *sizeKB
=======
int cellSaveDataGetListItem() //const char *dirName, CellSaveDataDirStat *dir, CellSaveDataSystemFileParam *sysFileParam, unsigned int *bind, int *sizeKB
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataUserListDelete () //CellSysutilUserId userId, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataListCallback funcList, CellSaveDataDoneCallback funcDone,sys_memory_container_t container, void *userdata
=======
int cellSaveDataUserListDelete() //CellSysutilUserId userId, CellSaveDataSetList *setList, CellSaveDataSetBuf *setBuf, CellSaveDataListCallback funcList, CellSaveDataDoneCallback funcDone,sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataUserListImport () //CellSysutilUserId userId, CellSaveDataSetList *setList, unsigned int maxSizeKB, CellSaveDataDoneCallback funcDone, sys_memory_container_t container, void *userdata
=======
int cellSaveDataUserListImport() //CellSysutilUserId userId, CellSaveDataSetList *setList, unsigned int maxSizeKB, CellSaveDataDoneCallback funcDone, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataUserListExport () //CellSysutilUserId userId, CellSaveDataSetList *setList, unsigned int maxSizeKB, CellSaveDataDoneCallback funcDone, sys_memory_container_t container, void *userdata
=======
int cellSaveDataUserListExport() //CellSysutilUserId userId, CellSaveDataSetList *setList, unsigned int maxSizeKB, CellSaveDataDoneCallback funcDone, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataUserFixedImport () //CellSysutilUserId userId, const char *dirName, unsigned int maxSizeKB, CellSaveDataDoneCallback funcDone, sys_memory_container_t container, void *userdata
=======
int cellSaveDataUserFixedImport() //CellSysutilUserId userId, const char *dirName, unsigned int maxSizeKB, CellSaveDataDoneCallback funcDone, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataUserFixedExport () //CellSysutilUserId userId, const char *dirName, unsigned int maxSizeKB, CellSaveDataDoneCallback funcDone, sys_memory_container_t container, void *userdata
=======
int cellSaveDataUserFixedExport() //CellSysutilUserId userId, const char *dirName, unsigned int maxSizeKB, CellSaveDataDoneCallback funcDone, sys_memory_container_t container, void *userdata
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
int cellSaveDataUserGetListItem () //CellSysutilUserId userId, const char *dirName, CellSaveDataDirStat *dir, CellSaveDataSystemFileParam *sysFileParam, unsigned int *bind, int *sizeKB
=======
int cellSaveDataUserGetListItem() //CellSysutilUserId userId, const char *dirName, CellSaveDataDirStat *dir, CellSaveDataSystemFileParam *sysFileParam, unsigned int *bind, int *sizeKB
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
{
UNIMPLEMENTED_FUNC(cellSaveData);
return CELL_SAVEDATA_RET_OK;
}
<<<<<<< HEAD
//Callback Functions
@ -427,4 +703,48 @@ void cellSaveData_init ()
cellSaveData.AddFunc (0xcdc6aefd, cellSaveDataUserAutoLoad);
cellSaveData.AddFunc (0x0e091c36, cellSaveDataUserListAutoSave);
//cellSaveData.AddFunc (0xe7fa820b, cellSaveDataEnableOverlay);
=======
// Callback Functions
void (*CellSaveDataFixedCallback)(); //CellSaveDataCBResult *cbResult, CellSaveDataListGet *get, CellSaveDataFixedSet *set
void (*CellSaveDataListCallback)(); //CellSaveDataCBResult *cbResult, CellSaveDataListGet *get, CellSaveDataListSet *set
void (*CellSaveDataStatCallback)(); //CellSaveDataCBResult *cbResult, CellSaveDataStatGet *get, CellSaveDataStatSet *set
void (*CellSaveDataFileCallback)(); //CellSaveDataCBResult *cbResult, CellSaveDataFileGet *get, CellSaveDataFileSet *set
void (*CellSaveDataDoneCallback)(); //CellSaveDataCBResult *cbResult, CellSaveDataDoneGet *get
void cellSaveData_init()
{
cellSaveData.AddFunc(0x04c06fc2, cellSaveDataGetListItem);
cellSaveData.AddFunc(0x273d116a, cellSaveDataUserListExport);
cellSaveData.AddFunc(0x27cb8bc2, cellSaveDataListDelete);
cellSaveData.AddFunc(0x39d6ee43, cellSaveDataUserListImport);
cellSaveData.AddFunc(0x46a2d878, cellSaveDataFixedExport);
cellSaveData.AddFunc(0x491cc554, cellSaveDataListExport);
cellSaveData.AddFunc(0x52541151, cellSaveDataFixedImport);
cellSaveData.AddFunc(0x529231b0, cellSaveDataUserFixedImport);
cellSaveData.AddFunc(0x6b4e0de6, cellSaveDataListImport);
cellSaveData.AddFunc(0x7048a9ba, cellSaveDataUserListDelete);
cellSaveData.AddFunc(0x95ae2cde, cellSaveDataUserFixedExport);
cellSaveData.AddFunc(0xf6482036, cellSaveDataUserGetListItem);
cellSaveData.AddFunc(0x2de0d663, cellSaveDataListSave2);
cellSaveData.AddFunc(0x1dfbfdd6, cellSaveDataListLoad2);
cellSaveData.AddFunc(0x2aae9ef5, cellSaveDataFixedSave2);
cellSaveData.AddFunc(0x2a8eada2, cellSaveDataFixedLoad2);
cellSaveData.AddFunc(0x8b7ed64b, cellSaveDataAutoSave2);
cellSaveData.AddFunc(0xfbd5c856, cellSaveDataAutoLoad2);
cellSaveData.AddFunc(0x4dd03a4e, cellSaveDataListAutoSave);
cellSaveData.AddFunc(0x21425307, cellSaveDataListAutoLoad);
cellSaveData.AddFunc(0xedadd797, cellSaveDataDelete2);
cellSaveData.AddFunc(0x0f03cfb0, cellSaveDataUserListSave);
cellSaveData.AddFunc(0x39dd8425, cellSaveDataUserListLoad);
cellSaveData.AddFunc(0x40b34847, cellSaveDataUserFixedSave);
cellSaveData.AddFunc(0x6e7264ed, cellSaveDataUserFixedLoad);
cellSaveData.AddFunc(0x52aac4fa, cellSaveDataUserAutoSave);
cellSaveData.AddFunc(0xcdc6aefd, cellSaveDataUserAutoLoad);
cellSaveData.AddFunc(0x0e091c36, cellSaveDataUserListAutoSave);
//cellSaveData.AddFunc(0xe7fa820b, cellSaveDataEnableOverlay);
>>>>>>> 3dd9683b472b89358a697210798c89df5b0e5baa
}

View File

@ -16,13 +16,22 @@ enum
CELL_SCREENSHOT_ERROR_UNSUPPORTED_COLOR_FORMAT = 0x8002d105,
};
int cellScreenShotSetParameter()
// Datatypes
struct CellScreenShotSetParam
{
const char *photo_title;
const char *game_title;
const char *game_comment;
};
// Functions
int cellScreenShotSetParameter() //const CellScreenShotSetParam *param
{
UNIMPLEMENTED_FUNC(cellScreenshot);
return CELL_OK;
}
int cellScreenShotSetOverlayImage()
int cellScreenShotSetOverlayImage() //const char *srcDir, const char *srcFile, s32 offset_x, s32 offset_y
{
UNIMPLEMENTED_FUNC(cellScreenshot);
return CELL_OK;

View File

@ -1,95 +1,218 @@
#include "stdafx.h"
#include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/SC_FUNC.h"
void cellSysmodule_init();
Module cellSysmodule("cellSysmodule", cellSysmodule_init);
enum
{
CELL_SYSMODULE_LOADED = CELL_OK,
CELL_SYSMODULE_ERROR_DUPLICATED = 0x80012001,
CELL_SYSMODULE_ERROR_UNKNOWN = 0x80012002,
CELL_SYSMODULE_ERROR_UNLOADED = 0x80012003,
CELL_SYSMODULE_ERROR_INVALID_MEMCONTAINER = 0x80012004,
CELL_SYSMODULE_ERROR_FATAL = 0x800120ff,
};
int cellSysmoduleInitialize()
{
cellSysmodule.Log("cellSysmoduleInitialize()");
return CELL_OK;
}
int cellSysmoduleFinalize()
{
cellSysmodule.Log("cellSysmoduleFinalize()");
return CELL_OK;
}
int cellSysmoduleSetMemcontainer(u32 ct_id)
{
cellSysmodule.Warning("TODO: cellSysmoduleSetMemcontainer(ct_id=0x%x)", ct_id);
return CELL_OK;
}
int cellSysmoduleLoadModule(u16 id)
{
cellSysmodule.Warning("cellSysmoduleLoadModule(id=0x%04x)", id);
Module* m = GetModuleById(id);
if(!m)
{
return CELL_SYSMODULE_ERROR_UNKNOWN;
}
if(m->IsLoaded())
{
return CELL_SYSMODULE_ERROR_DUPLICATED;
}
m->Load();
return CELL_OK;
}
int cellSysmoduleUnloadModule(u16 id)
{
cellSysmodule.Warning("cellSysmoduleUnloadModule(id=0x%04x)", id);
Module* m = GetModuleById(id);
if(!m)
{
return CELL_SYSMODULE_ERROR_UNKNOWN;
}
if(!m->IsLoaded())
{
return CELL_SYSMODULE_ERROR_UNLOADED;
}
m->UnLoad();
return CELL_OK;
}
int cellSysmoduleIsLoaded(u16 id)
{
cellSysmodule.Warning("cellSysmoduleIsLoaded(id=0x%04x)", id);
Module* m = GetModuleById(id);
if(!m)
{
return CELL_SYSMODULE_ERROR_UNKNOWN;
}
return m->IsLoaded() ? CELL_SYSMODULE_LOADED : CELL_SYSMODULE_ERROR_UNLOADED;
}
void cellSysmodule_init()
{
cellSysmodule.AddFunc(0x63ff6ff9, cellSysmoduleInitialize);
cellSysmodule.AddFunc(0x96c07adf, cellSysmoduleFinalize);
cellSysmodule.AddFunc(0xa193143c, cellSysmoduleSetMemcontainer);
cellSysmodule.AddFunc(0x32267a31, cellSysmoduleLoadModule);
cellSysmodule.AddFunc(0x112a5ee9, cellSysmoduleUnloadModule);
cellSysmodule.AddFunc(0x5a59e258, cellSysmoduleIsLoaded);
}
#include "stdafx.h"
#include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/SC_FUNC.h"
void cellSysmodule_init();
Module cellSysmodule("cellSysmodule", cellSysmodule_init);
enum
{
CELL_SYSMODULE_LOADED = CELL_OK,
CELL_SYSMODULE_ERROR_DUPLICATED = 0x80012001,
CELL_SYSMODULE_ERROR_UNKNOWN = 0x80012002,
CELL_SYSMODULE_ERROR_UNLOADED = 0x80012003,
CELL_SYSMODULE_ERROR_INVALID_MEMCONTAINER = 0x80012004,
CELL_SYSMODULE_ERROR_FATAL = 0x800120ff,
};
const char *getModuleName(int id) {
struct
{
const char *name;
int id;
} static const entries[] = {
{"CELL_SYSMODULE_INVALID", 0x0000ffff},
{"CELL_SYSMODULE_NET", 0x00000000},
{"CELL_SYSMODULE_HTTP", 0x00000001},
{"CELL_SYSMODULE_HTTP_UTIL", 0x00000002},
{"CELL_SYSMODULE_SSL", 0x00000003},
{"CELL_SYSMODULE_HTTPS", 0x00000004},
{"CELL_SYSMODULE_VDEC", 0x00000005},
{"CELL_SYSMODULE_ADEC", 0x00000006},
{"CELL_SYSMODULE_DMUX", 0x00000007},
{"CELL_SYSMODULE_VPOST", 0x00000008},
{"CELL_SYSMODULE_RTC", 0x00000009},
{"CELL_SYSMODULE_SPURS", 0x0000000a},
{"CELL_SYSMODULE_OVIS", 0x0000000b},
{"CELL_SYSMODULE_SHEAP", 0x0000000c},
{"CELL_SYSMODULE_SYNC", 0x0000000d},
{"CELL_SYSMODULE_FS", 0x0000000e},
{"CELL_SYSMODULE_JPGDEC", 0x0000000f},
{"CELL_SYSMODULE_GCM_SYS", 0x00000010},
{"CELL_SYSMODULE_GCM", 0x00000010},
{"CELL_SYSMODULE_AUDIO", 0x00000011},
{"CELL_SYSMODULE_PAMF", 0x00000012},
{"CELL_SYSMODULE_ATRAC3PLUS", 0x00000013},
{"CELL_SYSMODULE_NETCTL", 0x00000014},
{"CELL_SYSMODULE_SYSUTIL", 0x00000015},
{"CELL_SYSMODULE_SYSUTIL_NP", 0x00000016},
{"CELL_SYSMODULE_IO", 0x00000017},
{"CELL_SYSMODULE_PNGDEC", 0x00000018},
{"CELL_SYSMODULE_FONT", 0x00000019},
{"CELL_SYSMODULE_FONTFT", 0x0000001a},
{"CELL_SYSMODULE_FREETYPE", 0x0000001b},
{"CELL_SYSMODULE_USBD", 0x0000001c},
{"CELL_SYSMODULE_SAIL", 0x0000001d},
{"CELL_SYSMODULE_L10N", 0x0000001e},
{"CELL_SYSMODULE_RESC", 0x0000001f},
{"CELL_SYSMODULE_DAISY", 0x00000020},
{"CELL_SYSMODULE_KEY2CHAR", 0x00000021},
{"CELL_SYSMODULE_MIC", 0x00000022},
{"CELL_SYSMODULE_CAMERA", 0x00000023},
{"CELL_SYSMODULE_VDEC_MPEG2", 0x00000024},
{"CELL_SYSMODULE_VDEC_AVC", 0x00000025},
{"CELL_SYSMODULE_ADEC_LPCM", 0x00000026},
{"CELL_SYSMODULE_ADEC_AC3", 0x00000027},
{"CELL_SYSMODULE_ADEC_ATX", 0x00000028},
{"CELL_SYSMODULE_ADEC_AT3", 0x00000029},
{"CELL_SYSMODULE_DMUX_PAMF", 0x0000002a},
{"CELL_SYSMODULE_VDEC_AL", 0x0000002b},
{"CELL_SYSMODULE_ADEC_AL", 0x0000002c},
{"CELL_SYSMODULE_DMUX_AL", 0x0000002d},
{"CELL_SYSMODULE_LV2DBG", 0x0000002e},
{"CELL_SYSMODULE_USBPSPCM", 0x00000030},
{"CELL_SYSMODULE_AVCONF_EXT", 0x00000031},
{"CELL_SYSMODULE_SYSUTIL_USERINFO", 0x00000032},
{"CELL_SYSMODULE_SYSUTIL_SAVEDATA", 0x00000033},
{"CELL_SYSMODULE_SUBDISPLAY", 0x00000034},
{"CELL_SYSMODULE_SYSUTIL_REC", 0x00000035},
{"CELL_SYSMODULE_VIDEO_EXPORT", 0x00000036},
{"CELL_SYSMODULE_SYSUTIL_GAME_EXEC", 0x00000037},
{"CELL_SYSMODULE_SYSUTIL_NP2", 0x00000038},
{"CELL_SYSMODULE_SYSUTIL_AP", 0x00000039},
{"CELL_SYSMODULE_SYSUTIL_NP_CLANS", 0x0000003a},
{"CELL_SYSMODULE_SYSUTIL_OSK_EXT", 0x0000003b},
{"CELL_SYSMODULE_VDEC_DIVX", 0x0000003c},
{"CELL_SYSMODULE_JPGENC", 0x0000003d},
{"CELL_SYSMODULE_SYSUTIL_GAME", 0x0000003e},
{"CELL_SYSMODULE_BGDL", 0x0000003f},
{"CELL_SYSMODULE_FREETYPE_TT", 0x00000040},
{"CELL_SYSMODULE_SYSUTIL_VIDEO_UPLOAD", 0x00000041},
{"CELL_SYSMODULE_SYSUTIL_SYSCONF_EXT", 0x00000042},
{"CELL_SYSMODULE_FIBER", 0x00000043},
{"CELL_SYSMODULE_SYSUTIL_NP_COMMERCE2", 0x00000044},
{"CELL_SYSMODULE_SYSUTIL_NP_TUS", 0x00000045},
{"CELL_SYSMODULE_VOICE", 0x00000046},
{"CELL_SYSMODULE_ADEC_CELP8", 0x00000047},
{"CELL_SYSMODULE_CELP8ENC", 0x00000048},
{"CELL_SYSMODULE_SYSUTIL_LICENSEAREA", 0x00000049},
{"CELL_SYSMODULE_SYSUTIL_MUSIC2", 0x0000004a},
{"CELL_SYSMODULE_SYSUTIL_SCREENSHOT", 0x0000004e},
{"CELL_SYSMODULE_SYSUTIL_MUSIC_DECODE", 0x0000004f},
{"CELL_SYSMODULE_SPURS_JQ", 0x00000050},
{"CELL_SYSMODULE_PNGENC", 0x00000052},
{"CELL_SYSMODULE_SYSUTIL_MUSIC_DECODE2", 0x00000053},
{"CELL_SYSMODULE_SYNC2", 0x00000055},
{"CELL_SYSMODULE_SYSUTIL_NP_UTIL", 0x00000056},
{"CELL_SYSMODULE_RUDP", 0x00000057},
{"CELL_SYSMODULE_SYSUTIL_NP_SNS", 0x00000059},
{"CELL_SYSMODULE_GEM", 0x0000005a},
{"CELL_SYSMODULE_CELPENC", 0x0000f00a},
{"CELL_SYSMODULE_GIFDEC", 0x0000f010},
{"CELL_SYSMODULE_ADEC_CELP", 0x0000f019},
{"CELL_SYSMODULE_ADEC_M2BC", 0x0000f01b},
{"CELL_SYSMODULE_ADEC_M4AAC", 0x0000f01d},
{"CELL_SYSMODULE_ADEC_MP3", 0x0000f01e},
{"CELL_SYSMODULE_IMEJP", 0x0000f023},
{"CELL_SYSMODULE_SYSUTIL_MUSIC", 0x0000f028},
{"CELL_SYSMODULE_PHOTO_EXPORT", 0x0000f029},
{"CELL_SYSMODULE_PRINT", 0x0000f02a},
{"CELL_SYSMODULE_PHOTO_IMPORT", 0x0000f02b},
{"CELL_SYSMODULE_MUSIC_EXPORT", 0x0000f02c},
{"CELL_SYSMODULE_PHOTO_DECODE", 0x0000f02e},
{"CELL_SYSMODULE_SYSUTIL_SEARCH", 0x0000f02f},
{"CELL_SYSMODULE_SYSUTIL_AVCHAT2", 0x0000f030},
{"CELL_SYSMODULE_SAIL_REC", 0x0000f034},
{"CELL_SYSMODULE_SYSUTIL_NP_TROPHY", 0x0000f035},
{"CELL_SYSMODULE_LIBATRAC3MULTI", 0x0000f054},
};
for (int i = 0; i < sizeof(entries) / sizeof(entries[0]); ++i)
{
if (entries[i].id == id)
{
return entries[i].name;
}
}
return 0;
}
int cellSysmoduleInitialize()
{
cellSysmodule.Log("cellSysmoduleInitialize()");
return CELL_OK;
}
int cellSysmoduleFinalize()
{
cellSysmodule.Log("cellSysmoduleFinalize()");
return CELL_OK;
}
int cellSysmoduleSetMemcontainer(u32 ct_id)
{
cellSysmodule.Warning("TODO: cellSysmoduleSetMemcontainer(ct_id=0x%x)", ct_id);
return CELL_OK;
}
int cellSysmoduleLoadModule(u16 id)
{
cellSysmodule.Warning("cellSysmoduleLoadModule(%s)", getModuleName(id));
Module* m = GetModuleById(id);
if(!m)
{
return CELL_SYSMODULE_ERROR_UNKNOWN;
}
if(m->IsLoaded())
{
return CELL_SYSMODULE_ERROR_DUPLICATED;
}
m->Load();
return CELL_OK;
}
int cellSysmoduleUnloadModule(u16 id)
{
cellSysmodule.Warning("cellSysmoduleUnloadModule(%s)", getModuleName(id));
Module* m = GetModuleById(id);
if(!m)
{
return CELL_SYSMODULE_ERROR_UNKNOWN;
}
if(!m->IsLoaded())
{
return CELL_SYSMODULE_ERROR_UNLOADED;
}
m->UnLoad();
return CELL_OK;
}
int cellSysmoduleIsLoaded(u16 id)
{
cellSysmodule.Warning("cellSysmoduleIsLoaded(%s)", getModuleName(id));
Module* m = GetModuleById(id);
if(!m)
{
return CELL_SYSMODULE_ERROR_UNKNOWN;
}
return m->IsLoaded() ? CELL_SYSMODULE_LOADED : CELL_SYSMODULE_ERROR_UNLOADED;
}
void cellSysmodule_init()
{
cellSysmodule.AddFunc(0x63ff6ff9, cellSysmoduleInitialize);
cellSysmodule.AddFunc(0x96c07adf, cellSysmoduleFinalize);
cellSysmodule.AddFunc(0xa193143c, cellSysmoduleSetMemcontainer);
cellSysmodule.AddFunc(0x32267a31, cellSysmoduleLoadModule);
cellSysmodule.AddFunc(0x112a5ee9, cellSysmoduleUnloadModule);
cellSysmodule.AddFunc(0x5a59e258, cellSysmoduleIsLoaded);
}

View File

@ -102,9 +102,21 @@ enum
void cellSysutil_init();
Module cellSysutil(0x0015, cellSysutil_init);
void cellVideoOutGetDeviceInfo()
int cellVideoOutGetDeviceInfo(u32 videoOut, u32 deviceIndex, mem_struct_ptr_t<CellVideoOutDeviceInfo> info)
{
UNIMPLEMENTED_FUNC(cellSysutil);
cellSysutil.Error("Unimplemented function: cellVideoOutGetDeviceInfo(videoOut=%u, deviceIndex=%u, info_addr=0x%x)",
videoOut, deviceIndex, info.GetAddr());
if(deviceIndex) return CELL_VIDEO_OUT_ERROR_DEVICE_NOT_FOUND;
//info->portType = CELL_VIDEO_OUT_PORT_HDMI;
info->colorSpace = Emu.GetGSManager().GetColorSpace();
//info->latency = ;
//info->availableModeCount = ;
//info->state = CELL_VIDEO_OUT_DEVICE_STATE_AVAILABLE;
//info->rgbOutputRange = ;
return CELL_OK;
}
int cellSysutilGetSystemParamInt(int id, mem32_t value)

View File

@ -5,9 +5,140 @@
void sys_fs_init();
Module sys_fs(0x000e, sys_fs_init);
bool sdata_check(u32 version, u32 flags, u64 filesizeInput, u64 filesizeTmp)
{
if (version > 4 || flags & 0x7EFFFFC0){
printf("ERROR: unknown version");
return false;
}
if ((version == 1 && (flags & 0x7FFFFFFE)) ||
(version == 2 && (flags & 0x7EFFFFC0))){
printf("ERROR: unknown or unsupported type");
return false;
}
if (filesizeTmp > filesizeInput){
printf("ERROR: input file size is too short.");
return false;
}
if (!(flags & 0x80000000)){
printf("ERROR: cannot extract finalized edata.");
return false;
}
return true;
}
int sdata_unpack(wxString packed_file, wxString unpacked_file)
{
vfsStream* packed_stream = Emu.GetVFS().Open(packed_file, vfsRead);
vfsStream* unpacked_stream = Emu.GetVFS().Open(unpacked_file, vfsWrite);
if(!packed_stream || !packed_stream->IsOpened())
{
sys_fs.Error("'%s' not found! flags: 0x%08x", packed_file, vfsRead);
delete packed_stream;
return CELL_ENOENT;
}
if(!unpacked_stream || !unpacked_stream->IsOpened())
{
sys_fs.Error("'%s' couldn't be created! flags: 0x%08x", unpacked_file, vfsWrite);
delete unpacked_stream;
return CELL_ENOENT;
}
char buffer [10200];
packed_stream->Read(buffer, 256);
if (re32(*(u32*)&buffer[0]) != 0x4E504400) // "NPD\x00"
{
printf("ERROR: illegal format.");
return CELL_EFSSPECIFIC;
}
u32 version = re32(*(u32*)&buffer[0x04]);
u32 flags = re32(*(u32*)&buffer[0x80]);
u32 blockSize = re32(*(u32*)&buffer[0x84]);
u64 filesizeOutput = re64(*(u64*)&buffer[0x88]);
u64 filesizeInput = packed_stream->GetSize();
u32 blockCount = (filesizeOutput + blockSize-1) / blockSize;
// SDATA file is compressed
if (flags & 0x1)
{
sys_fs.Warning("cellFsSdataOpen: Compressed SDATA files are not supported yet.");
return CELL_EFSSPECIFIC;
}
// SDATA file is NOT compressed
else
{
u32 t1 = (flags & 0x20) ? 0x20 : 0x10;
u32 startOffset = (blockCount * t1) + 0x100;
u64 filesizeTmp = (filesizeOutput+0xF)&0xFFFFFFF0 + startOffset;
if (!sdata_check(version, flags, filesizeInput, filesizeTmp))
{
sys_fs.Error("cellFsSdataOpen: Wrong header information.");
return CELL_EFSSPECIFIC;
}
if (flags & 0x20)
packed_stream->Seek(0x100);
else
packed_stream->Seek(startOffset);
for (u32 i = 0; i < blockCount; i++)
{
if (flags & 0x20)
packed_stream->Seek(packed_stream->Tell() + t1);
if (!(blockCount-i-1))
blockSize = filesizeOutput-i*blockSize;
packed_stream->Read(buffer+256, blockSize);
unpacked_stream->Write(buffer+256, blockSize);
}
}
packed_stream->Close();
unpacked_stream->Close();
return CELL_OK;
}
int cellFsSdataOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size)
{
const wxString& path = Memory.ReadString(path_addr);
sys_fs.Warning("cellFsSdataOpen(path: %s, flags: 0x%x, fd_addr: 0x%x, arg_addr: 0x%x, size: 0x%llx)",
path, flags, fd.GetAddr(), arg.GetAddr(), size);
if (!fd.IsGood() || (!arg.IsGood() && size))
return CELL_EFAULT;
if (flags != CELL_O_RDONLY)
return CELL_EINVAL;
if (!path.Lower().EndsWith(".sdat"))
return CELL_ENOTSDATA;
wxString unpacked_path = "/dev_hdd1/"+path.AfterLast('/')+".unpacked";
int ret = sdata_unpack(path, unpacked_path);
if (ret) return ret;
vfsStream* stream = Emu.GetVFS().Open(unpacked_path, vfsRead);
fd = sys_fs.GetNewId(stream, flags);
return CELL_OK;
}
void sys_fs_init()
{
sys_fs.AddFunc(0x718bf5f8, cellFsOpen);
sys_fs.AddFunc(0xb1840b53, cellFsSdataOpen);
sys_fs.AddFunc(0x4d5ff8e2, cellFsRead);
sys_fs.AddFunc(0xecdcf2ab, cellFsWrite);
sys_fs.AddFunc(0x2cb51f0d, cellFsClose);

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

@ -10,33 +10,85 @@ static func_caller* sc_table[1024] =
{
null_func, bind_func(sys_process_getpid), null_func, bind_func(sys_process_exit), null_func, //4
null_func, null_func, null_func, null_func, null_func, //9
null_func, null_func, null_func, null_func, null_func, //14
null_func, null_func, null_func, null_func, null_func, //19
null_func, null_func, bind_func(sys_process_get_number_of_object), bind_func(sys_process_get_id), null_func, //14
null_func, null_func, null_func, bind_func(sys_process_getppid), null_func, //19
null_func, null_func, bind_func(sys_process_exit), null_func, null_func, //24
null_func, null_func, null_func, null_func, null_func, //29
null_func, null_func, null_func, null_func, null_func, //34
bind_func(sys_process_get_paramsfo), null_func, null_func, null_func, null_func, //34
null_func, null_func, null_func, null_func, null_func, //39
null_func, bind_func(sys_ppu_thread_exit), null_func, bind_func(sys_ppu_thread_yield), bind_func(sys_ppu_thread_join), //44
bind_func(sys_ppu_thread_detach), bind_func(sys_ppu_thread_get_join_state), bind_func(sys_ppu_thread_set_priority), bind_func(sys_ppu_thread_get_priority), bind_func(sys_ppu_thread_get_stack_information), //49
bind_func(sys_ppu_thread_stop), bind_func(sys_ppu_thread_restart), bind_func(sys_ppu_thread_create), null_func, null_func, //54
null_func, //40 (0x028)
bind_func(sys_ppu_thread_exit), //41 (0x029)
null_func, //42 (0x02A)
bind_func(sys_ppu_thread_yield), //43 (0x02B)
bind_func(sys_ppu_thread_join), //44 (0x02C)
bind_func(sys_ppu_thread_detach), //45 (0x02D)
bind_func(sys_ppu_thread_get_join_state), //46 (0x02E)
bind_func(sys_ppu_thread_set_priority), //47 (0x02F)
bind_func(sys_ppu_thread_get_priority), //48 (0x030)
bind_func(sys_ppu_thread_get_stack_information), //49 (0x031)
bind_func(sys_ppu_thread_stop), //50 (0x032)
bind_func(sys_ppu_thread_restart), //51 (0x033)
bind_func(sys_ppu_thread_create), //52 (0x034)
null_func, //53 (0x035)
null_func, //54 (0x036)
null_func, null_func, null_func, null_func, null_func, //59
null_func, null_func, null_func, null_func, null_func, //64
null_func, null_func, null_func, null_func, null_func, //69
null_func, null_func, null_func, null_func, null_func, //74
null_func, null_func, null_func, null_func, null_func, //49
bind_func(sys_trace_create), //60 (0x03C)
bind_func(sys_trace_start), //61 (0x03D)
bind_func(sys_trace_stop), //62 (0x03E)
bind_func(sys_trace_update_top_index), //63 (0x03F)
bind_func(sys_trace_destroy), //64 (0x040)
bind_func(sys_trace_drain), //65 (0x041)
bind_func(sys_trace_attach_process), //66 (0x042)
bind_func(sys_trace_allocate_buffer), //67 (0x043)
bind_func(sys_trace_free_buffer), //68 (0x044)
bind_func(sys_trace_create2), //69 (0x045)
bind_func(sys_timer_create), //70 (0x046)
bind_func(sys_timer_destroy), //71 (0x047)
bind_func(sys_timer_get_information), //72 (0x048)
bind_func(sys_timer_start), //73 (0x049)
bind_func(sys_timer_stop), //74 (0x04A)
bind_func(sys_timer_connect_event_queue), //75 (0x04B)
bind_func(sys_timer_disconnect_event_queue), //76 (0x04C)
null_func, //77 (0x04D)
null_func, //78 (0x04E)
null_func, //79 (0x04F)
null_func, null_func, null_func, null_func, null_func, //84
null_func, null_func, null_func, null_func, null_func, //89
bind_func(sys_semaphore_create), bind_func(sys_semaphore_destroy), bind_func(sys_semaphore_wait), bind_func(sys_semaphore_trywait), bind_func(sys_semaphore_post), //94
bind_func(sys_lwmutex_create), bind_func(sys_lwmutex_destroy), bind_func(sys_lwmutex_lock), bind_func(sys_lwmutex_trylock), bind_func(sys_lwmutex_unlock), //99
bind_func(sys_mutex_create), bind_func(sys_mutex_destroy), bind_func(sys_mutex_lock), bind_func(sys_mutex_trylock), bind_func(sys_mutex_unlock), //104
bind_func(sys_cond_create), bind_func(sys_cond_destroy), bind_func(sys_cond_wait), bind_func(sys_cond_signal), bind_func(sys_cond_signal_all), //109
bind_func(sys_semaphore_create), //90 (0x05A)
bind_func(sys_semaphore_destroy), //91 (0x05B)
bind_func(sys_semaphore_wait), //92 (0x05C)
bind_func(sys_semaphore_trywait), //93 (0x05D)
bind_func(sys_semaphore_post), //94 (0x05E)
bind_func(sys_lwmutex_create), //95 (0x05F)
bind_func(sys_lwmutex_destroy), //96 (0x060)
bind_func(sys_lwmutex_lock), //97 (0x061)
bind_func(sys_lwmutex_trylock), //98 (0x062)
bind_func(sys_lwmutex_unlock), //99 (0x063)
bind_func(sys_mutex_create), //100 (0x064)
bind_func(sys_mutex_destroy), //101 (0x065)
bind_func(sys_mutex_lock), //102 (0x066)
bind_func(sys_mutex_trylock), //103 (0x067)
bind_func(sys_mutex_unlock), //104 (0x068)
bind_func(sys_cond_create), //105 (0x069)
bind_func(sys_cond_destroy), //106 (0x06A)
bind_func(sys_cond_wait), //107 (0x06B)
bind_func(sys_cond_signal), //108 (0x06C)
bind_func(sys_cond_signal_all), //109 (0x06D)
null_func, null_func, null_func, null_func, null_func, //114
null_func, null_func, null_func, null_func, null_func, //119
null_func, null_func, null_func, null_func, null_func, //124
null_func, null_func, null_func, bind_func(sys_event_queue_create), null_func, //129
bind_func(sys_rwlock_create), //120 (0x078)
bind_func(sys_rwlock_destroy), //121 (0x079)
bind_func(sys_rwlock_rlock), //122 (0x07A)
bind_func(sys_rwlock_tryrlock), //123 (0x07B)
bind_func(sys_rwlock_runlock), //124 (0x07C)
bind_func(sys_rwlock_wlock), //125 (0x07D)
bind_func(sys_rwlock_trywlock), //126 (0x07E)
bind_func(sys_rwlock_wunlock), //127 (0x07F)
bind_func(sys_event_queue_create), //128 (0x080)
null_func, //129 (0x081)
bind_func(sys_event_queue_receive), null_func, null_func, null_func, bind_func(sys_event_port_create), //134
null_func, bind_func(sys_event_port_connect_local), null_func, bind_func(sys_event_port_send), null_func, //139
null_func, null_func, null_func, null_func, null_func, //144
null_func, bind_func(sys_timer_usleep), bind_func(sys_timer_sleep), null_func, bind_func(sys_time_get_timezone), //144
bind_func(sys_time_get_current_time), bind_func(sys_time_get_system_time), bind_func(sys_time_get_timebase_frequency), null_func, null_func, //149
null_func, null_func, null_func, null_func, null_func, //154
null_func, bind_func(sys_spu_image_open), null_func, null_func, null_func, //159
@ -141,9 +193,21 @@ static func_caller* sc_table[1024] =
null_func, null_func, null_func, null_func, null_func, //654
null_func, null_func, null_func, null_func, null_func, //659
null_func, null_func, null_func, null_func, null_func, //664
null_func, null_func, null_func, null_func, null_func, //669
null_func, null_func, null_func, null_func, null_func, //674
null_func, null_func, null_func, null_func, null_func, //679
null_func, //665 (0x299)
bind_func(sys_rsx_device_open), //666 (0x29A)
bind_func(sys_rsx_device_close), //667 (0x29B)
bind_func(sys_rsx_memory_allocate), //668 (0x29C)
bind_func(sys_rsx_memory_free), //669 (0x29D)
bind_func(sys_rsx_context_allocate), //670 (0x29E)
bind_func(sys_rsx_context_free), //671 (0x29F)
bind_func(sys_rsx_context_iomap), //672 (0x2A0)
bind_func(sys_rsx_context_iounmap), //673 (0x2A1)
bind_func(sys_rsx_context_attribute), //674 (0x2A2)
bind_func(sys_rsx_device_map), //675 (0x2A3)
bind_func(sys_rsx_device_unmap), //676 (0x2A4)
bind_func(sys_rsx_attribute), //677 (0x2A5)
null_func, //678 (0x2A6)
null_func, //679 (0x2A7)
null_func, null_func, null_func, null_func, null_func, //684
null_func, null_func, null_func, null_func, null_func, //689
null_func, null_func, null_func, null_func, null_func, //694
@ -168,9 +232,21 @@ static func_caller* sc_table[1024] =
null_func, null_func, null_func, null_func, null_func, //789
null_func, null_func, null_func, null_func, null_func, //794
null_func, null_func, null_func, null_func, null_func, //799
null_func, bind_func(cellFsOpen), bind_func(cellFsRead), bind_func(cellFsWrite), bind_func(cellFsClose), //804
bind_func(cellFsOpendir), bind_func(cellFsReaddir), bind_func(cellFsClosedir), null_func, bind_func(cellFsFstat), //809
null_func, bind_func(cellFsMkdir), bind_func(cellFsRename), bind_func(cellFsRmdir), null_func, //814
null_func, //800 (0x320)
bind_func(cellFsOpen), //801 (0x321)
bind_func(cellFsRead), //802 (0x322)
bind_func(cellFsWrite), //803 (0x323)
bind_func(cellFsClose), //804 (0x324)
bind_func(cellFsOpendir), //805 (0x325)
bind_func(cellFsReaddir), //806 (0x326)
bind_func(cellFsClosedir), //807 (0x327)
bind_func(cellFsStat), //808 (0x328)
bind_func(cellFsFstat), //809 (0x329)
null_func, //810 (0x32A)
bind_func(cellFsMkdir), //811 (0x32B)
bind_func(cellFsRename), //812 (0x32C)
bind_func(cellFsRmdir), //813 (0x32D)
null_func, //814 (0x32E)
null_func, null_func, null_func, bind_func(cellFsLseek), null_func, //819
null_func, null_func, null_func, null_func, null_func, //824
null_func, null_func, null_func, null_func, null_func, //829
@ -236,13 +312,6 @@ void default_syscall()
case 23: RESULT(lv2ProcessWaitForChild2(CPU)); return;
case 25: RESULT(lv2ProcessGetSdkVersion(CPU)); return;
*/
//timer
case 141:
case 142:
std::this_thread::sleep_for(std::chrono::nanoseconds(SC_ARGS_1));
RESULT(0);
return;
//tty
case 988:
ConLog.Warning("SysCall 988! r3: 0x%llx, r4: 0x%llx, pc: 0x%llx",
@ -267,14 +336,6 @@ void default_syscall()
return;
}
SysCalls::SysCalls(PPUThread& cpu) : CPU(cpu)
{
}
SysCalls::~SysCalls()
{
}
void SysCalls::DoSyscall(u32 code)
{
if(code < 1024)
@ -291,5 +352,6 @@ void SysCalls::DoSyscall(u32 code)
//return 0;
//TODO: remove this
declCPU();
RESULT(DoFunc(code));
}

View File

@ -1,6 +1,8 @@
#pragma once
#include "ErrorCodes.h"
#include "lv2/SC_FileSystem.h"
#include "lv2/SC_Timer.h"
#include "lv2/SC_Rwlock.h"
//#define SYSCALLS_DEBUG
#define declCPU PPUThread& CPU = GetCurrentPPUThread
@ -109,7 +111,12 @@ public:
//process
extern int sys_process_getpid();
extern int sys_process_getppid();
extern int sys_process_get_number_of_object(u32 object, mem32_t nump);
extern int sys_process_get_id(u32 object, mem8_ptr_t buffer, u32 size, mem32_t set_size);
extern int sys_process_get_paramsfo(mem8_ptr_t buffer);
extern int sys_process_exit(int errorcode);
extern int sys_process_is_stack(u32 addr); //TODO: Is this a lv2 SysCall? If so, where is its number?
extern int sys_game_process_exitspawn(u32 path_addr, u32 argv_addr, u32 envp_addr,
u32 data, u32 data_size, int prio, u64 flags );
@ -176,14 +183,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);
@ -272,52 +279,93 @@ extern int sys_spu_thread_read_ls(u32 id, u32 address, u32 value_addr, u32 type)
extern int sys_spu_thread_write_spu_mb(u32 id, u32 value);
//sys_time
extern int sys_time_get_timezone(mem32_t timezone, mem32_t summertime);
extern int sys_time_get_current_time(u32 sec_addr, u32 nsec_addr);
extern s64 sys_time_get_system_time();
extern u64 sys_time_get_timebase_frequency();
//sys_timer
extern int sys_timer_create(mem32_t timer_id);
extern int sys_timer_destroy(u32 timer_id);
extern int sys_timer_get_information(u32 timer_id, mem_struct_ptr_t<sys_timer_information_t> info);
extern int sys_timer_start(u32 timer_id, s64 basetime, u64 period);
extern int sys_timer_stop(u32 timer_id);
extern int sys_timer_connect_event_queue(u32 timer_id, u32 queue_id, u64 name, u64 data1, u64 data2);
extern int sys_timer_disconnect_event_queue(u32 timer_id);
extern int sys_timer_sleep(u32 sleep_time);
extern int sys_timer_usleep(u64 sleep_time);
//sys_trace
extern int sys_trace_create();
extern int sys_trace_start();
extern int sys_trace_stop();
extern int sys_trace_update_top_index();
extern int sys_trace_destroy();
extern int sys_trace_drain();
extern int sys_trace_attach_process();
extern int sys_trace_allocate_buffer();
extern int sys_trace_free_buffer();
extern int sys_trace_create2();
//sys_rwlock
extern int sys_rwlock_create(mem32_t rw_lock_id, mem_struct_ptr_t<sys_rwlock_attribute_t> attr);
extern int sys_rwlock_destroy(u32 rw_lock_id);
extern int sys_rwlock_rlock(u32 rw_lock_id, u64 timeout);
extern int sys_rwlock_tryrlock(u32 rw_lock_id);
extern int sys_rwlock_runlock(u32 rw_lock_id);
extern int sys_rwlock_wlock(u32 rw_lock_id, u64 timeout);
extern int sys_rwlock_trywlock(u32 rw_lock_id);
extern int sys_rwlock_wunlock(u32 rw_lock_id);
//sys_rsx
extern int sys_rsx_device_open();
extern int sys_rsx_device_close();
extern int sys_rsx_memory_allocate();
extern int sys_rsx_memory_free();
extern int sys_rsx_context_allocate();
extern int sys_rsx_context_free();
extern int sys_rsx_context_iomap();
extern int sys_rsx_context_iounmap();
extern int sys_rsx_context_attribute(s32 context_id, u64 a2, u64 a3, u64 a4, u64 a5, u64 a6);
extern int sys_rsx_device_map(mem32_t a1, mem32_t a2, u32 a3);
extern int sys_rsx_device_unmap();
extern int sys_rsx_attribute();
#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;
class SysCalls
{
PPUThread& CPU;
public:
//process
int lv2ProcessGetPid(PPUThread& CPU);
int lv2ProcessWaitForChild(PPUThread& CPU);
int lv2ProcessGetStatus(PPUThread& CPU);
int lv2ProcessDetachChild(PPUThread& CPU);
int lv2ProcessGetNumberOfObject(PPUThread& CPU);
int lv2ProcessGetId(PPUThread& CPU);
int lv2ProcessGetPpid(PPUThread& CPU);
int lv2ProcessKill(PPUThread& CPU);
int lv2ProcessWaitForChild2(PPUThread& CPU);
int lv2ProcessGetSdkVersion(PPUThread& CPU);
protected:
SysCalls(PPUThread& cpu);
~SysCalls();
public:
void DoSyscall(u32 code);
s64 DoFunc(const u32 id);
static void DoSyscall(u32 code);
static s64 DoFunc(const u32 id);
};
//extern SysCalls SysCallsManager;

View File

@ -47,7 +47,7 @@ int sys_event_queue_receive(u32 equeue_id, u32 event_addr, u32 timeout)
int result;
auto queue_receive = [&](int status) -> bool
{
if(status == PPCThread_Stopped)
if(status == CPUThread_Stopped)
{
result = CELL_ECANCELED;
return false;
@ -59,11 +59,11 @@ int sys_event_queue_receive(u32 equeue_id, u32 event_addr, u32 timeout)
if(!equeue->ports[i]->has_data && equeue->ports[i]->thread)
{
SPUThread* thr = (SPUThread*)equeue->ports[i]->thread;
if(thr->SPU_OutIntr_Mbox.GetCount())
if(thr->SPU.OutIntr_Mbox.GetCount())
{
u32 val;
thr->SPU_OutIntr_Mbox.Pop(val);
if(!thr->mfc.SPU_Out_MBox.Pop(val)) val = 0;
thr->SPU.OutIntr_Mbox.Pop(val);
if(!thr->SPU.Out_MBox.Pop(val)) val = 0;
equeue->ports[i]->data1 = val;
equeue->ports[i]->data2 = 0;
equeue->ports[i]->data3 = 0;

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,16 @@ 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);
if(Memory.IsGoodAddr(buf_addr) && !Memory.IsGoodAddr(buf_addr, nbytes))
{
MemoryBlock& block = Memory.GetMemByAddr(buf_addr);
nbytes = block.GetSize() - (buf_addr - block.GetStartAddr());
}
const u64 res = nbytes ? file.Read(Memory.GetMemFromAddr(buf_addr), nbytes) : 0;
if(nread.IsGood())
nread = res;
return CELL_OK;
}
@ -205,7 +134,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,86 +174,68 @@ 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());
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;
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_blksize = 4096;
// Check if path is a mount point. (TODO: Add information in sb_addr)
for(u32 i=0; i<Emu.GetVFS().m_devices.GetCount(); ++i)
{
if (path == Emu.GetVFS().m_devices[i].GetPs3Path().RemoveLast(1))
if(path.CmpNoCase(Emu.GetVFS().m_devices[i].GetPs3Path().RemoveLast(1)) == 0)
{
sys_fs.Log("cellFsFstat: '%s' is a mount point.", path);
sb->st_mode |= CELL_FS_S_IFDIR;
return CELL_OK;
}
}
auto f = Emu.OpenFile(path);
vfsFile f(path);
if(!f->IsOpened())
if(!f.IsOpened())
{
sys_fs.Warning("cellFsFstat: '%s' not found.", path);
return CELL_ENOENT;
}
CellFsStat stat;
stat.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_size = f.GetSize();
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 +293,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;
@ -401,19 +315,13 @@ int cellFsFtruncate(u32 fd, u64 size)
vfsStream& file = *(vfsStream*)id.m_data;
u64 initialSize = file.GetSize();
if (initialSize < size) // Is there any better way to fill the remaining bytes with 0, without allocating huge buffers in memory, or writing such a spaghetti code?
if (initialSize < size)
{
u64 last_pos = file.Tell();
file.Seek(0, vfsSeekEnd);
char* nullblock = (char*)calloc(4096, sizeof(char));
for(u64 i = (size-initialSize)/4096; i > 0; i--){
file.Write(nullblock, 4096);
}
free(nullblock);
char nullbyte = 0;
for(u64 i = (size-initialSize)%4096; i > 0; i--){
file.Write(&nullbyte, 1);
}
static const char nullbyte = 0;
file.Seek(size-initialSize-1, vfsSeekCur);
file.Write(&nullbyte, sizeof(char));
file.Seek(last_pos, vfsSeekSet);
}
@ -430,29 +338,22 @@ int cellFsTruncate(u32 path_addr, u64 size)
const wxString& path = Memory.ReadString(path_addr);
sys_fs.Log("cellFsTruncate(path: %s, size: %lld)", path, size);
vfsStream* f = Emu.GetVFS().Open(path, vfsRead);
if(!f || !f->IsOpened())
vfsFile f(path, vfsReadWrite);
if(!f.IsOpened())
{
sys_fs.Warning("cellFsTruncate: '%s' not found.", path);
Emu.GetVFS().Close(f);
return CELL_ENOENT;
}
u64 initialSize = f->GetSize();
u64 initialSize = f.GetSize();
if (initialSize < size) // Is there any better way to fill the remaining bytes with 0, without allocating huge buffers in memory, or writing such a spaghetti code?
if (initialSize < size)
{
u64 last_pos = f->Tell();
f->Seek(0, vfsSeekEnd);
char* nullblock = (char*)calloc(4096, sizeof(char));
for(u64 i = (size-initialSize)/4096; i > 0; i--){
f->Write(nullblock, 4096);
}
free(nullblock);
char nullbyte = 0;
for(u64 i = (size-initialSize)%4096; i > 0; i--){
f->Write(&nullbyte, 1);
}
f->Seek(last_pos, vfsSeekSet);
u64 last_pos = f.Tell();
f.Seek(0, vfsSeekEnd);
static const char nullbyte = 0;
f.Seek(size-initialSize-1, vfsSeekCur);
f.Write(&nullbyte, sizeof(char));
f.Seek(last_pos, vfsSeekSet);
}
if (initialSize > size)
@ -460,7 +361,6 @@ int cellFsTruncate(u32 path_addr, u64 size)
// (TODO)
}
Emu.GetVFS().Close(f);
return CELL_OK;
}

View File

@ -0,0 +1,86 @@
#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,
};
#pragma pack(4)
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];
};
#pragma pack()

View File

@ -109,7 +109,7 @@ int sys_lwmutex_unlock(u64 lwmutex_addr)
if(lmtx.lock_var.info.owner = lmtx.lock_var.info.waiter)
{
lmtx.lock_var.info.waiter = 0;
PPCThread* thr = Emu.GetCPU().GetThread(lmtx.lock_var.info.owner);
CPUThread* thr = Emu.GetCPU().GetThread(lmtx.lock_var.info.owner);
if(thr)
{
thr->Wait(false);

Some files were not shown because too many files have changed in this diff Show More