mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
Updated
This commit is contained in:
commit
584d4eb9d4
2
.gitignore
vendored
2
.gitignore
vendored
@ -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
154
Utilities/BEType.h
Normal 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(); }
|
||||
};
|
@ -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
4
bin/dev_hdd1/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
32
rpcs3.sln
32
rpcs3.sln
@ -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
|
||||
|
137
rpcs3/Emu/ARMv7/ARMv7Decoder.h
Normal file
137
rpcs3/Emu/ARMv7/ARMv7Decoder.h
Normal 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;
|
||||
}
|
||||
};
|
96
rpcs3/Emu/ARMv7/ARMv7DisAsm.h
Normal file
96
rpcs3/Emu/ARMv7/ARMv7DisAsm.h
Normal 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));
|
||||
}
|
||||
};
|
322
rpcs3/Emu/ARMv7/ARMv7Interpreter.h
Normal file
322
rpcs3/Emu/ARMv7/ARMv7Interpreter.h
Normal 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();
|
||||
}
|
||||
};
|
49
rpcs3/Emu/ARMv7/ARMv7Opcodes.h
Normal file
49
rpcs3/Emu/ARMv7/ARMv7Opcodes.h
Normal 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;
|
||||
};
|
96
rpcs3/Emu/ARMv7/ARMv7Thread.cpp
Normal file
96
rpcs3/Emu/ARMv7/ARMv7Thread.cpp
Normal 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()
|
||||
{
|
||||
}
|
99
rpcs3/Emu/ARMv7/ARMv7Thread.h
Normal file
99
rpcs3/Emu/ARMv7/ARMv7Thread.h
Normal 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
879
rpcs3/Emu/CPU/CPUDecoder.h
Normal 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
63
rpcs3/Emu/CPU/CPUDisAsm.h
Normal 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;
|
||||
}
|
||||
};
|
34
rpcs3/Emu/CPU/CPUInstrTable.h
Normal file
34
rpcs3/Emu/CPU/CPUInstrTable.h
Normal 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
338
rpcs3/Emu/CPU/CPUThread.cpp
Normal 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
185
rpcs3/Emu/CPU/CPUThread.h
Normal 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();
|
111
rpcs3/Emu/CPU/CPUThreadManager.cpp
Normal file
111
rpcs3/Emu/CPU/CPUThreadManager.cpp
Normal 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();
|
||||
}
|
||||
}
|
27
rpcs3/Emu/CPU/CPUThreadManager.h
Normal file
27
rpcs3/Emu/CPU/CPUThreadManager.h
Normal 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();
|
||||
};
|
9
rpcs3/Emu/Cell/PPCDecoder.cpp
Normal file
9
rpcs3/Emu/Cell/PPCDecoder.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
#include "stdafx.h"
|
||||
#include "PPCDecoder.h"
|
||||
|
||||
u8 PPCDecoder::DecodeMemory(const u64 address)
|
||||
{
|
||||
Decode(Memory.Read32(address));
|
||||
|
||||
return 4;
|
||||
}
|
@ -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);
|
||||
}
|
@ -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;
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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();
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
@ -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)";
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
84
rpcs3/Emu/FS/vfsFile.cpp
Normal 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
29
rpcs3/Emu/FS/vfsFile.h
Normal 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;
|
||||
};
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
{
|
@ -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
@ -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();
|
||||
};
|
@ -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);
|
@ -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);
|
@ -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;
|
@ -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)
|
||||
{
|
29
rpcs3/Emu/GS/GL/GLProgramBuffer.h
Normal file
29
rpcs3/Emu/GS/GL/GLProgramBuffer.h
Normal 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();
|
||||
};
|
@ -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;
|
@ -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;
|
||||
}
|
@ -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();
|
||||
};
|
@ -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();
|
||||
};
|
@ -32,6 +32,7 @@ void GSManager::Close()
|
||||
if(m_render)
|
||||
{
|
||||
m_render->Close();
|
||||
delete m_render;
|
||||
m_render = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
15
rpcs3/Emu/GS/RSXFragmentProgram.h
Normal file
15
rpcs3/Emu/GS/RSXFragmentProgram.h
Normal 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
@ -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();
|
||||
}
|
||||
};
|
||||
|
6
rpcs3/Emu/GS/RSXVertexProgram.h
Normal file
6
rpcs3/Emu/GS/RSXVertexProgram.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
struct RSXVertexProgram
|
||||
{
|
||||
Array<u32> data;
|
||||
};
|
160
rpcs3/Emu/Memory/DynamicMemoryBlockBase.inl
Normal file
160
rpcs3/Emu/Memory/DynamicMemoryBlockBase.inl
Normal 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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
@ -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
|
||||
}
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
@ -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));
|
||||
}
|
@ -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;
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
86
rpcs3/Emu/SysCalls/lv2/SC_FileSystem.h
Normal file
86
rpcs3/Emu/SysCalls/lv2/SC_FileSystem.h
Normal 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()
|
@ -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
Loading…
Reference in New Issue
Block a user