mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
- Implemented ARM9Thread.
- Improved OpenGL Renderer. - Improved RAW SPU mfc.
This commit is contained in:
parent
6622dc42b5
commit
0b35be32a4
69
rpcs3/Emu/ARM9/ARM9Thread.cpp
Normal file
69
rpcs3/Emu/ARM9/ARM9Thread.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
#include "stdafx.h"
|
||||
#include "ARM9Thread.h"
|
||||
|
||||
ARM9Thread::ARM9Thread() : CPUThread(CPU_THREAD_ARM9)
|
||||
{
|
||||
}
|
||||
|
||||
void ARM9Thread::InitRegs()
|
||||
{
|
||||
}
|
||||
|
||||
void ARM9Thread::InitStack()
|
||||
{
|
||||
}
|
||||
|
||||
u64 ARM9Thread::GetFreeStackSize() const
|
||||
{
|
||||
return GetStackSize() - m_stack_point;
|
||||
}
|
||||
|
||||
void ARM9Thread::SetArg(const uint pos, const u64 arg)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void ARM9Thread::SetPc(const u64 pc)
|
||||
{
|
||||
PC = pc;
|
||||
nPC = pc + 2;
|
||||
}
|
||||
|
||||
wxString ARM9Thread::RegsToString()
|
||||
{
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
wxString ARM9Thread::ReadRegString(wxString reg)
|
||||
{
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
bool ARM9Thread::WriteRegString(wxString reg, wxString value)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void ARM9Thread::DoReset()
|
||||
{
|
||||
}
|
||||
|
||||
void ARM9Thread::DoRun()
|
||||
{
|
||||
}
|
||||
|
||||
void ARM9Thread::DoPause()
|
||||
{
|
||||
}
|
||||
|
||||
void ARM9Thread::DoResume()
|
||||
{
|
||||
}
|
||||
|
||||
void ARM9Thread::DoStop()
|
||||
{
|
||||
}
|
||||
|
||||
void ARM9Thread::DoCode()
|
||||
{
|
||||
}
|
30
rpcs3/Emu/ARM9/ARM9Thread.h
Normal file
30
rpcs3/Emu/ARM9/ARM9Thread.h
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include "Emu\CPU\CPUThread.h"
|
||||
|
||||
class ARM9Thread : public CPUThread
|
||||
{
|
||||
public:
|
||||
ARM9Thread();
|
||||
|
||||
public:
|
||||
virtual void InitRegs();
|
||||
virtual void InitStack();
|
||||
virtual u64 GetFreeStackSize() const;
|
||||
virtual void SetArg(const uint pos, const u64 arg);
|
||||
|
||||
public:
|
||||
virtual void SetPc(const u64 pc);
|
||||
|
||||
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();
|
||||
};
|
873
rpcs3/Emu/CPU/CPUDecoder.h
Normal file
873
rpcs3/Emu/CPU/CPUDecoder.h
Normal file
@ -0,0 +1,873 @@
|
||||
#pragma once
|
||||
#include "CPUInstrTable.h"
|
||||
#pragma warning( disable : 4800 )
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
311
rpcs3/Emu/CPU/CPUThread.cpp
Normal file
311
rpcs3/Emu/CPU/CPUThread.cpp
Normal file
@ -0,0 +1,311 @@
|
||||
#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)
|
||||
{
|
||||
}
|
||||
|
||||
CPUThread::~CPUThread()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void CPUThread::Close()
|
||||
{
|
||||
if(IsAlive())
|
||||
{
|
||||
m_free_data = true;
|
||||
}
|
||||
|
||||
Stop();
|
||||
}
|
||||
|
||||
void CPUThread::Reset()
|
||||
{
|
||||
CloseStack();
|
||||
|
||||
m_sync_wait = 0;
|
||||
m_wait_thread_id = -1;
|
||||
|
||||
SetPc(0);
|
||||
cycle = 0;
|
||||
|
||||
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(m_is_step)
|
||||
{
|
||||
return CPUThread_Step;
|
||||
}
|
||||
|
||||
if(Emu.IsStopped())
|
||||
{
|
||||
return CPUThread_Stopped;
|
||||
}
|
||||
|
||||
if(TestDestroy())
|
||||
{
|
||||
return CPUThread_Break;
|
||||
}
|
||||
|
||||
if(Emu.IsPaused() || Sync())
|
||||
{
|
||||
return CPUThread_Sleeping;
|
||||
}
|
||||
|
||||
return CPUThread_Running;
|
||||
}
|
||||
|
||||
void CPUThread::SetEntry(const u64 pc)
|
||||
{
|
||||
entry = pc;
|
||||
}
|
||||
|
||||
void CPUThread::NextPc()
|
||||
{
|
||||
SetPc(nPC);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
nPC = 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;
|
||||
}
|
||||
|
||||
DoCode();
|
||||
NextPc();
|
||||
|
||||
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)
|
||||
free(this);
|
||||
}
|
183
rpcs3/Emu/CPU/CPUThread.h
Normal file
183
rpcs3/Emu/CPU/CPUThread.h
Normal file
@ -0,0 +1,183 @@
|
||||
#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_ARM9,
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
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_ARM9: return "ARM9";
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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();
|
||||
|
||||
virtual void NextPc();
|
||||
virtual void SetBranch(const u64 pc);
|
||||
virtual void SetPc(const u64 pc) = 0;
|
||||
virtual 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();
|
||||
virtual void DoCode() = 0;
|
||||
};
|
||||
|
||||
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\ARM9\ARM9Thread.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_ARM9: new_thread = new ARM9Thread(); 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();
|
||||
};
|
@ -1,24 +1,8 @@
|
||||
#pragma once
|
||||
#include "Emu/CPU/CPUDecoder.h"
|
||||
#include "PPCInstrTable.h"
|
||||
#pragma warning( disable : 4800 )
|
||||
|
||||
template<typename TO>
|
||||
class InstrCaller
|
||||
{
|
||||
public:
|
||||
virtual ~InstrCaller()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void operator ()(TO* op, u32 code) const = 0;
|
||||
|
||||
virtual u32 operator [](u32) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
class PPC_Decoder
|
||||
class PPCDecoder
|
||||
{
|
||||
protected:
|
||||
u32 m_code;
|
||||
@ -29,460 +13,6 @@ public:
|
||||
virtual void Decode(const u32 code)=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, 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 +30,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,19 @@
|
||||
|
||||
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)
|
||||
PPCThread::PPCThread(CPUThreadType type)
|
||||
: CPUThread(type)
|
||||
, 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)
|
||||
{
|
||||
}
|
||||
|
||||
@ -27,146 +25,25 @@ 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(m_is_step)
|
||||
{
|
||||
return PPCThread_Step;
|
||||
}
|
||||
|
||||
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)
|
||||
@ -175,191 +52,3 @@ void PPCThread::SetPc(const u64 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()
|
||||
{
|
||||
m_is_step = false;
|
||||
wxGetApp().SendDbgCommand(DID_EXEC_THREAD, this);
|
||||
ThreadBase::Start();
|
||||
//std::thread thr(std::bind(std::mem_fn(&PPCThread::Task), this));
|
||||
}
|
||||
|
||||
void PPCThread::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 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();
|
||||
|
||||
if(status == PPCThread_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", PPCThread::GetFName());
|
||||
|
||||
if(m_free_data)
|
||||
free(this);
|
||||
}
|
||||
|
@ -1,186 +1,38 @@
|
||||
#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,
|
||||
PPCThread_Step,
|
||||
};
|
||||
|
||||
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;
|
||||
PPCDecoder* m_dec;
|
||||
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;
|
||||
bool m_is_step;
|
||||
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);
|
||||
virtual void SetPc(const u64 pc) override;
|
||||
|
||||
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,8 +178,10 @@ void PPUThread::DoStop()
|
||||
|
||||
bool dump_enable = false;
|
||||
|
||||
void PPUThread::DoCode(const s32 code)
|
||||
void PPUThread::DoCode()
|
||||
{
|
||||
const u32 code = Memory.Read32(m_offset + PC);
|
||||
|
||||
#ifdef _DEBUG
|
||||
static bool is_last_enabled = false;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
@ -829,8 +828,7 @@ protected:
|
||||
virtual void DoResume();
|
||||
virtual void DoStop();
|
||||
|
||||
public:
|
||||
virtual void DoCode(const s32 code);
|
||||
virtual void DoCode();
|
||||
};
|
||||
|
||||
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,11 +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));
|
||||
DoCode();
|
||||
NextPc();
|
||||
|
||||
for(uint i=0; i<bp.GetCount(); ++i)
|
||||
@ -128,4 +334,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:
|
||||
|
@ -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()
|
||||
{
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
@ -71,7 +88,7 @@ void SPUThread::DoStop()
|
||||
m_dec = 0;
|
||||
}
|
||||
|
||||
void SPUThread::DoCode(const s32 code)
|
||||
void SPUThread::DoCode()
|
||||
{
|
||||
m_dec->Decode(code);
|
||||
m_dec->Decode(Memory.Read32(m_offset + PC));
|
||||
}
|
||||
|
@ -130,28 +130,95 @@ 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;
|
||||
|
||||
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 +226,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 +257,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 +265,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 +286,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 +310,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 +333,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("["))
|
||||
{
|
||||
@ -294,7 +366,7 @@ protected:
|
||||
virtual void DoStop();
|
||||
|
||||
protected:
|
||||
virtual void DoCode(const s32 code);
|
||||
virtual void DoCode();
|
||||
};
|
||||
|
||||
SPUThread& GetCurrentSPUThread();
|
@ -72,7 +72,8 @@ 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";
|
||||
@ -97,20 +98,27 @@ wxString FragmentDecompilerThread::GetMask()
|
||||
|
||||
wxString FragmentDecompilerThread::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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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()
|
||||
@ -200,11 +208,6 @@ wxString FragmentDecompilerThread::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();
|
||||
@ -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;
|
||||
}
|
||||
|
@ -104,6 +104,7 @@ struct FragmentDecompilerThread : public ThreadBase
|
||||
u32& m_size;
|
||||
u32 m_const_index;
|
||||
u32 m_offset;
|
||||
u32 m_location;
|
||||
|
||||
FragmentDecompilerThread(wxString& shader, ParamArray& parr, u32 addr, u32& size)
|
||||
: ThreadBase(false, "Fragment Shader Decompiler Thread")
|
||||
@ -112,6 +113,7 @@ struct FragmentDecompilerThread : public ThreadBase
|
||||
, m_addr(addr)
|
||||
, m_size(size)
|
||||
, m_const_index(0)
|
||||
, m_location(0)
|
||||
{
|
||||
m_size = 0;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -559,17 +559,14 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u
|
||||
if(m_fbo.IsCreated())
|
||||
{
|
||||
m_fbo.Bind(GL_READ_FRAMEBUFFER);
|
||||
m_fbo.Bind(GL_DRAW_FRAMEBUFFER, 0);
|
||||
m_fbo.Blit(
|
||||
GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0);
|
||||
GLfbo::Blit(
|
||||
m_surface_clip_x, m_surface_clip_y, m_surface_clip_x + m_surface_clip_w, m_surface_clip_y + m_surface_clip_h,
|
||||
m_surface_clip_x, m_surface_clip_y, m_surface_clip_x + m_surface_clip_w, m_surface_clip_y + m_surface_clip_h,
|
||||
GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||
m_fbo.Bind();
|
||||
checkForGlError("m_fbo.Blit");
|
||||
}
|
||||
|
||||
m_frame->Flip();
|
||||
//glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
m_gcm_current_buffer = args[0];
|
||||
@ -773,54 +770,9 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u
|
||||
m_surface_offset_b = args[4];
|
||||
m_surface_pitch_b = args[5];
|
||||
|
||||
m_depth_offset = m_surface_offset_z;
|
||||
|
||||
gcmBuffer* buffers = (gcmBuffer*)Memory.GetMemFromAddr(m_gcm_buffers_addr);
|
||||
m_width = re(buffers[m_gcm_current_buffer].width);
|
||||
m_height = re(buffers[m_gcm_current_buffer].height);
|
||||
|
||||
break;
|
||||
m_rbo.Create(2);
|
||||
checkForGlError("m_rbo.Create");
|
||||
m_rbo.Bind(0);
|
||||
m_rbo.Storage(GL_RGBA, m_width, m_height);
|
||||
checkForGlError("m_rbo.Storage(GL_RGBA)");
|
||||
m_rbo.Bind(1);
|
||||
|
||||
switch(m_surface_depth_format)
|
||||
{
|
||||
case 1:
|
||||
m_rbo.Storage(GL_DEPTH_COMPONENT16, m_width, m_height);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_rbo.Storage(GL_DEPTH24_STENCIL8, m_width, m_height);
|
||||
break;
|
||||
|
||||
default:
|
||||
ConLog.Error("Bad depth format! (%d)", m_surface_depth_format);
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
checkForGlError("m_rbo.Storage(GL_DEPTH24_STENCIL8)");
|
||||
m_fbo.Create();
|
||||
checkForGlError("m_fbo.Create");
|
||||
m_fbo.Bind();
|
||||
m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT0, m_rbo.GetId(0));
|
||||
checkForGlError("m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT0)");
|
||||
|
||||
if(m_surface_depth_format == 2)
|
||||
{
|
||||
m_fbo.Renderbuffer(GL_DEPTH_STENCIL_ATTACHMENT, m_rbo.GetId(1));
|
||||
checkForGlError("m_fbo.Renderbuffer(GL_DEPTH_STENCIL_ATTACHMENT)");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fbo.Renderbuffer(GL_DEPTH_ATTACHMENT, m_rbo.GetId(1));
|
||||
checkForGlError("m_fbo.Renderbuffer(GL_DEPTH_STENCIL_ATTACHMENT)");
|
||||
}
|
||||
//CMD_LOG("color_format=%d, depth_format=%d, type=%d, antialias=%d, width=%d, height=%d, pitch_a=%d, offset_a=0x%x, offset_z=0x%x, offset_b=0x%x, pitch_b=%d",
|
||||
// color_format, depth_format, type, antialias, width, height, pitch_a, offset_a, offset_z, offset_b, pitch_b);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -928,15 +880,16 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u
|
||||
|
||||
case NV4097_CLEAR_SURFACE:
|
||||
{
|
||||
if(m_set_clear_surface)
|
||||
{
|
||||
m_clear_surface_mask |= args[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_clear_surface_mask = args[0];
|
||||
m_set_clear_surface = true;
|
||||
}
|
||||
u32 a0 = args[0];
|
||||
|
||||
if(a0 & 0x01) m_clear_surface_z = m_clear_z;
|
||||
if(a0 & 0x02) m_clear_surface_s = m_clear_s;
|
||||
if(a0 & 0x10) m_clear_surface_color_r = m_clear_color_r;
|
||||
if(a0 & 0x20) m_clear_surface_color_g = m_clear_color_g;
|
||||
if(a0 & 0x40) m_clear_surface_color_b = m_clear_color_b;
|
||||
if(a0 & 0x80) m_clear_surface_color_a = m_clear_color_a;
|
||||
|
||||
m_clear_surface_mask |= a0;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1082,18 +1035,10 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u
|
||||
case NV4097_SET_COLOR_CLEAR_VALUE:
|
||||
{
|
||||
const u32 color = args[0];
|
||||
//m_set_clear_color = true;
|
||||
m_clear_color_a = (color >> 24) & 0xff;
|
||||
m_clear_color_r = (color >> 16) & 0xff;
|
||||
m_clear_color_g = (color >> 8) & 0xff;
|
||||
m_clear_color_b = color & 0xff;
|
||||
|
||||
glClearColor(
|
||||
m_clear_color_r / 255.0f,
|
||||
m_clear_color_g / 255.0f,
|
||||
m_clear_color_b / 255.0f,
|
||||
m_clear_color_a / 255.0f);
|
||||
checkForGlError("glClearColor");
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1452,6 +1397,12 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u
|
||||
{
|
||||
m_set_context_dma_color_c = true;
|
||||
m_context_dma_color_c = args[0];
|
||||
|
||||
if(count > 1)
|
||||
{
|
||||
m_set_context_dma_color_d = true;
|
||||
m_context_dma_color_d = args[1];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1461,7 +1412,7 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u
|
||||
m_context_dma_z = args[0];
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
case NV4097_SET_SURFACE_PITCH_A:
|
||||
{
|
||||
//TODO
|
||||
@ -1473,22 +1424,34 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u
|
||||
//TODO
|
||||
}
|
||||
break;
|
||||
|
||||
*/
|
||||
case NV4097_SET_SURFACE_PITCH_C:
|
||||
{
|
||||
//TODO
|
||||
if(count != 4)
|
||||
{
|
||||
ConLog.Error("NV4097_SET_SURFACE_PITCH_C: Bad count (%d)", count);
|
||||
break;
|
||||
}
|
||||
|
||||
m_surface_pitch_c = args[0];
|
||||
m_surface_pitch_d = args[1];
|
||||
m_surface_offset_c = args[2];
|
||||
m_surface_offset_d = args[3];
|
||||
}
|
||||
break;
|
||||
|
||||
case NV4097_SET_SURFACE_PITCH_Z:
|
||||
{
|
||||
m_depth_pitch = args[0];
|
||||
m_surface_pitch_z = args[0];
|
||||
}
|
||||
break;
|
||||
|
||||
case NV4097_SET_SHADER_WINDOW:
|
||||
{
|
||||
//TODO
|
||||
u32 a0 = args[0];
|
||||
m_shader_window_height = a0 & 0xfff;
|
||||
m_shader_window_origin = (a0 >> 12) & 0xf;
|
||||
m_shader_window_pixel_centers = a0 >> 16;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1527,7 +1490,7 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u
|
||||
|
||||
case NV4097_SET_SURFACE_COLOR_TARGET:
|
||||
{
|
||||
//TODO
|
||||
m_surface_colour_target = args[0];
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1553,10 +1516,9 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u
|
||||
|
||||
case NV4097_SET_ZSTENCIL_CLEAR_VALUE:
|
||||
{
|
||||
u32 clear_valuei = args[0];
|
||||
double clear_valuef = (double)clear_valuei / 0xffffffff;
|
||||
glClearDepth(clear_valuef);
|
||||
glClearStencil(clear_valuei);
|
||||
u32 a0 = args[0];
|
||||
m_clear_s = a0 & 0xff;
|
||||
m_clear_z = a0 >> 8;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1877,59 +1839,251 @@ void GLGSRender::WriteDepthBuffer()
|
||||
return;
|
||||
}
|
||||
|
||||
u32 address = GetAddress(m_depth_offset, m_context_dma_z - 0xfeed0000);
|
||||
u32 address = GetAddress(m_surface_offset_z, m_context_dma_z - 0xfeed0000);
|
||||
if(!Memory.IsGoodAddr(address))
|
||||
{
|
||||
ConLog.Warning("Bad depth address: address=0x%x, offset=0x%x, dma=0x%x", address, m_depth_offset, m_context_dma_z);
|
||||
ConLog.Warning("Bad depth address: address=0x%x, offset=0x%x, dma=0x%x", address, m_surface_offset_z, m_context_dma_z);
|
||||
return;
|
||||
}
|
||||
|
||||
u8* dst = &Memory[address];
|
||||
//m_fbo.Bind(GL_READ_FRAMEBUFFER);
|
||||
//glPixelStorei(GL_PACK_ROW_LENGTH, m_depth_pitch);
|
||||
glReadPixels(0, 0, m_width, m_height, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, &Memory[address]);
|
||||
checkForGlError("glReadPixels");
|
||||
|
||||
m_fbo.Bind(GL_READ_FRAMEBUFFER);
|
||||
GLuint depth_tex;
|
||||
glGenTextures(1, &depth_tex);
|
||||
glBindTexture(GL_TEXTURE_2D, depth_tex);
|
||||
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 0, 0, m_width, m_height, 0);
|
||||
checkForGlError("glCopyTexImage2D");
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_FLOAT, dst);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &Memory[address]);
|
||||
checkForGlError("glTexImage2D");
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &Memory[address]);
|
||||
checkForGlError("glGetTexImage");
|
||||
glDeleteTextures(1, &depth_tex);
|
||||
wxFile f("depth.raw", wxFile::write);
|
||||
f.Write(dst, m_width * m_height * 4);
|
||||
m_fbo.Bind();
|
||||
/*
|
||||
GLBufferObject pbo;
|
||||
pbo.Create(GL_PIXEL_PACK_BUFFER);
|
||||
pbo.Bind();
|
||||
glReadPixels(0, 0, m_width, m_height, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
|
||||
GLuint *src = (GLuint*)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
|
||||
if(src)
|
||||
}
|
||||
|
||||
void GLGSRender::WriteColourBufferA()
|
||||
{
|
||||
if(!m_set_context_dma_color_a)
|
||||
{
|
||||
wxFile f("depth.raw", wxFile::write);
|
||||
f.Write(src, m_width * m_height * 4);
|
||||
memcpy(dst, src, m_width * m_height * 4);
|
||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
u32 address = GetAddress(m_surface_offset_a, m_context_dma_color_a - 0xfeed0000);
|
||||
if(!Memory.IsGoodAddr(address))
|
||||
{
|
||||
ConLog.Error("glMapBuffer failed.");
|
||||
ConLog.Warning("Bad colour buffer a address: address=0x%x, offset=0x%x, dma=0x%x", address, m_surface_offset_a, m_context_dma_color_a);
|
||||
return;
|
||||
}
|
||||
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
checkForGlError("glReadBuffer(GL_COLOR_ATTACHMENT0)");
|
||||
glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &Memory[address]);
|
||||
checkForGlError("glReadPixels(GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)");
|
||||
}
|
||||
|
||||
void GLGSRender::WriteColourBufferB()
|
||||
{
|
||||
if(!m_set_context_dma_color_b)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
u32 address = GetAddress(m_surface_offset_b, m_context_dma_color_b - 0xfeed0000);
|
||||
if(!Memory.IsGoodAddr(address))
|
||||
{
|
||||
ConLog.Warning("Bad colour buffer b address: address=0x%x, offset=0x%x, dma=0x%x", address, m_surface_offset_b, m_context_dma_color_b);
|
||||
return;
|
||||
}
|
||||
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT1);
|
||||
checkForGlError("glReadBuffer(GL_COLOR_ATTACHMENT1)");
|
||||
glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &Memory[address]);
|
||||
checkForGlError("glReadPixels(GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)");
|
||||
}
|
||||
|
||||
void GLGSRender::WriteColourBufferC()
|
||||
{
|
||||
if(!m_set_context_dma_color_c)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
u32 address = GetAddress(m_surface_offset_c, m_context_dma_color_c - 0xfeed0000);
|
||||
if(!Memory.IsGoodAddr(address))
|
||||
{
|
||||
ConLog.Warning("Bad colour buffer c address: address=0x%x, offset=0x%x, dma=0x%x", address, m_surface_offset_c, m_context_dma_color_c);
|
||||
return;
|
||||
}
|
||||
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT2);
|
||||
checkForGlError("glReadBuffer(GL_COLOR_ATTACHMENT2)");
|
||||
glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &Memory[address]);
|
||||
checkForGlError("glReadPixels(GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)");
|
||||
}
|
||||
|
||||
void GLGSRender::WriteColourBufferD()
|
||||
{
|
||||
if(!m_set_context_dma_color_d)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
u32 address = GetAddress(m_surface_offset_d, m_context_dma_color_d - 0xfeed0000);
|
||||
if(!Memory.IsGoodAddr(address))
|
||||
{
|
||||
ConLog.Warning("Bad colour buffer d address: address=0x%x, offset=0x%x, dma=0x%x", address, m_surface_offset_d, m_context_dma_color_d);
|
||||
return;
|
||||
}
|
||||
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT3);
|
||||
checkForGlError("glReadBuffer(GL_COLOR_ATTACHMENT3)");
|
||||
glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &Memory[address]);
|
||||
checkForGlError("glReadPixels(GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)");
|
||||
}
|
||||
|
||||
void GLGSRender::WriteBuffers()
|
||||
{
|
||||
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
|
||||
switch(m_surface_colour_target)
|
||||
{
|
||||
case 0x0:
|
||||
return;
|
||||
|
||||
case 0x1:
|
||||
WriteColourBufferA();
|
||||
break;
|
||||
|
||||
case 0x2:
|
||||
WriteColourBufferB();
|
||||
break;
|
||||
|
||||
case 0x13:
|
||||
WriteColourBufferA();
|
||||
WriteColourBufferB();
|
||||
break;
|
||||
|
||||
case 0x17:
|
||||
WriteColourBufferA();
|
||||
WriteColourBufferB();
|
||||
WriteColourBufferC();
|
||||
break;
|
||||
|
||||
case 0x1f:
|
||||
WriteColourBufferA();
|
||||
WriteColourBufferB();
|
||||
WriteColourBufferC();
|
||||
WriteColourBufferD();
|
||||
break;
|
||||
}
|
||||
pbo.UnBind();
|
||||
pbo.Delete();
|
||||
*/
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
void GLGSRender::ExecCMD()
|
||||
{
|
||||
if(LoadProgram())
|
||||
{
|
||||
if(m_set_surface_clip_horizontal && m_set_surface_clip_vertical)
|
||||
static int last_width = 0, last_height = 0, last_depth_format = 0;
|
||||
|
||||
if(m_width != last_width || m_height != last_height || last_depth_format != m_surface_depth_format)
|
||||
{
|
||||
//ConLog.Write("surface clip width: %d, height: %d, x: %d, y: %d", m_width, m_height, m_surface_clip_x, m_surface_clip_y);
|
||||
ConLog.Warning("New FBO (%dx%d)", m_width, m_height);
|
||||
last_width = m_width;
|
||||
last_height = m_height;
|
||||
last_depth_format = m_surface_depth_format;
|
||||
|
||||
m_fbo.Create();
|
||||
checkForGlError("m_fbo.Create");
|
||||
m_fbo.Bind();
|
||||
|
||||
m_rbo.Create(4 + 1);
|
||||
checkForGlError("m_rbo.Create");
|
||||
|
||||
for(int i=0; i<4; ++i)
|
||||
{
|
||||
m_rbo.Bind(i);
|
||||
m_rbo.Storage(GL_RGBA, m_width, m_height);
|
||||
checkForGlError("m_rbo.Storage(GL_RGBA)");
|
||||
}
|
||||
|
||||
m_rbo.Bind(4);
|
||||
|
||||
switch(m_surface_depth_format)
|
||||
{
|
||||
case 1:
|
||||
m_rbo.Storage(GL_DEPTH_COMPONENT16, m_width, m_height);
|
||||
checkForGlError("m_rbo.Storage(GL_DEPTH_COMPONENT16)");
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_rbo.Storage(GL_DEPTH24_STENCIL8, m_width, m_height);
|
||||
checkForGlError("m_rbo.Storage(GL_DEPTH24_STENCIL8)");
|
||||
break;
|
||||
|
||||
default:
|
||||
ConLog.Error("Bad depth format! (%d)", m_surface_depth_format);
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
for(int i=0; i<4; ++i)
|
||||
{
|
||||
m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT0 + i, m_rbo.GetId(i));
|
||||
checkForGlError(wxString::Format("m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT%d)", i));
|
||||
}
|
||||
|
||||
m_fbo.Renderbuffer(GL_DEPTH_ATTACHMENT, m_rbo.GetId(4));
|
||||
checkForGlError("m_fbo.Renderbuffer(GL_DEPTH_ATTACHMENT)");
|
||||
|
||||
if(m_surface_depth_format == 2)
|
||||
{
|
||||
m_fbo.Renderbuffer(GL_STENCIL_ATTACHMENT, m_rbo.GetId(4));
|
||||
checkForGlError("m_fbo.Renderbuffer(GL_STENCIL_ATTACHMENT)");
|
||||
}
|
||||
}
|
||||
|
||||
if(!m_set_surface_clip_horizontal)
|
||||
{
|
||||
m_surface_clip_x = 0;
|
||||
m_surface_clip_w = m_width;
|
||||
}
|
||||
|
||||
if(!m_set_surface_clip_vertical)
|
||||
{
|
||||
m_surface_clip_y = 0;
|
||||
m_surface_clip_h = m_height;
|
||||
}
|
||||
|
||||
m_fbo.Bind();
|
||||
WriteDepthBuffer();
|
||||
static const GLenum draw_buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 };
|
||||
|
||||
switch(m_surface_colour_target)
|
||||
{
|
||||
case 0x0:
|
||||
break;
|
||||
|
||||
case 0x1:
|
||||
glDrawBuffer(draw_buffers[0]);
|
||||
break;
|
||||
|
||||
case 0x2:
|
||||
glDrawBuffer(draw_buffers[1]);
|
||||
break;
|
||||
|
||||
case 0x13:
|
||||
glDrawBuffers(2, draw_buffers);
|
||||
break;
|
||||
|
||||
case 0x17:
|
||||
glDrawBuffers(3, draw_buffers);
|
||||
break;
|
||||
|
||||
case 0x1f:
|
||||
glDrawBuffers(4, draw_buffers);
|
||||
break;
|
||||
|
||||
default:
|
||||
ConLog.Error("Bad surface colour target: %d", m_surface_colour_target);
|
||||
break;
|
||||
}
|
||||
|
||||
if(m_set_color_mask)
|
||||
@ -1950,21 +2104,35 @@ void GLGSRender::ExecCMD()
|
||||
checkForGlError("glScissor");
|
||||
}
|
||||
|
||||
if(m_set_clear_color)
|
||||
{
|
||||
glClearColor(
|
||||
m_clear_color_r / 255.0f,
|
||||
m_clear_color_g / 255.0f,
|
||||
m_clear_color_b / 255.0f,
|
||||
m_clear_color_a / 255.0f);
|
||||
}
|
||||
|
||||
if(m_set_clear_surface)
|
||||
if(m_clear_surface_mask)
|
||||
{
|
||||
GLbitfield f = 0;
|
||||
if (m_clear_surface_mask & 0x1) f |= GL_DEPTH_BUFFER_BIT;
|
||||
if (m_clear_surface_mask & 0x2) f |= GL_STENCIL_BUFFER_BIT;
|
||||
if ((m_clear_surface_mask & 0xF0) == 0xF0) f |= GL_COLOR_BUFFER_BIT;
|
||||
|
||||
if (m_clear_surface_mask & 0x1)
|
||||
{
|
||||
glClearDepth(m_clear_surface_z / (float)0xffffff);
|
||||
|
||||
f |= GL_DEPTH_BUFFER_BIT;
|
||||
}
|
||||
|
||||
if (m_clear_surface_mask & 0x2)
|
||||
{
|
||||
glClearStencil(m_clear_surface_s);
|
||||
|
||||
f |= GL_STENCIL_BUFFER_BIT;
|
||||
}
|
||||
|
||||
if (m_clear_surface_mask & 0xF0)
|
||||
{
|
||||
glClearColor(
|
||||
m_clear_surface_color_r / 255.0f,
|
||||
m_clear_surface_color_g / 255.0f,
|
||||
m_clear_surface_color_b / 255.0f,
|
||||
m_clear_surface_color_a / 255.0f);
|
||||
|
||||
f |= GL_COLOR_BUFFER_BIT;
|
||||
}
|
||||
|
||||
glClear(f);
|
||||
}
|
||||
|
||||
@ -1984,7 +2152,6 @@ void GLGSRender::ExecCMD()
|
||||
Enable(m_set_stencil_test, GL_STENCIL_TEST);
|
||||
Enable(m_set_line_smooth, GL_LINE_SMOOTH);
|
||||
Enable(m_set_poly_smooth, GL_POLYGON_SMOOTH);
|
||||
checkForGlError("glEnable");
|
||||
|
||||
if(m_set_clip_plane)
|
||||
{
|
||||
@ -1998,26 +2165,28 @@ void GLGSRender::ExecCMD()
|
||||
checkForGlError("m_set_clip_plane");
|
||||
}
|
||||
|
||||
if(m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass)
|
||||
{
|
||||
glStencilOp(m_stencil_fail, m_stencil_zfail, m_stencil_zpass);
|
||||
checkForGlError("glStencilOp");
|
||||
}
|
||||
|
||||
if(m_set_stencil_mask)
|
||||
{
|
||||
glStencilMask(m_stencil_mask);
|
||||
checkForGlError("glStencilMask");
|
||||
}
|
||||
|
||||
if(m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask)
|
||||
{
|
||||
glStencilFunc(m_stencil_func, m_stencil_func_ref, m_stencil_func_mask);
|
||||
checkForGlError("glStencilFunc");
|
||||
}
|
||||
checkForGlError("glEnable");
|
||||
|
||||
if(m_set_two_sided_stencil_test_enable)
|
||||
{
|
||||
if(m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass)
|
||||
{
|
||||
glStencilOpSeparate(GL_FRONT, m_stencil_fail, m_stencil_zfail, m_stencil_zpass);
|
||||
checkForGlError("glStencilOpSeparate");
|
||||
}
|
||||
|
||||
if(m_set_stencil_mask)
|
||||
{
|
||||
glStencilMaskSeparate(GL_FRONT, m_stencil_mask);
|
||||
checkForGlError("glStencilMaskSeparate");
|
||||
}
|
||||
|
||||
if(m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask)
|
||||
{
|
||||
glStencilFuncSeparate(GL_FRONT, m_stencil_func, m_stencil_func_ref, m_stencil_func_mask);
|
||||
checkForGlError("glStencilFuncSeparate");
|
||||
}
|
||||
|
||||
if(m_set_back_stencil_fail && m_set_back_stencil_zfail && m_set_back_stencil_zpass)
|
||||
{
|
||||
glStencilOpSeparate(GL_BACK, m_back_stencil_fail, m_back_stencil_zfail, m_back_stencil_zpass);
|
||||
@ -2036,6 +2205,26 @@ void GLGSRender::ExecCMD()
|
||||
checkForGlError("glStencilFuncSeparate(GL_BACK)");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass)
|
||||
{
|
||||
glStencilOp(m_stencil_fail, m_stencil_zfail, m_stencil_zpass);
|
||||
checkForGlError("glStencilOp");
|
||||
}
|
||||
|
||||
if(m_set_stencil_mask)
|
||||
{
|
||||
glStencilMask(m_stencil_mask);
|
||||
checkForGlError("glStencilMask");
|
||||
}
|
||||
|
||||
if(m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask)
|
||||
{
|
||||
glStencilFunc(m_stencil_func, m_stencil_func_ref, m_stencil_func_mask);
|
||||
checkForGlError("glStencilFunc");
|
||||
}
|
||||
}
|
||||
|
||||
if(m_set_shade_mode)
|
||||
{
|
||||
@ -2176,7 +2365,7 @@ void GLGSRender::ExecCMD()
|
||||
|
||||
m_fragment_constants.Clear();
|
||||
|
||||
//WriteDepthBuffer();
|
||||
WriteBuffers();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -189,11 +189,10 @@ public:
|
||||
//TODO: safe init
|
||||
checkForGlError("GLTexture::Init() -> glBindTexture");
|
||||
|
||||
glPixelStorei(GL_PACK_ROW_LENGTH, m_pitch);
|
||||
|
||||
int format = m_format & ~(0x20 | 0x40);
|
||||
bool is_swizzled = (m_format & 0x20) == 0;
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, m_pitch);
|
||||
char* pixels = (char*)Memory.GetMemFromAddr(m_offset);
|
||||
|
||||
switch(format)
|
||||
@ -267,10 +266,8 @@ public:
|
||||
default: ConLog.Error("Init tex error: Bad tex format (0x%x | 0x%x | 0x%x)", format, m_format & 0x20, m_format & 0x40); break;
|
||||
}
|
||||
|
||||
if(m_mipmap > 1)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, m_mipmap - 1);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, m_mipmap > 1);
|
||||
|
||||
if(format != 0x81 && format != 0x94)
|
||||
{
|
||||
@ -292,7 +289,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 +301,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);
|
||||
|
||||
glTexEnvi(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);
|
||||
|
||||
|
||||
static const int gl_tex_filter[] =
|
||||
{
|
||||
GL_NEAREST,
|
||||
@ -496,6 +492,105 @@ struct GLRSXThread : public ThreadBase
|
||||
virtual void Task();
|
||||
};
|
||||
|
||||
class PostDrawObj
|
||||
{
|
||||
protected:
|
||||
ShaderProgram m_fp;
|
||||
VertexProgram m_vp;
|
||||
Program m_program;
|
||||
GLfbo m_fbo;
|
||||
GLrbo m_rbo;
|
||||
|
||||
public:
|
||||
virtual void Draw()
|
||||
{
|
||||
static bool s_is_initialized = false;
|
||||
|
||||
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
|
||||
@ -520,6 +615,7 @@ private:
|
||||
VertexProgram* m_cur_vertex_prog;
|
||||
Array<TransformConstant> m_transform_constants;
|
||||
Array<TransformConstant> m_fragment_constants;
|
||||
ArrayF<PostDrawObj> m_post_draw_objs;
|
||||
|
||||
Program m_program;
|
||||
int m_fp_buf_num;
|
||||
@ -557,6 +653,13 @@ private:
|
||||
virtual void Close();
|
||||
bool LoadProgram();
|
||||
void WriteDepthBuffer();
|
||||
void WriteColourBufferA();
|
||||
void WriteColourBufferB();
|
||||
void WriteColourBufferC();
|
||||
void WriteColourBufferD();
|
||||
void WriteBuffers();
|
||||
|
||||
void DrawObjects();
|
||||
|
||||
public:
|
||||
void DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u32 count);
|
||||
|
@ -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);
|
@ -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), 0, 0, 0).xxxx"); break; //DP3
|
||||
case 0x06: AddVecCode("vec4(dot(vec4(" + GetSRC(0) + ".xyz, 1), " + GetSRC(1) + "), 0, 0, 0).xxxx"); break; //DPH
|
||||
case 0x07: AddVecCode("vec4(dot(" + GetSRC(0) + ", " + GetSRC(1) + "), 0, 0, 0).xxxx"); break; //DP4
|
||||
case 0x08: AddVecCode("vec4(distance(" + GetSRC(0) + ", " + GetSRC(1) + "), 0, 0, 0).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:
|
||||
|
@ -45,8 +45,9 @@ 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;
|
||||
@ -123,11 +124,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;
|
||||
@ -175,11 +177,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;
|
||||
@ -190,6 +187,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;
|
||||
|
||||
@ -209,8 +209,23 @@ public:
|
||||
bool m_set_alpha_ref;
|
||||
u32 m_alpha_ref;
|
||||
|
||||
u32 m_depth_offset;
|
||||
u32 m_depth_pitch;
|
||||
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;
|
||||
|
||||
@ -227,6 +242,14 @@ public:
|
||||
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;
|
||||
|
||||
Reset();
|
||||
}
|
||||
@ -241,7 +264,7 @@ public:
|
||||
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_stencil_mask = false;
|
||||
@ -251,7 +274,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;
|
||||
@ -264,7 +286,6 @@ public:
|
||||
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;
|
||||
@ -273,9 +294,8 @@ 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;
|
||||
|
@ -466,52 +466,24 @@ u8* DynamicMemoryBlock::GetMem(u64 addr) const
|
||||
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 +529,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,6 +1,12 @@
|
||||
#pragma once
|
||||
#include "MemoryBlock.h"
|
||||
|
||||
enum MemoryType
|
||||
{
|
||||
Memory_PS3,
|
||||
Memory_Vita,
|
||||
};
|
||||
|
||||
class MemoryBase
|
||||
{
|
||||
NullMemoryBlock NullMem;
|
||||
@ -126,21 +132,29 @@ 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(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_Vita:
|
||||
break;
|
||||
}
|
||||
|
||||
ConLog.Write("Memory initialized.");
|
||||
}
|
||||
@ -181,15 +195,6 @@ public:
|
||||
MemoryBlocks.Clear();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
if(!m_inited) return;
|
||||
|
||||
ConLog.Write("Resetting memory...");
|
||||
Close();
|
||||
Init();
|
||||
}
|
||||
|
||||
void Write8(const u64 addr, const u8 data);
|
||||
void Write16(const u64 addr, const u16 data);
|
||||
void Write32(const u64 addr, const u32 data);
|
||||
|
@ -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");
|
||||
@ -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);
|
||||
|
@ -267,14 +267,6 @@ void default_syscall()
|
||||
return;
|
||||
}
|
||||
|
||||
SysCalls::SysCalls(PPUThread& cpu) : CPU(cpu)
|
||||
{
|
||||
}
|
||||
|
||||
SysCalls::~SysCalls()
|
||||
{
|
||||
}
|
||||
|
||||
void SysCalls::DoSyscall(u32 code)
|
||||
{
|
||||
if(code < 1024)
|
||||
@ -291,5 +283,6 @@ void SysCalls::DoSyscall(u32 code)
|
||||
//return 0;
|
||||
|
||||
//TODO: remove this
|
||||
declCPU();
|
||||
RESULT(DoFunc(code));
|
||||
}
|
@ -305,32 +305,12 @@ extern u64 sys_time_get_timebase_frequency();
|
||||
#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;
|
||||
|
@ -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);
|
||||
|
@ -38,7 +38,7 @@ int sys_ppu_thread_join(u32 thread_id, u32 vptr_addr)
|
||||
{
|
||||
sysPrxForUser.Warning("sys_ppu_thread_join(thread_id=%d, vptr_addr=0x%x)", thread_id, vptr_addr);
|
||||
|
||||
PPCThread* thr = Emu.GetCPU().GetThread(thread_id);
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
|
||||
if(!thr) return CELL_ESRCH;
|
||||
|
||||
GetCurrentPPUThread().Wait(*thr);
|
||||
@ -62,7 +62,7 @@ int sys_ppu_thread_set_priority(u32 thread_id, int prio)
|
||||
{
|
||||
sysPrxForUser.Warning("sys_ppu_thread_set_priority(thread_id=%d, prio=%d)", thread_id, prio);
|
||||
|
||||
PPCThread* thr = Emu.GetCPU().GetThread(thread_id);
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
|
||||
if(!thr) return CELL_ESRCH;
|
||||
|
||||
thr->SetPrio(prio);
|
||||
@ -74,7 +74,7 @@ int sys_ppu_thread_get_priority(u32 thread_id, u32 prio_addr)
|
||||
{
|
||||
sysPrxForUser.Log("sys_ppu_thread_get_priority(thread_id=%d, prio_addr=0x%x)", thread_id, prio_addr);
|
||||
|
||||
PPCThread* thr = Emu.GetCPU().GetThread(thread_id);
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
|
||||
if(!thr) return CELL_ESRCH;
|
||||
if(!Memory.IsGoodAddr(prio_addr)) return CELL_EFAULT;
|
||||
|
||||
@ -101,7 +101,7 @@ int sys_ppu_thread_stop(u32 thread_id)
|
||||
{
|
||||
sysPrxForUser.Warning("sys_ppu_thread_stop(thread_id=%d)", thread_id);
|
||||
|
||||
PPCThread* thr = Emu.GetCPU().GetThread(thread_id);
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
|
||||
if(!thr) return CELL_ESRCH;
|
||||
|
||||
thr->Stop();
|
||||
@ -113,7 +113,7 @@ int sys_ppu_thread_restart(u32 thread_id)
|
||||
{
|
||||
sysPrxForUser.Warning("sys_ppu_thread_restart(thread_id=%d)", thread_id);
|
||||
|
||||
PPCThread* thr = Emu.GetCPU().GetThread(thread_id);
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
|
||||
if(!thr) return CELL_ESRCH;
|
||||
|
||||
thr->Stop();
|
||||
@ -132,13 +132,13 @@ int sys_ppu_thread_create(u32 thread_id_addr, u32 entry, u32 arg, int prio, u32
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
PPCThread& new_thread = Emu.GetCPU().AddThread(PPC_THREAD_PPU);
|
||||
CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU);
|
||||
|
||||
Memory.Write32(thread_id_addr, new_thread.GetId());
|
||||
new_thread.SetEntry(entry);
|
||||
new_thread.SetArg(0, arg);
|
||||
new_thread.SetPrio(prio);
|
||||
new_thread.stack_size = stacksize;
|
||||
new_thread.SetStackSize(stacksize);
|
||||
//new_thread.flags = flags;
|
||||
new_thread.SetName(Memory.ReadString(threadname_addr));
|
||||
new_thread.Run();
|
||||
@ -155,7 +155,7 @@ void sys_ppu_thread_once(u32 once_ctrl_addr, u32 entry)
|
||||
{
|
||||
Memory.Write32(once_ctrl_addr, SYS_PPU_THREAD_DONE_INIT);
|
||||
|
||||
PPCThread& new_thread = Emu.GetCPU().AddThread(PPC_THREAD_PPU);
|
||||
CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU);
|
||||
new_thread.SetEntry(entry);
|
||||
new_thread.Run();
|
||||
new_thread.Exec();
|
||||
|
@ -32,7 +32,7 @@ int sys_game_process_exitspawn( u32 path_addr, u32 argv_addr, u32 envp_addr,
|
||||
sc_p.Log("flags: %d", flags);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
int SysCalls::lv2ProcessWaitForChild(PPUThread& CPU)
|
||||
{
|
||||
ConLog.Warning("lv2ProcessWaitForChild");
|
||||
@ -73,14 +73,7 @@ int SysCalls::lv2ProcessKill(PPUThread& CPU)
|
||||
CPU.Close();
|
||||
return CELL_OK;
|
||||
}
|
||||
/*
|
||||
int SysCalls::lv2ProcessExit(PPUThread& CPU)
|
||||
{
|
||||
ConLog.Warning("lv2ProcessExit(%lld)", CPU.GPR[3]);
|
||||
Emu.Pause();
|
||||
return CELL_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
int SysCalls::lv2ProcessWaitForChild2(PPUThread& CPU)
|
||||
{
|
||||
ConLog.Warning("lv2ProcessWaitForChild2[r3: 0x%llx, r4: 0x%llx, r5: 0x%llx, r6: 0x%llx, r7: 0x%llx, r8: 0x%llx]",
|
||||
@ -92,4 +85,5 @@ int SysCalls::lv2ProcessGetSdkVersion(PPUThread& CPU)
|
||||
ConLog.Warning("lv2ProcessGetSdkVersion[r3: 0x%llx, r4: 0x%llx]", CPU.GPR[3], CPU.GPR[4]);
|
||||
CPU.GPR[4] = 0x360001; //TODO
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
*/
|
@ -1,7 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Loader/ELF.h"
|
||||
#include "Emu/Cell/SPUThread.h"
|
||||
#include "Emu/Cell/RawSPUThread.h"
|
||||
|
||||
SysCallBase sc_spu("sys_spu");
|
||||
|
||||
@ -40,12 +40,12 @@ static const u32 g_spu_group_thr_count = 255;
|
||||
|
||||
struct SpuGroupInfo
|
||||
{
|
||||
PPCThread* threads[g_spu_group_thr_count];
|
||||
CPUThread* threads[g_spu_group_thr_count];
|
||||
sys_spu_thread_group_attribute& attr;
|
||||
|
||||
SpuGroupInfo(sys_spu_thread_group_attribute& attr) : attr(attr)
|
||||
{
|
||||
memset(threads, 0, sizeof(PPCThread*) * g_spu_group_thr_count);
|
||||
memset(threads, 0, sizeof(CPUThread*) * g_spu_group_thr_count);
|
||||
}
|
||||
};
|
||||
|
||||
@ -150,7 +150,7 @@ int sys_spu_thread_initialize(u32 thread_addr, u32 group, u32 spu_num, u32 img_a
|
||||
ConLog.Write("a4 = 0x%x", a4);
|
||||
ConLog.SkipLn();
|
||||
|
||||
PPCThread& new_thread = Emu.GetCPU().AddThread(PPC_THREAD_SPU);
|
||||
CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_SPU);
|
||||
new_thread.SetOffset(g_spu_offset);
|
||||
new_thread.SetEntry(entry - g_spu_offset);
|
||||
new_thread.SetName(name);
|
||||
@ -170,9 +170,9 @@ int sys_spu_thread_initialize(u32 thread_addr, u32 group, u32 spu_num, u32 img_a
|
||||
int sys_spu_thread_set_argument(u32 id, u32 arg_addr)
|
||||
{
|
||||
sc_spu.Warning("sys_spu_thread_set_argument(id=0x%x, arg_addr=0x%x)", id, arg_addr);
|
||||
PPCThread* thr = Emu.GetCPU().GetThread(id);
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(id);
|
||||
|
||||
if(!thr || thr->GetType() == PPC_THREAD_PPU)
|
||||
if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
@ -268,8 +268,8 @@ int sys_raw_spu_create(u32 id_addr, u32 attr_addr)
|
||||
sc_spu.Warning("sys_raw_spu_create(id_addr=0x%x, attr_addr=0x%x)", id_addr, attr_addr);
|
||||
|
||||
//Emu.GetIdManager().GetNewID("sys_raw_spu", new u32(attr_addr));
|
||||
PPCThread& new_thread = Emu.GetCPU().AddThread(PPC_THREAD_RAW_SPU);
|
||||
Memory.Write32(id_addr, Emu.GetCPU().GetThreadNumById(PPC_THREAD_RAW_SPU, new_thread.GetId()));
|
||||
CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_RAW_SPU);
|
||||
Memory.Write32(id_addr, ((RawSPUThread&)new_thread).GetIndex());
|
||||
new_thread.Run();
|
||||
new_thread.Exec();
|
||||
|
||||
@ -286,10 +286,10 @@ int sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu)
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
if(!Memory.InitSpuRawMem(max_raw_spu))
|
||||
{
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
//if(!Memory.InitSpuRawMem(max_raw_spu))
|
||||
//{
|
||||
// return CELL_ENOMEM;
|
||||
//}
|
||||
|
||||
//enable_log = true;
|
||||
//dump_enable = true;
|
||||
@ -303,9 +303,9 @@ int sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type)
|
||||
sc_spu.Warning("sys_spu_thread_write_ls(id=0x%x, address=0x%x, value=0x%llx, type=0x%x)",
|
||||
id, address, value, type);
|
||||
|
||||
PPCThread* thr = Emu.GetCPU().GetThread(id);
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(id);
|
||||
|
||||
if(!thr || thr->GetType() == PPC_THREAD_PPU)
|
||||
if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
@ -321,9 +321,9 @@ int sys_spu_thread_read_ls(u32 id, u32 address, u32 value_addr, u32 type)
|
||||
sc_spu.Warning("sys_spu_thread_read_ls(id=0x%x, address=0x%x, value_addr=0x%x, type=0x%x)",
|
||||
id, address, value_addr, type);
|
||||
|
||||
PPCThread* thr = Emu.GetCPU().GetThread(id);
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(id);
|
||||
|
||||
if(!thr || thr->GetType() == PPC_THREAD_PPU)
|
||||
if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
@ -343,14 +343,14 @@ int sys_spu_thread_write_spu_mb(u32 id, u32 value)
|
||||
{
|
||||
sc_spu.Warning("sys_spu_thread_write_spu_mb(id=0x%x, value=0x%x)", id, value);
|
||||
|
||||
PPCThread* thr = Emu.GetCPU().GetThread(id);
|
||||
CPUThread* thr = Emu.GetCPU().GetThread(id);
|
||||
|
||||
if(!thr || !thr->GetType() == PPC_THREAD_PPU)
|
||||
if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if(!(*(SPUThread*)thr).mfc.SPU_In_MBox.Push(value))
|
||||
if(!(*(SPUThread*)thr).SPU.In_MBox.Push(value))
|
||||
{
|
||||
ConLog.Warning("sys_spu_thread_write_spu_mb(id=0x%x, value=0x%x): used all mbox items.");
|
||||
return CELL_EBUSY; //?
|
||||
|
@ -3,7 +3,6 @@
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Ini.h"
|
||||
|
||||
#include "Emu/Cell/PPCThreadManager.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "Emu/Cell/SPUThread.h"
|
||||
#include "Emu/Cell/PPUInstrTable.h"
|
||||
@ -44,7 +43,7 @@ void Emulator::SetPath(const wxString& path, const wxString& elf_path)
|
||||
|
||||
void Emulator::CheckStatus()
|
||||
{
|
||||
ArrayF<PPCThread>& threads = GetCPU().GetThreads();
|
||||
ArrayF<CPUThread>& threads = GetCPU().GetThreads();
|
||||
if(!threads.GetCount())
|
||||
{
|
||||
Stop();
|
||||
@ -83,7 +82,6 @@ void Emulator::Load()
|
||||
{
|
||||
if(!wxFileExists(m_path)) return;
|
||||
ConLog.Write("Loading '%s'...", m_path);
|
||||
Memory.Init();
|
||||
GetInfo().Reset();
|
||||
m_vfs.Init(m_path);
|
||||
//m_vfs.Mount("/", vfsDevice::GetRoot(m_path), new vfsLocalFile());
|
||||
@ -117,7 +115,19 @@ void Emulator::Load()
|
||||
|
||||
try
|
||||
{
|
||||
is_error = !l.Load() || l.GetMachine() == MACHINE_Unknown;
|
||||
if(!(is_error = !l.Analyze() || l.GetMachine() == MACHINE_Unknown))
|
||||
{
|
||||
switch(l.GetMachine())
|
||||
{
|
||||
case MACHINE_SPU:
|
||||
case MACHINE_PPC64:
|
||||
Memory.Init(Memory_PS3);
|
||||
break;
|
||||
}
|
||||
|
||||
is_error = !l.Load();
|
||||
}
|
||||
|
||||
}
|
||||
catch(const wxString& e)
|
||||
{
|
||||
@ -130,6 +140,21 @@ void Emulator::Load()
|
||||
is_error = true;
|
||||
}
|
||||
|
||||
CPUThreadType thread_type;
|
||||
|
||||
if(!is_error)
|
||||
{
|
||||
switch(l.GetMachine())
|
||||
{
|
||||
case MACHINE_PPC64: thread_type = CPU_THREAD_PPU; break;
|
||||
case MACHINE_SPU: thread_type = CPU_THREAD_SPU; break;
|
||||
|
||||
default:
|
||||
is_error = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(is_error)
|
||||
{
|
||||
Memory.Close();
|
||||
@ -138,17 +163,20 @@ void Emulator::Load()
|
||||
}
|
||||
|
||||
LoadPoints(BreakPointsDBName);
|
||||
PPCThread& thread = GetCPU().AddThread(l.GetMachine() == MACHINE_PPC64 ? PPC_THREAD_PPU : PPC_THREAD_SPU);
|
||||
|
||||
if(l.GetMachine() == MACHINE_SPU)
|
||||
CPUThread& thread = GetCPU().AddThread(thread_type);
|
||||
|
||||
switch(l.GetMachine())
|
||||
{
|
||||
case MACHINE_SPU:
|
||||
ConLog.Write("offset = 0x%llx", Memory.MainMem.GetStartAddr());
|
||||
ConLog.Write("max addr = 0x%x", l.GetMaxAddr());
|
||||
thread.SetOffset(Memory.MainMem.GetStartAddr());
|
||||
Memory.MainMem.Alloc(Memory.MainMem.GetStartAddr() + l.GetMaxAddr(), 0xFFFFED - l.GetMaxAddr());
|
||||
thread.SetEntry(l.GetEntry() - Memory.MainMem.GetStartAddr());
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
case MACHINE_PPC64:
|
||||
{
|
||||
thread.SetEntry(l.GetEntry());
|
||||
Memory.StackMem.Alloc(0x1000);
|
||||
@ -172,6 +200,12 @@ void Emulator::Load()
|
||||
ppu_thr_exit_data += SC(2);
|
||||
ppu_thr_exit_data += BCLR(0x10 | 0x04, 0, 0, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
thread.SetEntry(l.GetEntry());
|
||||
break;
|
||||
}
|
||||
|
||||
if(!m_dbg_console)
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Gui/MemoryViewer.h"
|
||||
#include "Emu/Cell/PPCThreadManager.h"
|
||||
#include "Emu/CPU/CPUThreadManager.h"
|
||||
#include "Emu/Io/Pad.h"
|
||||
#include "Emu/Io/Keyboard.h"
|
||||
#include "Emu/Io/Mouse.h"
|
||||
@ -78,7 +78,7 @@ class Emulator
|
||||
Array<u64> m_break_points;
|
||||
Array<u64> m_marked_points;
|
||||
|
||||
PPCThreadManager m_thread_manager;
|
||||
CPUThreadManager m_thread_manager;
|
||||
PadManager m_pad_manager;
|
||||
KeyboardManager m_keyboard_manager;
|
||||
MouseManager m_mouse_manager;
|
||||
@ -109,7 +109,7 @@ public:
|
||||
return std::shared_ptr<vfsStream>(m_vfs.Open(path, mode));
|
||||
}
|
||||
|
||||
PPCThreadManager& GetCPU() { return m_thread_manager; }
|
||||
CPUThreadManager& GetCPU() { return m_thread_manager; }
|
||||
PadManager& GetPadManager() { return m_pad_manager; }
|
||||
KeyboardManager& GetKeyboardManager() { return m_keyboard_manager; }
|
||||
MouseManager& GetMouseManager() { return m_mouse_manager; }
|
||||
|
@ -24,7 +24,7 @@ struct EventPort
|
||||
u64 data2;
|
||||
u64 data3;
|
||||
bool has_data;
|
||||
PPCThread* thread;
|
||||
CPUThread* thread;
|
||||
EventQueue* queue[127];
|
||||
int pos;
|
||||
};
|
||||
|
@ -87,7 +87,7 @@ void DisAsmFrame::AddLine(const wxString line)
|
||||
{
|
||||
if(Emu.IsRunning()) Emu.Pause();
|
||||
finished = true;
|
||||
CPU.PrevPc();
|
||||
CPU.PC -= 4;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -113,8 +113,8 @@ bool ElfType64 = false;
|
||||
class DumperThread : public ThreadBase
|
||||
{
|
||||
volatile uint id;
|
||||
PPC_DisAsm* disasm;
|
||||
PPC_Decoder* decoder;
|
||||
PPCDisAsm* disasm;
|
||||
PPCDecoder* decoder;
|
||||
volatile bool* done;
|
||||
volatile u8 cores;
|
||||
MTProgressDialog* prog_dial;
|
||||
@ -135,16 +135,16 @@ public:
|
||||
|
||||
*done = false;
|
||||
|
||||
if(Emu.GetCPU().GetThreads()[0].GetType() != PPC_THREAD_PPU)
|
||||
if(Emu.GetCPU().GetThreads()[0].GetType() != CPU_THREAD_PPU)
|
||||
{
|
||||
SPU_DisAsm& dis_asm = *new SPU_DisAsm(*(PPCThread*)NULL, DumpMode);
|
||||
decoder = new SPU_Decoder(dis_asm);
|
||||
SPUDisAsm& dis_asm = *new SPUDisAsm(CPUDisAsm_DumpMode);
|
||||
decoder = new SPUDecoder(dis_asm);
|
||||
disasm = &dis_asm;
|
||||
}
|
||||
else
|
||||
{
|
||||
PPU_DisAsm& dis_asm = *new PPU_DisAsm(*(PPCThread*)NULL, DumpMode);
|
||||
decoder = new PPU_Decoder(dis_asm);
|
||||
PPUDisAsm& dis_asm = *new PPUDisAsm(CPUDisAsm_DumpMode);
|
||||
decoder = new PPUDecoder(dis_asm);
|
||||
disasm = &dis_asm;
|
||||
}
|
||||
}
|
||||
@ -338,21 +338,28 @@ void DisAsmFrame::Dump(wxCommandEvent& WXUNUSED(event))
|
||||
default: ConLog.Error("Corrupted ELF!"); return;
|
||||
}
|
||||
|
||||
PPC_DisAsm* disasm;
|
||||
PPC_Decoder* decoder;
|
||||
PPCDisAsm* disasm;
|
||||
PPCDecoder* decoder;
|
||||
|
||||
if(Emu.GetCPU().GetThreads()[0].GetType() != PPC_THREAD_PPU)
|
||||
switch(Emu.GetCPU().GetThreads()[0].GetType())
|
||||
{
|
||||
SPU_DisAsm& dis_asm = *new SPU_DisAsm(*(PPCThread*)NULL, DumpMode);
|
||||
decoder = new SPU_Decoder(dis_asm);
|
||||
case CPU_THREAD_PPU:
|
||||
{
|
||||
PPUDisAsm& dis_asm = *new PPUDisAsm(CPUDisAsm_DumpMode);
|
||||
decoder = new PPUDecoder(dis_asm);
|
||||
disasm = &dis_asm;
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
case CPU_THREAD_SPU:
|
||||
case CPU_THREAD_RAW_SPU:
|
||||
{
|
||||
PPU_DisAsm& dis_asm = *new PPU_DisAsm(*(PPCThread*)NULL, DumpMode);
|
||||
decoder = new PPU_Decoder(dis_asm);
|
||||
SPUDisAsm& dis_asm = *new SPUDisAsm(CPUDisAsm_DumpMode);
|
||||
decoder = new SPUDecoder(dis_asm);
|
||||
disasm = &dis_asm;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
const u32 shdr_count = ElfType64 ? shdr_arr_64->GetCount() : shdr_arr_32->GetCount();
|
||||
|
||||
|
@ -2,8 +2,8 @@ class InstructionEditorDialog
|
||||
: public wxDialog
|
||||
{
|
||||
u64 pc;
|
||||
PPC_DisAsm* disasm;
|
||||
PPC_Decoder* decoder;
|
||||
PPCDisAsm* disasm;
|
||||
PPCDecoder* decoder;
|
||||
wxTextCtrl* t2_instr;
|
||||
wxStaticText* t3_preview;
|
||||
|
||||
@ -11,12 +11,12 @@ public:
|
||||
PPCThread* CPU;
|
||||
|
||||
public:
|
||||
InstructionEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPC_Decoder* _decoder, PPC_DisAsm* _disasm);
|
||||
InstructionEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPCDecoder* _decoder, PPCDisAsm* _disasm);
|
||||
|
||||
void updatePreview(wxCommandEvent& event);
|
||||
};
|
||||
|
||||
InstructionEditorDialog::InstructionEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPC_Decoder* _decoder, PPC_DisAsm* _disasm)
|
||||
InstructionEditorDialog::InstructionEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPCDecoder* _decoder, PPCDisAsm* _disasm)
|
||||
: wxDialog(parent, wxID_ANY, "Edit instruction", wxDefaultPosition)
|
||||
, pc(_pc)
|
||||
, CPU(_CPU)
|
||||
|
@ -110,18 +110,25 @@ void InterpreterDisAsmFrame::OnSelectUnit(wxCommandEvent& event)
|
||||
|
||||
if(CPU)
|
||||
{
|
||||
if(CPU->GetType() != PPC_THREAD_PPU)
|
||||
switch(CPU->GetType())
|
||||
{
|
||||
SPU_DisAsm& dis_asm = *new SPU_DisAsm(*CPU, InterpreterMode);
|
||||
decoder = new SPU_Decoder(dis_asm);
|
||||
case CPU_THREAD_PPU:
|
||||
{
|
||||
PPUDisAsm& dis_asm = *new PPUDisAsm(CPUDisAsm_InterpreterMode);
|
||||
decoder = new PPUDecoder(dis_asm);
|
||||
disasm = &dis_asm;
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
case CPU_THREAD_SPU:
|
||||
case CPU_THREAD_RAW_SPU:
|
||||
{
|
||||
PPU_DisAsm& dis_asm = *new PPU_DisAsm(*CPU, InterpreterMode);
|
||||
decoder = new PPU_Decoder(dis_asm);
|
||||
SPUDisAsm& dis_asm = *new SPUDisAsm(CPUDisAsm_InterpreterMode);
|
||||
decoder = new SPUDecoder(dis_asm);
|
||||
disasm = &dis_asm;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoUpdate();
|
||||
|
@ -8,8 +8,8 @@
|
||||
class InterpreterDisAsmFrame : public wxPanel
|
||||
{
|
||||
wxListView* m_list;
|
||||
PPC_DisAsm* disasm;
|
||||
PPC_Decoder* decoder;
|
||||
PPCDisAsm* disasm;
|
||||
PPCDecoder* decoder;
|
||||
u64 PC;
|
||||
Array<u32> remove_markedPC;
|
||||
wxTextCtrl* m_regs;
|
||||
|
@ -1,9 +1,8 @@
|
||||
class RegisterEditorDialog
|
||||
: public wxDialog
|
||||
class RegisterEditorDialog : public wxDialog
|
||||
{
|
||||
u64 pc;
|
||||
PPC_DisAsm* disasm;
|
||||
PPC_Decoder* decoder;
|
||||
PPCDisAsm* disasm;
|
||||
PPCDecoder* decoder;
|
||||
wxComboBox* t1_register;
|
||||
wxTextCtrl* t2_value;
|
||||
wxStaticText* t3_preview;
|
||||
@ -12,13 +11,13 @@ public:
|
||||
PPCThread* CPU;
|
||||
|
||||
public:
|
||||
RegisterEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPC_Decoder* _decoder, PPC_DisAsm* _disasm);
|
||||
RegisterEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPCDecoder* _decoder, PPCDisAsm* _disasm);
|
||||
|
||||
void updateRegister(wxCommandEvent& event);
|
||||
void updatePreview(wxCommandEvent& event);
|
||||
};
|
||||
|
||||
RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPC_Decoder* _decoder, PPC_DisAsm* _disasm)
|
||||
RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPCDecoder* _decoder, PPCDisAsm* _disasm)
|
||||
: wxDialog(parent, wxID_ANY, "Edit registers", wxDefaultPosition)
|
||||
, pc(_pc)
|
||||
, CPU(_CPU)
|
||||
@ -64,10 +63,11 @@ RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u64 _pc, PPCThread*
|
||||
s_panel_margin_x->Add(s_panel_margin_y);
|
||||
s_panel_margin_x->AddSpacer(12);
|
||||
|
||||
this->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(RegisterEditorDialog::updateRegister));
|
||||
Connect(wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(RegisterEditorDialog::updateRegister));
|
||||
|
||||
if (CPU->GetType() == PPC_THREAD_PPU)
|
||||
switch(CPU->GetType())
|
||||
{
|
||||
case CPU_THREAD_PPU:
|
||||
for (int i=0; i<32; i++) t1_register->Append(wxString::Format("GPR[%d]",i));
|
||||
for (int i=0; i<32; i++) t1_register->Append(wxString::Format("FPR[%d]",i));
|
||||
for (int i=0; i<32; i++) t1_register->Append(wxString::Format("VPR[%d]",i));
|
||||
@ -76,20 +76,17 @@ RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u64 _pc, PPCThread*
|
||||
t1_register->Append("CTR");
|
||||
t1_register->Append("XER");
|
||||
t1_register->Append("FPSCR");
|
||||
}
|
||||
if (CPU->GetType() == PPC_THREAD_SPU)
|
||||
{
|
||||
break;
|
||||
|
||||
case CPU_THREAD_SPU:
|
||||
case CPU_THREAD_RAW_SPU:
|
||||
for (int i=0; i<128; i++) t1_register->Append(wxString::Format("GPR[%d]",i));
|
||||
}
|
||||
if (CPU->GetType() == PPC_THREAD_RAW_SPU)
|
||||
{
|
||||
wxMessageBox("RawSPU threads not yet supported.","Error");
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
this->SetSizerAndFit(s_panel_margin_x);
|
||||
SetSizerAndFit(s_panel_margin_x);
|
||||
|
||||
if(this->ShowModal() == wxID_OK)
|
||||
if(ShowModal() == wxID_OK)
|
||||
{
|
||||
wxString reg = t1_register->GetStringSelection();
|
||||
wxString value = t2_value->GetValue();
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include "PSF.h"
|
||||
#include "Emu/FS/vfsLocalFile.h"
|
||||
|
||||
static const u64 g_spu_offset = 0x10000;
|
||||
|
||||
const wxString Ehdr_DataToString(const u8 data)
|
||||
{
|
||||
if(data > 1) return wxString::Format("%d's complement, big endian", data);
|
||||
@ -39,7 +41,7 @@ const wxString Ehdr_MachineToString(const u16 machine)
|
||||
{
|
||||
switch(machine)
|
||||
{
|
||||
case MACHINE_MIPS: return "MIPS";
|
||||
case MACHINE_MIPS: return "MIPS";
|
||||
case MACHINE_PPC64: return "PowerPC64";
|
||||
case MACHINE_SPU: return "SPU";
|
||||
};
|
||||
@ -92,14 +94,24 @@ const wxString Phdr_TypeToString(const u32 type)
|
||||
return wxString::Format("Unknown (%x)", type);
|
||||
}
|
||||
|
||||
Loader::Loader() : m_stream(nullptr)
|
||||
Loader::Loader()
|
||||
: m_stream(nullptr)
|
||||
, m_loader(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Loader::Loader(vfsFileBase& stream) : m_stream(&stream)
|
||||
Loader::Loader(vfsFileBase& stream)
|
||||
: m_stream(&stream)
|
||||
, m_loader(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Loader::~Loader()
|
||||
{
|
||||
delete m_loader;
|
||||
m_loader = nullptr;
|
||||
}
|
||||
|
||||
void Loader::Open(vfsFileBase& stream)
|
||||
{
|
||||
m_stream = &stream;
|
||||
@ -120,27 +132,35 @@ LoaderBase* Loader::SearchLoader()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Loader::Load()
|
||||
bool Loader::Analyze()
|
||||
{
|
||||
static const u64 spu_offset = 0x10000;
|
||||
delete m_loader;
|
||||
|
||||
ScopedPtr<LoaderBase> l = SearchLoader();
|
||||
m_loader = SearchLoader();
|
||||
|
||||
if(!l)
|
||||
if(!m_loader)
|
||||
{
|
||||
ConLog.Error("Unknown file type");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!l->LoadData(l->GetMachine() == MACHINE_SPU ? spu_offset : 0))
|
||||
machine = m_loader->GetMachine();
|
||||
entry = m_loader->GetMachine() == MACHINE_SPU ? m_loader->GetEntry() + g_spu_offset : m_loader->GetEntry();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Loader::Load()
|
||||
{
|
||||
if(!m_loader)
|
||||
return false;
|
||||
|
||||
if(!m_loader->LoadData(m_loader->GetMachine() == MACHINE_SPU ? g_spu_offset : 0))
|
||||
{
|
||||
ConLog.Error("Broken file");
|
||||
return false;
|
||||
}
|
||||
|
||||
machine = l->GetMachine();
|
||||
entry = l->GetMachine() == MACHINE_SPU ? l->GetEntry() + spu_offset : l->GetEntry();
|
||||
|
||||
const wxString& root = wxFileName(wxFileName(m_stream->GetPath()).GetPath()).GetPath();
|
||||
const wxString& psf_path = root + "\\" + "PARAM.SFO";
|
||||
if(wxFileExists(psf_path))
|
||||
|
@ -105,17 +105,16 @@ __forceinline static void Write16LE(wxFile& f, const u16 data)
|
||||
|
||||
__forceinline static void Write32LE(wxFile& f, const u32 data)
|
||||
{
|
||||
Write16(f, data);
|
||||
Write16(f, data >> 16);
|
||||
Write16LE(f, data);
|
||||
Write16LE(f, data >> 16);
|
||||
}
|
||||
|
||||
__forceinline static void Write64LE(wxFile& f, const u64 data)
|
||||
{
|
||||
Write32(f, data);
|
||||
Write32(f, data >> 32);
|
||||
Write32LE(f, data);
|
||||
Write32LE(f, data >> 32);
|
||||
}
|
||||
|
||||
|
||||
const wxString Ehdr_DataToString(const u8 data);
|
||||
const wxString Ehdr_TypeToString(const u16 type);
|
||||
const wxString Ehdr_OS_ABIToString(const u8 os_abi);
|
||||
@ -194,6 +193,7 @@ public:
|
||||
virtual bool LoadInfo() { return false; }
|
||||
virtual bool LoadData(u64 offset = 0) { return false; }
|
||||
Elf_Machine GetMachine() { return machine; }
|
||||
|
||||
u32 GetEntry() { return entry; }
|
||||
u32 GetMinAddr() { return min_addr; }
|
||||
u32 GetMaxAddr() { return min_addr; }
|
||||
@ -202,13 +202,16 @@ public:
|
||||
class Loader : public LoaderBase
|
||||
{
|
||||
vfsFileBase* m_stream;
|
||||
LoaderBase* m_loader;
|
||||
|
||||
public:
|
||||
Loader();
|
||||
Loader(vfsFileBase& stream);
|
||||
~Loader();
|
||||
|
||||
void Open(const wxString& path);
|
||||
void Open(vfsFileBase& stream);
|
||||
bool Analyze();
|
||||
|
||||
bool Load();
|
||||
|
||||
|
@ -45,7 +45,7 @@ void Rpcs3App::Exit()
|
||||
wxApp::Exit();
|
||||
}
|
||||
|
||||
void Rpcs3App::SendDbgCommand(DbgCommand id, PPCThread* thr)
|
||||
void Rpcs3App::SendDbgCommand(DbgCommand id, CPUThread* thr)
|
||||
{
|
||||
wxCommandEvent event(wxEVT_DBG_COMMAND, id);
|
||||
event.SetClientData(thr);
|
||||
|
@ -61,7 +61,7 @@ public:
|
||||
virtual bool OnInit();
|
||||
virtual void Exit();
|
||||
|
||||
void SendDbgCommand(DbgCommand id, PPCThread* thr=nullptr);
|
||||
void SendDbgCommand(DbgCommand id, CPUThread* thr=nullptr);
|
||||
};
|
||||
|
||||
DECLARE_APP(Rpcs3App)
|
||||
|
@ -104,11 +104,13 @@
|
||||
<Optimization>Disabled</Optimization>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>adv.lib;base.lib;core.lib;aui.lib;wxtiff.lib;wxjpeg.lib;wxpng.lib;wxzlib.lib;odbc32.lib;odbccp32.lib;comctl32.lib;ws2_32.lib;shlwapi.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
<DataExecutionPrevention>false</DataExecutionPrevention>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>
|
||||
@ -126,6 +128,7 @@
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>adv.lib;base.lib;core.lib;aui.lib;wxtiff.lib;wxjpeg.lib;wxpng.lib;wxzlib.lib;odbc32.lib;odbccp32.lib;comctl32.lib;ws2_32.lib;shlwapi.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
<DataExecutionPrevention>false</DataExecutionPrevention>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>$(SolutionDir)\Utilities\git-version-gen.cmd</Command>
|
||||
@ -156,6 +159,7 @@
|
||||
<IgnoreAllDefaultLibraries>
|
||||
</IgnoreAllDefaultLibraries>
|
||||
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
<DataExecutionPrevention>false</DataExecutionPrevention>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>
|
||||
@ -187,6 +191,7 @@
|
||||
<IgnoreAllDefaultLibraries>
|
||||
</IgnoreAllDefaultLibraries>
|
||||
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
<DataExecutionPrevention>false</DataExecutionPrevention>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>
|
||||
@ -196,13 +201,15 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\Utilities\Thread.cpp" />
|
||||
<ClCompile Include="AppConnector.cpp" />
|
||||
<ClCompile Include="Emu\ARM9\ARM9Thread.cpp" />
|
||||
<ClCompile Include="Emu\Cell\MFC.cpp" />
|
||||
<ClCompile Include="Emu\Cell\PPCThread.cpp" />
|
||||
<ClCompile Include="Emu\Cell\PPCThreadManager.cpp" />
|
||||
<ClCompile Include="Emu\Cell\PPUProgramCompiler.cpp" />
|
||||
<ClCompile Include="Emu\Cell\PPUThread.cpp" />
|
||||
<ClCompile Include="Emu\Cell\RawSPUThread.cpp" />
|
||||
<ClCompile Include="Emu\Cell\SPUThread.cpp" />
|
||||
<ClCompile Include="Emu\CPU\CPUThread.cpp" />
|
||||
<ClCompile Include="Emu\CPU\CPUThreadManager.cpp" />
|
||||
<ClCompile Include="Emu\DbgConsole.cpp" />
|
||||
<ClCompile Include="Emu\FS\VFS.cpp" />
|
||||
<ClCompile Include="Emu\FS\vfsDevice.cpp" />
|
||||
|
@ -17,9 +17,6 @@
|
||||
<UniqueIdentifier>{adfec460-d940-4482-9fdb-18cb0814c3d5}</UniqueIdentifier>
|
||||
<ParseFiles>true</ParseFiles>
|
||||
</Filter>
|
||||
<Filter Include="Emu\CPU">
|
||||
<UniqueIdentifier>{f66e37f9-5e58-443b-bcff-2e9e002ac89e}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Loader">
|
||||
<UniqueIdentifier>{6c36f15e-07fd-45d6-a81c-1ab43ee1b58b}</UniqueIdentifier>
|
||||
</Filter>
|
||||
@ -47,6 +44,15 @@
|
||||
<Filter Include="Emu\HDD">
|
||||
<UniqueIdentifier>{718bc358-b7ef-4988-8547-2148d14bb08b}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Emu\Cell">
|
||||
<UniqueIdentifier>{f66e37f9-5e58-443b-bcff-2e9e002ac89e}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Emu\CPU">
|
||||
<UniqueIdentifier>{041a844e-9f8b-4b4b-a4c5-6c72ecbde475}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Emu\ARM9">
|
||||
<UniqueIdentifier>{bee6a4b4-6371-4c1b-8558-fc7888b1574e}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="rpcs3.cpp">
|
||||
@ -116,13 +122,10 @@
|
||||
<Filter>Loader</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\Cell\PPCThread.cpp">
|
||||
<Filter>Emu\CPU</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\Cell\PPCThreadManager.cpp">
|
||||
<Filter>Emu\CPU</Filter>
|
||||
<Filter>Emu\Cell</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\Cell\SPUThread.cpp">
|
||||
<Filter>Emu\CPU</Filter>
|
||||
<Filter>Emu\Cell</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\SysCalls\FuncList.cpp">
|
||||
<Filter>Emu\SysCalls</Filter>
|
||||
@ -188,7 +191,7 @@
|
||||
<Filter>Emu\GS</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\Cell\PPUThread.cpp">
|
||||
<Filter>Emu\CPU</Filter>
|
||||
<Filter>Emu\Cell</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\SysCalls\lv2\SC_Time.cpp">
|
||||
<Filter>Emu\SysCalls\lv2</Filter>
|
||||
@ -251,7 +254,7 @@
|
||||
<Filter>rpcs3</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\Cell\PPUProgramCompiler.cpp">
|
||||
<Filter>Emu\CPU</Filter>
|
||||
<Filter>Emu\Cell</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\SysCalls\lv2\SC_Event.cpp">
|
||||
<Filter>Emu\SysCalls\lv2</Filter>
|
||||
@ -263,10 +266,10 @@
|
||||
<Filter>Emu\SysCalls\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\Cell\RawSPUThread.cpp">
|
||||
<Filter>Emu\CPU</Filter>
|
||||
<Filter>Emu\Cell</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\Cell\MFC.cpp">
|
||||
<Filter>Emu\CPU</Filter>
|
||||
<Filter>Emu\Cell</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\HDD\HDD.cpp">
|
||||
<Filter>Emu\HDD</Filter>
|
||||
@ -310,6 +313,15 @@
|
||||
<ClCompile Include="Emu\FS\vfsFile.cpp">
|
||||
<Filter>Emu\FS</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\CPU\CPUThread.cpp">
|
||||
<Filter>Emu\CPU</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\CPU\CPUThreadManager.cpp">
|
||||
<Filter>Emu\CPU</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARM9\ARM9Thread.cpp">
|
||||
<Filter>Emu\ARM9</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="rpcs3.rc" />
|
||||
|
Loading…
Reference in New Issue
Block a user