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

Merge pull request #1 from DHrpcs3/wip

Wip
This commit is contained in:
DHrpcs3 2013-08-26 07:27:35 -07:00
commit 555ad9472a
115 changed files with 10883 additions and 2539 deletions

2014
GL/glext.h

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
template<typename T> class Array
{
protected:
u32 m_count;
T* m_array;
@ -87,11 +88,14 @@ public:
return m_count - 1;
}
inline bool AddCpy(const u32 pos, const T* data, u64 count = 1)
inline bool AddCpy(const u32 pos, const T* data, u32 count = 1)
{
if(!InsertRoom(pos, count)) return false;
memcpy(m_array + pos, data, sizeof(T) * count);
for(u32 i=0; i<count; ++i)
{
new (m_array + pos + i) T(data[i]);
}
return true;
}
@ -101,11 +105,14 @@ public:
return AddCpy(pos, &data);
}
inline u32 AddCpy(const T* data, u64 count = 1)
inline u32 AddCpy(const T* data, u32 count = 1)
{
_InsertRoomEnd(count);
memcpy(m_array + m_count - count, data, sizeof(T)*count);
for(u32 i=0; i<count; ++i)
{
new (m_array + m_count - count + i) T(data[i]);
}
return m_count - count;
}
@ -120,7 +127,13 @@ public:
u32 count = m_count;
m_count = 0;
for(u32 i=0; i<count; ++i) m_array[i].~T();
safe_delete(m_array);
safe_free(m_array);
}
inline void ClearF()
{
m_count = 0;
safe_free(m_array);
}
inline T& Get(u32 num)
@ -129,15 +142,15 @@ public:
return m_array[num];
}
u32 GetCount() const { return m_count; }
virtual u32 GetCount() const { return m_count; }
void SetCount(const u32 count, bool memzero = true)
virtual void SetCount(const u32 count, bool memzero = true)
{
if(GetCount() >= count) return;
_InsertRoomEnd(count - GetCount());
if(m_count >= count) return;
if(memzero) memset(m_array + GetCount(), 0, count - GetCount());
_InsertRoomEnd(count - m_count);
if(memzero) memset(m_array + m_count - count, 0, sizeof(T) * (m_count - count));
}
void Reserve(const u32 count)
@ -162,6 +175,7 @@ public:
}
inline T* GetPtr() { return m_array; }
inline const T* GetPtr() const { return m_array; }
T& operator[](u32 num) const { return m_array[num]; }
@ -185,6 +199,96 @@ protected:
}
};
class ArrayString : public Array<char>
{
public:
ArrayString() : Array()
{
}
ArrayString(const wxString& value) : Array()
{
*this = value;
}
ArrayString(const char* value) : Array()
{
*this = value;
}
virtual u32 GetCount() const
{
return m_array ? strlen(m_array) : 0;
}
virtual void SetCount(const u32 count, bool memzero = true)
{
if(m_count && count < m_count - 1)
{
m_array[count] = '\0';
}
else
{
Array::SetCount(count + 1, memzero);
}
}
ArrayString& operator = (const char* right)
{
Clear();
if(right)
{
size_t len = strlen(right);
if(len)
{
SetCount(len);
memcpy(m_array, right, len * sizeof(char));
m_array[len] = '\0';
}
}
return *this;
}
ArrayString& operator = (const ArrayString& right)
{
Clear();
if(size_t len = right.GetCount())
{
SetCount(len);
memcpy(m_array, right.GetPtr(), len * sizeof(char));
m_array[len] = '\0';
}
return *this;
}
ArrayString& operator = (const wxString& right)
{
Clear();
if(size_t len = right.Len())
{
SetCount(len);
memcpy(m_array, right.c_str(), len * sizeof(char));
m_array[len] = '\0';
}
return *this;
}
ArrayString* Clone() const
{
ArrayString* new_array = new ArrayString();
(*new_array) = m_array;
return new_array;
}
};
template<typename T> struct Stack : public Array<T>
{
Stack() : Array<T>()
@ -209,6 +313,61 @@ template<typename T> struct Stack : public Array<T>
}
};
template<typename T, size_t size> class SizedStack
{
T m_ptr[size];
uint m_count;
public:
SizedStack()
{
Clear();
}
~SizedStack()
{
Clear();
}
void Clear()
{
m_count = 0;
}
bool Pop(T& dst)
{
if(!m_count)
return false;
dst = m_ptr[--m_count];
return true;
}
bool Push(const T& src)
{
if(m_count + 1 > size)
return false;
m_ptr[m_count++] = src;
return true;
}
size_t GetFreeCount() const
{
return size - m_count;
}
size_t GetCount() const
{
return m_count;
}
size_t GetMaxCount() const
{
return size;
}
};
template<typename T> class ArrayF
{
u32 m_count;

View File

@ -1,5 +1,9 @@
#pragma once
#include "Array.h"
#include <functional>
#include <thread>
#include <mutex>
#include <condition_variable>
class ThreadExec;
@ -59,7 +63,7 @@ public:
m_parent = nullptr;
//if(wait)
if(wait)
{
Delete();
//wxCriticalSectionLocker lock(m_wait_for_exit);

Binary file not shown.

Binary file not shown.

2
rpcs3/Emu/Cell/MFC.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "stdafx.h"
#include "MFC.h"

252
rpcs3/Emu/Cell/MFC.h Normal file
View File

@ -0,0 +1,252 @@
#pragma once
#include <atomic>
enum
{
MFC_PUT_CMD = 0x20,
MFC_GET_CMD = 0x40,
MFC_MASK_CMD = 0xffff,
};
enum
{
MFC_SPU_TO_PPU_MAILBOX_STATUS_MASK = 0x000000FF,
MFC_SPU_TO_PPU_MAILBOX_STATUS_SHIFT = 0x0,
MFC_PPU_TO_SPU_MAILBOX_STATUS_MASK = 0x0000FF00,
MFC_PPU_TO_SPU_MAILBOX_STATUS_SHIFT = 0x8,
MFC_PPU_TO_SPU_MAILBOX_MAX = 0x4,
MFC_SPU_TO_PPU_INT_MAILBOX_STATUS_MASK = 0x00FF0000,
MFC_SPU_TO_PPU_INT_MAILBOX_STATUS_SHIFT = 0x10,
};
enum
{
MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL = 0x00,
MFC_PPU_DMA_CMD_SEQUENCE_ERROR = 0x01,
MFC_PPU_DMA_QUEUE_FULL = 0x02,
};
enum
{
MFC_PPU_MAX_QUEUE_SPACE = 0x08,
MFC_SPU_MAX_QUEUE_SPACE = 0x10,
};
struct DMAC_Queue
{
bool is_valid;
u64 ea;
u32 lsa;
u16 size;
u32 op;
u8 tag;
u8 rt;
u16 list_addr;
u16 list_size;
u32 dep_state;
u32 cmd;
u32 dep_type;
};
struct DMAC_Proxy
{
u64 ea;
u32 lsa;
u16 size;
u32 op;
u8 tag;
u8 rt;
u16 list_addr;
u16 list_size;
u32 dep_state;
u32 cmd;
u32 dep_type;
};
template<size_t _max_count>
class SPUReg
{
u64 m_addr;
u32 m_pos;
public:
static const size_t max_count = _max_count;
static const size_t size = max_count * 4;
SPUReg()
{
Init();
}
void Init()
{
m_pos = 0;
}
void SetAddr(u64 addr)
{
m_addr = addr;
}
u64 GetAddr() const
{
return m_addr;
}
__forceinline bool Pop(u32& res)
{
if(!m_pos) return false;
res = Memory.Read32(m_addr + m_pos--);
return true;
}
__forceinline bool Push(u32 value)
{
if(m_pos >= max_count) return false;
Memory.Write32(m_addr + m_pos++, value);
return true;
}
u32 GetCount() const
{
return m_pos;
}
u32 GetFreeCount() const
{
return max_count - m_pos;
}
void SetValue(u32 value)
{
Memory.Write32(m_addr, value);
}
u32 GetValue() const
{
return Memory.Read32(m_addr);
}
};
struct DMAC
{
DMAC_Queue queue[MFC_SPU_MAX_QUEUE_SPACE];
DMAC_Proxy proxy[MFC_PPU_MAX_QUEUE_SPACE];
u64 ls_offset;
std::atomic<u32> queue_pos;
std::atomic<u32> proxy_pos;
u32 Cmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
{
if(!Memory.IsGoodAddr(ls_offset + lsa, size) || !Memory.IsGoodAddr(ea, size))
{
return MFC_PPU_DMA_CMD_SEQUENCE_ERROR;
}
if(proxy_pos >= MFC_PPU_MAX_QUEUE_SPACE)
{
return MFC_PPU_DMA_QUEUE_FULL;
}
DMAC_Proxy& p = proxy[proxy_pos++];
p.cmd = cmd;
p.tag = tag;
p.lsa = lsa;
p.ea = ea;
p.size = size;
return MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL;
}
void DoCmd()
{
if(proxy_pos)
{
DMAC_Proxy p = proxy[0];
memcpy(proxy, proxy + 1, proxy_pos--);
switch(p.cmd)
{
case MFC_PUT_CMD:
memcpy(Memory + ls_offset + p.lsa, Memory + p.ea, p.size);
break;
case MFC_GET_CMD:
memcpy(Memory + p.ea, Memory + ls_offset + p.lsa, p.size);
break;
default:
ConLog.Error("Unknown DMA cmd.");
break;
}
}
}
};
struct MFC
{
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;
DMAC dmac;
void Handle()
{
u32 cmd = MFC_CMDStatus.GetValue();
if(cmd)
{
u16 op = cmd & 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("RawSPU DMA %s:", 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(cmd, tag, lsa, ea, size));
}
break;
default:
ConLog.Error("Unknown MFC cmd. (opcode=0x%x, cmd=0x%x)", op, cmd);
break;
}
}
if(Prxy_QueryType.GetValue() == 2)
{
Prxy_QueryType.SetValue(0);
u32 mask = Prxy_QueryMask.GetValue();
//
MFC_QStatus.SetValue(mask);
}
}
};

View File

@ -1,6 +1,6 @@
#pragma once
#include "PPCInstrTable.h"
#pragma warning( disable : 4800 4554 )
#pragma warning( disable : 4800 )
template<typename TO>
class InstrCaller
@ -381,7 +381,11 @@ public:
, m_parent(nullptr)
, m_opcode(-1)
{
memset(m_instrs, 0, sizeof(InstrCaller<TO>*) * count);
for(int i=0; i<count; ++i)
{
m_instrs[i] = error_func;
}
memset(m_instrs_info, 0, sizeof(InstrBase<TO>*) * count);
}
@ -413,6 +417,14 @@ public:
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;
}
@ -442,16 +454,7 @@ public:
void decode(TO* op, u32 entry, u32 code) const
{
InstrCaller<TO>* instr = m_instrs[entry];
if(instr)
{
(*instr)(op, code);
}
else if(m_error_func)
{
(*m_error_func)(op, code);
}
(*m_instrs[entry])(op, code);
}
virtual void operator ()(TO* op, u32 code) const
@ -482,21 +485,21 @@ static InstrList<count2, TO>* connect_list(InstrList<count1, TO>* parent, InstrL
}
template<typename TO, uint from, uint to>
static InstrList<1 << (to - from + 1), TO>* new_list(const CodeField<from, to>& func, InstrCaller<TO>* error_func = nullptr)
static InstrList<1 << CodeField<from, to>::size, TO>* new_list(const CodeField<from, to>& func, InstrCaller<TO>* error_func = nullptr)
{
return new InstrList<1 << (to - from + 1), TO>(func, error_func);
return new InstrList<1 << CodeField<from, to>::size, TO>(func, error_func);
}
template<int count, typename TO, uint from, uint to>
static InstrList<1 << (to - from + 1), TO>* new_list(InstrList<count, TO>* parent, int opcode, const CodeField<from, to>& func, InstrCaller<TO>* error_func = nullptr)
static InstrList<1 << CodeField<from, to>::size, TO>* new_list(InstrList<count, TO>* parent, int opcode, const CodeField<from, to>& func, InstrCaller<TO>* error_func = nullptr)
{
return connect_list(parent, new InstrList<1 << (to - from + 1), TO>(func, error_func), opcode);
return connect_list(parent, new InstrList<1 << CodeField<from, to>::size, TO>(func, error_func), opcode);
}
template<int count, typename TO, uint from, uint to>
static InstrList<1 << (to - from + 1), TO>* new_list(InstrList<count, TO>* parent, const CodeField<from, to>& func, InstrCaller<TO>* error_func = nullptr)
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 << (to - from + 1), TO>(func, error_func));
return connect_list(parent, new InstrList<1 << CodeField<from, to>::size, TO>(func, error_func));
}
template<typename TO, int opcode, int count>

View File

@ -23,7 +23,7 @@ protected:
{
case DumpMode:
{
wxString mem = wxString::Format("\t%x:\t", dump_pc);
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));
@ -36,14 +36,11 @@ protected:
case InterpreterMode:
{
wxString mem = wxString::Format("[%x] ", 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 + ": " + value;
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;
@ -55,12 +52,14 @@ protected:
public:
wxString last_opcode;
uint dump_pc;
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;

View File

@ -1,10 +1,12 @@
#pragma once
template<int size, typename T> __forceinline static T sign(const T value)
template<uint size, typename T> __forceinline static T sign(const T value)
{
if(value & (1 << (size - 1)))
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 - (1 << size);
return value - sub_value;
}
return value;
@ -52,6 +54,7 @@ public:
{
}
static const u32 size = to - from + 1;
static const u32 shift = 31 - to;
static const u32 mask = ((1ULL << ((to - from) + 1)) - 1) << shift;

View File

@ -10,13 +10,15 @@ PPCThread* GetCurrentPPCThread()
PPCThread::PPCThread(PPCThreadType type)
: ThreadBase(true, "PPCThread")
, m_type(type)
, DisAsmFrame(NULL)
, m_arg(0)
, m_dec(NULL)
, DisAsmFrame(nullptr)
, m_dec(nullptr)
, stack_size(0)
, stack_addr(0)
, m_prio(0)
, m_offset(0)
, m_sync_wait(false)
, m_wait_thread_id(-1)
, m_free_data(false)
{
}
@ -27,18 +29,28 @@ PPCThread::~PPCThread()
void PPCThread::Close()
{
Stop();
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;
@ -83,8 +95,6 @@ void PPCThread::CloseStack()
void PPCThread::SetId(const u32 id)
{
m_id = id;
ID& thread = Emu.GetIdManager().GetIDData(m_id);
thread.m_name = GetName();
}
void PPCThread::SetName(const wxString& name)
@ -92,6 +102,46 @@ void PPCThread::SetName(const wxString& name)
m_name = name;
}
void PPCThread::Wait(bool wait)
{
wxCriticalSectionLocker lock(m_cs_sync);
m_sync_wait = wait;
}
void PPCThread::Wait(const PPCThread& thr)
{
wxCriticalSectionLocker lock(m_cs_sync);
m_wait_thread_id = thr.GetId();
m_sync_wait = true;
}
bool PPCThread::Sync()
{
wxCriticalSectionLocker lock(m_cs_sync);
return m_sync_wait;
}
int PPCThread::ThreadStatus()
{
if(Emu.IsStopped())
{
return PPCThread_Stopped;
}
if(TestDestroy())
{
return PPCThread_Break;
}
if(Emu.IsPaused() || Sync())
{
return PPCThread_Sleeping;
}
return PPCThread_Running;
}
void PPCThread::NextBranchPc()
{
SetPc(nPC);
@ -127,9 +177,9 @@ void PPCThread::SetEntry(const u64 pc)
void PPCThread::SetBranch(const u64 pc)
{
if(!Memory.IsGoodAddr(pc))
if(!Memory.IsGoodAddr(m_offset + pc))
{
ConLog.Error("%s branch error: bad address 0x%llx #pc: 0x%llx", GetFName(), pc, PC);
ConLog.Error("%s branch error: bad address 0x%llx #pc: 0x%llx", GetFName(), m_offset+ pc, m_offset + PC);
Emu.Pause();
}
nPC = pc;
@ -151,7 +201,7 @@ void PPCThread::SetError(const u32 error)
wxArrayString PPCThread::ErrorToString(const u32 error)
{
wxArrayString earr;
earr.Clear();
if(error == 0) return earr;
earr.Add("Unknown error");
@ -217,12 +267,11 @@ void PPCThread::Stop()
wxGetApp().SendDbgCommand(DID_STOP_THREAD, this);
m_status = Stopped;
ThreadBase::Stop(false);
Reset();
DoStop();
Emu.CheckStatus();
ThreadBase::Stop();
wxGetApp().SendDbgCommand(DID_STOPED_THREAD, this);
}
@ -230,6 +279,7 @@ void PPCThread::Exec()
{
wxGetApp().SendDbgCommand(DID_EXEC_THREAD, this);
ThreadBase::Start();
//std::thread thr(std::bind(std::mem_fn(&PPCThread::Task), this));
}
void PPCThread::ExecOnce()
@ -240,7 +290,7 @@ void PPCThread::ExecOnce()
void PPCThread::Task()
{
ConLog.Write("%s enter", PPCThread::GetFName());
//ConLog.Write("%s enter", PPCThread::GetFName());
const Array<u64>& bp = Emu.GetBreakPoints();
@ -255,9 +305,16 @@ void PPCThread::Task()
}
}
while(!Emu.IsStopped() && !TestDestroy())
while(true)
{
if(Emu.IsPaused())
int status = ThreadStatus();
if(status == PPCThread_Stopped || status == PPCThread_Break)
{
break;
}
if(status == PPCThread_Sleeping)
{
Sleep(1);
continue;
@ -285,5 +342,8 @@ void PPCThread::Task()
ConLog.Error("Exception: %s", e);
}
ConLog.Write("%s leave", PPCThread::GetFName());
//ConLog.Write("%s leave", PPCThread::GetFName());
if(m_free_data)
free(this);
}

View File

@ -6,6 +6,17 @@ enum PPCThreadType
{
PPC_THREAD_PPU,
PPC_THREAD_SPU,
PPC_THREAD_RAW_SPU,
};
enum PPCThreadStatus
{
PPCThread_Ready,
PPCThread_Running,
PPCThread_Paused,
PPCThread_Stopped,
PPCThread_Sleeping,
PPCThread_Break,
};
class PPCThread : public ThreadBase
@ -17,12 +28,14 @@ protected:
wxWindow* DisAsmFrame;
u32 m_id;
PPCThreadType m_type;
u64 m_arg;
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;
public:
u64 stack_size;
@ -37,13 +50,17 @@ public:
virtual u64 GetStackAddr() const { return stack_addr; }
virtual u64 GetStackSize() const { return stack_size; }
virtual u64 GetFreeStackSize() const=0;
void SetArg(const u64 arg) { m_arg = arg; }
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
@ -62,6 +79,7 @@ public:
{
case PPC_THREAD_PPU: return "PPU";
case PPC_THREAD_SPU: return "SPU";
case PPC_THREAD_RAW_SPU: return "RawSPU";
}
return "Unknown";
@ -88,6 +106,25 @@ protected:
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();
@ -100,7 +137,6 @@ public:
static wxArrayString ErrorToString(const u32 error);
wxArrayString ErrorToString() { return ErrorToString(m_error); }
bool IsSPU() const { return m_type == PPC_THREAD_SPU; }
bool IsOk() const { return m_error == 0; }
bool IsRunned() const { return m_status == Runned; }
bool IsPaused() const { return m_status == Paused; }
@ -113,6 +149,7 @@ public:
u32 GetError() const { return m_error; }
u32 GetId() const { return m_id; }
PPCThreadType GetType() const { return m_type; }
void Reset();
void Close();
@ -135,6 +172,7 @@ protected:
virtual void DoResume()=0;
virtual void DoStop()=0;
public:
virtual void Task();
private:

View File

@ -2,6 +2,7 @@
#include "PPCThreadManager.h"
#include "PPUThread.h"
#include "SPUThread.h"
#include "RawSPUThread.h"
PPCThreadManager::PPCThreadManager()
{
@ -17,13 +18,21 @@ void PPCThreadManager::Close()
while(m_threads.GetCount()) RemoveThread(m_threads[0].GetId());
}
PPCThread& PPCThreadManager::AddThread(bool isPPU)
PPCThread& PPCThreadManager::AddThread(PPCThreadType type)
{
PPCThread* new_thread = isPPU ? (PPCThread*)new PPUThread() : (PPCThread*)new SPUThread();
std::lock_guard<std::mutex> lock(m_mtx_thread);
new_thread->SetId(Emu.GetIdManager().GetNewID(
wxString::Format("%s Thread", isPPU ? "PPU" : "SPU"), new_thread, 0)
);
PPCThread* new_thread;
char* name;
switch(type)
{
case PPC_THREAD_PPU: new_thread = new PPUThread(); name = "PPU"; break;
case PPC_THREAD_SPU: new_thread = new SPUThread(); name = "SPU"; break;
case PPC_THREAD_RAW_SPU: new_thread = new RawSPUThread(); name = "RawSPU"; break;
default: assert(0);
}
new_thread->SetId(Emu.GetIdManager().GetNewID(wxString::Format("%s Thread", name), new_thread));
m_threads.Add(new_thread);
wxGetApp().SendDbgCommand(DID_CREATE_THREAD, new_thread);
@ -33,30 +42,47 @@ PPCThread& PPCThreadManager::AddThread(bool isPPU)
void PPCThreadManager::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;
wxGetApp().SendDbgCommand(DID_REMOVE_THREAD, &m_threads[i]);
m_threads[i].Close();
delete &m_threads[i];
m_threads.RemoveFAt(i);
PPCThread* thr = &m_threads[i];
wxGetApp().SendDbgCommand(DID_REMOVE_THREAD, thr);
if(thr->IsAlive())
{
thr->Close();
}
else
{
thr->Close();
delete thr;
}
break;
m_threads.RemoveFAt(i);
i--;
}
Emu.GetIdManager().RemoveID(id, false);
Emu.CheckStatus();
}
s32 PPCThreadManager::GetThreadNumById(bool isPPU, u32 id)
s32 PPCThreadManager::GetThreadNumById(PPCThreadType 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].IsSPU() == !isPPU) num++;
if(m_threads[i].GetType() == type) num++;
}
return -1;

View File

@ -7,6 +7,9 @@ class PPCThreadManager
//ArrayF<PPUThread> m_ppu_threads;
//ArrayF<SPUThread> m_spu_threads;
ArrayF<PPCThread> m_threads;
std::mutex m_mtx_thread;
wxSemaphore m_sem_task;
Stack<u32> m_delete_threads;
public:
PPCThreadManager();
@ -14,13 +17,14 @@ public:
void Close();
PPCThread& AddThread(bool isPPU);
PPCThread& AddThread(PPCThreadType type);
void RemoveThread(const u32 id);
ArrayF<PPCThread>& GetThreads() { return m_threads; }
s32 GetThreadNumById(bool isPPU, u32 id);
s32 GetThreadNumById(PPCThreadType type, u32 id);
PPCThread* GetThread(u32 id);
//IdManager& GetIDs() {return m_threads_id;}
void Exec();
void Task();
};

View File

@ -274,9 +274,9 @@ private:
{
DisAsm_V2("vlogefp", vd, vb);
}
void VMADDFP(u32 vd, u32 va, u32 vb, u32 vc)
void VMADDFP(u32 vd, u32 va, u32 vc, u32 vb)
{
DisAsm_V4("vmaddfp", vd, va, vb, vc);
DisAsm_V4("vmaddfp", vd, va, vc, vb);
}
void VMAXFP(u32 vd, u32 va, u32 vb)
{
@ -426,9 +426,9 @@ private:
{
DisAsm_V3("vmulouh", vd, va, vb);
}
void VNMSUBFP(u32 vd, u32 va, u32 vb, u32 vc)
void VNMSUBFP(u32 vd, u32 va, u32 vc, u32 vb)
{
DisAsm_V4("vnmsubfp", vd, va, vb, vc);
DisAsm_V4("vnmsubfp", vd, va, vc, vb);
}
void VNOR(u32 vd, u32 va, u32 vb)
{
@ -1051,9 +1051,9 @@ private:
{
DisAsm_R3("lwarx", rd, ra, rb);
}
void LDX(u32 ra, u32 rs, u32 rb)
void LDX(u32 rd, u32 ra, u32 rb)
{
DisAsm_R3("ldx", ra, rs, rb);
DisAsm_R3("ldx", rd, ra, rb);
}
void LWZX(u32 rd, u32 ra, u32 rb)
{
@ -1166,9 +1166,16 @@ private:
{
DisAsm_R3_OE_RC("adde", rd, ra, rb, oe, rc);
}
void MTOCRF(u32 crm, u32 rs)
void MTOCRF(u32 l, u32 crm, u32 rs)
{
DisAsm_INT1_R1("mtocrf", crm, rs);
if(l)
{
DisAsm_INT1_R1("mtocrf", crm, rs);
}
else
{
DisAsm_INT1_R1("mtcrf", crm, rs);
}
}
void STDX(u32 rs, u32 ra, u32 rb)
{
@ -1284,10 +1291,6 @@ private:
{
DisAsm_V1_R2("lvxl", vd, ra, rb);
}
void ABS(u32 rd, u32 ra, u32 oe, bool rc)
{
DisAsm_R2_OE_RC("abs", rd, ra, oe, rc);
}
void MFTB(u32 rd, u32 spr)
{
const u32 n = (spr >> 5) | ((spr & 0x1f) << 5);

View File

@ -70,18 +70,6 @@ namespace PPU_instr
//This field is used to specify a bit in the CR, or in the FPSCR, as the destination of the result of an instruction
static CodeField<6, 10> CRBD(FIELD_R_CR);
//
static CodeField<6, 10> BT;
//
static CodeField<11, 15> BA;
//
static CodeField<16, 20> BB;
//
static CodeField<6, 10> BF;
//This field is used to specify options for the branch conditional instructions
static CodeField<6, 10> BO;
@ -125,8 +113,10 @@ namespace PPU_instr
*/
static CodeField<30> AA;
static CodeFieldSignedOffset<6, 29, 2> LI(FIELD_BRANCH);
//
static CodeFieldSigned<6, 31> LL(FIELD_BRANCH);
static CodeFieldSignedOffset<6, 29, 2> LL(FIELD_BRANCH);
/*
Link bit.
0 Does not update the link register (LR).
@ -156,7 +146,7 @@ namespace PPU_instr
static CodeField<6, 10> FRS;
//
static CodeField<7, 14> FLM;
static CodeField<7, 14> FM;
//This field is used to specify an FPR as a source
static CodeField<11, 15> FRA(FIELD_R_FPR);
@ -177,36 +167,7 @@ namespace PPU_instr
static CodeFieldSigned<16, 31> D;
//
struct : public CodeFieldSigned<16, 31>
{
static __forceinline u32 decode(u32 data)
{
int res = sign<size>((data & mask) >> shift);
if(res < 0) return res - 1;
return res;
}
static __forceinline void encode(u32& data, u32 value)
{
if((s32)value < 0)
{
value++;
}
data &= ~mask;
data |= (value << shift) & mask;
}
virtual u32 operator ()(u32 data) const
{
return decode(data);
}
virtual void operator ()(u32& data, u32 value) const
{
return encode(data, value);
}
} static DS;
static CodeFieldSignedOffset<16, 29, 2> DS;
//This immediate field is used to specify a 16-bit signed integer
static CodeFieldSigned<16, 31> simm16;
@ -269,7 +230,7 @@ namespace PPU_instr
bind_instr(main_list, ADDIS, RD, RA, simm16);
bind_instr(main_list, BC, BO, BI, BD, AA, LK);
bind_instr(main_list, SC, SYS);
bind_instr(main_list, B, LL, AA, LK);
bind_instr(main_list, B, LI, AA, LK);
bind_instr(main_list, RLWIMI, RA, RS, SH, MB, ME, RC);
bind_instr(main_list, RLWINM, RA, RS, SH, MB, ME, RC);
bind_instr(main_list, RLWNM, RA, RS, RB, MB, ME, RC);
@ -302,7 +263,7 @@ namespace PPU_instr
bind_instr(main_list, STFD, FRS, RA, D);
bind_instr(main_list, STFDU, FRS, RA, D);
bind_instr(g04_list, VMADDFP, VD, VA, VB, VC);
bind_instr(g04_list, VMADDFP, VD, VA, VC, VB);
bind_instr(g04_list, VMHADDSHS, VD, VA, VB, VC);
bind_instr(g04_list, VMHRADDSHS, VD, VA, VB, VC);
bind_instr(g04_list, VMLADDUHM, VD, VA, VB, VC);
@ -312,7 +273,7 @@ namespace PPU_instr
bind_instr(g04_list, VMSUMUBM, VD, VA, VB, VC);
bind_instr(g04_list, VMSUMUHM, VD, VA, VB, VC);
bind_instr(g04_list, VMSUMUHS, VD, VA, VB, VC);
bind_instr(g04_list, VNMSUBFP, VD, VA, VB, VC);
bind_instr(g04_list, VNMSUBFP, VD, VA, VC, VB);
bind_instr(g04_list, VPERM, VD, VA, VB, VC);
bind_instr(g04_list, VSEL, VD, VA, VB, VC);
bind_instr(g04_list, VSLDOI, VD, VA, VB, VSH);
@ -489,7 +450,7 @@ namespace PPU_instr
/*0x00b*/bind_instr(g1f_list, MULHWU, RD, RA, RB, RC);
/*0x013*/bind_instr(g1f_list, MFOCRF, L_11, RD, CRM);
/*0x014*/bind_instr(g1f_list, LWARX, RD, RA, RB);
/*0x015*/bind_instr(g1f_list, LDX, RA, RS, RB);
/*0x015*/bind_instr(g1f_list, LDX, RD, RA, RB);
/*0x017*/bind_instr(g1f_list, LWZX, RD, RA, RB);
/*0x018*/bind_instr(g1f_list, SLW, RA, RS, RB, RC);
/*0x01a*/bind_instr(g1f_list, CNTLZW, RA, RS, RC);
@ -515,7 +476,7 @@ namespace PPU_instr
/*0x087*/bind_instr(g1f_list, STVEBX, VS, RA, RB);
/*0x088*/bind_instr(g1f_list, SUBFE, RD, RA, RB, OE, RC);
/*0x08a*/bind_instr(g1f_list, ADDE, RD, RA, RB, OE, RC);
/*0x090*/bind_instr(g1f_list, MTOCRF, CRM, RS);
/*0x090*/bind_instr(g1f_list, MTOCRF, L_11, CRM, RS);
/*0x095*/bind_instr(g1f_list, STDX, RS, RA, RB);
/*0x096*/bind_instr(g1f_list, STWCX_, RS, RA, RB);
/*0x097*/bind_instr(g1f_list, STWX, RS, RA, RB);
@ -541,7 +502,6 @@ namespace PPU_instr
/*0x156*/bind_instr(g1f_list, DST, RA, RB, STRM, L_6);
/*0x157*/bind_instr(g1f_list, LHAX, RD, RA, RB);
/*0x167*/bind_instr(g1f_list, LVXL, VD, RA, RB);
/*0x168*/bind_instr(g1f_list, ABS, RD, RA, OE, RC);
/*0x173*/bind_instr(g1f_list, MFTB, RD, SPR);
/*0x176*/bind_instr(g1f_list, DSTST, RA, RB, STRM, L_6);
/*0x177*/bind_instr(g1f_list, LHAUX, RD, RA, RB);
@ -554,7 +514,7 @@ namespace PPU_instr
/*0x1d3*/bind_instr(g1f_list, MTSPR, SPR, RS);
/*0x1d6*///DCBI
/*0x1dc*/bind_instr(g1f_list, NAND, RA, RS, RB, RC);
/*0x1e7*/bind_instr(g1f_list, STVXL, RS, RA, RB);
/*0x1e7*/bind_instr(g1f_list, STVXL, VS, RA, RB);
/*0x1e9*/bind_instr(g1f_list, DIVD, RD, RA, RB, OE, RC);
/*0x1eb*/bind_instr(g1f_list, DIVW, RD, RA, RB, OE, RC);
/*0x207*/bind_instr(g1f_list, LVLX, VD, RA, RB);
@ -568,9 +528,9 @@ namespace PPU_instr
/*0x257*/bind_instr(g1f_list, LFDX, FRD, RA, RB);
/*0x277*/bind_instr(g1f_list, LFDUX, FRD, RA, RB);
/*0x287*/bind_instr(g1f_list, STVLX, VS, RA, RB);
/*0x297*/bind_instr(g1f_list, STFSX, RS, RA, RB);
/*0x297*/bind_instr(g1f_list, STFSX, FRS, RA, RB);
/*0x2a7*/bind_instr(g1f_list, STVRX, VS, RA, RB);
/*0x2d7*/bind_instr(g1f_list, STFDX, RS, RA, RB);
/*0x2d7*/bind_instr(g1f_list, STFDX, FRS, RA, RB);
/*0x307*/bind_instr(g1f_list, LVLXL, VD, RA, RB);
/*0x316*/bind_instr(g1f_list, LHBRX, RD, RA, RB);
/*0x318*/bind_instr(g1f_list, SRAW, RA, RS, RB, RC);
@ -581,14 +541,16 @@ namespace PPU_instr
/*0x33a*/bind_instr(g1f_list, SRADI1, RA, RS, sh, RC);
/*0x33b*/bind_instr(g1f_list, SRADI2, RA, RS, sh, RC);
/*0x356*/bind_instr(g1f_list, EIEIO);
/*0x387*/bind_instr(g1f_list, STVLXL, VS, RA, RB);
/*0x39a*/bind_instr(g1f_list, EXTSH, RA, RS, RC);
/*0x387*/bind_instr(g1f_list, STVRXL, VS, RA, RB);
/*0x3ba*/bind_instr(g1f_list, EXTSB, RA, RS, RC);
/*0x3d7*/bind_instr(g1f_list, STFIWX, FRS, RA, RB);
/*0x3da*/bind_instr(g1f_list, EXTSW, RA, RS, RC);
/*0x3d6*///ICBI
/*0x3f6*/bind_instr(g1f_list, DCBZ, RA, RB);
bind_instr(g3a_list, LD, RD, RA, D);
bind_instr(g3a_list, LD, RD, RA, DS);
bind_instr(g3a_list, LDU, RD, RA, DS);
bind_instr(g3b_list, FDIVS, FRD, FRA, FRB, RC);
@ -602,7 +564,7 @@ namespace PPU_instr
bind_instr(g3b_list, FNMSUBS, FRD, FRA, FRC, FRB, RC);
bind_instr(g3b_list, FNMADDS, FRD, FRA, FRC, FRB, RC);
bind_instr(g3e_list, STD, RS, RA, D);
bind_instr(g3e_list, STD, RS, RA, DS);
bind_instr(g3e_list, STDU, RS, RA, DS);
bind_instr(g3f_list, FSEL, FRD, FRA, FRC, FRB, RC);
@ -630,12 +592,12 @@ namespace PPU_instr
bind_instr(g3f_0_list, FCTID, FRD, FRB, RC);
bind_instr(g3f_0_list, FCTIDZ, FRD, FRB, RC);
bind_instr(g3f_0_list, MTFSB1, BT, RC);
bind_instr(g3f_0_list, MCRFS, BF, BFA);
bind_instr(g3f_0_list, MTFSB0, BT, RC);
bind_instr(g3f_0_list, MTFSB1, CRBD, RC);
bind_instr(g3f_0_list, MCRFS, CRFD, CRFS);
bind_instr(g3f_0_list, MTFSB0, CRBD, RC);
bind_instr(g3f_0_list, MTFSFI, CRFD, I, RC);
bind_instr(g3f_0_list, MFFS, FRD, RC);
bind_instr(g3f_0_list, MTFSF, FLM, FRB, RC);
bind_instr(g3f_0_list, MTFSF, FM, FRB, RC);
#undef bind_instr
};

View File

@ -61,10 +61,10 @@ private:
void SysCall()
{
CPU.GPR[3] = CPU.DoSyscall(CPU.GPR[11]);
CPU.DoSyscall(CPU.GPR[11]);
//if((s32)CPU.GPR[3] < 0)
//ConLog.Warning("SysCall[%lld] done with code [0x%x]! #pc: 0x%llx", CPU.GPR[11], (u32)CPU.GPR[3], CPU.PC);
if(enable_log)
ConLog.Warning("SysCall[%lld] done with code [0x%llx]! #pc: 0x%llx", CPU.GPR[11], CPU.GPR[3], CPU.PC);
#ifdef HLE_CALL_DEBUG
ConLog.Write("SysCall[%lld] done with code [0x%llx]! #pc: 0x%llx", CPU.GPR[11], CPU.GPR[3], CPU.PC);
#endif
@ -97,18 +97,12 @@ private:
const u8 bo1 = (bo & 0x08) ? 1 : 0;
const u8 bo2 = (bo & 0x04) ? 1 : 0;
const u8 bo3 = (bo & 0x02) ? 1 : 0;
const u8 bo4 = (bo & 0x01) ? 1 : 0;
if(!bo2) --CPU.CTR;
const u8 ctr_ok = bo2 | ((CPU.CTR != 0) ^ bo3);
const u8 cond_ok = bo0 | (CPU.IsCR(bi) ^ (~bo1 & 0x1));
//if(bo1) CPU.SetCR(bi, bo4 ? 1 : 0);
//if(bo1) return !bo4;
//ConLog.Write("bo0: 0x%x, bo1: 0x%x, bo2: 0x%x, bo3: 0x%x", bo0, bo1, bo2, bo3);
return ctr_ok && cond_ok;
}
@ -805,7 +799,7 @@ private:
CPU.VPR[vd]._f[w] = log(CPU.VPR[vb]._f[w]) / log(2.0f);
}
}
void VMADDFP(u32 vd, u32 va, u32 vb, u32 vc)
void VMADDFP(u32 vd, u32 va, u32 vc, u32 vb)
{
for (uint w = 0; w < 4; w++)
{
@ -955,50 +949,56 @@ private:
}
void VMRGHB(u32 vd, u32 va, u32 vb)
{
VPR_reg VA = CPU.VPR[va];
VPR_reg VB = CPU.VPR[vb];
for (uint h = 0; h < 8; h++)
{
CPU.VPR[vd]._u8[h*2] = CPU.VPR[va]._u8[h];
CPU.VPR[vd]._u8[h*2 + 1] = CPU.VPR[vb]._u8[h];
CPU.VPR[vd]._u8[15 - h*2] = VA._u8[15 - h];
CPU.VPR[vd]._u8[15 - h*2 - 1] = VB._u8[15 - h];
}
}
void VMRGHH(u32 vd, u32 va, u32 vb)
{
VPR_reg VA = CPU.VPR[va];
VPR_reg VB = CPU.VPR[vb];
for (uint w = 0; w < 4; w++)
{
CPU.VPR[vd]._u16[w*2] = CPU.VPR[va]._u16[w];
CPU.VPR[vd]._u16[w*2 + 1] = CPU.VPR[vb]._u16[w];
CPU.VPR[vd]._u16[7 - w*2] = VA._u16[7 - w];
CPU.VPR[vd]._u16[7 - w*2 - 1] = VB._u16[7 - w];
}
}
void VMRGHW(u32 vd, u32 va, u32 vb)
{
VPR_reg VA = CPU.VPR[va];
VPR_reg VB = CPU.VPR[vb];
for (uint d = 0; d < 2; d++)
{
CPU.VPR[vd]._u32[d*2] = CPU.VPR[va]._u32[d];
CPU.VPR[vd]._u32[d*2 + 1] = CPU.VPR[vb]._u32[d];
CPU.VPR[vd]._u32[3 - d*2] = VA._u32[3 - d];
CPU.VPR[vd]._u32[3 - d*2 - 1] = VB._u32[3 - d];
}
}
void VMRGLB(u32 vd, u32 va, u32 vb)
{
for (uint h = 0; h < 8; h++)
{
CPU.VPR[vd]._u8[h*2] = CPU.VPR[va]._u8[h + 8];
CPU.VPR[vd]._u8[h*2 + 1] = CPU.VPR[vb]._u8[h + 8];
CPU.VPR[vd]._u8[15 - h*2] = CPU.VPR[va]._u8[7 - h];
CPU.VPR[vd]._u8[15 - h*2 - 1] = CPU.VPR[vb]._u8[7 - h];
}
}
void VMRGLH(u32 vd, u32 va, u32 vb)
{
for (uint w = 0; w < 4; w++)
{
CPU.VPR[vd]._u16[w*2] = CPU.VPR[va]._u16[w + 4];
CPU.VPR[vd]._u16[w*2 + 1] = CPU.VPR[vb]._u16[w + 4];
CPU.VPR[vd]._u16[7 - w*2] = CPU.VPR[va]._u16[3 - w];
CPU.VPR[vd]._u16[7 - w*2 - 1] = CPU.VPR[vb]._u16[3 - w];
}
}
void VMRGLW(u32 vd, u32 va, u32 vb)
{
for (uint d = 0; d < 2; d++)
{
CPU.VPR[vd]._u32[d*2] = CPU.VPR[va]._u32[d + 2];
CPU.VPR[vd]._u32[d*2 + 1] = CPU.VPR[vb]._u32[d + 2];
CPU.VPR[vd]._u32[3 - d*2] = CPU.VPR[va]._u32[1 - d];
CPU.VPR[vd]._u32[3 - d*2 - 1] = CPU.VPR[vb]._u32[1 - d];
}
}
void VMSUMMBM(u32 vd, u32 va, u32 vb, u32 vc)
@ -1172,11 +1172,11 @@ private:
CPU.VPR[vd]._u32[w] = (u32)CPU.VPR[va]._u16[w*2] * (u32)CPU.VPR[vb]._u16[w*2];
}
}
void VNMSUBFP(u32 vd, u32 va, u32 vb, u32 vc)
void VNMSUBFP(u32 vd, u32 va, u32 vc, u32 vb)
{
for (uint w = 0; w < 4; w++)
{
CPU.VPR[vd]._f[w] = (double)CPU.VPR[vb]._f[w] - (double)CPU.VPR[va]._f[w] * (double)CPU.VPR[vc]._f[w];
CPU.VPR[vd]._f[w] = -(CPU.VPR[va]._f[w] * CPU.VPR[vc]._f[w] - CPU.VPR[vb]._f[w]);
}
}
void VNOR(u32 vd, u32 va, u32 vb)
@ -1617,7 +1617,7 @@ private:
{
assert(uimm5 < 4);
u32 word = CPU.VPR[vb]._u32[uimm5];
u32 word = CPU.VPR[vb]._u32[3 - uimm5];
for (uint w = 0; w < 4; w++)
{
@ -2028,11 +2028,11 @@ private:
}
void CMPLI(u32 crfd, u32 l, u32 ra, u32 uimm16)
{
CPU.UpdateCRn<u64>(crfd, l ? CPU.GPR[ra] : (u32)CPU.GPR[ra], uimm16);
CPU.UpdateCRnU(l, crfd, CPU.GPR[ra], uimm16);
}
void CMPI(u32 crfd, u32 l, u32 ra, s32 simm16)
{
CPU.UpdateCRn<s64>(crfd, l ? CPU.GPR[ra] : (s32)CPU.GPR[ra], simm16);
CPU.UpdateCRnS(l, crfd, CPU.GPR[ra], simm16);
}
void ADDIC(u32 rd, u32 ra, s32 simm16)
{
@ -2086,48 +2086,48 @@ private:
CPU.SetBranch(branchTarget(0, CPU.LR));
if(lk) CPU.LR = CPU.PC + 4;
}
void CRNOR(u32 bt, u32 ba, u32 bb)
void CRNOR(u32 crbd, u32 crba, u32 crbb)
{
const u8 v = 1 ^ (CPU.IsCR(ba) | CPU.IsCR(bb));
CPU.SetCRBit2(bt, v & 0x1);
const u8 v = 1 ^ (CPU.IsCR(crba) | CPU.IsCR(crbb));
CPU.SetCRBit2(crbd, v & 0x1);
}
void CRANDC(u32 bt, u32 ba, u32 bb)
void CRANDC(u32 crbd, u32 crba, u32 crbb)
{
const u8 v = CPU.IsCR(ba) & (1 ^ CPU.IsCR(bb));
CPU.SetCRBit2(bt, v & 0x1);
const u8 v = CPU.IsCR(crba) & (1 ^ CPU.IsCR(crbb));
CPU.SetCRBit2(crbd, v & 0x1);
}
void ISYNC()
{
}
void CRXOR(u32 bt, u32 ba, u32 bb)
void CRXOR(u32 crbd, u32 crba, u32 crbb)
{
const u8 v = CPU.IsCR(ba) ^ CPU.IsCR(bb);
CPU.SetCRBit2(bt, v & 0x1);
const u8 v = CPU.IsCR(crba) ^ CPU.IsCR(crbb);
CPU.SetCRBit2(crbd, v & 0x1);
}
void CRNAND(u32 bt, u32 ba, u32 bb)
void CRNAND(u32 crbd, u32 crba, u32 crbb)
{
const u8 v = 1 ^ (CPU.IsCR(ba) & CPU.IsCR(bb));
CPU.SetCRBit2(bt, v & 0x1);
const u8 v = 1 ^ (CPU.IsCR(crba) & CPU.IsCR(crbb));
CPU.SetCRBit2(crbd, v & 0x1);
}
void CRAND(u32 bt, u32 ba, u32 bb)
void CRAND(u32 crbd, u32 crba, u32 crbb)
{
const u8 v = CPU.IsCR(ba) & CPU.IsCR(bb);
CPU.SetCRBit2(bt, v & 0x1);
const u8 v = CPU.IsCR(crba) & CPU.IsCR(crbb);
CPU.SetCRBit2(crbd, v & 0x1);
}
void CREQV(u32 bt, u32 ba, u32 bb)
void CREQV(u32 crbd, u32 crba, u32 crbb)
{
const u8 v = 1 ^ (CPU.IsCR(ba) ^ CPU.IsCR(bb));
CPU.SetCRBit2(bt, v & 0x1);
const u8 v = 1 ^ (CPU.IsCR(crba) ^ CPU.IsCR(crbb));
CPU.SetCRBit2(crbd, v & 0x1);
}
void CRORC(u32 bt, u32 ba, u32 bb)
void CRORC(u32 crbd, u32 crba, u32 crbb)
{
const u8 v = CPU.IsCR(ba) | (1 ^ CPU.IsCR(bb));
CPU.SetCRBit2(bt, v & 0x1);
const u8 v = CPU.IsCR(crba) | (1 ^ CPU.IsCR(crbb));
CPU.SetCRBit2(crbd, v & 0x1);
}
void CROR(u32 bt, u32 ba, u32 bb)
void CROR(u32 crbd, u32 crba, u32 crbb)
{
const u8 v = CPU.IsCR(ba) | CPU.IsCR(bb);
CPU.SetCRBit2(bt, v & 0x1);
const u8 v = CPU.IsCR(crba) | CPU.IsCR(crbb);
CPU.SetCRBit2(crbd, v & 0x1);
}
void BCCTR(u32 bo, u32 bi, u32 bh, u32 lk)
{
@ -2172,12 +2172,12 @@ private:
void ANDI_(u32 ra, u32 rs, u32 uimm16)
{
CPU.GPR[ra] = CPU.GPR[rs] & uimm16;
CPU.UpdateCR0<s64>(CPU.GPR[ra]);
CPU.UpdateCR0<s16>(CPU.GPR[ra]);
}
void ANDIS_(u32 ra, u32 rs, u32 uimm16)
{
CPU.GPR[ra] = CPU.GPR[rs] & (uimm16 << 16);
CPU.UpdateCR0<s64>(CPU.GPR[ra]);
CPU.UpdateCR0<s32>(CPU.GPR[ra]);
}
void RLDICL(u32 ra, u32 rs, u32 sh, u32 mb, bool rc)
{
@ -2202,7 +2202,7 @@ private:
}
void CMP(u32 crfd, u32 l, u32 ra, u32 rb)
{
CPU.UpdateCRn<s64>(crfd, l ? CPU.GPR[ra] : (s32)CPU.GPR[ra], l ? CPU.GPR[rb] : (s32)CPU.GPR[rb]);
CPU.UpdateCRnS(l, crfd, CPU.GPR[ra], CPU.GPR[rb]);
}
void TW(u32 to, u32 ra, u32 rb)
{
@ -2256,7 +2256,7 @@ private:
{
const s64 RA = CPU.GPR[ra];
const s64 RB = CPU.GPR[rb];
CPU.GPR[rd] = RB - RA;
CPU.GPR[rd] = ~RA + RB + 1;
CPU.XER.CA = CPU.IsCarry(RA, RB);
if(oe) UNK("subfco");
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]);
@ -2334,9 +2334,9 @@ private:
CPU.reserve = true;
CPU.GPR[rd] = Memory.Read32(addr);
}
void LDX(u32 ra, u32 rs, u32 rb)
void LDX(u32 rd, u32 ra, u32 rb)
{
CPU.GPR[ra] = Memory.Read64(rs ? CPU.GPR[rs] + CPU.GPR[rb] : CPU.GPR[rb]);
CPU.GPR[rd] = Memory.Read64(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]);
}
void LWZX(u32 rd, u32 ra, u32 rb)
{
@ -2362,11 +2362,16 @@ private:
CPU.GPR[ra] = i;
if(rc) CPU.UpdateCR0<u32>(CPU.GPR[ra]);
if(rc) CPU.UpdateCR0<s32>(CPU.GPR[ra]);
}
void SLD(u32 ra, u32 rs, u32 rb, bool rc)
{
CPU.GPR[ra] = CPU.GPR[rb] & 0x40 ? 0 : CPU.GPR[rs] << (CPU.GPR[rb] & 0x3f);
const u32 n = CPU.GPR[rb] & 0x3f;
const u64 r = rotl64(CPU.GPR[rs], n);
const u64 m = (CPU.GPR[rb] & 0x30) ? 0 : rotate_mask[0][63 - n];
CPU.GPR[ra] = r & m;
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[ra]);
}
void AND(u32 ra, u32 rs, u32 rb, bool rc)
@ -2376,7 +2381,7 @@ private:
}
void CMPL(u32 crfd, u32 l, u32 ra, u32 rb)
{
CPU.UpdateCRn<u64>(crfd, l ? CPU.GPR[ra] : (u32)CPU.GPR[ra], l ? CPU.GPR[rb] : (u32)CPU.GPR[rb]);
CPU.UpdateCRnU(l, crfd, CPU.GPR[ra], CPU.GPR[rb]);
}
void LVSR(u32 vd, u32 ra, u32 rb)
{
@ -2544,24 +2549,38 @@ private:
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]);
if(oe) UNK("addeo");
}
void MTOCRF(u32 crm, u32 rs)
void MTOCRF(u32 l, u32 crm, u32 rs)
{
u32 n = 0, count = 0;
for(u32 i=0; i<8; ++i)
if(l)
{
if(crm & (1 << i))
u32 n = 0, count = 0;
for(u32 i=0; i<8; ++i)
{
n = i;
count++;
if(crm & (1 << i))
{
n = i;
count++;
}
}
if(count == 1)
{
//CR[4*n : 4*n+3] = RS[32+4*n : 32+4*n+3];
CPU.SetCR(n, (CPU.GPR[rs] >> (4*n)) & 0xf);
}
else
CPU.CR.CR = 0;
}
else
{
for(u32 i=0; i<8; ++i)
{
if(crm & (1 << i))
{
CPU.SetCR(i, CPU.GPR[rs] & (0xf << i));
}
}
}
if(count == 1)
{
//CR[4*n : 4*n+3] = RS[32+4*n : 32+4*n+3];
CPU.SetCR(n, (CPU.GPR[rs] >> (4*n)) & 0xf);
}
else CPU.CR.CR = 0;
}
void STDX(u32 rs, u32 ra, u32 rb)
{
@ -2570,21 +2589,24 @@ private:
void STWCX_(u32 rs, u32 ra, u32 rb)
{
CPU.SetCR(0, CPU.XER.SO ? CR_SO : 0);
if(!CPU.reserve) return;
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
if(addr == CPU.reserve_addr)
if(CPU.reserve)
{
Memory.Write32(addr, CPU.GPR[rs]);
CPU.SetCR_EQ(0, true);
}
else
{
static const bool u = 0;
if(u) Memory.Write32(addr, CPU.GPR[rs]);
CPU.SetCR_EQ(0, u);
CPU.reserve = false;
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
if(addr == CPU.reserve_addr)
{
Memory.Write32(addr, CPU.GPR[rs]);
CPU.SetCR_EQ(0, true);
CPU.reserve = false;
}
else
{
static const bool u = 0;
if(u) Memory.Write32(addr, CPU.GPR[rs]);
CPU.SetCR_EQ(0, u);
CPU.reserve = false;
}
}
}
void STWX(u32 rs, u32 ra, u32 rb)
@ -2621,21 +2643,22 @@ private:
void STDCX_(u32 rs, u32 ra, u32 rb)
{
CPU.SetCR(0, CPU.XER.SO ? CR_SO : 0);
if(!CPU.reserve) return;
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
if(addr == CPU.reserve_addr)
if(!CPU.reserve)
{
Memory.Write64(addr, CPU.GPR[rs]);
CPU.SetCR_EQ(0, true);
}
else
{
static const bool u = 0;
if(u) Memory.Write64(addr, CPU.GPR[rs]);
CPU.SetCR_EQ(0, u);
CPU.reserve = false;
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
if(addr == CPU.reserve_addr)
{
Memory.Write64(addr, CPU.GPR[rs]);
CPU.SetCR_EQ(0, true);
}
else
{
static const bool u = 0;
if(u) Memory.Write64(addr, CPU.GPR[rs]);
CPU.SetCR_EQ(0, u);
CPU.reserve = false;
}
}
}
void STBX(u32 rs, u32 ra, u32 rb)
@ -2724,12 +2747,6 @@ private:
{
CPU.VPR[vd]._u128 = Memory.Read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL);
}
void ABS(u32 rd, u32 ra, u32 oe, bool rc)
{
CPU.GPR[rd] = abs((s64)CPU.GPR[ra]);
if(oe) UNK("abso");
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]);
}
void MFTB(u32 rd, u32 spr)
{
const u32 n = (spr >> 5) | ((spr & 0x1f) << 5);
@ -2824,10 +2841,10 @@ private:
const s64 RA = CPU.GPR[ra];
const s64 RB = CPU.GPR[rb];
if (RB == 0 || ((u64)RA == 0x8000000000000000 && RB == -1))
if (RB == 0 || ((u64)RA == (1ULL << 63) && RB == -1))
{
if(oe) UNK("divdo");
CPU.GPR[rd] = (((u64)RA & 0x8000000000000000) && RB == 0) ? -1 : 0;
CPU.GPR[rd] = (((u64)RA & (1ULL << 63)) && RB == 0) ? -1 : 0;
}
else
{
@ -2841,10 +2858,10 @@ private:
const s32 RA = CPU.GPR[ra];
const s32 RB = CPU.GPR[rb];
if (RB == 0 || ((u32)RA == 0x80000000 && RB == -1))
if (RB == 0 || ((u32)RA == (1 << 31) && RB == -1))
{
if(oe) UNK("divwo");
CPU.GPR[rd] = (((u32)RA & 0x80000000) && RB == 0) ? -1 : 0;
CPU.GPR[rd] = (((u32)RA & (1 << 31)) && RB == 0) ? -1 : 0;
}
else
{
@ -2871,12 +2888,20 @@ private:
}
void SRW(u32 ra, u32 rs, u32 rb, bool rc)
{
CPU.GPR[ra] = CPU.GPR[rb] & 0x20 ? 0 : (u32)CPU.GPR[rs] >> (CPU.GPR[rb] & 0x1f);
u32 n = CPU.GPR[rb] & 0x1f;
u64 r = rotl32((u32)CPU.GPR[rs], 64 - n);
u64 m = CPU.GPR[rb] & 0x20 ? 0 : rotate_mask[32 + n][63];
CPU.GPR[ra] = r & m;
if(rc) CPU.UpdateCR0<s32>(CPU.GPR[ra]);
}
void SRD(u32 ra, u32 rs, u32 rb, bool rc)
{
CPU.GPR[ra] = CPU.GPR[rb] & 0x40 ? 0 : CPU.GPR[rs] >> (CPU.GPR[rb] & 0x3f);
u32 n = CPU.GPR[rb] & 0x3f;
u64 r = rotl64(CPU.GPR[rs], 64 - n);
u64 m = CPU.GPR[rb] & 0x40 ? 0 : rotate_mask[n][63];
CPU.GPR[ra] = r & m;
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[ra]);
}
void LVRX(u32 vd, u32 ra, u32 rb)
@ -2915,7 +2940,7 @@ private:
}
void STFSX(u32 frs, u32 ra, u32 rb)
{
Memory.Write32((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), PPCdouble(CPU.FPR[frs]).To32());
Memory.Write32((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), CPU.FPR[frs].To32());
}
void STVRX(u32 vs, u32 ra, u32 rb)
{
@ -2940,7 +2965,7 @@ private:
CPU.GPR[rd] = (u16&)Memory[ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]];
}
void SRAW(u32 ra, u32 rs, u32 rb, bool rc)
{
{
s32 RS = CPU.GPR[rs];
s32 RB = CPU.GPR[rb];
CPU.GPR[ra] = RS >> RB;
@ -3128,12 +3153,12 @@ private:
}
void STFS(u32 frs, u32 ra, s32 d)
{
Memory.Write32(ra ? CPU.GPR[ra] + d : d, PPCdouble(CPU.FPR[frs]).To32());
Memory.Write32(ra ? CPU.GPR[ra] + d : d, CPU.FPR[frs].To32());
}
void STFSU(u32 frs, u32 ra, s32 d)
{
const u64 addr = CPU.GPR[ra] + d;
Memory.Write32(addr, PPCdouble(CPU.FPR[frs]).To32());
Memory.Write32(addr, CPU.FPR[frs].To32());
CPU.GPR[ra] = addr;
}
void STFD(u32 frs, u32 ra, s32 d)
@ -3159,32 +3184,116 @@ private:
}
void FDIVS(u32 frd, u32 fra, u32 frb, bool rc)
{
if(CPU.FPR[frb] == 0.0) CPU.SetFPSCRException(FPSCR_ZX);
CPU.FPR[frd] = static_cast<float>(CPU.FPR[fra] / CPU.FPR[frb]);
CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType();
if(FPRdouble::IsNaN(CPU.FPR[fra]))
{
CPU.FPR[frd] = CPU.FPR[fra];
}
else if(FPRdouble::IsNaN(CPU.FPR[frb]))
{
CPU.FPR[frd] = CPU.FPR[frb];
}
else
{
if(CPU.FPR[frb] == 0.0)
{
if(CPU.FPR[fra] == 0.0)
{
CPU.FPSCR.VXZDZ = true;
CPU.FPR[frd] = FPR_NAN;
}
else
{
CPU.FPR[frd] = (float)(CPU.FPR[fra] / CPU.FPR[frb]);
}
CPU.FPSCR.ZX = true;
}
else if(FPRdouble::IsINF(CPU.FPR[fra]) && FPRdouble::IsINF(CPU.FPR[frb]))
{
CPU.FPSCR.VXIDI = true;
CPU.FPR[frd] = FPR_NAN;
}
else
{
CPU.FPR[frd] = (float)(CPU.FPR[fra] / CPU.FPR[frb]);
}
}
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) UNK("fdivs.");//CPU.UpdateCR1(CPU.FPR[frd]);
}
void FSUBS(u32 frd, u32 fra, u32 frb, bool rc)
{
CPU.FPR[frd] = static_cast<float>(CPU.FPR[fra] - CPU.FPR[frb]);
CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType();
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) UNK("fsubs.");//CPU.UpdateCR1(CPU.FPR[frd]);
}
void FADDS(u32 frd, u32 fra, u32 frb, bool rc)
{
CPU.FPR[frd] = static_cast<float>(CPU.FPR[fra] + CPU.FPR[frb]);
CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType();
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) UNK("fadds.");//CPU.UpdateCR1(CPU.FPR[frd]);
}
void FSQRTS(u32 frd, u32 frb, bool rc)
{
CPU.FPR[frd] = static_cast<float>(sqrt((float)CPU.FPR[frb]));
CPU.FPR[frd] = static_cast<float>(sqrt(CPU.FPR[frb]));
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) UNK("fsqrts.");//CPU.UpdateCR1(CPU.FPR[frd]);
}
void FRES(u32 frd, u32 frb, bool rc)
{
if(CPU.FPR[frb] == 0.0) CPU.SetFPSCRException(FPSCR_ZX);
CPU.FPR[frd] = static_cast<float>(1.0f/CPU.FPR[frb]);
double res;
if(_fpclass(CPU.FPR[frb]) >= _FPCLASS_NZ)
{
res = static_cast<float>(1.0 / CPU.FPR[frb]);
if(FPRdouble::IsINF(res) && CPU.FPR[frb] != 0.0)
{
if(res > 0.0)
{
(u64&)res = 0x47EFFFFFE0000000ULL;
}
else
{
(u64&)res = 0xC7EFFFFFE0000000ULL;
}
}
}
else
{
u64 v = CPU.FPR[frb];
if(v == 0ULL)
{
v = 0x7FF0000000000000ULL;
}
else if(v == 0x8000000000000000ULL)
{
v = 0xFFF0000000000000ULL;
}
else if(FPRdouble::IsNaN(CPU.FPR[frb]))
{
v = 0x7FF8000000000000ULL;
}
else if(CPU.FPR[frb] < 0.0)
{
v = 0x8000000000000000ULL;
}
else
{
v = 0ULL;
}
res = (double&)v;
}
if(CPU.FPR[frb] == 0.0)
{
CPU.SetFPSCRException(FPSCR_ZX);
}
CPU.FPR[frd] = res;
if(rc) UNK("fres.");//CPU.UpdateCR1(CPU.FPR[frd]);
}
void FMULS(u32 frd, u32 fra, u32 frc, bool rc)
@ -3192,31 +3301,31 @@ private:
CPU.FPR[frd] = static_cast<float>(CPU.FPR[fra] * CPU.FPR[frc]);
CPU.FPSCR.FI = 0;
CPU.FPSCR.FR = 0;
CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType();
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) UNK("fmuls.");//CPU.UpdateCR1(CPU.FPR[frd]);
}
void FMADDS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc)
{
CPU.FPR[frd] = static_cast<float>(CPU.FPR[fra] * CPU.FPR[frc] + CPU.FPR[frb]);
CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType();
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) UNK("fmadds.");//CPU.UpdateCR1(CPU.FPR[frd]);
}
void FMSUBS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc)
{
CPU.FPR[frd] = static_cast<float>(CPU.FPR[fra] * CPU.FPR[frc] - CPU.FPR[frb]);
CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType();
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) UNK("fmsubs.");//CPU.UpdateCR1(CPU.FPR[frd]);
}
void FNMSUBS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc)
{
CPU.FPR[frd] = static_cast<float>(-(CPU.FPR[fra] * CPU.FPR[frc] - CPU.FPR[frb]));
CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType();
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) UNK("fnmsubs.");////CPU.UpdateCR1(CPU.FPR[frd]);
}
void FNMADDS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc)
{
CPU.FPR[frd] = static_cast<float>(-(CPU.FPR[fra] * CPU.FPR[frc] + CPU.FPR[frb]));
CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType();
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) UNK("fnmadds.");//CPU.UpdateCR1(CPU.FPR[frd]);
}
void STD(u32 rs, u32 ra, s32 d)
@ -3230,26 +3339,45 @@ private:
Memory.Write64(addr, CPU.GPR[rs]);
CPU.GPR[ra] = addr;
}
void MTFSB1(u32 bt, bool rc)
void MTFSB1(u32 crbd, bool rc)
{
UNIMPLEMENTED();
u64 mask = (1ULL << crbd);
CPU.FPSCR.FPSCR |= mask;
if(rc) UNIMPLEMENTED();
}
void MCRFS(u32 bf, u32 bfa)
void MCRFS(u32 crbd, u32 crbs)
{
UNIMPLEMENTED();
u64 mask = (1ULL << crbd);
CPU.CR.CR &= ~mask;
CPU.CR.CR |= CPU.FPSCR.FPSCR & mask;
}
void MTFSB0(u32 bt, bool rc)
void MTFSB0(u32 crbd, bool rc)
{
UNIMPLEMENTED();
u64 mask = (1ULL << crbd);
CPU.FPSCR.FPSCR &= ~mask;
if(rc) UNIMPLEMENTED();
}
void MTFSFI(u32 crfd, u32 i, bool rc)
{
UNIMPLEMENTED();
u64 mask = (0x1ULL << crfd);
if(i)
{
CPU.FPSCR.FPSCR |= mask;
}
else
{
CPU.FPSCR.FPSCR &= ~mask;
}
if(rc) UNIMPLEMENTED();
}
void MFFS(u32 frd, bool rc)
{
(u64&)CPU.FPR[frd] = CPU.FPSCR.FPSCR;
if(rc) UNK("mffs.");
if(rc) UNIMPLEMENTED();
}
void MTFSF(u32 flm, u32 frb, bool rc)
{
@ -3264,7 +3392,9 @@ private:
}
void FCMPU(u32 crfd, u32 fra, u32 frb)
{
if((CPU.FPSCR.FPRF = FPRdouble::Cmp(CPU.FPR[fra], CPU.FPR[frb])) == 1)
int cmp_res = FPRdouble::Cmp(CPU.FPR[fra], CPU.FPR[frb]);
if(cmp_res == CR_SO)
{
if(FPRdouble::IsSNaN(CPU.FPR[fra]) || FPRdouble::IsSNaN(CPU.FPR[frb]))
{
@ -3272,7 +3402,8 @@ private:
}
}
CPU.SetCR(crfd, CPU.FPSCR.FPRF);
CPU.FPSCR.FPRF = cmp_res;
CPU.SetCR(crfd, cmp_res);
}
void FRSP(u32 frd, u32 frb, bool rc)
{
@ -3392,39 +3523,63 @@ private:
}
void FDIV(u32 frd, u32 fra, u32 frb, bool rc)
{
if(FPRdouble::IsINF(CPU.FPR[fra]) == 0.0 && CPU.FPR[frb] == 0.0)
double res;
if(FPRdouble::IsNaN(CPU.FPR[fra]))
{
CPU.FPSCR.VXZDZ = 1;
res = CPU.FPR[fra];
}
else if(FPRdouble::IsINF(CPU.FPR[fra]) && FPRdouble::IsINF(CPU.FPR[frb]))
else if(FPRdouble::IsNaN(CPU.FPR[frb]))
{
CPU.FPSCR.VXIDI = 1;
res = CPU.FPR[frb];
}
else if(CPU.FPR[fra] != 0.0 && CPU.FPR[frb] == 0.0)
else
{
CPU.SetFPSCRException(FPSCR_ZX);
if(CPU.FPR[frb] == 0.0)
{
if(CPU.FPR[fra] == 0.0)
{
CPU.FPSCR.VXZDZ = 1;
res = FPR_NAN;
}
else
{
res = CPU.FPR[fra] / CPU.FPR[frb];
}
CPU.SetFPSCRException(FPSCR_ZX);
}
else if(FPRdouble::IsINF(CPU.FPR[fra]) && FPRdouble::IsINF(CPU.FPR[frb]))
{
CPU.FPSCR.VXIDI = 1;
res = FPR_NAN;
}
else
{
res = CPU.FPR[fra] / CPU.FPR[frb];
}
}
CPU.FPR[frd] = CPU.FPR[fra] / CPU.FPR[frb];
CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType();
CPU.FPR[frd] = res;
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) UNK("fdiv.");//CPU.UpdateCR1(CPU.FPR[frd]);
}
void FSUB(u32 frd, u32 fra, u32 frb, bool rc)
{
CPU.FPR[frd] = CPU.FPR[fra] - CPU.FPR[frb];
CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType();
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) UNK("fsub.");//CPU.UpdateCR1(CPU.FPR[frd]);
}
void FADD(u32 frd, u32 fra, u32 frb, bool rc)
{
CPU.FPR[frd] = CPU.FPR[fra] + CPU.FPR[frb];
CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType();
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) UNK("fadd.");//CPU.UpdateCR1(CPU.FPR[frd]);
}
void FSQRT(u32 frd, u32 frb, bool rc)
{
CPU.FPR[frd] = sqrt(CPU.FPR[frb]);
CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType();
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) UNK("fsqrt.");//CPU.UpdateCR1(CPU.FPR[frd]);
}
void FSEL(u32 frd, u32 fra, u32 frc, u32 frb, bool rc)
@ -3434,50 +3589,68 @@ private:
}
void FMUL(u32 frd, u32 fra, u32 frc, bool rc)
{
CPU.FPR[frd] = CPU.FPR[fra] * CPU.FPR[frc];
CPU.FPSCR.FI = 0;
CPU.FPSCR.FR = 0;
CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType();
if((FPRdouble::IsINF(CPU.FPR[fra]) && CPU.FPR[frc] == 0.0) || (FPRdouble::IsINF(CPU.FPR[frc]) && CPU.FPR[fra] == 0.0))
{
CPU.SetFPSCRException(FPSCR_VXIMZ);
CPU.FPR[frd] = FPR_NAN;
CPU.FPSCR.FI = 0;
CPU.FPSCR.FR = 0;
CPU.FPSCR.FPRF = FPR_QNAN;
}
else
{
if(FPRdouble::IsSNaN(CPU.FPR[fra]) || FPRdouble::IsSNaN(CPU.FPR[frc]))
{
CPU.SetFPSCRException(FPSCR_VXSNAN);
}
CPU.FPR[frd] = CPU.FPR[fra] * CPU.FPR[frc];
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
}
if(rc) UNK("fmul.");//CPU.UpdateCR1(CPU.FPR[frd]);
}
void FRSQRTE(u32 frd, u32 frb, bool rc)
{
UNIMPLEMENTED();
//CPU.FPR[frd] = 1.0f / (float)sqrt(CPU.FPR[frb]);
}
void FMSUB(u32 frd, u32 fra, u32 frc, u32 frb, bool rc)
{
CPU.FPR[frd] = CPU.FPR[fra] * CPU.FPR[frc] - CPU.FPR[frb];
CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType();
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) UNK("fmsub.");//CPU.UpdateCR1(CPU.FPR[frd]);
}
void FMADD(u32 frd, u32 fra, u32 frc, u32 frb, bool rc)
{
CPU.FPR[frd] = CPU.FPR[fra] * CPU.FPR[frc] + CPU.FPR[frb];
CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType();
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) UNK("fmadd.");//CPU.UpdateCR1(CPU.FPR[frd]);
}
void FNMSUB(u32 frd, u32 fra, u32 frc, u32 frb, bool rc)
{
CPU.FPR[frd] = -(CPU.FPR[fra] * CPU.FPR[frc] - CPU.FPR[frb]);
CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType();
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) UNK("fnmsub.");//CPU.UpdateCR1(CPU.FPR[frd]);
}
void FNMADD(u32 frd, u32 fra, u32 frc, u32 frb, bool rc)
{
CPU.FPR[frd] = -(CPU.FPR[fra] * CPU.FPR[frc] + CPU.FPR[frb]);
CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType();
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) UNK("fnmadd.");//CPU.UpdateCR1(CPU.FPR[frd]);
}
void FCMPO(u32 crfd, u32 fra, u32 frb)
{
if((CPU.FPSCR.FPRF = FPRdouble::Cmp(CPU.FPR[fra], CPU.FPR[frb])) == 1)
int cmp_res = FPRdouble::Cmp(CPU.FPR[fra], CPU.FPR[frb]);
if(cmp_res == CR_SO)
{
if(FPRdouble::IsSNaN(CPU.FPR[fra]) || FPRdouble::IsSNaN(CPU.FPR[frb]))
{
CPU.SetFPSCRException(FPSCR_VXSNAN);
if(!CPU.FPSCR.VE) CPU.SetFPSCRException(FPSCR_VXVC);
}
else if(FPRdouble::IsQNaN(CPU.FPR[fra]) || FPRdouble::IsQNaN(CPU.FPR[frb]))
else
{
CPU.SetFPSCRException(FPSCR_VXVC);
}
@ -3485,7 +3658,8 @@ private:
CPU.FPSCR.FX = 1;
}
CPU.SetCR(crfd, CPU.FPSCR.FPRF);
CPU.FPSCR.FPRF = cmp_res;
CPU.SetCR(crfd, cmp_res);
}
void FNEG(u32 frd, u32 frb, bool rc)
{
@ -3499,7 +3673,7 @@ private:
}
void FNABS(u32 frd, u32 frb, bool rc)
{
(u64&)CPU.FPR[frd] = (u64&)CPU.FPR[frb] | 0x8000000000000000ULL;
CPU.FPR[frd] = -fabs(CPU.FPR[frb]);
if(rc) UNK("fnabs.");//CPU.UpdateCR1(CPU.FPR[frd]);
}
void FABS(u32 frd, u32 frb, bool rc)
@ -3610,7 +3784,24 @@ private:
}
void FCFID(u32 frd, u32 frb, bool rc)
{
CPU.FPR[frd] = (double)(u64&)CPU.FPR[frb];
s64 bi = (s64&)CPU.FPR[frb];
double bf = (double)bi;
s64 bfi = (s64)bf;
if(bi == bfi)
{
CPU.SetFPSCR_FI(0);
CPU.FPSCR.FR = 0;
}
else
{
CPU.SetFPSCR_FI(1);
CPU.FPSCR.FR = abs(bfi) > abs(bi);
}
CPU.FPR[frd] = bf;
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) UNK("fcfid.");//CPU.UpdateCR1(CPU.FPR[frd]);
}

View File

@ -318,7 +318,6 @@ namespace PPU_opcodes
DST = 0x156, //Data Stream Touch
LHAX = 0x157,
LVXL = 0x167, //Load Vector Indexed Last
ABS = 0x168,
MFTB = 0x173,
DSTST = 0x176, //Data Stream Touch for Store
LHAUX = 0x177,
@ -436,8 +435,8 @@ public:
static u64 branchTarget(const u64 pc, const u64 imm)
{
return pc + (imm & ~0x3);
}
return pc + (imm & ~0x3ULL);
}
virtual void NULL_OP() = 0;
virtual void NOP() = 0;
@ -498,7 +497,7 @@ public:
virtual void VCTUXS(u32 vd, u32 uimm5, u32 vb) = 0;
virtual void VEXPTEFP(u32 vd, u32 vb) = 0;
virtual void VLOGEFP(u32 vd, u32 vb) = 0;
virtual void VMADDFP(u32 vd, u32 va, u32 vb, u32 vc) = 0;
virtual void VMADDFP(u32 vd, u32 va, u32 vc, u32 vb) = 0;
virtual void VMAXFP(u32 vd, u32 va, u32 vb) = 0;
virtual void VMAXSB(u32 vd, u32 va, u32 vb) = 0;
virtual void VMAXSH(u32 vd, u32 va, u32 vb) = 0;
@ -536,7 +535,7 @@ public:
virtual void VMULOSH(u32 vd, u32 va, u32 vb) = 0;
virtual void VMULOUB(u32 vd, u32 va, u32 vb) = 0;
virtual void VMULOUH(u32 vd, u32 va, u32 vb) = 0;
virtual void VNMSUBFP(u32 vd, u32 va, u32 vb, u32 vc) = 0;
virtual void VNMSUBFP(u32 vd, u32 va, u32 vc, u32 vb) = 0;
virtual void VNOR(u32 vd, u32 va, u32 vb) = 0;
virtual void VOR(u32 vd, u32 va, u32 vb) = 0;
virtual void VPERM(u32 vd, u32 va, u32 vb, u32 vc) = 0;
@ -675,7 +674,7 @@ public:
virtual void STVEBX(u32 vs, u32 ra, u32 rb) = 0;
virtual void SUBFE(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) = 0;
virtual void ADDE(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) = 0;
virtual void MTOCRF(u32 crm, u32 rs) = 0;
virtual void MTOCRF(u32 l, u32 crm, u32 rs) = 0;
virtual void STDX(u32 rs, u32 ra, u32 rb) = 0;
virtual void STWCX_(u32 rs, u32 ra, u32 rb) = 0;
virtual void STWX(u32 rs, u32 ra, u32 rb) = 0;
@ -701,7 +700,6 @@ public:
virtual void DST(u32 ra, u32 rb, u32 strm, u32 t) = 0;
virtual void LHAX(u32 rd, u32 ra, u32 rb) = 0;
virtual void LVXL(u32 vd, u32 ra, u32 rb) = 0;
virtual void ABS(u32 rd, u32 ra, u32 oe, bool rc) = 0;
virtual void MFTB(u32 rd, u32 spr) = 0;
virtual void DSTST(u32 ra, u32 rb, u32 strm, u32 t) = 0;
virtual void LHAUX(u32 rd, u32 ra, u32 rb) = 0;
@ -741,7 +739,7 @@ public:
virtual void SRADI1(u32 ra, u32 rs, u32 sh, bool rc) = 0;
virtual void SRADI2(u32 ra, u32 rs, u32 sh, bool rc) = 0;
virtual void EIEIO() = 0;
virtual void STVLXL(u32 sd, u32 ra, u32 rb) = 0;
virtual void STVLXL(u32 vs, u32 ra, u32 rb) = 0;
virtual void EXTSH(u32 ra, u32 rs, bool rc) = 0;
virtual void STVRXL(u32 sd, u32 ra, u32 rb) = 0;
virtual void EXTSB(u32 ra, u32 rs, bool rc) = 0;

View File

@ -72,7 +72,7 @@ SectionInfo::SectionInfo(const wxString& _name) : name(_name)
shdr.sh_offset = section_offs;
shdr.sh_name = section_name_offs;
section_name_offs += name.Len() + 1;
section_name_offs += name.GetCount() + 1;
}
void SectionInfo::SetDataSize(u32 size, u32 align)
@ -107,11 +107,11 @@ SectionInfo::~SectionInfo()
for(u32 i=section_num + 1; i<sections_list.GetCount(); ++i)
{
sections_list[i].shdr.sh_offset -= code.GetCount();
sections_list[i].shdr.sh_name -= name.Len();
sections_list[i].shdr.sh_name -= name.GetCount();
}
section_offs -= code.GetCount();
section_name_offs -= name.Len();
section_name_offs -= name.GetCount();
}
CompilePPUProgram::CompilePPUProgram(
@ -302,7 +302,7 @@ int CompilePPUProgram::GetArg(wxString& result, bool func)
case 'r': result = result(0, pos) + '\r' + result(pos+2, result.Len()-(pos+2)); break;
case 't': result = result(0, pos) + '\t' + result(pos+2, result.Len()-(pos+2)); break;
}
pos++;
}
}
@ -354,7 +354,7 @@ bool CompilePPUProgram::CheckEnd(bool show_err)
void CompilePPUProgram::DetectArgInfo(Arg& arg)
{
const wxString str = arg.string;
const wxString str = arg.string.GetPtr();
if(str.Len() <= 0)
{
@ -372,7 +372,7 @@ void CompilePPUProgram::DetectArgInfo(Arg& arg)
{
for(u32 i=0; i<m_branches.GetCount(); ++i)
{
if(m_branches[i].m_name.Cmp(str) != 0) continue;
if(str.Cmp(m_branches[i].m_name.GetPtr()) != 0) continue;
arg.type = ARG_BRANCH;
arg.value = GetBranchValue(str);
@ -532,7 +532,7 @@ u32 CompilePPUProgram::GetBranchValue(const wxString& branch)
{
for(u32 i=0; i<m_branches.GetCount(); ++i)
{
if(m_branches[i].m_name.Cmp(branch) != 0) continue;
if(branch.Cmp(m_branches[i].m_name.GetPtr()) != 0) continue;
if(m_branches[i].m_pos >= 0) return m_text_addr + m_branches[i].m_pos * 4;
return m_branches[i].m_addr;
@ -664,7 +664,7 @@ CompilePPUProgram::Branch& CompilePPUProgram::GetBranch(const wxString& name)
{
for(u32 i=0; i<m_branches.GetCount(); ++i)
{
if(m_branches[i].m_name.Cmp(name) != 0) continue;
if(name.Cmp(m_branches[i].m_name.GetPtr()) != 0) continue;
return m_branches[i];
}
@ -684,7 +684,7 @@ void CompilePPUProgram::SetSp(const wxString& name, u32 addr, bool create)
for(u32 i=0; i<m_branches.GetCount(); ++i)
{
if(m_branches[i].m_name.Cmp(name) != 0) continue;
if(name.Cmp(m_branches[i].m_name.GetPtr()) != 0) continue;
m_branches[i].m_addr = addr;
}
}
@ -803,7 +803,7 @@ void CompilePPUProgram::LoadSp(const wxString& op, Elf64_Shdr& s_opd)
for(u32 i=0; i<m_sp_string.GetCount(); ++i)
{
if(m_sp_string[i].m_data.Cmp(src1) != 0) continue;
if(src1.Cmp(m_sp_string[i].m_data.GetPtr()) != 0) continue;
*dst_branch = Branch(dst, -1, m_sp_string[i].m_addr);
founded = true;
}
@ -827,7 +827,7 @@ void CompilePPUProgram::LoadSp(const wxString& op, Elf64_Shdr& s_opd)
{
if(m_sp_string[i].m_addr == a_src1.value)
{
*dst_branch = Branch(dst, -1, m_sp_string[i].m_data.Len());
*dst_branch = Branch(dst, -1, m_sp_string[i].m_data.GetCount());
break;
}
}
@ -1335,7 +1335,7 @@ void CompilePPUProgram::Compile()
for(u32 i=0; i<m_branches.GetCount(); ++i)
{
if(name.Cmp(m_branches[i].m_name) != 0) continue;
if(name.Cmp(m_branches[i].m_name.GetPtr()) != 0) continue;
WriteError(wxString::Format("'%s' already declared", name));
m_error = true;
break;
@ -1365,7 +1365,7 @@ void CompilePPUProgram::Compile()
bool has_entry = false;
for(u32 i=0; i<m_branches.GetCount(); ++i)
{
if(m_branches[i].m_name.Cmp("entry") != 0) continue;
if(wxString("entry").Cmp(m_branches[i].m_name.GetPtr()) != 0) continue;
has_entry = true;
break;
@ -1510,7 +1510,7 @@ void CompilePPUProgram::Compile()
u32 entry_point = s_text.sh_addr;
for(u32 i=0; i<m_branches.GetCount(); ++i)
{
if(m_branches[i].m_name.Cmp("entry") == 0)
if(wxString("entry").Cmp(m_branches[i].m_name.GetPtr()) == 0)
{
entry_point += m_branches[i].m_pos * 4;
break;
@ -1561,7 +1561,7 @@ void CompilePPUProgram::Compile()
for(u32 i=0; i<m_sp_string.GetCount(); ++i)
{
f.Seek(s_opd.sh_offset + (m_sp_string[i].m_addr - s_opd.sh_addr));
f.Write(&m_sp_string[i].m_data[0], m_sp_string[i].m_data.Len() + 1);
f.Write(&m_sp_string[i].m_data[0], m_sp_string[i].m_data.GetCount() + 1);
}
f.Seek(s_sceStub_text.sh_offset);
@ -1576,16 +1576,6 @@ void CompilePPUProgram::Compile()
Write32(f, LWZ(2, 12, 4));
Write32(f, MTSPR(0x009, 0));
Write32(f, BCCTR(20, 0, 0, 0));
/*
Write32(f, ToOpcode(ADDI) | ToRD(12)); //li r12,0
Write32(f, ToOpcode(ORIS) | ToRD(12) | ToRA(12) | ToIMM16(addr >> 16)); //oris r12,r12,addr>>16
Write32(f, ToOpcode(LWZ) | ToRD(12) | ToRA(12) | ToIMM16(addr)); //lwz r12,addr&0xffff(r12)
Write32(f, 0xf8410028); //std r2,40(r1)
Write32(f, ToOpcode(LWZ) | ToRD(0) | ToRA(12) | ToIMM16(0)); //lwz r0,0(r12)
Write32(f, ToOpcode(LWZ) | ToRD(2) | ToRA(12) | ToIMM16(4)); //lwz r2,4(r12)
Write32(f, 0x7c0903a6); //mtctr r0
Write32(f, 0x4e800420); //bctr
*/
}
f.Seek(s_lib_stub_top.sh_offset);

View File

@ -19,7 +19,7 @@ enum ArgType
struct Arg
{
wxString string;
ArrayString string;
u32 value;
ArgType type;
@ -34,7 +34,7 @@ struct Arg
struct SectionInfo
{
Elf64_Shdr shdr;
wxString name;
ArrayString name;
Array<u8> code;
u32 section_num;
@ -62,7 +62,7 @@ class CompilePPUProgram
{
struct Branch
{
wxString m_name;
ArrayString m_name;
s32 m_pos;
s32 m_id;
s32 m_addr;
@ -101,7 +101,7 @@ class CompilePPUProgram
struct SpData
{
wxString m_data;
ArrayString m_data;
u32 m_addr;
SpData(const wxString& data, u32 addr)

View File

@ -3,14 +3,14 @@
#include "Emu/Cell/PPUDecoder.h"
#include "Emu/Cell/PPUInterpreter.h"
#include "Emu/Cell/PPUDisAsm.h"
#include <thread>
extern gcmInfo gcm_info;
PPUThread& GetCurrentPPUThread()
{
PPCThread* thread = GetCurrentPPCThread();
if(!thread || thread->IsSPU()) throw wxString("GetCurrentPPUThread: bad thread");
if(!thread || thread->GetType() != PPC_THREAD_PPU) throw wxString("GetCurrentPPUThread: bad thread");
return *(PPUThread*)thread;
}
@ -60,28 +60,15 @@ void PPUThread::AddArgv(const wxString& arg)
void PPUThread::InitRegs()
{
const u32 entry = Memory.Read32(PC);
const u32 rtoc = Memory.Read32(PC + 4);
const u32 pc = Memory.Read32(entry);
const u32 rtoc = Memory.Read32(entry + 4);
ConLog.Write("entry = 0x%x", entry);
ConLog.Write("rtoc = 0x%x", rtoc);
//ConLog.Write("entry = 0x%x", entry);
//ConLog.Write("rtoc = 0x%x", rtoc);
SetPc(entry);
u64 argc = m_arg;
u64 argv = 0;
SetPc(pc);
if(argv_addr.GetCount())
{
argc = argv_addr.GetCount();
stack_point -= 0xc + 4 * argc;
argv = stack_point;
mem64_t argv_list(argv);
for(int i=0; i<argc; ++i) argv_list += argv_addr[i];
}
const s32 thread_num = Emu.GetCPU().GetThreadNumById(!IsSPU(), GetId());
const s32 thread_num = Emu.GetCPU().GetThreadNumById(GetType(), GetId());
if(thread_num < 0)
{
@ -106,31 +93,50 @@ void PPUThread::InitRegs()
GPR[1] = stack_point;
GPR[2] = rtoc;
if(argc)
for(int i=4; i<32; ++i)
{
if(i != 6)
GPR[i] = (i+1) * 0x10000;
}
if(argv_addr.GetCount())
{
u64 argc = argv_addr.GetCount();
stack_point -= 0xc + 4 * argc;
u64 argv = stack_point;
mem64_t argv_list(argv);
for(int i=0; i<argc; ++i) argv_list += argv_addr[i];
GPR[3] = argc;
GPR[4] = argv;
GPR[5] = argv ? argv - 0xc - 4 * argc : 0; //unk
GPR[5] = argv ? argv + 0xc + 4 * argc : 0; //unk
}
else
{
GPR[3] = m_arg;
GPR[3] = m_args[0];
GPR[4] = m_args[1];
GPR[5] = m_args[2];
GPR[6] = m_args[3];
}
GPR[0] = entry;
//GPR[7] = 0x80d90;
u32 prx_mem = Memory.PRXMem.Alloc(0x10000);
Memory.Write64(prx_mem, 0xDEADBEEFABADCAFE);
GPR[0] = pc;
GPR[8] = entry;
//GPR[10] = 0x131700;
GPR[11] = 0x80;
GPR[12] = Emu.GetMallocPageSize();
GPR[13] = Memory.MainMem.Alloc(0x10000) + 0x7060;
GPR[13] = prx_mem + 0x7060;
GPR[28] = GPR[4];
GPR[29] = GPR[3];
GPR[31] = GPR[5];
LR = Emu.GetPPUThreadExit();
CTR = PC;
CR.CR = 0x22000082;
VSCR.NJ = 1;
TB = 0;
}
u64 PPUThread::GetFreeStackSize() const
@ -174,15 +180,31 @@ bool dump_enable = false;
void PPUThread::DoCode(const s32 code)
{
#ifdef _DEBUG
static bool is_last_enabled = false;
if(dump_enable)
{
static wxFile f("dump.txt", wxFile::write);
static PPU_DisAsm disasm(*this, DumpMode);
static PPU_Decoder decoder(disasm);
if(!is_last_enabled)
{
f.Write(RegsToString() + "\n");
}
disasm.dump_pc = PC;
decoder.Decode(code);
f.Write(disasm.last_opcode);
is_last_enabled = true;
}
else
{
is_last_enabled = false;
}
#endif
if(++cycle > 220)
{
@ -195,7 +217,7 @@ void PPUThread::DoCode(const s32 code)
bool FPRdouble::IsINF(PPCdouble d)
{
return wxFinite(d) ? 1 : 0;
return ((u64&)d & 0x7FFFFFFFFFFFFFFFULL) == 0x7FF0000000000000ULL;
}
bool FPRdouble::IsNaN(PPCdouble d)
@ -205,12 +227,18 @@ bool FPRdouble::IsNaN(PPCdouble d)
bool FPRdouble::IsQNaN(PPCdouble d)
{
return d.GetType() == FPR_QNAN;
return
((u64&)d & 0x7FF0000000000000ULL) == 0x7FF0000000000000ULL &&
((u64&)d & 0x0007FFFFFFFFFFFULL) == 0ULL &&
((u64&)d & 0x000800000000000ULL) != 0ULL;
}
bool FPRdouble::IsSNaN(PPCdouble d)
{
return d.GetType() == FPR_SNAN;
return
((u64&)d & 0x7FF0000000000000ULL) == 0x7FF0000000000000ULL &&
((u64&)d & 0x000FFFFFFFFFFFFFULL) != 0ULL &&
((u64&)d & 0x0008000000000000ULL) == 0ULL;
}
int FPRdouble::Cmp(PPCdouble a, PPCdouble b)

View File

@ -18,6 +18,18 @@ enum
CR_SO = 0x1,
};
enum
{
PPU_THREAD_STATUS_IDLE = (1 << 0),
PPU_THREAD_STATUS_RUNNABLE = (1 << 1),
PPU_THREAD_STATUS_ONPROC = (1 << 2),
PPU_THREAD_STATUS_SLEEP = (1 << 3),
PPU_THREAD_STATUS_STOP = (1 << 4),
PPU_THREAD_STATUS_ZOMBIE = (1 << 5),
PPU_THREAD_STATUS_DELETED = (1 << 6),
PPU_THREAD_STATUS_UNKNOWN = (1 << 7),
};
enum FPSCR_EXP
{
FPSCR_FX = 0x80000000,
@ -286,11 +298,11 @@ union VSCRhdr
enum FPRType
{
FPR_NORM,
FPR_ZERO,
FPR_SNAN,
//FPR_NORM,
//FPR_ZERO,
//FPR_SNAN,
//FPR_QNAN,
FPR_INF,
//FPR_INF,
FPR_PZ = 0x2,
FPR_PN = 0x4,
FPR_PINF = 0x5,
@ -302,6 +314,9 @@ enum FPRType
FPR_ND = 0x18,
};
static const u64 FPR_NAN_I = 0x7FF8000000000000ULL;
static const double& FPR_NAN = (double&)FPR_NAN_I;
struct PPCdouble
{
union
@ -342,7 +357,7 @@ struct PPCdouble
switch(fpc)
{
case _FPCLASS_SNAN: return FPR_SNAN;
case _FPCLASS_SNAN:// return FPR_SNAN;
case _FPCLASS_QNAN: return FPR_QNAN;
case _FPCLASS_NINF: return FPR_NINF;
case _FPCLASS_NN: return FPR_NN;
@ -652,6 +667,30 @@ public:
SetCR_SO(n, XER.SO);
}
void UpdateCRnU(const u8 l, const u8 n, const u64 a, const u64 b)
{
if(l)
{
UpdateCRn<u64>(n, a, b);
}
else
{
UpdateCRn<u32>(n, a, b);
}
}
void UpdateCRnS(const u8 l, const u8 n, const u64 a, const u64 b)
{
if(l)
{
UpdateCRn<s64>(n, a, b);
}
else
{
UpdateCRn<s32>(n, a, b);
}
}
template<typename T> void UpdateCR0(const T val)
{
UpdateCRn<T>(0, val, 0);
@ -683,7 +722,7 @@ public:
void SetFPSCR_FI(const u32 val)
{
if(val) SetFPSCRException(FPSCR_XX);
FPSCR.FI = val;
FPSCR.FI = val;
}
virtual wxString RegsToString()

View File

@ -0,0 +1,131 @@
#include "stdafx.h"
#include "Emu/Cell/RawSPUThread.h"
RawSPUThread::RawSPUThread(PPCThreadType type) : SPUThread(type)
{
Reset();
}
RawSPUThread::~RawSPUThread()
{
}
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];
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();
}
void RawSPUThread::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;
}
}
bool is_last_paused = false;
while(true)
{
int status = ThreadStatus();
if(status == PPCThread_Stopped || status == PPCThread_Break)
{
break;
}
if(status == PPCThread_Sleeping)
{
Sleep(1);
continue;
}
mfc.Handle();
if(mfc.SPU_RunCntl.GetValue() != SPU_RUNCNTL_RUNNABLE)
{
if(!is_last_paused)
{
if(is_last_paused = mfc.SPU_RunCntl.GetValue() != SPU_RUNCNTL_RUNNABLE)
{
mfc.SPU_NPC.SetValue(PC);
mfc.SPU_Status.SetValue(SPU_STATUS_WAITING_FOR_CHANNEL);
}
}
Sleep(1);
continue;
}
if(is_last_paused)
{
is_last_paused = false;
PC = mfc.SPU_NPC.GetValue();
mfc.SPU_Status.SetValue(SPU_STATUS_RUNNING);
}
DoCode(Memory.Read32(m_offset + PC));
NextPc();
for(uint i=0; i<bp.GetCount(); ++i)
{
if(bp[i] == m_offset + PC)
{
Emu.Pause();
break;
}
}
}
}
catch(const wxString& e)
{
ConLog.Error("Exception: %s", e);
}
catch(const char* e)
{
ConLog.Error("Exception: %s", e);
}
ConLog.Write("%s leave", PPCThread::GetFName());
}

View File

@ -0,0 +1,71 @@
#pragma once
#include "SPUThread.h"
#include "Emu/event.h"
enum
{
MFC_LSA_offs = 0x3004,
MFC_EAH_offs = 0x3008,
MFC_EAL_offs = 0x300C,
MFC_Size_Tag_offs = 0x3010,
MFC_Class_CMD_offs = 0x3014,
MFC_CMDStatus_offs = 0x3014,
MFC_QStatus_offs = 0x3104,
Prxy_QueryType_offs = 0x3204,
Prxy_QueryMask_offs = 0x321C,
Prxy_TagStatus_offs = 0x322C,
SPU_Out_MBox_offs = 0x4004,
SPU_In_MBox_offs = 0x400C,
SPU_MBox_Status_offs = 0x4014,
SPU_RunCntl_offs = 0x401C,
SPU_Status_offs = 0x4024,
SPU_NPC_offs = 0x4034,
SPU_RdSigNotify1_offs = 0x1400C,
SPU_RdSigNotify2_offs = 0x1C00C,
};
enum : u64
{
RAW_SPU_OFFSET = 0x0000000000100000,
RAW_SPU_BASE_ADDR = 0x00000000E0000000,
RAW_SPU_LS_OFFSET = 0x0000000000000000,
RAW_SPU_PROB_OFFSET = 0x0000000000040000,
};
__forceinline static u32 GetRawSPURegAddrByNum(int num, int offset)
{
return RAW_SPU_OFFSET * num + RAW_SPU_BASE_ADDR + RAW_SPU_PROB_OFFSET + offset;
}
__forceinline static u32 GetRawSPURegAddrById(int id, int offset)
{
return GetRawSPURegAddrByNum(Emu.GetCPU().GetThreadNumById(PPC_THREAD_RAW_SPU, id), offset);
}
class RawSPUThread : public SPUThread
{
public:
RawSPUThread(PPCThreadType type = PPC_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 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); }
public:
virtual void InitRegs();
private:
virtual void Task();
};
SPUThread& GetCurrentSPUThread();

View File

@ -24,9 +24,3 @@ public:
(*SPU_instr::rrr_list)(m_op, code);
}
};
#undef START_OPCODES_GROUP_
#undef START_OPCODES_GROUP
#undef ADD_OPCODE
#undef ADD_NULL_OPCODE
#undef END_OPCODES_GROUP

File diff suppressed because it is too large Load Diff

View File

@ -27,18 +27,22 @@ private:
//0 - 10
void STOP(u32 code)
{
Emu.Pause();
if(code & 0x2000)
{
CPU.SetExitStatus(code & 0xfff);
CPU.Stop();
}
}
void LNOP()
{
}
void SYNC(u32 Cbit)
{
UNIMPLEMENTED();
//UNIMPLEMENTED();
}
void DSYNC()
{
UNIMPLEMENTED();
//UNIMPLEMENTED();
}
void MFSPR(u32 rt, u32 sa)
{
@ -51,7 +55,7 @@ private:
void RCHCNT(u32 rt, u32 ra)
{
CPU.GPR[rt].Reset();
CPU.GPR[rt]._u32[0] = CPU.GetChannelCount(ra);
CPU.GPR[rt]._u32[3] = CPU.GetChannelCount(ra);
}
void SF(u32 rt, u32 ra, u32 rb)
{
@ -280,16 +284,15 @@ private:
}
void STQX(u32 rt, u32 ra, u32 rb)
{
CPU.LSA = CPU.GPR[ra]._u32[0] + CPU.GPR[rb]._u32[0];
CPU.WriteLSA128(CPU.GPR[rt]._u128);
CPU.WriteLS128(CPU.GPR[ra]._u32[0] + CPU.GPR[rb]._u32[0], CPU.GPR[rt]._u128);
}
void BI(u32 ra)
{
CPU.SetBranch(CPU.GPR[ra]._u32[0] & 0xfffffffc);
CPU.SetBranch(CPU.GPR[ra]._u32[3] & 0xfffffffc);
}
void BISL(u32 rt, u32 ra)
{
CPU.SetBranch(CPU.GPR[ra]._u32[0] & 0xfffffffc);
CPU.SetBranch(CPU.GPR[ra]._u32[3] & 0xfffffffc);
CPU.GPR[rt].Reset();
CPU.GPR[rt]._u32[0] = CPU.PC + 4;
}
@ -353,8 +356,7 @@ private:
}
void LQX(u32 rt, u32 ra, u32 rb)
{
CPU.LSA = CPU.GPR[ra]._u32[0] + CPU.GPR[rb]._u32[0];
CPU.GPR[rt]._u128 = CPU.ReadLSA128();
CPU.GPR[rt]._u128 = CPU.ReadLS128(CPU.GPR[ra]._u32[0] + CPU.GPR[rb]._u32[0]);
}
void ROTQBYBI(u32 rt, u32 ra, u32 rb)
{
@ -870,8 +872,6 @@ private:
UNIMPLEMENTED();
}
//0 - 9
void CFLTS(u32 rt, u32 ra, s32 i8)
{
@ -890,35 +890,31 @@ private:
UNIMPLEMENTED();
}
//0 - 8
void BRZ(u32 rt, s32 i16)
{
if(!CPU.GPR[rt]._u32[0]) CPU.SetBranch(branchTarget(CPU.PC, i16));
if(!CPU.GPR[rt]._u32[3]) CPU.SetBranch(branchTarget(CPU.PC, i16));
}
void STQA(u32 rt, s32 i16)
{
CPU.LSA = i16 << 2;
CPU.WriteLSA128(CPU.GPR[rt]._u128);
CPU.WriteLS128(i16 << 2, CPU.GPR[rt]._u128);
}
void BRNZ(u32 rt, s32 i16)
{
if(CPU.GPR[rt]._u32[0] != 0)
if(CPU.GPR[rt]._u32[3] != 0)
CPU.SetBranch(branchTarget(CPU.PC, i16));
}
void BRHZ(u32 rt, s32 i16)
{
if(!CPU.GPR[rt]._u16[0]) CPU.SetBranch(branchTarget(CPU.PC, i16));
if(!CPU.GPR[rt]._u16[7]) CPU.SetBranch(branchTarget(CPU.PC, i16));
}
void BRHNZ(u32 rt, s32 i16)
{
if(CPU.GPR[rt]._u16[0]) CPU.SetBranch(branchTarget(CPU.PC, i16));
if(CPU.GPR[rt]._u16[7]) CPU.SetBranch(branchTarget(CPU.PC, i16));
}
void STQR(u32 rt, s32 i16)
{
CPU.LSA = branchTarget(CPU.PC, i16);
CPU.WriteLSA128(CPU.GPR[rt]._u128);
CPU.WriteLS128(branchTarget(CPU.PC, i16), CPU.GPR[rt]._u128);
}
void BRA(s32 i16)
{
@ -926,14 +922,7 @@ private:
}
void LQA(u32 rt, s32 i16)
{
CPU.LSA = i16 << 2;
if(!Memory.IsGoodAddr(CPU.LSA))
{
ConLog.Warning("LQA: Bad addr: 0x%x", CPU.LSA);
return;
}
CPU.GPR[rt]._u128 = CPU.ReadLSA128();
CPU.GPR[rt]._u128 = CPU.ReadLS128(i16 << 2);
}
void BRASL(u32 rt, s32 i16)
{
@ -964,19 +953,12 @@ private:
void BRSL(u32 rt, s32 i16)
{
CPU.GPR[rt].Reset();
CPU.GPR[rt]._u32[0] = CPU.PC + 4;
CPU.GPR[rt]._u32[3] = CPU.PC + 4;
CPU.SetBranch(branchTarget(CPU.PC, i16));
}
void LQR(u32 rt, s32 i16)
{
CPU.LSA = branchTarget(CPU.PC, i16);
if(!Memory.IsGoodAddr(CPU.LSA))
{
ConLog.Warning("LQR: Bad addr: 0x%x", CPU.LSA);
return;
}
CPU.GPR[rt]._u128 = CPU.ReadLSA128();
CPU.GPR[rt]._u128 = CPU.ReadLS128(branchTarget(CPU.PC, i16));
}
void IL(u32 rt, s32 i16)
{
@ -988,7 +970,7 @@ private:
void ILHU(u32 rt, s32 i16)
{
for (int w = 0; w < 4; w++)
CPU.GPR[rt]._u16[w*2] = i16;
CPU.GPR[rt]._u16[w*2 + 1] = i16;
}
void ILH(u32 rt, s32 i16)
{
@ -1061,13 +1043,11 @@ private:
}
void STQD(u32 rt, s32 i10, u32 ra)
{
CPU.LSA = branchTarget(0, i10 + CPU.GPR[ra]._u32[0]);
CPU.WriteLSA128(CPU.GPR[rt]._u128);
CPU.WriteLS128(CPU.GPR[ra]._u32[3] + i10, CPU.GPR[rt]._u128);
}
void LQD(u32 rt, s32 i10, u32 ra)
{
CPU.LSA = branchTarget(0, i10 + CPU.GPR[ra]._u32[0]);
CPU.GPR[rt]._u128 = CPU.ReadLSA128();
CPU.GPR[rt]._u128 = CPU.ReadLS128(CPU.GPR[ra]._u32[3] + i10);
}
void XORI(u32 rt, u32 ra, s32 i10)
{
@ -1167,10 +1147,6 @@ private:
}
void HBRR(s32 ro, s32 i16)
{
UNIMPLEMENTED();
//CHECK ME
//CPU.GPR[0]._u64[0] = branchTarget(CPU.PC, i16);
//CPU.SetBranch(branchTarget(CPU.PC, ro));
}
void ILA(u32 rt, s32 i18)
{
@ -1189,14 +1165,8 @@ private:
( CPU.GPR[rc]._u32[i] & CPU.GPR[rb]._u32[i]) |
(~CPU.GPR[rc]._u32[i] & CPU.GPR[ra]._u32[i]);
}
/*
CPU.GPR[rt] = _mm_or_si128(
_mm_and_si128(CPU.GPR[rc], CPU.GPR[rb]),
_mm_andnot_si128(CPU.GPR[rc], CPU.GPR[ra])
);
*/
}
void SHUFB(u32 rc, u32 ra, u32 rb, u32 rt)
void SHUFB(u32 rt, u32 ra, u32 rb, u32 rc)
{
ConLog.Warning("SHUFB");
}
@ -1205,7 +1175,7 @@ private:
for (int w = 0; w < 4; w++)
CPU.GPR[rt]._i32[w] = CPU.GPR[ra]._i16[w*2 + 1] * CPU.GPR[rb]._i16[w*2 + 1] + CPU.GPR[rc]._i32[w];
}
void FNMS(u32 rc, u32 ra, u32 rb, u32 rt)
void FNMS(u32 rt, u32 ra, u32 rb, u32 rc)
{
UNIMPLEMENTED();
}

View File

@ -231,8 +231,8 @@ class SPU_Opcodes
public:
static u32 branchTarget(const u64 pc, const s32 imm)
{
return (pc + ((imm << 2) & ~0x3)) & 0x3fff0;
}
return (pc + (imm << 2)) & 0x3fffc;
}
virtual void Exit()=0;

View File

@ -8,12 +8,12 @@ SPUThread& GetCurrentSPUThread()
{
PPCThread* thread = GetCurrentPPCThread();
if(!thread || !thread->IsSPU()) throw wxString("GetCurrentSPUThread: bad thread");
if(!thread || thread->GetType() == PPC_THREAD_PPU) throw wxString("GetCurrentSPUThread: bad thread");
return *(SPUThread*)thread;
}
SPUThread::SPUThread() : PPCThread(PPC_THREAD_SPU)
SPUThread::SPUThread(PPCThreadType type) : PPCThread(type)
{
Reset();
}
@ -26,13 +26,15 @@ void SPUThread::DoReset()
{
//reset regs
for(u32 i=0; i<128; ++i) GPR[i].Reset();
LSA = 0;
}
void SPUThread::InitRegs()
{
GPR[1]._u64[0] = stack_point;
//GPR[1]._u64[0] = stack_point;
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];
}
u64 SPUThread::GetFreeStackSize() const

View File

@ -1,29 +1,31 @@
#pragma once
#include "PPCThread.h"
#include "Emu/event.h"
#include "MFC.h"
static const wxString spu_reg_name[128] =
{
"$LR", "$SP", "$3", "$4", "$5", "$6", "$7", "$8",
"$9", "$10", "$11", "$12", "$13", "$14", "$15", "$16",
"$17", "$18", "$19", "$20", "$21", "$22", "$23", "$24",
"$25", "$26", "$27", "$28", "$29", "$30", "$31", "$32",
"$33", "$34", "$35", "$36", "$37", "$38", "$39", "$40",
"$41", "$42", "$43", "$44", "$45", "$46", "$47", "$48",
"$49", "$50", "$51", "$52", "$53", "$54", "$55", "$56",
"$57", "$58", "$59", "$60", "$61", "$62", "$63", "$64",
"$65", "$66", "$67", "$68", "$69", "$70", "$71", "$72",
"$73", "$74", "$75", "$76", "$77", "$78", "$79", "$80",
"$81", "$82", "$83", "$84", "$85", "$86", "$87", "$88",
"$89", "$90", "$91", "$92", "$93", "$94", "$95", "$96",
"$97", "$98", "$99", "$100", "$101", "$102", "$103", "$104",
"$105", "$106", "$107", "$108", "$109", "$110", "$111", "$112",
"$113", "$114", "$115", "$116", "$117", "$118", "$119", "$120",
"$121", "$122", "$123", "$124", "$125", "$126", "$127",
"$LR", "$SP", "$2", "$3", "$4", "$5", "$6", "$7",
"$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
"$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
"$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31",
"$32", "$33", "$34", "$35", "$36", "$37", "$38", "$39",
"$40", "$41", "$42", "$43", "$44", "$45", "$46", "$47",
"$48", "$49", "$50", "$51", "$52", "$53", "$54", "$55",
"$56", "$57", "$58", "$59", "$60", "$61", "$62", "$63",
"$64", "$65", "$66", "$67", "$68", "$69", "$70", "$71",
"$72", "$73", "$74", "$75", "$76", "$77", "$78", "$79",
"$80", "$81", "$82", "$83", "$84", "$85", "$86", "$87",
"$88", "$89", "$90", "$91", "$92", "$93", "$94", "$95",
"$96", "$97", "$98", "$99", "$100", "$101", "$102", "$103",
"$104", "$105", "$106", "$107", "$108", "$109", "$110", "$111",
"$112", "$113", "$114", "$115", "$116", "$117", "$118", "$119",
"$120", "$121", "$122", "$123", "$124", "$125", "$126", "$127",
};
static const wxString spu_ch_name[128] =
{
"$SPU_RdEventStat", "$SPU_WrEventMask", "$SPU_RdSigNotify1",
"$SPU_RdEventStat", "$SPU_WrEventMask", "$SPU_WrEventAck", "$SPU_RdSigNotify1",
"$SPU_RdSigNotify2", "$ch5", "$ch6", "$SPU_WrDec", "$SPU_RdDec",
"$MFC_WrMSSyncReq", "$ch10", "$SPU_RdEventMask", "$MFC_RdTagMask", "$SPU_RdMachStat",
"$SPU_WrSRR0", "$SPU_RdSRR0", "$MFC_LSA", "$MFC_EAH", "$MFC_EAL", "$MFC_Size",
@ -80,10 +82,24 @@ enum MFCchannels
MFC_RdAtomicStat = 27, //Read completion status of last completed immediate MFC atomic update command
};
enum
{
SPU_RUNCNTL_STOP = 0,
SPU_RUNCNTL_RUNNABLE = 1,
};
enum
{
SPU_STATUS_STOPPED = 0x0,
SPU_STATUS_RUNNING = 0x1,
SPU_STATUS_STOPPED_BY_STOP = 0x2,
SPU_STATUS_STOPPED_BY_HALT = 0x4,
SPU_STATUS_WAITING_FOR_CHANNEL = 0x8,
SPU_STATUS_SINGLE_STEP = 0x10,
};
union SPU_GPR_hdr
{
//__m128i _m128i;
u128 _u128;
s128 _i128;
u64 _u64[2];
@ -96,19 +112,6 @@ union SPU_GPR_hdr
s8 _i8[16];
SPU_GPR_hdr() {}
/*
SPU_GPR_hdr(const __m128i val){_u128._u64[0] = val.m128i_u64[0]; _u128._u64[1] = val.m128i_u64[1];}
SPU_GPR_hdr(const u128 val) { _u128 = val; }
SPU_GPR_hdr(const u64 val) { Reset(); _u64[0] = val; }
SPU_GPR_hdr(const u32 val) { Reset(); _u32[0] = val; }
SPU_GPR_hdr(const u16 val) { Reset(); _u16[0] = val; }
SPU_GPR_hdr(const u8 val) { Reset(); _u8[0] = val; }
SPU_GPR_hdr(const s128 val) { _i128 = val; }
SPU_GPR_hdr(const s64 val) { Reset(); _i64[0] = val; }
SPU_GPR_hdr(const s32 val) { Reset(); _i32[0] = val; }
SPU_GPR_hdr(const s16 val) { Reset(); _i16[0] = val; }
SPU_GPR_hdr(const s8 val) { Reset(); _i8[0] = val; }
*/
wxString ToString() const
{
@ -119,41 +122,34 @@ union SPU_GPR_hdr
{
memset(this, 0, sizeof(*this));
}
//operator __m128i() { __m128i ret; ret.m128i_u64[0]=_u128._u64[0]; ret.m128i_u64[1]=_u128._u64[1]; return ret; }
/*
SPU_GPR_hdr operator ^ (__m128i right) { return _mm_xor_si128(*this, right); }
SPU_GPR_hdr operator | (__m128i right) { return _mm_or_si128 (*this, right); }
SPU_GPR_hdr operator & (__m128i right) { return _mm_and_si128(*this, right); }
SPU_GPR_hdr operator << (int right) { return _mm_slli_epi32(*this, right); }
SPU_GPR_hdr operator << (__m128i right) { return _mm_sll_epi32(*this, right); }
SPU_GPR_hdr operator >> (int right) { return _mm_srai_epi32(*this, right); }
SPU_GPR_hdr operator >> (__m128i right) { return _mm_sra_epi32(*this, right); }
SPU_GPR_hdr operator | (__m128i right) { return _mm_or_si128 (*this, right); }
SPU_GPR_hdr operator & (__m128i right) { return _mm_and_si128(*this, right); }
SPU_GPR_hdr operator << (int right) { return _mm_slli_epi32(*this, right); }
SPU_GPR_hdr operator << (__m128i right) { return _mm_sll_epi32(*this, right); }
SPU_GPR_hdr operator >> (int right) { return _mm_srai_epi32(*this, right); }
SPU_GPR_hdr operator >> (__m128i right) { return _mm_sra_epi32(*this, right); }
SPU_GPR_hdr operator ^= (__m128i right) { return *this = *this ^ right; }
SPU_GPR_hdr operator |= (__m128i right) { return *this = *this | right; }
SPU_GPR_hdr operator &= (__m128i right) { return *this = *this & right; }
SPU_GPR_hdr operator <<= (int right) { return *this = *this << right; }
SPU_GPR_hdr operator <<= (__m128i right){ return *this = *this << right; }
SPU_GPR_hdr operator >>= (int right) { return *this = *this >> right; }
SPU_GPR_hdr operator >>= (__m128i right){ return *this = *this >> right; }
*/
};
class SPUThread : public PPCThread
{
public:
SPU_GPR_hdr GPR[128]; //General-Purpose Register
Stack<u32> Mbox;
u32 LSA; //local storage address
/*
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;
u32 LSA;
MFC mfc;
union
{
@ -165,11 +161,14 @@ public:
{
switch(ch)
{
case SPU_WrOutMbox:
return mfc.SPU_Out_MBox.GetFreeCount();
case SPU_RdInMbox:
return 1;
return mfc.SPU_In_MBox.GetCount();
case SPU_WrOutIntrMbox:
return 0;
return 0;//return SPU_OutIntr_Mbox.GetFreeCount();
default:
ConLog.Error("%s error: unknown/illegal channel (%d).", __FUNCTION__, ch);
@ -181,12 +180,25 @@ public:
void WriteChannel(u32 ch, const SPU_GPR_hdr& r)
{
const u32 v = r._u32[0];
const u32 v = r._u32[3];
switch(ch)
{
case SPU_WrOutIntrMbox:
Mbox.Push(v);
ConLog.Warning("SPU_WrOutIntrMbox = 0x%x", v);
if(!SPU_OutIntr_Mbox.Push(v))
{
ConLog.Warning("Not enought free rooms.");
}
break;
case SPU_WrOutMbox:
ConLog.Warning("SPU_WrOutMbox = 0x%x", v);
if(!mfc.SPU_Out_MBox.Push(v))
{
ConLog.Warning("Not enought free rooms.");
}
mfc.SPU_Status.SetValue((mfc.SPU_Status.GetValue() & ~0xff) | 1);
break;
default:
@ -198,12 +210,13 @@ public:
void ReadChannel(SPU_GPR_hdr& r, u32 ch)
{
r.Reset();
u32& v = r._u32[0];
u32& v = r._u32[3];
switch(ch)
{
case SPU_RdInMbox:
v = Mbox.Pop();
if(!mfc.SPU_In_MBox.Pop(v)) v = 0;
mfc.SPU_Status.SetValue((mfc.SPU_Status.GetValue() & ~0xff00) | (mfc.SPU_In_MBox.GetCount() << 8));
break;
default:
@ -212,20 +225,21 @@ public:
}
}
u8 ReadLSA8 () { return Memory.Read8 (LSA + m_offset); }
u16 ReadLSA16 () { return Memory.Read16 (LSA + m_offset); }
u32 ReadLSA32 () { return Memory.Read32 (LSA + m_offset); }
u64 ReadLSA64 () { return Memory.Read64 (LSA + m_offset); }
u128 ReadLSA128() { return Memory.Read128(LSA + m_offset); }
bool IsGoodLSA(const u32 lsa) const { return Memory.IsGoodAddr(lsa + m_offset); }
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); }
void WriteLSA8 (const u8& data) { Memory.Write8 (LSA + m_offset, data); }
void WriteLSA16 (const u16& data) { Memory.Write16 (LSA + m_offset, data); }
void WriteLSA32 (const u32& data) { Memory.Write32 (LSA + m_offset, data); }
void WriteLSA64 (const u64& data) { Memory.Write64 (LSA + m_offset, data); }
void WriteLSA128(const u128& data) { Memory.Write128(LSA + m_offset, data); }
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); }
public:
SPUThread();
SPUThread(PPCThreadType type = PPC_THREAD_SPU);
~SPUThread();
virtual wxString RegsToString()
@ -246,7 +260,7 @@ protected:
virtual void DoResume();
virtual void DoStop();
private:
protected:
virtual void DoCode(const s32 code);
};

View File

@ -1,5 +1,6 @@
#include "stdafx.h"
#include "VFS.h"
#include "Emu\HDD\HDD.h"
int sort_devices(const void* _a, const void* _b)
{
@ -31,13 +32,23 @@ void VFS::UnMount(const wxString& ps3_path)
{
if(!m_devices[i].GetPs3Path().Cmp(ps3_path))
{
m_devices.RemoveAt(i);
delete &m_devices[i];
m_devices.RemoveFAt(i);
return;
}
}
}
void VFS::UnMountAll()
{
for(u32 i=0; i<m_devices.GetCount(); ++i)
{
delete &m_devices[i];
m_devices.RemoveFAt(i);
}
}
vfsStream* VFS::Open(const wxString& ps3_path, vfsOpenMode mode)
{
vfsDevice* stream = nullptr;
@ -89,3 +100,106 @@ vfsDevice* VFS::GetDevice(const wxString& ps3_path, wxString& path)
path = vfsDevice::GetWinPath(m_devices[max_i].GetLocalPath(), ps3_path(max_eq, ps3_path.Len() - max_eq));
return &m_devices[max_i];
}
void VFS::Init(const wxString& path)
{
Array<VFSManagerEntry> entries;
SaveLoadDevices(entries, true);
for(uint i=0; i<entries.GetCount(); ++i)
{
vfsDevice* dev;
switch(entries[i].device)
{
case vfsDevice_LocalFile:
dev = new vfsLocalFile();
break;
case vfsDevice_HDD:
dev = new vfsHDD(entries[i].device_path.GetPtr());
break;
default:
continue;
}
wxString mpath = entries[i].path.GetPtr();
mpath.Replace("$(EmulatorDir)", wxGetCwd());
mpath.Replace("$(GameDir)", vfsDevice::GetRoot(path));
Mount(entries[i].mount.GetPtr(), mpath, dev);
}
}
void VFS::SaveLoadDevices(Array<VFSManagerEntry>& res, bool is_load)
{
IniEntry<int> entries_count;
entries_count.Init("count", "VFSManager");
int count = 0;
if(is_load)
{
count = entries_count.LoadValue(count);
if(!count)
{
int idx;
idx = res.Move(new VFSManagerEntry());
res[idx].path = "$(EmulatorDir)\\dev_hdd0\\";
res[idx].mount = "/dev_hdd0/";
res[idx].device = vfsDevice_LocalFile;
idx = res.Move(new VFSManagerEntry());
res[idx].path = "$(GameDir)";
res[idx].mount = "";
res[idx].device = vfsDevice_LocalFile;
idx = res.Move(new VFSManagerEntry());
res[idx].path = "$(GameDir)";
res[idx].mount = "/";
res[idx].device = vfsDevice_LocalFile;
idx = res.Move(new VFSManagerEntry());
res[idx].path = "$(GameDir)";
res[idx].mount = "/app_home/";
res[idx].device = vfsDevice_LocalFile;
return;
}
res.SetCount(count);
}
else
{
count = res.GetCount();
entries_count.SaveValue(res.GetCount());
}
for(int i=0; i<count; ++i)
{
IniEntry<wxString> entry_path;
IniEntry<wxString> entry_device_path;
IniEntry<wxString> entry_mount;
IniEntry<int> entry_device;
entry_path.Init(wxString::Format("path[%d]", i), "VFSManager");
entry_device_path.Init(wxString::Format("device_path[%d]", i), "VFSManager");
entry_mount.Init(wxString::Format("mount[%d]", i), "VFSManager");
entry_device.Init(wxString::Format("device[%d]", i), "VFSManager");
if(is_load)
{
new (res + i) VFSManagerEntry();
res[i].path = entry_path.LoadValue(wxEmptyString);
res[i].device_path = entry_device_path.LoadValue(wxEmptyString);
res[i].mount = entry_mount.LoadValue(wxEmptyString);
res[i].device = (vfsDeviceType)entry_device.LoadValue(vfsDevice_LocalFile);
}
else
{
entry_path.SaveValue(res[i].path.GetPtr());
entry_device_path.SaveValue(res[i].device_path.GetPtr());
entry_mount.SaveValue(res[i].mount.GetPtr());
entry_device.SaveValue(res[i].device);
}
}
}

View File

@ -1,15 +1,42 @@
#pragma once
#include "vfsDevice.h"
enum vfsDeviceType
{
vfsDevice_LocalFile,
vfsDevice_HDD,
};
static const char* vfsDeviceTypeNames[] =
{
"Local",
"HDD",
};
struct VFSManagerEntry
{
ArrayString device_path;
ArrayString path;
ArrayString mount;
vfsDeviceType device;
VFSManagerEntry() : device(vfsDevice_LocalFile)
{
}
};
struct VFS
{
ArrayF<vfsDevice> m_devices;
void Mount(const wxString& ps3_path, const wxString& local_path, vfsDevice* device);
void UnMount(const wxString& ps3_path);
void UnMountAll();
vfsStream* Open(const wxString& ps3_path, vfsOpenMode mode);
void Create(const wxString& ps3_path);
void Close(vfsStream*& device);
vfsDevice* GetDevice(const wxString& ps3_path, wxString& path);
void Init(const wxString& path);
void SaveLoadDevices(Array<VFSManagerEntry>& res, bool is_load);
};

View File

@ -198,4 +198,19 @@ wxString vfsDevice::GetPs3Path(const wxString& l, const wxString& r)
if(r.IsEmpty()) return GetPs3Path(l);
return GetPs3Path(l + '/' + r, false);
}
void vfsDevice::Lock() const
{
m_mtx_lock.lock();
}
void vfsDevice::Unlock() const
{
m_mtx_lock.unlock();
}
bool vfsDevice::TryLock() const
{
return m_mtx_lock.try_lock();
}

View File

@ -1,19 +1,23 @@
#pragma once
#include "vfsStream.h"
#include <mutex>
enum vfsOpenMode
{
vfsRead,
vfsWrite,
vfsReadWrite,
vfsWriteExcl,
vfsWriteAppend,
vfsRead = 0x1,
vfsWrite = 0x2,
vfsExcl = 0x4,
vfsAppend = 0x8,
vfsReadWrite = vfsRead | vfsWrite,
vfsWriteExcl = vfsWrite | vfsExcl,
vfsWriteAppend = vfsWrite | vfsAppend,
};
class vfsDevice : public vfsStream
{
wxString m_ps3_path;
wxString m_local_path;
mutable std::mutex m_mtx_lock;
public:
vfsDevice(const wxString& ps3_path, const wxString& local_path);
@ -36,4 +40,24 @@ public:
static wxString GetWinPath(const wxString& l, const wxString& r);
static wxString GetPs3Path(const wxString& p, bool is_dir = true);
static wxString GetPs3Path(const wxString& l, const wxString& r);
void Lock() const;
void Unlock() const;
bool TryLock() const;
};
class vfsDeviceLocker
{
vfsDevice& m_device;
public:
vfsDeviceLocker(vfsDevice& device) : m_device(device)
{
m_device.Lock();
}
~vfsDeviceLocker()
{
m_device.Unlock();
}
};

View File

@ -40,4 +40,4 @@ wxString vfsFileBase::GetPath() const
vfsOpenMode vfsFileBase::GetOpenMode() const
{
return m_mode;
}
}

View File

@ -21,4 +21,4 @@ public:
*/
wxString GetPath() const;
vfsOpenMode GetOpenMode() const;
};
};

View File

@ -92,4 +92,4 @@ u64 vfsLocalFile::Tell() const
bool vfsLocalFile::IsOpened() const
{
return m_file.IsOpened() && vfsFileBase::IsOpened();
}
}

View File

@ -1,26 +1,64 @@
#include "stdafx.h"
#include "FragmentProgram.h"
void FragmentDecompilerThread::AddCode(wxString code)
void FragmentDecompilerThread::AddCode(wxString code, bool append_mask)
{
if(!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_le) return;
if(!src0.exec_if_eq || !src0.exec_if_gr || !src0.exec_if_le)
if(!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt) return;
const wxString mask = GetMask();
wxString cond = wxEmptyString;
if(!src0.exec_if_gr || !src0.exec_if_lt || !src0.exec_if_eq)
{
ConLog.Error("Bad cond! eq: %d gr: %d le: %d", src0.exec_if_eq, src0.exec_if_gr, src0.exec_if_le);
Emu.Pause();
return;
static const char f[4] = {'x', 'y', 'z', 'w'};
wxString swizzle = wxEmptyString;
swizzle += f[src0.cond_swizzle_x];
swizzle += f[src0.cond_swizzle_y];
swizzle += f[src0.cond_swizzle_z];
swizzle += f[src0.cond_swizzle_w];
if(src0.exec_if_gr && src0.exec_if_eq)
{
cond = "greaterThanEqual";
}
else if(src0.exec_if_lt && src0.exec_if_eq)
{
cond = "lessThanEqual";
}
else if(src0.exec_if_gr && src0.exec_if_lt)
{
cond = "notEqual";
}
else if(src0.exec_if_gr)
{
cond = "greaterThan";
}
else if(src0.exec_if_lt)
{
cond = "lessThan";
}
else //if(src0.exec_if_eq)
{
cond = "equal";
}
cond = wxString::Format("if(all(%s(%s.%s, vec4(0, 0, 0, 0)))) ", cond, AddCond(dst.no_dest), swizzle);
//ConLog.Error("cond! [eq: %d gr: %d lt: %d] (%s)", src0.exec_if_eq, src0.exec_if_gr, src0.exec_if_lt, cond);
//Emu.Pause();
//return;
}
if(src1.scale)
{
switch(src1.scale)
{
case 1: code = "(" + code + ") * 2"; break;
case 2: code = "(" + code + ") * 4"; break;
case 3: code = "(" + code + ") * 8"; break;
case 5: code = "(" + code + ") / 2"; break;
case 6: code = "(" + code + ") / 4"; break;
case 7: code = "(" + code + ") / 8"; break;
case 1: code = "(" + code + " * 2)"; break;
case 2: code = "(" + code + " * 4)"; break;
case 3: code = "(" + code + " * 8)"; break;
case 5: code = "(" + code + " / 2)"; break;
case 6: code = "(" + code + " / 4)"; break;
case 7: code = "(" + code + " / 8)"; break;
default:
ConLog.Error("Bad scale: %d", src1.scale);
@ -29,7 +67,13 @@ void FragmentDecompilerThread::AddCode(wxString code)
}
}
code = AddReg(dst.dest_reg) + GetMask() + " = " + code + GetMask();
if(dst.saturate)
{
code = "clamp(" + code + ", 0.0, 1.0)";
}
code = cond + (dst.set_cond ? AddCond(dst.fp16) : AddReg(dst.dest_reg, dst.fp16)) + mask
+ " = " + code + (append_mask ? mask : wxEmptyString);
main += "\t" + code + ";\n";
}
@ -38,28 +82,53 @@ wxString FragmentDecompilerThread::GetMask()
{
wxString ret = wxEmptyString;
if(dst.mask_x) ret += 'x';
if(dst.mask_y) ret += 'y';
if(dst.mask_z) ret += 'z';
if(dst.mask_w) ret += 'w';
static const char dst_mask[4] =
{
'x', 'y', 'z', 'w',
};
return ret.IsEmpty() || ret == "xyzw" ? wxEmptyString : ("." + ret);
if(dst.mask_x) ret += dst_mask[0];
if(dst.mask_y) ret += dst_mask[1];
if(dst.mask_z) ret += dst_mask[2];
if(dst.mask_w) ret += dst_mask[3];
return ret.IsEmpty() || strncmp(ret, dst_mask, 4) == 0 ? wxEmptyString : ("." + ret);
}
wxString FragmentDecompilerThread::AddReg(u32 index)
wxString FragmentDecompilerThread::AddReg(u32 index, int fp16)
{
//if(!index) return "gl_FragColor";
return m_parr.AddParam(index ? PARAM_NONE : PARAM_OUT, "vec4", wxString::Format("r%d", index), index ? -1 : 0);
//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);
}
bool FragmentDecompilerThread::HasReg(u32 index, int fp16)
{
return m_parr.HasParam((index || fp16) ? PARAM_NONE : 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);
}
wxString FragmentDecompilerThread::AddConst()
{
return m_parr.AddParam(PARAM_CONST, "vec4", wxString::Format("fc%d", m_const_index++));
mem32_t data(m_addr + m_size + m_offset);
m_offset += 4 * 4;
u32 x = GetData(data[0]);
u32 y = GetData(data[1]);
u32 z = GetData(data[2]);
u32 w = GetData(data[3]);
return m_parr.AddParam(PARAM_UNIFORM, "vec4", wxString::Format("fc%u", m_size + 4 * 4),
wxString::Format("vec4(%f, %f, %f, %f)", (float&)x, (float&)y, (float&)z, (float&)w));
}
wxString FragmentDecompilerThread::AddTex()
{
return m_parr.AddParam(PARAM_CONST, "sampler2D", wxString::Format("tex_%d", dst.tex_num));
return m_parr.AddParam(PARAM_UNIFORM, "sampler2D", wxString::Format("tex%d", dst.tex_num));
}
template<typename T> wxString FragmentDecompilerThread::GetSRC(T src)
@ -69,7 +138,7 @@ template<typename T> wxString FragmentDecompilerThread::GetSRC(T src)
switch(src.reg_type)
{
case 0: //tmp
ret += AddReg(src.tmp_reg_index);
ret += AddReg(src.tmp_reg_index, src.fp16);
break;
case 1: //input
@ -102,7 +171,6 @@ template<typename T> wxString FragmentDecompilerThread::GetSRC(T src)
break;
case 2: //const
ConLog.Write("reg index = %d", src.tmp_reg_index);
ret += AddConst();
break;
@ -113,13 +181,14 @@ template<typename T> wxString FragmentDecompilerThread::GetSRC(T src)
}
static const char f[4] = {'x', 'y', 'z', 'w'};
wxString swizzle = wxEmptyString;
swizzle += f[src.swizzle_x];
swizzle += f[src.swizzle_y];
swizzle += f[src.swizzle_z];
swizzle += f[src.swizzle_w];
if(swizzle != "xyzw") ret += "." + swizzle;
if(strncmp(swizzle, f, 4) != 0) ret += "." + swizzle;
if(src.abs) ret = "abs(" + ret + ")";
if(src.neg) ret = "-" + ret;
@ -131,6 +200,11 @@ 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();
@ -157,33 +231,35 @@ void FragmentDecompilerThread::Task()
src1.HEX = GetData(data[2]);
src2.HEX = GetData(data[3]);
switch(dst.opcode)
m_offset = 4 * 4;
switch(dst.opcode | (src1.opcode_is_branch << 6))
{
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("dot(" + GetSRC(src0) + ".xyz, " + GetSRC(src1) + ".xyz)"); break; // DP3
case 0x06: AddCode("dot(" + GetSRC(src0) + ", " + GetSRC(src1) + ")"); break; // DP4
//case 0x07: break; // DST
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 0x08: AddCode("min(" + GetSRC(src0) + ", " + GetSRC(src1) + ")"); break; // MIN
case 0x09: AddCode("max(" + GetSRC(src0) + ", " + GetSRC(src1) + ")"); break; // MAX
//case 0x0a: break; // SLT
//case 0x0b: break; // SGE
//case 0x0c: break; // SLE
//case 0x0d: break; // SGT
//case 0x0e: break; // SNE
//case 0x0f: break; // SEQ
case 0x0a: AddCode("vec4(lessThan(" + GetSRC(src0) + ", " + GetSRC(src1) + "))"); break; // SLT
case 0x0b: AddCode("vec4(greaterThanEqual(" + GetSRC(src0) + ", " + GetSRC(src1) + "))"); break; // SGE
case 0x0c: AddCode("vec4(lessThanEqual(" + GetSRC(src0) + ", " + GetSRC(src1) + "))"); break; // SLE
case 0x0d: AddCode("vec4(greaterThan(" + GetSRC(src0) + ", " + GetSRC(src1) + "))"); break; // SGT
case 0x0e: AddCode("vec4(notEqual(" + GetSRC(src0) + ", " + GetSRC(src1) + "))"); break; // SNE
case 0x0f: AddCode("vec4(equal(" + GetSRC(src0) + ", " + GetSRC(src1) + "))"); break; // SEQ
//case 0x10: break; // FRC
//case 0x11: break; // FLR
case 0x10: AddCode("fract(" + GetSRC(src0) + ")"); break; // FRC
case 0x11: AddCode("floor(" + GetSRC(src0) + ")"); break; // FLR
//case 0x12: break; // KIL
//case 0x13: break; // PK4
//case 0x14: break; // UP4
case 0x15: AddCode("ddx(" + GetSRC(src0) + ")"); break; // DDX
case 0x16: AddCode("ddy(" + GetSRC(src0) + ")"); break; // DDY
case 0x17: AddCode("texture(" + AddTex() + ", (" + GetSRC(src0) + ").xy)"); break; //TEX
case 0x17: AddCode("texture(" + AddTex() + ", " + GetSRC(src0) + ".xy)"); break; //TEX
//case 0x18: break; // TXP
//case 0x19: break; // TXD
case 0x1a: AddCode("1 / (" + GetSRC(src0) + ")"); break; // RCP
@ -199,7 +275,7 @@ void FragmentDecompilerThread::Task()
case 0x23: AddCode("sin(" + GetSRC(src0) + ")"); break; // SIN
//case 0x24: break; // PK2
//case 0x25: break; // UP2
//case 0x26: break; // POW
case 0x26: AddCode("pow(" + GetSRC(src0) + ", " + GetSRC(src1) +")"); break; // POW
//case 0x27: break; // PKB
//case 0x28: break; // UPB
//case 0x29: break; // PK16
@ -216,25 +292,25 @@ void FragmentDecompilerThread::Task()
//case 0x35: break; // BEMLUM
//case 0x36: break; // REFL
//case 0x37: break; // TIMESWTEX
//case 0x38: break; // DP2
//case 0x39: break; // NRM
//case 0x3a: break; // DIV
//case 0x3b: break; // DIVSQ
case 0x38: AddCode("vec4(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
//case 0x3c: break; // LIF
//case 0x3d: break; // FENCT
//case 0x3e: break; // FENCB
case 0x3d: break; // FENCT
case 0x3e: break; // FENCB
default:
ConLog.Error("Unknown opcode 0x%x", dst.opcode);
ConLog.Error("Unknown opcode 0x%x (inst %d)", dst.opcode, m_size / (4 * 4));
Emu.Pause();
break;
}
m_size += 4 * 4;
m_size += m_offset;
if(dst.end) break;
data.SetOffset(4 * 4);
data.SetOffset(m_offset);
}
m_shader = BuildCode();
@ -242,7 +318,7 @@ void FragmentDecompilerThread::Task()
}
ShaderProgram::ShaderProgram()
: m_decompiler_thread(NULL)
: m_decompiler_thread(nullptr)
, id(0)
{
}

View File

@ -33,22 +33,24 @@ struct FragmentDecompilerThread : public ThreadBase
struct
{
u32 reg_type : 2;
u32 tmp_reg_index : 6;
u32 fp16 : 1;
u32 swizzle_x : 2;
u32 swizzle_y : 2;
u32 swizzle_z : 2;
u32 swizzle_w : 2;
u32 neg : 1;
u32 exec_if_le : 1;
u32 exec_if_eq : 1;
u32 exec_if_gr : 1;
u32 cond_swizzle_x : 2;
u32 cond_swizzle_y : 2;
u32 cond_swizzle_z : 2;
u32 cond_swizzle_w : 2;
u32 abs : 1;
u32 reg_type : 2;
u32 tmp_reg_index : 6;
u32 fp16 : 1;
u32 swizzle_x : 2;
u32 swizzle_y : 2;
u32 swizzle_z : 2;
u32 swizzle_w : 2;
u32 neg : 1;
u32 exec_if_lt : 1;
u32 exec_if_eq : 1;
u32 exec_if_gr : 1;
u32 cond_swizzle_x : 2;
u32 cond_swizzle_y : 2;
u32 cond_swizzle_z : 2;
u32 cond_swizzle_w : 2;
u32 abs : 1;
u32 cond_mod_reg_index : 1;
u32 cond_reg_index : 1;
};
} src0;
@ -67,8 +69,8 @@ struct FragmentDecompilerThread : public ThreadBase
u32 swizzle_w : 2;
u32 neg : 1;
u32 abs : 1;
u32 input_prec : 2;
u32 : 7;
u32 input_mod_src0 : 3;
u32 : 6;
u32 scale : 3;
u32 opcode_is_branch : 1;
};
@ -91,6 +93,7 @@ struct FragmentDecompilerThread : public ThreadBase
u32 abs : 1;
u32 addr_reg : 11;
u32 use_index_reg : 1;
u32 perspective_corr: 1;
};
} src2;
@ -100,6 +103,7 @@ struct FragmentDecompilerThread : public ThreadBase
u32 m_addr;
u32& m_size;
u32 m_const_index;
u32 m_offset;
FragmentDecompilerThread(wxString& shader, ParamArray& parr, u32 addr, u32& size)
: ThreadBase(false, "Fragment Shader Decompiler Thread")
@ -114,8 +118,10 @@ struct FragmentDecompilerThread : public ThreadBase
wxString GetMask();
void AddCode(wxString code);
wxString AddReg(u32 index);
void AddCode(wxString code, bool append_mask = true);
wxString AddReg(u32 index, int fp16);
bool HasReg(u32 index, int fp16);
wxString AddCond(int fp16);
wxString AddConst();
wxString AddTex();
@ -138,6 +144,7 @@ struct ShaderProgram
u32 size;
u32 addr;
u32 offset;
wxString shader;
u32 id;

View File

@ -36,6 +36,7 @@ void GLBufferObject::Delete()
void GLBufferObject::Bind(u32 type, u32 num)
{
assert(num < m_id.GetCount());
glBindBuffer(type, m_id[num]);
}
@ -105,15 +106,147 @@ void GLvao::Bind() const
glBindVertexArray(m_id);
}
void GLvao::Unbind()
{
glBindVertexArray(0);
}
void GLvao::Delete()
{
if(!IsCreated()) return;
Unbind();
glDeleteVertexArrays(1, &m_id);
m_id = 0;
}
bool GLvao::IsCreated() const
{
return m_id != 0;
}
GLrbo::GLrbo()
{
}
GLrbo::~GLrbo()
{
}
void GLrbo::Create(u32 count)
{
if(m_id.GetCount())
{
return;
}
m_id.SetCount(count);
glGenRenderbuffers(count, m_id.GetPtr());
}
void GLrbo::Bind(u32 num) const
{
assert(num < m_id.GetCount());
glBindRenderbuffer(GL_RENDERBUFFER, m_id[num]);
}
void GLrbo::Storage(u32 format, u32 width, u32 height)
{
glRenderbufferStorage(GL_RENDERBUFFER, format, width, height);
}
void GLrbo::Unbind()
{
glBindRenderbuffer(GL_RENDERBUFFER, 0);
}
void GLrbo::Delete()
{
glDeleteRenderbuffers(m_id.GetCount(), m_id.GetPtr());
m_id.Clear();
}
bool GLrbo::IsCreated() const
{
return m_id.GetCount();
}
u32 GLrbo::GetId(u32 num) const
{
assert(num < m_id.GetCount());
return m_id[num];
}
GLfbo::GLfbo()
{
}
GLfbo::~GLfbo()
{
}
void GLfbo::Create()
{
if(m_id)
{
return;
}
glGenFramebuffers(1, &m_id);
}
void GLfbo::Bind(u32 type, int id)
{
if(id != -1)
assert(m_id);
m_type = type;
glBindFramebuffer(m_type, id == -1 ? m_id : id);
}
void GLfbo::Texture1D(u32 attachment, u32 texture, int level)
{
glFramebufferTexture1D(m_type, attachment, GL_TEXTURE_1D, texture, level);
}
void GLfbo::Texture2D(u32 attachment, u32 texture, int level)
{
glFramebufferTexture2D(m_type, attachment, GL_TEXTURE_2D, texture, level);
}
void GLfbo::Texture3D(u32 attachment, u32 texture, int zoffset, int level)
{
glFramebufferTexture3D(m_type, attachment, GL_TEXTURE_3D, texture, level, zoffset);
}
void GLfbo::Renderbuffer(u32 attachment, u32 renderbuffer)
{
glFramebufferRenderbuffer(m_type, attachment, GL_RENDERBUFFER, renderbuffer);
}
void GLfbo::Blit(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, u32 mask, u32 filter)
{
glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
}
void GLfbo::Unbind()
{
Unbind(m_type);
}
void GLfbo::Unbind(u32 type)
{
glBindFramebuffer(type, 0);
}
void GLfbo::Delete()
{
glDeleteFramebuffers(1, &m_id);
m_id = 0;
}
bool GLfbo::IsCreated() const
{
return m_id != 0;
}

View File

@ -43,6 +43,48 @@ public:
void Create();
void Bind() const;
static void Unbind();
void Delete();
bool IsCreated() const;
};
class GLrbo
{
protected:
Array<GLuint> m_id;
public:
GLrbo();
~GLrbo();
void Create(u32 count = 1);
void Bind(u32 num = 0) const;
void Storage(u32 format, u32 width, u32 height);
static void Unbind();
void Delete();
bool IsCreated() const;
u32 GetId(u32 num) const;
};
class GLfbo
{
protected:
GLuint m_id;
GLuint m_type;
public:
GLfbo();
~GLfbo();
void Create();
void Bind(u32 type = GL_FRAMEBUFFER, int id = -1);
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);
void Unbind();
static void Unbind(u32 type);
void Delete();
bool IsCreated() const;
};

File diff suppressed because it is too large Load Diff

View File

@ -10,6 +10,7 @@
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "gl.lib")
void printGlError(GLenum err, const char* situation);
void checkForGlError(const char* situation);
class GLTexture
@ -23,21 +24,62 @@ class GLTexture
u8 m_dimension;
u32 m_format;
u16 m_mipmap;
u32 m_pitch;
u16 m_depth;
u16 m_minlod;
u16 m_maxlod;
u8 m_maxaniso;
u8 m_wraps;
u8 m_wrapt;
u8 m_wrapr;
u8 m_unsigned_remap;
u8 m_zfunc;
u8 m_gamma;
u8 m_aniso_bias;
u8 m_signed_remap;
u32 m_remap;
public:
GLTexture()
: m_width(0), m_height(0),
m_id(0),
m_offset(0),
m_enabled(false),
: m_width(0), m_height(0)
, m_id(0)
, m_offset(0)
, m_enabled(false)
m_cubemap(false),
m_dimension(0),
m_format(0),
m_mipmap(0)
, m_cubemap(false)
, m_dimension(0)
, m_format(0)
, m_mipmap(0)
, m_minlod(0)
, m_maxlod(1000)
, m_maxaniso(0)
{
}
void Create()
{
if(m_id)
{
Delete();
}
if(!m_id)
{
glGenTextures(1, &m_id);
checkForGlError("GLTexture::Init() -> glGenTextures");
Bind();
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
}
}
void SetRect(const u32 width, const u32 height)
{
m_width = width;
@ -54,6 +96,37 @@ public:
m_mipmap = mipmap;
}
void SetAddress(u8 wraps, u8 wrapt, u8 wrapr, u8 unsigned_remap, u8 zfunc, u8 gamma, u8 aniso_bias, u8 signed_remap)
{
m_wraps = wraps;
m_wrapt = wrapt;
m_wrapr = wrapr;
m_unsigned_remap = unsigned_remap;
m_zfunc = zfunc;
m_gamma = gamma;
m_aniso_bias = aniso_bias;
m_signed_remap = signed_remap;
}
void SetControl0(const bool enable, const u16 minlod, const u16 maxlod, const u8 maxaniso)
{
m_enabled = enable;
m_minlod = minlod;
m_maxlod = maxlod;
m_maxaniso = maxaniso;
}
void SetControl1(u32 remap)
{
m_remap = remap;
}
void SetControl3(u16 depth, u32 pitch)
{
m_depth = depth;
m_pitch = pitch;
}
u32 GetFormat() const { return m_format; }
void SetOffset(const u32 offset)
@ -66,59 +139,193 @@ public:
return wxSize(m_width, m_height);
}
void Init()
int GetGlWrap(int wrap)
{
if(!m_id)
switch(wrap)
{
glGenTextures(1, &m_id);
checkForGlError("GLTexture::Init() -> glGenTextures");
glBindTexture(GL_TEXTURE_2D, m_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
}
else
{
glBindTexture(GL_TEXTURE_2D, m_id);
case 1: return GL_REPEAT;
case 2: return GL_MIRRORED_REPEAT;
case 3: return GL_CLAMP_TO_EDGE;
case 4: return GL_TEXTURE_BORDER;
case 5: return GL_CLAMP_TO_EDGE;//GL_CLAMP;
//case 6: return GL_MIRROR_CLAMP_TO_EDGE_EXT;
}
ConLog.Error("Texture wrap error: bad wrap (%d).", wrap);
return GL_REPEAT;
}
void Init()
{
Bind();
if(!Memory.IsGoodAddr(m_offset))
{
ConLog.Error("Bad texture address=0x%x", m_offset);
return;
}
//ConLog.Warning("texture addr = 0x%x, width = %d, height = %d, max_aniso=%d, mipmap=%d, remap=0x%x, zfunc=0x%x, wraps=0x%x, wrapt=0x%x, wrapr=0x%x, minlod=0x%x, maxlod=0x%x",
// m_offset, m_width, m_height, m_maxaniso, m_mipmap, m_remap, m_zfunc, m_wraps, m_wrapt, m_wrapr, m_minlod, m_maxlod);
//TODO: safe init
checkForGlError("GLTexture::Init() -> glBindTexture");
switch(m_format & ~(0x20 | 0x40))
glPixelStorei(GL_PACK_ROW_LENGTH, m_pitch);
int format = m_format & ~(0x20 | 0x40);
bool is_swizzled = (m_format & 0x20) == 0;
char* pixels = (char*)Memory.GetMemFromAddr(m_offset);
switch(format)
{
case 0x81:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RED, GL_UNSIGNED_BYTE, Memory.GetMemFromAddr(m_offset));
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_BLUE, GL_UNSIGNED_BYTE, pixels);
checkForGlError("GLTexture::Init() -> glTexImage2D");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_BLUE);
checkForGlError("GLTexture::Init() -> glTexParameteri");
break;
case 0x85:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, Memory.GetMemFromAddr(m_offset));
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, pixels);
checkForGlError("GLTexture::Init() -> glTexImage2D");
break;
default: ConLog.Error("Init tex error: Bad tex format (0x%x)", m_format); break;
case 0x86:
{
u32 size = ((m_width + 3) / 4) * ((m_height + 3) / 4) * 8;
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, m_width, m_height, 0, size, pixels);
checkForGlError("GLTexture::Init() -> glCompressedTexImage2D");
}
break;
case 0x87:
{
u32 size = ((m_width + 3) / 4) * ((m_height + 3) / 4) * 16;
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, m_width, m_height, 0, size, pixels);
checkForGlError("GLTexture::Init() -> glCompressedTexImage2D");
}
break;
case 0x88:
{
u32 size = ((m_width + 3) / 4) * ((m_height + 3) / 4) * 16;
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, m_width, m_height, 0, size, pixels);
checkForGlError("GLTexture::Init() -> glCompressedTexImage2D");
}
break;
case 0x94:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RED, GL_SHORT, pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_ONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_ONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
checkForGlError("GLTexture::Init() -> glTexImage2D");
break;
case 0x9a:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_BGRA, GL_HALF_FLOAT, pixels);
checkForGlError("GLTexture::Init() -> glTexImage2D");
break;
case 0x9e:
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, pixels);
checkForGlError("GLTexture::Init() -> glTexImage2D");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE);
}
break;
default: ConLog.Error("Init tex error: Bad tex format (0x%x | 0x%x | 0x%x)", format, m_format & 0x20, m_format & 0x40); break;
}
//glBindTexture(GL_TEXTURE_2D, 0);
if(m_mipmap > 1)
{
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
}
if(format != 0x81 && format != 0x94)
{
u8 remap_a = m_remap & 0x3;
u8 remap_r = (m_remap >> 2) & 0x3;
u8 remap_g = (m_remap >> 4) & 0x3;
u8 remap_b = (m_remap >> 6) & 0x3;
static const int gl_remap[] =
{
GL_ALPHA,
GL_RED,
GL_GREEN,
GL_BLUE,
};
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, gl_remap[remap_a]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, gl_remap[remap_r]);
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,
GL_LESS,
GL_EQUAL,
GL_LEQUAL,
GL_GREATER,
GL_NOTEQUAL,
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_aniso_bias);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, m_minlod);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, m_maxlod);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, m_maxaniso);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//Unbind();
}
void Save(const wxString& name)
{
if(!m_id || !m_offset) return;
if(!m_id || !m_offset || !m_width || !m_height) return;
ConLog.Write("start");
u32* alldata = new u32[m_width * m_height];
glBindTexture(GL_TEXTURE_2D, m_id);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, alldata);
Bind();
switch(m_format & ~(0x20 | 0x40))
{
case 0x81:
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, alldata);
break;
case 0x85:
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, alldata);
break;
default:
delete[] alldata;
return;
}
{
wxFile f(name + ".raw", wxFile::write);
f.Write(alldata, m_width * m_height * 4);
}
u8* data = new u8[m_width * m_height * 3];
u8* alpha = new u8[m_width * m_height];
@ -133,7 +340,6 @@ public:
*dst_a++ = *src++;
}
ConLog.Write("end");
wxImage out;
out.Create(m_width, m_height, data, alpha);
out.SaveFile(name, wxBITMAP_TYPE_PNG);
@ -160,10 +366,46 @@ public:
glBindTexture(GL_TEXTURE_2D, m_id);
}
void Enable(bool enable) { m_enabled = enable; }
void Unbind()
{
glBindTexture(GL_TEXTURE_2D, 0);
}
void Delete()
{
if(m_id)
{
glDeleteTextures(1, &m_id);
m_id = 0;
}
}
bool IsEnabled() const { return m_enabled; }
};
struct TransformConstant
{
u32 id;
float x, y, z, w;
TransformConstant()
: x(0.0f)
, y(0.0f)
, z(0.0f)
, w(0.0f)
{
}
TransformConstant(u32 id, float x, float y, float z, float w)
: id(id)
, x(x)
, y(y)
, z(z)
, w(w)
{
}
};
struct IndexArrayData
{
Array<u8> m_data;
@ -211,8 +453,6 @@ private:
virtual void OnSize(wxSizeEvent& event);
};
extern gcmBuffer gcmBuffers[2];
struct GLRSXThread : public ThreadBase
{
wxWindow* m_parent;
@ -228,16 +468,26 @@ class GLGSRender
, public GSRender
, public ExecRSXCMDdata
{
public:
static const uint m_vertex_count = 16;
static const uint m_fragment_count = 16;
static const uint m_textures_count = 16;
private:
GLRSXThread* m_rsx_thread;
IndexArrayData m_indexed_array;
ShaderProgram m_shader_prog;
VertexData m_vertex_data[16];
ShaderProgram m_shader_progs[m_fragment_count];
ShaderProgram* m_cur_shader_prog;
int m_cur_shader_prog_num;
VertexData m_vertex_data[m_vertex_count];
Array<u8> m_vdata;
VertexProgram m_vertex_progs[16];
VertexProgram m_vertex_progs[m_vertex_count];
VertexProgram* m_cur_vertex_prog;
Array<TransformConstant> m_transform_constants;
Array<TransformConstant> m_fragment_constants;
Program m_program;
int m_fp_buf_num;
int m_vp_buf_num;
@ -245,8 +495,13 @@ private:
int m_draw_mode;
ProgramBuffer m_prog_buffer;
u32 m_width;
u32 m_height;
GLvao m_vao;
GLvbo m_vbo;
GLrbo m_rbo;
GLfbo m_fbo;
public:
GLGSFrame* m_frame;
@ -261,6 +516,7 @@ private:
void DisableVertexData();
void LoadVertexData(u32 first, u32 count);
void InitVertexData();
void InitFragmentData();
void Enable(bool enable, const u32 cap);
virtual void Init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress);

View File

@ -30,6 +30,17 @@ OPENGL_PROC(PFNGLBINDATTRIBLOCATIONPROC, BindAttribLocation);
OPENGL_PROC(PFNGLGETUNIFORMLOCATIONPROC, GetUniformLocation);
OPENGL_PROC(PFNGLGETPROGRAMIVPROC, GetProgramiv);
OPENGL_PROC(PFNGLGETPROGRAMINFOLOGPROC, GetProgramInfoLog);
OPENGL_PROC(PFNGLVERTEXATTRIB4BVPROC, VertexAttrib4bv);
OPENGL_PROC(PFNGLVERTEXATTRIB4UBVPROC, VertexAttrib4ubv);
OPENGL_PROC(PFNGLVERTEXATTRIB1SPROC, VertexAttrib1s);
OPENGL_PROC(PFNGLVERTEXATTRIB2SVPROC, VertexAttrib2sv);
OPENGL_PROC(PFNGLVERTEXATTRIB3SVPROC, VertexAttrib3sv);
OPENGL_PROC(PFNGLVERTEXATTRIB4SVPROC, VertexAttrib4sv);
OPENGL_PROC(PFNGLVERTEXATTRIB4IVPROC, VertexAttrib4iv);
OPENGL_PROC(PFNGLVERTEXATTRIB1FPROC, VertexAttrib1f);
OPENGL_PROC(PFNGLVERTEXATTRIB2FVPROC, VertexAttrib2fv);
OPENGL_PROC(PFNGLVERTEXATTRIB3FVPROC, VertexAttrib3fv);
OPENGL_PROC(PFNGLVERTEXATTRIB4FVPROC, VertexAttrib4fv);
OPENGL_PROC(PFNGLVERTEXATTRIBPOINTERPROC, VertexAttribPointer);
OPENGL_PROC(PFNGLENABLEVERTEXATTRIBARRAYPROC, EnableVertexAttribArray);
OPENGL_PROC(PFNGLDISABLEVERTEXATTRIBARRAYPROC, DisableVertexAttribArray);
@ -39,7 +50,49 @@ OPENGL_PROC(PFNGLDELETEVERTEXARRAYSPROC, DeleteVertexArrays);
OPENGL_PROC(PFNGLDEPTHRANGEFPROC, DepthRangef);
OPENGL_PROC(PFNGLUNIFORM1IPROC, Uniform1i);
OPENGL_PROC(PFNGLUNIFORM1FPROC, Uniform1f);
OPENGL_PROC(PFNGLUNIFORM1UIPROC, Uniform1ui);
OPENGL_PROC(PFNGLUNIFORM1IVPROC, Uniform1iv);
OPENGL_PROC(PFNGLUNIFORM1FVPROC, Uniform1fv);
OPENGL_PROC(PFNGLUNIFORM1UIVPROC, Uniform1uiv);
OPENGL_PROC(PFNGLUNIFORM2IPROC, Uniform2i);
OPENGL_PROC(PFNGLUNIFORM2FPROC, Uniform2f);
OPENGL_PROC(PFNGLUNIFORM2UIPROC, Uniform2ui);
OPENGL_PROC(PFNGLUNIFORM2IVPROC, Uniform2iv);
OPENGL_PROC(PFNGLUNIFORM2FVPROC, Uniform2fv);
OPENGL_PROC(PFNGLUNIFORM2UIVPROC, Uniform2uiv);
OPENGL_PROC(PFNGLUNIFORM3IPROC, Uniform3i);
OPENGL_PROC(PFNGLUNIFORM3FPROC, Uniform3f);
OPENGL_PROC(PFNGLUNIFORM3UIPROC, Uniform3ui);
OPENGL_PROC(PFNGLUNIFORM3IVPROC, Uniform3iv);
OPENGL_PROC(PFNGLUNIFORM3FVPROC, Uniform3fv);
OPENGL_PROC(PFNGLUNIFORM3UIVPROC, Uniform3uiv);
OPENGL_PROC(PFNGLUNIFORM4FPROC, Uniform4i);
OPENGL_PROC(PFNGLUNIFORM4FPROC, Uniform4f);
OPENGL_PROC(PFNGLUNIFORM4UIPROC, Uniform4ui);
OPENGL_PROC(PFNGLUNIFORM4IVPROC, Uniform4iv);
OPENGL_PROC(PFNGLUNIFORM4FVPROC, Uniform4fv);
OPENGL_PROC(PFNGLUNIFORM4UIVPROC, Uniform4uiv);
OPENGL_PROC(PFNGLPROGRAMUNIFORM1IPROC, ProgramUniform1i);
OPENGL_PROC(PFNGLPROGRAMUNIFORM1FPROC, ProgramUniform1f);
OPENGL_PROC(PFNGLPROGRAMUNIFORM4FPROC, ProgramUniform4f);
OPENGL_PROC(PFNGLUNIFORMMATRIX4FVPROC, UniformMatrix4fv);
OPENGL_PROC(PFNGLUSEPROGRAMPROC, UseProgram);
OPENGL_PROC2(PFNWGLSWAPINTERVALEXTPROC, SwapInterval, wglSwapIntervalEXT);
OPENGL_PROC2(PFNWGLSWAPINTERVALEXTPROC, SwapInterval, wglSwapIntervalEXT);
OPENGL_PROC2(PFNGLDEPTHBOUNDSEXTPROC, DepthBounds, glDepthBoundsEXT);
OPENGL_PROC(PFNGLSTENCILOPSEPARATEPROC, StencilOpSeparate);
OPENGL_PROC(PFNGLSTENCILFUNCSEPARATEPROC, StencilFuncSeparate);
OPENGL_PROC(PFNGLSTENCILMASKSEPARATEPROC, StencilMaskSeparate);
OPENGL_PROC(PFNGLCOMPRESSEDTEXIMAGE2DPROC, CompressedTexImage2D);
OPENGL_PROC(PFNGLGENERATEMIPMAPPROC, GenerateMipmap);
OPENGL_PROC(PFNGLBINDRENDERBUFFERPROC, BindRenderbuffer);
OPENGL_PROC(PFNGLDELETERENDERBUFFERSPROC, DeleteRenderbuffers);
OPENGL_PROC(PFNGLGENRENDERBUFFERSPROC, GenRenderbuffers);
OPENGL_PROC(PFNGLRENDERBUFFERSTORAGEPROC, RenderbufferStorage);
OPENGL_PROC(PFNGLBINDFRAMEBUFFERPROC, BindFramebuffer);
OPENGL_PROC(PFNGLDELETEFRAMEBUFFERSPROC, DeleteFramebuffers);
OPENGL_PROC(PFNGLGENFRAMEBUFFERSPROC, GenFramebuffers);
OPENGL_PROC(PFNGLFRAMEBUFFERTEXTURE1DPROC, FramebufferTexture1D);
OPENGL_PROC(PFNGLFRAMEBUFFERTEXTURE2DPROC, FramebufferTexture2D);
OPENGL_PROC(PFNGLFRAMEBUFFERTEXTURE3DPROC, FramebufferTexture3D);
OPENGL_PROC(PFNGLFRAMEBUFFERRENDERBUFFERPROC, FramebufferRenderbuffer);
OPENGL_PROC(PFNGLBLITFRAMEBUFFERPROC, BlitFramebuffer);

View File

@ -19,7 +19,9 @@ int Program::GetLocation(const wxString& name)
u32 pos = m_locations.Move(new Location());
m_locations[pos].name = name;
return m_locations[pos].loc = glGetUniformLocation(id, name);
m_locations[pos].loc = glGetUniformLocation(id, name);
checkForGlError(wxString::Format("glGetUniformLocation(0x%x, %s)", id, name));
return m_locations[pos].loc;
}
bool Program::IsCreated() const
@ -72,6 +74,12 @@ void Program::Create(const u32 vp, const u32 fp)
}
}
void Program::UnUse()
{
id = 0;
m_locations.Clear();
}
void Program::Use()
{
glUseProgram(id);
@ -80,8 +88,10 @@ void Program::Use()
void Program::SetTex(u32 index)
{
glUniform1i(GetLocation(wxString::Format("tex_%d", index)), index);
checkForGlError(wxString::Format("SetTex(%d)", index));
int loc = GetLocation(wxString::Format("tex%u", index));
checkForGlError(wxString::Format("GetLocation(tex%u)", index));
glProgramUniform1i(id, loc, index);
checkForGlError(wxString::Format("SetTex(%u - %d - %d)", id, index, loc));
}
void Program::Delete()
@ -89,4 +99,5 @@ void Program::Delete()
if(!IsCreated()) return;
glDeleteProgram(id);
id = 0;
m_locations.Clear();
}

View File

@ -22,6 +22,7 @@ public:
bool IsCreated() const;
void Create(const u32 vp, const u32 fp);
void Use();
void UnUse();
void SetTex(u32 index);
void Delete();
};

View File

@ -8,7 +8,7 @@ int ProgramBuffer::SearchFp(ShaderProgram& fp)
if(memcmp(&m_buf[i].fp_data[0], &Memory[fp.addr], m_buf[i].fp_data.GetCount()) != 0) continue;
fp.id = m_buf[i].fp_id;
fp.shader = m_buf[i].fp_shader;
fp.shader = m_buf[i].fp_shader.GetPtr();
return i;
}
@ -21,10 +21,10 @@ int ProgramBuffer::SearchVp(VertexProgram& vp)
for(u32 i=0; i<m_buf.GetCount(); ++i)
{
if(m_buf[i].vp_data.GetCount() != vp.data.GetCount()) continue;
if(memcmp(&m_buf[i].vp_data[0], &vp.data[0], vp.data.GetCount() * 4) != 0) continue;
if(memcmp(m_buf[i].vp_data.GetPtr(), vp.data.GetPtr(), vp.data.GetCount() * 4) != 0) continue;
vp.id = m_buf[i].vp_id;
vp.shader = m_buf[i].vp_shader;
vp.shader = m_buf[i].vp_shader.GetPtr();
return i;
}
@ -35,18 +35,30 @@ int ProgramBuffer::SearchVp(VertexProgram& vp)
bool ProgramBuffer::CmpVP(const u32 a, const u32 b) const
{
if(m_buf[a].vp_data.GetCount() != m_buf[b].vp_data.GetCount()) return false;
return memcmp(&m_buf[a].vp_data[0], &m_buf[b].vp_data[0], m_buf[a].vp_data.GetCount() * 4) == 0;
return memcmp(m_buf[a].vp_data.GetPtr(), m_buf[b].vp_data.GetPtr(), m_buf[a].vp_data.GetCount() * 4) == 0;
}
bool ProgramBuffer::CmpFP(const u32 a, const u32 b) const
{
if(m_buf[a].fp_data.GetCount() != m_buf[b].fp_data.GetCount()) return false;
return memcmp(&m_buf[a].fp_data[0], &m_buf[b].fp_data[0], m_buf[a].fp_data.GetCount()) == 0;
return memcmp(m_buf[a].fp_data.GetPtr(), m_buf[b].fp_data.GetPtr(), m_buf[a].fp_data.GetCount()) == 0;
}
u32 ProgramBuffer::GetProg(u32 fp, u32 vp) const
{
if(fp == vp) return m_buf[fp].prog_id;
if(fp == vp)
{
/*
ConLog.Write("Get program (%d):", fp);
ConLog.Write("*** prog id = %d", m_buf[fp].prog_id);
ConLog.Write("*** vp id = %d", m_buf[fp].vp_id);
ConLog.Write("*** fp id = %d", m_buf[fp].fp_id);
ConLog.Write("*** vp shader = \n%s", m_buf[fp].vp_shader);
ConLog.Write("*** fp shader = \n%s", m_buf[fp].fp_shader);
*/
return m_buf[fp].prog_id;
}
for(u32 i=0; i<m_buf.GetCount(); ++i)
{
@ -54,13 +66,15 @@ u32 ProgramBuffer::GetProg(u32 fp, u32 vp) const
if(CmpVP(vp, i) && CmpFP(fp, i))
{
/*
ConLog.Write("Get program (%d):", i);
ConLog.Write("*** prog id = %d", m_buf[i].prog_id);
ConLog.Write("*** vp id = %d", m_buf[i].vp_id);
ConLog.Write("*** fp id = %d", m_buf[i].fp_id);
ConLog.Write("*** vp shader = %s\n", m_buf[i].vp_shader);
ConLog.Write("*** fp shader = %s\n", m_buf[i].fp_shader);
ConLog.Write("*** vp shader = \n%s", m_buf[i].vp_shader);
ConLog.Write("*** fp shader = \n%s", m_buf[i].fp_shader);
*/
return m_buf[i].prog_id;
}
}
@ -79,8 +93,8 @@ void ProgramBuffer::Add(Program& prog, ShaderProgram& fp, VertexProgram& vp)
ConLog.Write("*** vp data size = %d", vp.data.GetCount() * 4);
ConLog.Write("*** fp data size = %d", fp.size);
ConLog.Write("*** vp shader = %s\n", vp.shader);
ConLog.Write("*** fp shader = %s\n", fp.shader);
ConLog.Write("*** vp shader = \n%s", vp.shader);
ConLog.Write("*** fp shader = \n%s", fp.shader);
new_buf.prog_id = prog.id;
new_buf.vp_id = vp.id;

View File

@ -8,8 +8,8 @@ struct BufferInfo
u32 vp_id;
Array<u8> fp_data;
Array<u32> vp_data;
wxString fp_shader;
wxString vp_shader;
ArrayString fp_shader;
ArrayString vp_shader;
};
struct ProgramBuffer

View File

@ -5,18 +5,21 @@ enum ParamFlag
{
PARAM_IN,
PARAM_OUT,
PARAM_UNIFORM,
PARAM_CONST,
PARAM_NONE,
};
struct ParamItem
{
wxString name;
wxString location;
ArrayString name;
ArrayString location;
ArrayString value;
ParamItem(const wxString& _name, int _location)
ParamItem(const wxString& _name, int _location, const wxString& _value = wxEmptyString)
: name(_name)
, location(_location > -1 ? wxString::Format("layout (location = %d) ", _location) : "")
, value(_value)
{
}
};
@ -24,7 +27,7 @@ struct ParamItem
struct ParamType
{
const ParamFlag flag;
wxString type;
ArrayString type;
Array<ParamItem> items;
ParamType(const ParamFlag _flag, const wxString& _type)
@ -37,7 +40,7 @@ struct ParamType
{
for(u32 i=0; i<items.GetCount(); ++i)
{
if(items[i].name.Cmp(name) == 0) return true;
if(name.Cmp(items[i].name.GetPtr()) == 0) return true;
}
return false;
@ -49,10 +52,15 @@ struct ParamType
for(u32 n=0; n<items.GetCount(); ++n)
{
ret += items[n].location;
ret += type;
ret += items[n].location.GetPtr();
ret += type.GetPtr();
ret += " ";
ret += items[n].name;
ret += items[n].name.GetPtr();
if(items[n].value.GetCount())
{
ret += " = ";
ret += items[n].value.GetPtr();
}
ret += ";\n";
}
@ -68,10 +76,10 @@ struct ParamArray
{
for(u32 i=0; i<params.GetCount(); ++i)
{
if(params[i].type.Cmp(type) == 0) return &params[i];
if(type.Cmp(params[i].type.GetPtr()) == 0) return &params[i];
}
return NULL;
return nullptr;
}
wxString GetParamFlag(const ParamFlag flag)
@ -80,12 +88,39 @@ struct ParamArray
{
case PARAM_OUT: return "out ";
case PARAM_IN: return "in ";
case PARAM_CONST: return "uniform ";
case PARAM_UNIFORM: return "uniform ";
case PARAM_CONST: return "const ";
}
return wxEmptyString;
}
bool HasParam(const ParamFlag flag, wxString type, const wxString& name)
{
type = GetParamFlag(flag) + type;
ParamType* t = SearchParam(type);
return t && t->SearchName(name);
}
wxString AddParam(const ParamFlag flag, wxString type, const wxString& name, const wxString& value)
{
type = GetParamFlag(flag) + type;
ParamType* t = SearchParam(type);
if(t)
{
if(!t->SearchName(name)) t->items.Move(new ParamItem(name, -1, value));
}
else
{
const u32 num = params.GetCount();
params.Move(new ParamType(flag, type));
params[num].items.Move(new ParamItem(name, -1, value));
}
return name;
}
wxString AddParam(const ParamFlag flag, wxString type, const wxString& name, int location = -1)
{
type = GetParamFlag(flag) + type;

View File

@ -1,28 +1,36 @@
#include "stdafx.h"
#include "VertexProgram.h"
wxString VertexDecompilerThread::GetVecMask()
wxString VertexDecompilerThread::GetMask(bool is_sca)
{
wxString ret = wxEmptyString;
if(d3.vec_writemask_x) ret += "x";
if(d3.vec_writemask_y) ret += "y";
if(d3.vec_writemask_z) ret += "z";
if(d3.vec_writemask_w) ret += "w";
if(is_sca)
{
if(d3.sca_writemask_x) ret += "x";
if(d3.sca_writemask_y) ret += "y";
if(d3.sca_writemask_z) ret += "z";
if(d3.sca_writemask_w) ret += "w";
}
else
{
if(d3.vec_writemask_x) ret += "x";
if(d3.vec_writemask_y) ret += "y";
if(d3.vec_writemask_z) ret += "z";
if(d3.vec_writemask_w) ret += "w";
}
return ret.IsEmpty() || ret == "xyzw" ? wxEmptyString : ("." + ret);
}
wxString VertexDecompilerThread::GetVecMask()
{
return GetMask(false);
}
wxString VertexDecompilerThread::GetScaMask()
{
wxString ret = wxEmptyString;
if(d3.sca_writemask_x) ret += "x";
if(d3.sca_writemask_y) ret += "y";
if(d3.sca_writemask_z) ret += "z";
if(d3.sca_writemask_w) ret += "w";
return ret.IsEmpty() || ret == "xyzw" ? wxEmptyString : ("." + ret);
return GetMask(true);
}
wxString VertexDecompilerThread::GetDST(bool isSca)
@ -32,32 +40,31 @@ wxString VertexDecompilerThread::GetDST(bool isSca)
"gl_Position",
"col0", "col1",
"bfc0", "bfc1",
"fogc",
"gl_Pointsize",
"gl_ClipDistance[%d]",
"gl_ClipDistance[%d]",
"tc0", "tc1", "tc2", "tc3", "tc4", "tc5", "tc6", "tc7"
};
wxString ret = wxEmptyString;
u32 dst = isSca ? d3.sca_dst : d3.dst;
switch(dst)
switch(isSca ? 0x1f : d3.dst)
{
case 0x0: case 0x6:
ret += reg_table[dst];
case 0x0: case 0x5: case 0x6:
ret += reg_table[d3.dst];
break;
case 0x1f:
ret += m_parr.AddParam(PARAM_NONE, "vec4", wxString::Format("tmp%d", d0.dst_tmp));
ret += m_parr.AddParam(PARAM_NONE, "vec4", wxString::Format("tmp%u", isSca ? d3.sca_dst_tmp : d0.dst_tmp));
break;
default:
if(dst < WXSIZEOF(reg_table))
if(d3.dst < WXSIZEOF(reg_table))
{
ret += m_parr.AddParam(PARAM_OUT, "vec4", reg_table[dst]);
ret += m_parr.AddParam(PARAM_OUT, "vec4", reg_table[d3.dst]);
}
else
{
ConLog.Error("Bad dst reg num: %d", dst);
ConLog.Error("Bad dst reg num: %d", d3.dst);
ret += m_parr.AddParam(PARAM_OUT, "vec4", "unk");
}
break;
@ -83,7 +90,7 @@ wxString VertexDecompilerThread::GetSRC(const u32 n, bool isSca)
switch(src[n].reg_type)
{
case 1: //temp
ret += m_parr.AddParam(PARAM_NONE, "vec4", wxString::Format("tmp%d", src[n].tmp_src));
ret += m_parr.AddParam(PARAM_NONE, "vec4", wxString::Format("tmp%u", src[n].tmp_src));
break;
case 2: //input
if(d1.input_src < WXSIZEOF(reg_table))
@ -97,19 +104,16 @@ wxString VertexDecompilerThread::GetSRC(const u32 n, bool isSca)
}
break;
case 3: //const
ret += m_parr.AddParam(PARAM_CONST, "vec4", wxString::Format("vc%d", d1.const_src));
ret += m_parr.AddParam(PARAM_UNIFORM, "vec4", wxString::Format("vc%u", d1.const_src));
break;
default:
ConLog.Error("Bad src%d reg type: %d", n, src[n].reg_type);
ConLog.Error("Bad src%u reg type: %d", n, src[n].reg_type);
Emu.Pause();
break;
}
static const char f[4] = {'x', 'z', 'w', 'y'};
static const char fSca[4] = {'x', 'z', 'y', 'w'};
wxString swizzle = wxEmptyString;
static const wxString f = "xyzw";
if (isSca)
{
@ -117,16 +121,19 @@ wxString VertexDecompilerThread::GetSRC(const u32 n, bool isSca)
assert(src[n].swz_z == src[n].swz_w);
assert(src[n].swz_x == src[n].swz_z);
ret += "." + fSca[src[n].swz_x];
ret += '.';
ret += f[src[n].swz_x];
}
else
{
wxString swizzle = wxEmptyString;
swizzle += f[src[n].swz_x];
swizzle += f[src[n].swz_y];
swizzle += f[src[n].swz_z];
swizzle += f[src[n].swz_w];
if(swizzle != "xyzw") ret += "." + swizzle;
if(swizzle != f) ret += '.' + swizzle;
}
bool abs;
@ -144,34 +151,78 @@ wxString VertexDecompilerThread::GetSRC(const u32 n, bool isSca)
return ret;
}
void VertexDecompilerThread::AddVecCode(wxString code, bool src_mask)
void VertexDecompilerThread::AddCode(bool is_sca, wxString code, bool src_mask)
{
if(d0.cond == 0) return;
if(d0.cond != 7)
enum
{
ConLog.Error("Bad cond! %d", d0.cond);
Emu.Pause();
return;
lt = 0x1,
eq = 0x2,
gt = 0x4,
};
wxString cond;
if(d0.cond != (lt | gt | eq))
{
if((d0.cond & (lt | gt)) == (lt | gt))
{
cond = "!=";
}
else
{
if(d0.cond & lt) cond = "<";
else if(d0.cond & gt) cond = ">";
else if(d0.cond & eq) cond = "=";
if(d0.cond & eq) cond += "=";
}
//ConLog.Error("cond! %d (%d %s %d %d)", d0.cond, d0.dst_tmp, cond, d1.input_src, d1.const_src);
cond = wxString::Format("if(tmp%d.x %s 0) ", d0.dst_tmp, cond);
}
code = GetDST() + GetVecMask() + " = " + (src_mask ? code + GetVecMask() : code);
wxString value = src_mask ? code + GetMask(is_sca) : code;
if(d0.staturate)
{
value = "clamp(" + value + ", 0.0, 1.0)";
}
wxString dest;
if(d3.dst == 5 || d3.dst == 6)
{
int num = d3.dst == 5 ? 0 : 3;
if(d3.vec_writemask_x)
{
ConLog.Error("Bad clip mask.");
}
//if(d3.vec_writemask_y) num += 0;
if(d3.vec_writemask_z) num += 1;
else if(d3.vec_writemask_w) num += 2;
dest = wxString::Format(GetDST(is_sca), num);
}
else
{
dest = GetDST(is_sca) + GetMask(is_sca);
}
code = cond + dest + " = " + value;
main += "\t" + code + ";\n";
}
void VertexDecompilerThread::AddScaCode(wxString code, bool src_mask)
void VertexDecompilerThread::AddVecCode(const wxString& code, bool src_mask)
{
if(d0.cond == 0) return;
if(d0.cond != 7)
{
ConLog.Error("Bad cond! %d", d0.cond);
Emu.Pause();
return;
}
AddCode(false, code, src_mask);
}
code = GetDST(true) + GetScaMask() + " = " + (src_mask ? code + GetScaMask() : code);
main += "\t" + code + ";\n";
void VertexDecompilerThread::AddScaCode(const wxString& code)
{
AddCode(true, code, false);
}
wxString VertexDecompilerThread::BuildCode()
@ -187,7 +238,7 @@ wxString VertexDecompilerThread::BuildCode()
"#version 330\n"
"\n"
"%s\n"
"void main()\n{\n%s}\n";
"void main()\n{\n\tgl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);\n%s}\n";
return wxString::Format(prot, p, main);
}
@ -201,16 +252,18 @@ void VertexDecompilerThread::Task()
d2.HEX = m_data[i++];
d3.HEX = m_data[i++];
src[0].HEX = d2.src0l | (d1.src0h << 9);
src[1].HEX = d2.src1;
src[2].HEX = d3.src2l | (d2.src2h << 11);
src[0].src0l = d2.src0l;
src[0].src0h = d1.src0h;
src[1].src1 = d2.src1;
src[2].src2l = d3.src2l;
src[2].src2h = d2.src2h;
switch(d1.sca_opcode)
{
case 0x00: break; // NOP
case 0x01: AddScaCode(GetSRC(2, true)); break; // MOV
case 0x02: AddScaCode("1 / (" + GetSRC(2, true) + ")"); break; // RCP
case 0x03: AddScaCode("clamp(1 / (" + GetSRC(2, true) + "), 5.42101e-20, 1.884467e19"); break; // RCC
case 0x03: AddScaCode("clamp(1 / (" + GetSRC(2, true) + "), 5.42101e-20, 1.884467e19)"); break; // RCC
case 0x04: AddScaCode("inversesqrt(" + GetSRC(2, true) + ")"); break; // RSQ
case 0x05: AddScaCode("exp(" + GetSRC(2, true) + ")"); break; // EXP
case 0x06: AddScaCode("log(" + GetSRC(2, true) + ")"); break; // LOG
@ -229,7 +282,6 @@ void VertexDecompilerThread::Task()
//case 0x13: break; // PSH : works differently (PSH o[1].x A0;)
//case 0x14: break; // POP : works differently (POP o[1].x;)
default:
ConLog.Error("Unknown vp sca_opcode 0x%x", d1.sca_opcode);
Emu.Pause();
@ -241,26 +293,25 @@ void VertexDecompilerThread::Task()
case 0x00: break; //NOP
case 0x01: AddVecCode(GetSRC(0)); break; //MOV
case 0x02: AddVecCode("(" + GetSRC(0) + " * " + GetSRC(1) + ")"); break; //MUL
case 0x03: AddVecCode("(" + GetSRC(0) + " + " + GetSRC(1) + ")"); break; //ADD
case 0x03: AddVecCode("(" + GetSRC(0) + " + " + GetSRC(2) + ")"); break; //ADD
case 0x04: AddVecCode("(" + GetSRC(0) + " * " + GetSRC(1) + " + " + GetSRC(2) + ")"); break; //MAD
case 0x05: AddVecCode("dot(" + GetSRC(0) + ".xyz, " + GetSRC(1) + ".xyz)", false); break; //DP3
case 0x06: AddVecCode("(dot(" + GetSRC(0) + ".xyz, " + GetSRC(1) + ".xyz) + " + GetSRC(1) + ".w)", false); break; //DPH
case 0x07: AddVecCode("dot(" + GetSRC(0) + ", " + GetSRC(1) + ")", false); break; //DP4
case 0x08: AddVecCode("distance(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //DST
case 0x05: AddVecCode("vec4(dot(" + GetSRC(0) + ".xyz, " + GetSRC(1) + ".xyz)).xxxx"); break; //DP3
case 0x06: AddVecCode("vec4(dot(vec4(" + GetSRC(0) + ".xyz, 1), " + GetSRC(1) + ")).xxxx"); break; //DPH
case 0x07: AddVecCode("vec4(dot(" + GetSRC(0) + ", " + GetSRC(1) + ")).xxxx"); break; //DP4
case 0x08: AddVecCode("vec4(distance(" + GetSRC(0) + ", " + GetSRC(1) + ")).xxxx"); break; //DST
case 0x09: AddVecCode("min(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //MIN
case 0x0a: AddVecCode("max(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //MAX
case 0x0b: AddVecCode("lessThan(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //SLT
case 0x0c: AddVecCode("greaterThanEqual(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //SGE
case 0x0b: AddVecCode("vec4(lessThan(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SLT
case 0x0c: AddVecCode("vec4(greaterThanEqual(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SGE
case 0x0e: AddVecCode("fract(" + GetSRC(0) + ")"); break; //FRC
case 0x0f: AddVecCode("floor(" + GetSRC(0) + ")"); break; //FLR
case 0x10: AddVecCode("equal(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //SEQ
case 0x11: AddVecCode("vec4(0.0f, 0.0f, 0.0f, 0.0f)"); break; //SFL
case 0x12: AddVecCode("greaterThan(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //SGT
case 0x13: AddVecCode("lessThanEqual(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //SLE
case 0x14: AddVecCode("notEqual(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //SNE
case 0x15: AddVecCode("vec4(1.0f, 1.0f, 1.0f, 1.0f)"); break; //STR
case 0x16: AddVecCode("sign(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //SSG
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 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 0x16: AddVecCode("sign(" + GetSRC(0) + ")"); break; //SSG
default:
ConLog.Error("Unknown vp opcode 0x%x", d1.vec_opcode);
@ -272,11 +323,12 @@ void VertexDecompilerThread::Task()
}
m_shader = BuildCode();
main = wxEmptyString;
}
VertexProgram::VertexProgram()
: m_decompiler_thread(NULL)
: m_decompiler_thread(nullptr)
, id(0)
{
}
@ -358,13 +410,7 @@ void VertexProgram::Compile()
void VertexProgram::Delete()
{
data.Clear();
for(u32 i=0; i<parr.params.GetCount(); ++i)
{
parr.params[i].items.Clear();
parr.params[i].type.Clear();
}
parr.params.Clear();
constants4.Clear();
shader.Clear();
if(id)
@ -374,9 +420,32 @@ void VertexProgram::Delete()
}
}
VertexData::VertexData()
: frequency(0)
, stride(0)
, size(0)
, type(0)
, addr(0)
, data()
{
}
void VertexData::Reset()
{
frequency = 0;
stride = 0;
size = 0;
type = 0;
addr = 0;
data.ClearF();
}
void VertexData::Load(u32 start, u32 count)
{
if(!addr) return;
const u32 tsize = GetTypeSize();
data.SetCount((start + count) * tsize * size);
for(u32 i=start; i<start + count; ++i)

View File

@ -72,8 +72,7 @@ struct VertexDecompilerThread : public ThreadBase
u32 end : 1;
u32 index_const : 1;
u32 dst : 5;
u32 sca_dst : 5;
u32 sca_result : 1;
u32 sca_dst_tmp : 6;
u32 vec_writemask_w : 1;
u32 vec_writemask_z : 1;
u32 vec_writemask_y : 1;
@ -93,17 +92,37 @@ struct VertexDecompilerThread : public ThreadBase
union SRC
{
u16 HEX;
union
{
u32 HEX;
struct
{
u32 src0l : 9;
u32 src0h : 8;
};
struct
{
u32 src1 : 17;
};
struct
{
u32 src2l : 11;
u32 src2h : 6;
};
};
struct
{
u16 reg_type : 2;
u16 tmp_src : 5;
u16 swz_w : 2;
u16 swz_z : 2;
u16 swz_y : 2;
u16 swz_x : 2;
u16 neg : 1;
u32 reg_type : 2;
u32 tmp_src : 6;
u32 swz_w : 2;
u32 swz_z : 2;
u32 swz_y : 2;
u32 swz_x : 2;
u32 neg : 1;
};
} src[3];
@ -120,12 +139,14 @@ struct VertexDecompilerThread : public ThreadBase
{
}
wxString GetMask(bool is_sca);
wxString GetVecMask();
wxString GetScaMask();
wxString GetDST(bool isSca = false);
wxString GetSRC(const u32 n, bool isSca = false);
void AddVecCode(wxString code, bool src_mask = true);
void AddScaCode(wxString code, bool src_mask = true);
wxString GetDST(bool is_sca = false);
wxString GetSRC(const u32 n, bool is_sca = false);
void AddCode(bool is_sca, wxString code, bool src_mask = true);
void AddVecCode(const wxString& code, bool src_mask = true);
void AddScaCode(const wxString& code);
wxString BuildCode();
virtual void Task();
@ -140,14 +161,6 @@ struct VertexProgram
VertexProgram();
~VertexProgram();
struct Constant4
{
u32 id;
float x, y, z, w;
};
Array<Constant4> constants4;
Array<u32> data;
ParamArray parr;
@ -165,20 +178,19 @@ struct VertexProgram
struct VertexData
{
u32 index;
u32 frequency;
u32 stride;
u32 size;
u32 type;
u32 addr;
u32 constant_count;
Array<u8> data;
VertexData() { memset(this, 0, sizeof(*this)); }
~VertexData() { data.Clear(); }
VertexData();
void Reset();
bool IsEnabled() { return size > 0; }
void Load(u32 start, u32 count);
u32 GetTypeSize();

View File

@ -8,7 +8,7 @@ BEGIN_EVENT_TABLE(GSFrame, wxFrame)
EVT_SIZE(GSFrame::OnSize)
END_EVENT_TABLE()
GSManager::GSManager() : m_render(NULL)
GSManager::GSManager() : m_render(nullptr)
{
}

View File

@ -38,15 +38,8 @@ struct gcmBuffer
u32 pitch;
u32 width;
u32 height;
bool update;
gcmBuffer() : update(false)
{
}
};
extern gcmBuffer gcmBuffers[2];
class GSManager
{
GSInfo m_info;

View File

@ -78,9 +78,10 @@ void GSFrame::SetSize(int width, int height)
GSRender::GSRender()
: m_ctrl(NULL)
: m_ctrl(nullptr)
, m_flip_status(0)
, m_flip_mode(CELL_GCM_DISPLAY_VSYNC)
, m_main_mem_addr(0)
{
}
@ -88,9 +89,11 @@ u32 GSRender::GetAddress(u32 offset, u8 location)
{
switch(location)
{
case CELL_GCM_LOCATION_LOCAL: return Memory.RSXFBMem.GetStartAddr() + offset;
case CELL_GCM_LOCATION_MAIN: return offset;
case CELL_GCM_LOCATION_LOCAL: return m_local_mem_addr + offset;
case CELL_GCM_LOCATION_MAIN: return m_main_mem_addr + offset;
}
ConLog.Error("GetAddress(offset=0x%x, location=0x%x", location);
return 0;
}

View File

@ -1,5 +1,7 @@
#pragma once
#include "Emu/GS/GCM.h"
#include "Emu/SysCalls/Callback.h"
#include "rpcs3.h"
enum Method
{
@ -38,9 +40,109 @@ private:
DECLARE_EVENT_TABLE();
};
struct CellGcmSurface
{
u8 type;
u8 antialias;
u8 color_format;
u8 color_target;
u8 color_location[4];
u32 color_offset[4];
u32 color_pitch[4];
u8 depth_format;
u8 depth_location;
u16 pad;
u32 depth_offset;
u32 depth_pitch;
u16 width;
u16 height;
u16 x;
u16 y;
};
struct CellGcmReportData
{
u64 timer;
u32 value;
u32 pad;
};
struct CellGcmZcullInfo
{
u32 region;
u32 size;
u32 start;
u32 offset;
u32 status0;
u32 status1;
};
struct CellGcmTileInfo
{
u32 tile;
u32 limit;
u32 pitch;
u32 format;
};
struct GcmZcullInfo
{
u32 m_offset;
u32 m_width;
u32 m_height;
u32 m_cullStart;
u32 m_zFormat;
u32 m_aaFormat;
u32 m_zCullDir;
u32 m_zCullFormat;
u32 m_sFunc;
u32 m_sRef;
u32 m_sMask;
bool m_binded;
GcmZcullInfo()
{
memset(this, 0, sizeof(*this));
}
};
struct GcmTileInfo
{
u8 m_location;
u32 m_offset;
u32 m_size;
u32 m_pitch;
u8 m_comp;
u16 m_base;
u8 m_bank;
bool m_binded;
GcmTileInfo()
{
memset(this, 0, sizeof(*this));
}
CellGcmTileInfo Pack()
{
CellGcmTileInfo ret;
re(ret.tile, (m_location + 1) | (m_bank << 4) | ((m_offset / 0x10000) << 16) | (m_location << 31));
re(ret.limit, ((m_offset + m_size - 1) / 0x10000) << 16 | (m_location << 31));
re(ret.pitch, (m_pitch / 0x100) << 8);
re(ret.format, m_base | ((m_base + ((m_size - 1) / 0x10000)) << 13) | (m_comp << 26) | (1 << 30));
return ret;
}
};
static const int g_tiles_count = 15;
struct GSRender
{
u32 m_ioAddress, m_ioSize, m_ctrlAddress, m_localAddress;
u32 m_ioAddress, m_ioSize, m_ctrlAddress;
CellGcmControl* m_ctrl;
wxCriticalSection m_cs_main;
wxSemaphore m_sem_flush;
@ -48,6 +150,20 @@ struct GSRender
int m_flip_status;
int m_flip_mode;
volatile bool m_draw;
Callback m_flip_handler;
GcmTileInfo m_tiles[g_tiles_count];
u32 m_tiles_addr;
u32 m_zculls_addr;
u32 m_gcm_buffers_addr;
u32 m_gcm_buffers_count;
u32 m_gcm_current_buffer;
u32 m_ctxt_addr;
u32 m_report_main_addr;
u32 m_local_mem_addr, m_main_mem_addr;
Array<MemInfo> m_main_mem_info;
GSRender();

View File

@ -71,7 +71,7 @@ private:
m_ioAddress = ioAddress;
m_ctrlAddress = ctrlAddress;
m_ioSize = ioSize;
m_localAddress = localAddress;
m_local_mem_addr = localAddress;
m_ctrl = (CellGcmControl*)Memory.GetMemFromAddr(m_ctrlAddress);
(m_rsx_thread = new NullRSXThread(this))->Start();

View File

@ -3,7 +3,7 @@
class ExecRSXCMDdata
{
protected:
public:
bool m_set_color_mask;
bool m_color_mask_r;
bool m_color_mask_g;
@ -21,6 +21,12 @@ protected:
bool m_set_blend;
bool m_set_depth_bounds_test;
bool m_depth_test_enable;
bool m_set_logic_op;
bool m_set_cull_face;
bool m_set_dither;
bool m_set_stencil_test;
bool m_set_line_smooth;
bool m_set_poly_smooth;
bool m_set_viewport_horizontal;
bool m_set_viewport_vertical;
@ -36,6 +42,162 @@ protected:
u16 m_scissor_w;
u16 m_scissor_h;
bool m_set_front_polygon_mode;
u32 m_front_polygon_mode;
bool m_set_clear_surface;
u32 m_clear_surface_mask;
bool m_set_blend_sfactor;
u16 m_blend_sfactor_rgb;
u16 m_blend_sfactor_alpha;
bool m_set_blend_dfactor;
u16 m_blend_dfactor_rgb;
u16 m_blend_dfactor_alpha;
bool m_set_stencil_mask;
u32 m_stencil_mask;
bool m_set_stencil_func;
u32 m_stencil_func;
bool m_set_stencil_func_ref;
u32 m_stencil_func_ref;
bool m_set_stencil_func_mask;
u32 m_stencil_func_mask;
bool m_set_stencil_fail;
u32 m_stencil_fail;
bool m_set_stencil_zfail;
u32 m_stencil_zfail;
bool m_set_stencil_zpass;
u32 m_stencil_zpass;
bool m_set_two_sided_stencil_test_enable;
bool m_set_back_stencil_mask;
u32 m_back_stencil_mask;
bool m_set_back_stencil_func;
u32 m_back_stencil_func;
bool m_set_back_stencil_func_ref;
u32 m_back_stencil_func_ref;
bool m_set_back_stencil_func_mask;
u32 m_back_stencil_func_mask;
bool m_set_back_stencil_fail;
u32 m_back_stencil_fail;
bool m_set_back_stencil_zfail;
u32 m_back_stencil_zfail;
bool m_set_back_stencil_zpass;
u32 m_back_stencil_zpass;
bool m_set_blend_equation;
u16 m_blend_equation_rgb;
u16 m_blend_equation_alpha;
bool m_set_depth_mask;
u32 m_depth_mask;
bool m_set_line_width;
u32 m_line_width;
bool m_set_shade_mode;
u32 m_shade_mode;
bool m_set_blend_color;
u8 m_blend_color_r;
u8 m_blend_color_g;
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;
u32 m_context_dma_img_src;
u32 m_context_dma_img_dst;
u32 m_dst_offset;
u32 m_color_format;
u16 m_color_format_src_pitch;
u16 m_color_format_dst_pitch;
u32 m_color_conv;
u32 m_color_conv_fmt;
u32 m_color_conv_op;
u16 m_color_conv_in_x;
u16 m_color_conv_in_y;
u16 m_color_conv_in_w;
u16 m_color_conv_in_h;
u16 m_color_conv_out_x;
u16 m_color_conv_out_y;
u16 m_color_conv_out_w;
u16 m_color_conv_out_h;
u32 m_color_conv_dsdx;
u32 m_color_conv_dtdy;
bool m_set_semaphore_offset;
u32 m_semaphore_offset;
bool m_set_fog_mode;
u32 m_fog_mode;
bool m_set_fog_params;
float m_fog_param0;
float m_fog_param1;
bool m_set_clip_plane;
u32 m_clip_plane_0;
u32 m_clip_plane_1;
u32 m_clip_plane_2;
u32 m_clip_plane_3;
u32 m_clip_plane_4;
u32 m_clip_plane_5;
bool m_set_surface_format;
u8 m_surface_color_format;
u8 m_surface_depth_format;
u8 m_surface_type;
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;
bool m_set_context_dma_color_b;
u32 m_context_dma_color_b;
bool m_set_context_dma_color_c;
u32 m_context_dma_color_c;
bool m_set_context_dma_z;
u32 m_context_dma_z;
bool m_set_surface_clip_horizontal;
u16 m_surface_clip_x;
u16 m_surface_clip_w;
bool m_set_surface_clip_vertical;
u16 m_surface_clip_y;
u16 m_surface_clip_h;
u8 m_begin_end;
public:
ExecRSXCMDdata()
{
@ -55,6 +217,49 @@ public:
m_set_viewport_vertical = false;
m_set_scissor_horizontal = false;
m_set_scissor_vertical = false;
m_set_front_polygon_mode = false;
m_set_clear_surface = false;
m_set_blend_sfactor = false;
m_set_blend_dfactor = false;
m_set_logic_op = false;
m_set_cull_face = false;
m_set_dither = false;
m_set_stencil_test = false;
m_set_stencil_mask = false;
m_set_stencil_func = false;
m_set_stencil_func_ref = false;
m_set_stencil_func_mask = false;
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;
m_set_back_stencil_func_mask = false;
m_set_back_stencil_fail = false;
m_set_back_stencil_zfail = false;
m_set_back_stencil_zpass = false;
m_set_blend_equation = false;
m_set_depth_mask = false;
m_set_line_smooth = false;
m_set_poly_smooth = false;
m_set_line_width = false;
m_set_shade_mode = false;
m_set_blend_color = false;
m_set_clear_color = false;
m_set_semaphore_offset = false;
m_set_fog_mode = false;
m_set_fog_params = false;
m_set_clip_plane = false;
m_set_surface_format = false;
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_z = false;
m_set_surface_clip_horizontal = false;
m_set_surface_clip_vertical = false;
m_begin_end = 0;
}
virtual void ExecCMD()=0;

3
rpcs3/Emu/HDD/HDD.cpp Normal file
View File

@ -0,0 +1,3 @@
#include "stdafx.h"
#include "HDD.h"

864
rpcs3/Emu/HDD/HDD.h Normal file
View File

@ -0,0 +1,864 @@
#pragma once
#include "Emu/FS/vfsDevice.h"
static const u64 g_hdd_magic = *(u64*)"PS3eHDD\0";
static const u16 g_hdd_version = 0x0001;
struct vfsHDD_Block
{
struct
{
u64 is_used : 1;
u64 next_block : 63;
};
} static const g_null_block = {0}, g_used_block = {1};
struct vfsHDD_Hdr : public vfsHDD_Block
{
u64 magic;
u16 version;
u64 block_count;
u32 block_size;
};
enum vfsHDD_EntryType : u8
{
vfsHDD_Entry_Dir = 0,
vfsHDD_Entry_File = 1,
vfsHDD_Entry_Link = 2,
};
struct vfsHDD_Entry : public vfsHDD_Block
{
u64 data_block;
vfsOpenMode access;
vfsHDD_EntryType type;
u64 size;
u64 ctime;
u64 mtime;
u64 atime;
};
class vfsHDDManager
{
public:
static void CreateBlock(vfsHDD_Block& block)
{
block.is_used = true;
block.next_block = 0;
}
static void CreateEntry(vfsHDD_Entry& entry)
{
memset(&entry, 0, sizeof(vfsHDD_Entry));
u64 ctime = time(nullptr);
entry.atime = ctime;
entry.ctime = ctime;
entry.mtime = ctime;
entry.access = vfsReadWrite;
CreateBlock(entry);
}
static void CreateHDD(const wxString& path, u64 size, u64 block_size)
{
wxFile f(path, wxFile::write);
static const u64 cur_dir_block = 1;
vfsHDD_Hdr hdr;
CreateBlock(hdr);
hdr.next_block = cur_dir_block;
hdr.magic = g_hdd_magic;
hdr.version = g_hdd_version;
hdr.block_count = (size + block_size) / block_size;
hdr.block_size = block_size;
f.Write(&hdr, sizeof(vfsHDD_Hdr));
{
vfsHDD_Entry entry;
CreateEntry(entry);
entry.type = vfsHDD_Entry_Dir;
entry.data_block = hdr.next_block;
entry.next_block = 0;
f.Seek(cur_dir_block * hdr.block_size);
f.Write(&entry, sizeof(vfsHDD_Entry));
f.Write(".");
}
u8 null = 0;
f.Seek(hdr.block_count * hdr.block_size - sizeof(null));
f.Write(&null, sizeof(null));
}
void Format()
{
}
void AppendEntry(vfsHDD_Entry entry)
{
}
};
class vfsHDDFile
{
u64 m_info_block;
vfsHDD_Entry m_info;
const vfsHDD_Hdr& m_hdd_info;
vfsLocalFile& m_hdd;
u32 m_position;
u64 m_cur_block;
bool goto_block(u64 n)
{
vfsHDD_Block block_info;
if(m_info.data_block >= m_hdd_info.block_count)
{
return false;
}
m_hdd.Seek(m_info.data_block * m_hdd_info.block_size);
block_info.next_block = m_info.data_block;
for(u64 i=0; i<n; ++i)
{
if(!block_info.next_block || !block_info.is_used || block_info.next_block >= m_hdd_info.block_count)
{
return false;
}
m_hdd.Seek(block_info.next_block * m_hdd_info.block_size);
m_hdd.Read(&block_info, sizeof(vfsHDD_Block));
}
return true;
}
void RemoveBlocks(u64 start_block)
{
vfsHDD_Block block_info;
block_info.next_block = start_block;
while(block_info.next_block && block_info.is_used)
{
u64 offset = block_info.next_block * m_hdd_info.block_size;
ReadBlock(offset, block_info);
WriteBlock(offset, g_null_block);
}
}
void WriteBlock(u64 block, const vfsHDD_Block& data)
{
m_hdd.Seek(block * m_hdd_info.block_size);
m_hdd.Write(&data, sizeof(vfsHDD_Block));
}
void ReadBlock(u64 block, vfsHDD_Block& data)
{
m_hdd.Seek(block * m_hdd_info.block_size);
m_hdd.Read(&data, sizeof(vfsHDD_Block));
}
void WriteEntry(u64 block, const vfsHDD_Entry& data)
{
m_hdd.Seek(block * m_hdd_info.block_size);
m_hdd.Write(&data, sizeof(vfsHDD_Entry));
}
void ReadEntry(u64 block, vfsHDD_Entry& data)
{
m_hdd.Seek(block * m_hdd_info.block_size);
m_hdd.Read(&data, sizeof(vfsHDD_Entry));
}
void ReadEntry(u64 block, vfsHDD_Entry& data, wxString& name)
{
m_hdd.Seek(block * m_hdd_info.block_size);
m_hdd.Read(&data, sizeof(vfsHDD_Entry));
m_hdd.Read(wxStringBuffer(name, GetMaxNameLen()), GetMaxNameLen());
}
void ReadEntry(u64 block, wxString& name)
{
m_hdd.Seek(block * m_hdd_info.block_size + sizeof(vfsHDD_Entry));
m_hdd.Read(wxStringBuffer(name, GetMaxNameLen()), GetMaxNameLen());
}
void WriteEntry(u64 block, const vfsHDD_Entry& data, const wxString& name)
{
m_hdd.Seek(block * m_hdd_info.block_size);
m_hdd.Write(&data, sizeof(vfsHDD_Entry));
m_hdd.Write(name.c_str(), min<size_t>(GetMaxNameLen() - 1, name.Len() + 1));
}
__forceinline u32 GetMaxNameLen() const
{
return m_hdd_info.block_size - sizeof(vfsHDD_Entry);
}
public:
vfsHDDFile(vfsLocalFile& hdd, const vfsHDD_Hdr& hdd_info)
: m_hdd(hdd)
, m_hdd_info(hdd_info)
{
}
~vfsHDDFile()
{
}
void Open(u64 info_block)
{
m_info_block = info_block;
ReadEntry(m_info_block, m_info);
m_position = 0;
m_cur_block = m_info.data_block;
}
u64 FindFreeBlock()
{
vfsHDD_Block block_info;
for(u64 i = 0; i<m_hdd_info.block_count; ++i)
{
ReadBlock(i, block_info);
if(!block_info.is_used)
{
return i;
}
}
return 0;
}
u64 GetSize()
{
return m_info.size;
}
bool Seek(u64 pos)
{
if(!goto_block(pos / m_hdd_info.block_size))
{
return false;
}
m_position = pos % m_hdd_info.block_size;
return true;
}
void SaveInfo()
{
m_hdd.Seek(m_info_block * m_hdd_info.block_size);
m_hdd.Write(&m_info, sizeof(vfsHDD_Entry));
}
u64 Read(void* dst, u64 size)
{
if(!size)
return 0;
vfsDeviceLocker lock(m_hdd);
const u32 block_size = m_hdd_info.block_size - sizeof(vfsHDD_Block);
u64 rsize = min<u64>(block_size - m_position, size);
vfsHDD_Block cur_block_info;
m_hdd.Seek(m_cur_block * m_hdd_info.block_size);
m_hdd.Read(&cur_block_info, sizeof(vfsHDD_Block));
m_hdd.Seek(m_cur_block * m_hdd_info.block_size + sizeof(vfsHDD_Block) + m_position);
m_hdd.Read(dst, rsize);
size -= rsize;
m_position += rsize;
if(!size)
{
return rsize;
}
u64 offset = rsize;
for(; size; size -= rsize, offset += rsize)
{
if(!cur_block_info.is_used || !cur_block_info.next_block || cur_block_info.next_block >= m_hdd_info.block_count)
{
return offset;
}
m_cur_block = cur_block_info.next_block;
rsize = min<u64>(block_size, size);
m_hdd.Seek(cur_block_info.next_block * m_hdd_info.block_size);
m_hdd.Read(&cur_block_info, sizeof(vfsHDD_Block));
if(m_hdd.Read((u8*)dst + offset, rsize) != rsize)
{
return offset;
}
}
m_position = rsize;
return offset;
}
u64 Write(const void* src, u64 size)
{
if(!size)
return 0;
vfsDeviceLocker lock(m_hdd);
const u32 block_size = m_hdd_info.block_size - sizeof(vfsHDD_Block);
if(!m_cur_block)
{
if(!m_info.data_block)
{
u64 new_block = FindFreeBlock();
if(!new_block)
{
return 0;
}
WriteBlock(new_block, g_used_block);
m_info.data_block = new_block;
m_info.size = 0;
SaveInfo();
}
m_cur_block = m_info.data_block;
m_position = 0;
}
u64 wsize = min<u64>(block_size - m_position, size);
vfsHDD_Block block_info;
ReadBlock(m_cur_block, block_info);
if(wsize)
{
m_hdd.Seek(m_cur_block * m_hdd_info.block_size + sizeof(vfsHDD_Block) + m_position);
m_hdd.Write(src, wsize);
size -= wsize;
m_info.size += wsize;
m_position += wsize;
SaveInfo();
if(!size)
return wsize;
}
u64 last_block = m_cur_block;
block_info.is_used = true;
u64 offset = wsize;
for(; size; size -= wsize, offset += wsize, m_info.size += wsize)
{
u64 new_block = FindFreeBlock();
if(!new_block)
{
m_position = 0;
SaveInfo();
return offset;
}
m_cur_block = new_block;
wsize = min<u64>(block_size, size);
block_info.next_block = m_cur_block;
m_hdd.Seek(last_block * m_hdd_info.block_size);
if(m_hdd.Write(&block_info, sizeof(vfsHDD_Block)) != sizeof(vfsHDD_Block))
{
m_position = 0;
SaveInfo();
return offset;
}
block_info.next_block = 0;
m_hdd.Seek(m_cur_block * m_hdd_info.block_size);
if(m_hdd.Write(&block_info, sizeof(vfsHDD_Block)) != sizeof(vfsHDD_Block))
{
m_position = 0;
SaveInfo();
return offset;
}
if((m_position = m_hdd.Write((u8*)src + offset, wsize)) != wsize)
{
m_info.size += wsize;
SaveInfo();
return offset;
}
last_block = m_cur_block;
}
SaveInfo();
m_position = wsize;
return offset;
}
bool Eof() const
{
return m_info.size <= (m_cur_block * m_hdd_info.block_size + m_position);
}
};
class vfsHDD : public vfsFileBase
{
vfsHDD_Hdr m_hdd_info;
vfsHDD_Entry m_cur_dir;
u64 m_cur_dir_block;
vfsHDDFile m_file;
vfsLocalFile m_hdd_file;
const wxString& m_hdd_path;
public:
vfsHDD(const wxString& hdd_path)
: m_hdd_file(hdd_path, vfsReadWrite)
, m_file(m_hdd_file, m_hdd_info)
, m_hdd_path(hdd_path)
{
m_hdd_file.Read(&m_hdd_info, sizeof(vfsHDD_Hdr));
m_cur_dir_block = m_hdd_info.next_block;
if(!m_hdd_info.block_size)
{
ConLog.Error("Bad block size!");
m_hdd_info.block_size = 2048;
}
m_hdd_file.Seek(m_cur_dir_block * m_hdd_info.block_size);
m_hdd_file.Read(&m_cur_dir, sizeof(vfsHDD_Entry));
}
virtual vfsDevice* GetNew()
{
return new vfsHDD(m_hdd_path);
}
__forceinline u32 GetMaxNameLen() const
{
return m_hdd_info.block_size - sizeof(vfsHDD_Entry);
}
bool SearchEntry(const wxString& name, u64& entry_block, u64* parent_block = nullptr)
{
u64 last_block = 0;
u64 block = m_cur_dir_block;
vfsHDD_Entry entry;
wxString buf;
while(block)
{
ReadEntry(block, entry, buf);
if(name.CmpNoCase(buf) == 0)
{
entry_block = block;
if(parent_block)
*parent_block = last_block;
return true;
}
last_block = block;
block = entry.is_used ? entry.next_block : 0ULL;
}
return false;
}
int OpenDir(const wxString& name)
{
ConLog.Warning("OpenDir(%s)", name);
u64 entry_block;
if(!SearchEntry(name, entry_block))
return -1;
m_hdd_file.Seek(entry_block * m_hdd_info.block_size);
vfsHDD_Entry entry;
m_hdd_file.Read(&entry, sizeof(vfsHDD_Entry));
if(entry.type == vfsHDD_Entry_File)
return 1;
m_cur_dir_block = entry.data_block;
ReadEntry(m_cur_dir_block, m_cur_dir);
return 0;
}
bool Rename(const wxString& from, const wxString& to)
{
u64 entry_block;
if(!SearchEntry(from, entry_block))
{
return false;
}
vfsHDD_Entry entry;
ReadEntry(entry_block, entry);
WriteEntry(entry_block, entry, to);
return true;
}
u64 FindFreeBlock()
{
vfsHDD_Block block_info;
for(u64 i = 0; i<m_hdd_info.block_count; ++i)
{
ReadBlock(i, block_info);
if(!block_info.is_used)
{
return i;
}
}
return 0;
}
void WriteBlock(u64 block, const vfsHDD_Block& data)
{
m_hdd_file.Seek(block * m_hdd_info.block_size);
m_hdd_file.Write(&data, sizeof(vfsHDD_Block));
}
void ReadBlock(u64 block, vfsHDD_Block& data)
{
m_hdd_file.Seek(block * m_hdd_info.block_size);
m_hdd_file.Read(&data, sizeof(vfsHDD_Block));
}
void WriteEntry(u64 block, const vfsHDD_Entry& data)
{
m_hdd_file.Seek(block * m_hdd_info.block_size);
m_hdd_file.Write(&data, sizeof(vfsHDD_Entry));
}
void ReadEntry(u64 block, vfsHDD_Entry& data)
{
m_hdd_file.Seek(block * m_hdd_info.block_size);
m_hdd_file.Read(&data, sizeof(vfsHDD_Entry));
}
void ReadEntry(u64 block, vfsHDD_Entry& data, wxString& name)
{
m_hdd_file.Seek(block * m_hdd_info.block_size);
m_hdd_file.Read(&data, sizeof(vfsHDD_Entry));
m_hdd_file.Read(wxStringBuffer(name, GetMaxNameLen()), GetMaxNameLen());
}
void ReadEntry(u64 block, wxString& name)
{
m_hdd_file.Seek(block * m_hdd_info.block_size + sizeof(vfsHDD_Entry));
m_hdd_file.Read(wxStringBuffer(name, GetMaxNameLen()), GetMaxNameLen());
}
void WriteEntry(u64 block, const vfsHDD_Entry& data, const wxString& name)
{
m_hdd_file.Seek(block * m_hdd_info.block_size);
m_hdd_file.Write(&data, sizeof(vfsHDD_Entry));
m_hdd_file.Write(name.c_str(), min<size_t>(GetMaxNameLen() - 1, name.Len() + 1));
}
bool Create(vfsHDD_EntryType type, const wxString& name)
{
if(HasEntry(name))
{
return false;
}
u64 new_block = FindFreeBlock();
ConLog.Write("CREATION ENTRY AT 0x%llx", new_block);
if(!new_block)
{
return false;
}
WriteBlock(new_block, g_used_block);
{
vfsHDD_Entry new_entry;
vfsHDDManager::CreateEntry(new_entry);
new_entry.next_block = 0;
new_entry.type = type;
if(type == vfsHDD_Entry_Dir)
{
u64 block_cur = FindFreeBlock();
if(!block_cur)
{
return false;
}
WriteBlock(block_cur, g_used_block);
u64 block_last = FindFreeBlock();
if(!block_last)
{
return false;
}
WriteBlock(block_last, g_used_block);
vfsHDD_Entry entry_cur, entry_last;
vfsHDDManager::CreateEntry(entry_cur);
vfsHDDManager::CreateEntry(entry_last);
entry_cur.type = vfsHDD_Entry_Dir;
entry_cur.data_block = block_cur;
entry_cur.next_block = block_last;
entry_last.type = vfsHDD_Entry_Dir;
entry_last.data_block = m_cur_dir_block;
entry_last.next_block = 0;
new_entry.data_block = block_cur;
WriteEntry(block_cur, entry_cur, ".");
WriteEntry(block_last, entry_last, "..");
}
WriteEntry(new_block, new_entry, name);
}
{
u64 block = m_cur_dir_block;
vfsHDD_Block tmp;
while(block)
{
ReadBlock(block, tmp);
if(!tmp.next_block)
break;
block = tmp.next_block;
}
tmp.next_block = new_block;
WriteBlock(block, tmp);
}
return true;
}
bool GetFirstEntry(u64& block, vfsHDD_Entry& entry, wxString& name)
{
if(!m_cur_dir_block)
{
return false;
}
ReadEntry(m_cur_dir_block, entry, name);
block = entry.is_used ? entry.next_block : 0;
return true;
}
bool GetNextEntry(u64& block, vfsHDD_Entry& entry, wxString& name)
{
if(!block)
{
return false;
}
ReadEntry(block, entry, name);
block = entry.is_used ? entry.next_block : 0;
return true;
}
virtual bool Open(const wxString& path, vfsOpenMode mode = vfsRead)
{
const char* s = path.c_str();
u64 from = 0;
u64 pos = 0;
u64 file_pos = -1;
do
{
if(s[pos] == '\\' || s[pos] == '\0')
{
if(file_pos != -1)
{
return false;
}
if(from != -1)
{
if(pos - from > 1)
{
int res = OpenDir(wxString(s + from, pos));
if(res == -1)
{
return false;
}
if(res == 1)
{
file_pos = from;
}
}
from = pos;
}
else
{
from = pos;
}
}
}
while(s[pos++] != '\0');
if(file_pos == -1)
{
return false;
}
u64 file_block;
if(!SearchEntry(wxString(s + file_pos), file_block))
{
return false;
}
ConLog.Write("ENTRY FINDED AT 0x%llx", file_block);
m_file.Open(file_block);
return vfsFileBase::Open(path, mode);
}
bool HasEntry(const wxString& name)
{
u64 file_block;
if(!SearchEntry(name, file_block))
{
return false;
}
return true;
}
void RemoveBlocksDir(u64 start_block)
{
wxString name;
u64 block = start_block;
vfsHDD_Entry entry;
while(block)
{
ReadEntry(block, entry, name);
WriteBlock(block, g_null_block);
if(entry.type == vfsHDD_Entry_Dir && name != "." && name != "..")
{
ConLog.Warning("removing sub folder '%s'", name);
RemoveBlocksDir(entry.data_block);
}
else if(entry.type == vfsHDD_Entry_File)
{
RemoveBlocksFile(entry.data_block);
}
block = entry.next_block;
}
}
void RemoveBlocksFile(u64 start_block)
{
u64 block = start_block;
vfsHDD_Block block_data;
while(block)
{
ReadBlock(block, block_data);
WriteBlock(block, g_null_block);
block = block_data.next_block;
}
}
bool RemoveEntry(const wxString& name)
{
u64 entry_block, parent_entry;
if(!SearchEntry(name, entry_block, &parent_entry))
{
return false;
}
vfsHDD_Entry entry;
ReadEntry(entry_block, entry);
if(entry.type == vfsHDD_Entry_Dir)
{
RemoveBlocksDir(entry.data_block);
}
else if(entry.type == vfsHDD_Entry_File)
{
RemoveBlocksFile(entry.data_block);
}
if(parent_entry)
{
u64 next = entry.next_block;
ReadEntry(parent_entry, entry);
entry.next_block = next;
WriteEntry(parent_entry, entry);
}
WriteBlock(entry_block, g_null_block);
return true;
}
virtual bool Create(const wxString& path)
{
return false;
}
virtual u32 Write(const void* src, u32 size)
{
return vfsFileBase::Write(src, m_file.Write(src, size));
}
virtual u32 Read(void* dst, u32 size)
{
return vfsFileBase::Read(dst, m_file.Read(dst, size));
}
virtual u64 Seek(s64 offset, vfsSeekMode mode = vfsSeekSet)
{
switch(mode)
{
case vfsSeekCur:
m_file.Seek(Tell() + offset);
break;
case vfsSeekSet:
m_file.Seek(offset);
break;
case vfsSeekEnd:
m_file.Seek(m_file.GetSize() + offset);
break;
}
return vfsFileBase::Seek(offset, mode);
}
virtual bool Eof()
{
return m_file.Eof();
}
virtual u64 GetSize()
{
return m_file.GetSize();
}
};

View File

@ -4,7 +4,7 @@
#include "Windows/WindowsPadHandler.h"
PadManager::PadManager()
: m_pad_handler(NULL)
: m_pad_handler(nullptr)
, m_inited(false)
{
}
@ -32,7 +32,7 @@ void PadManager::Init(const u32 max_connect)
void PadManager::Close()
{
if(m_pad_handler) m_pad_handler->Close();
m_pad_handler = NULL;
m_pad_handler = nullptr;
m_inited = false;
}

View File

@ -90,9 +90,11 @@ struct Button
u32 m_keyCode;
u32 m_outKeyCode;
bool m_pressed;
bool m_flush;
Button(u32 offset, u32 keyCode, u32 outKeyCode)
: m_pressed(false)
, m_flush(false)
, m_offset(offset)
, m_keyCode(keyCode)
, m_outKeyCode(outKeyCode)
@ -169,8 +171,8 @@ struct Pad
struct PadInfo
{
u32 max_connect;
u32 now_connect;
u32 system_info;
u32 now_connect;
u32 system_info;
};
class PadHandlerBase
@ -191,7 +193,14 @@ public:
{
Button& button = GetButtons(p).Get(b);
if(button.m_keyCode != code) continue;
button.m_pressed = pressed;
if(button.m_pressed && !pressed)
{
button.m_flush = true;
}
else
{
button.m_pressed = pressed;
}
}
}
}

View File

@ -88,7 +88,7 @@ MemoryBlock* MemoryBlock::SetRange(const u64 start, const u32 size)
bool MemoryBlock::IsMyAddress(const u64 addr)
{
return addr >= GetStartAddr() && addr < GetEndAddr();
return mem && addr >= GetStartAddr() && addr < GetEndAddr();
}
__forceinline const u8 MemoryBlock::FastRead8(const u64 addr) const
@ -466,24 +466,52 @@ 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);
}
@ -529,6 +557,13 @@ 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())
{
@ -540,6 +575,13 @@ u8 MemoryBase::Read8(u64 addr)
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())
{
@ -551,6 +593,13 @@ u16 MemoryBase::Read16(u64 addr)
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())
{
@ -562,6 +611,13 @@ u32 MemoryBase::Read32(u64 addr)
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())
{

View File

@ -63,16 +63,16 @@ public:
*/
}
template<typename T> static __forceinline T Reverse(T val);
template<> static __forceinline u8 Reverse(u8 val) { return val; };
template<> static __forceinline u16 Reverse(u16 val) { return Reverse16(val); };
template<> static __forceinline u32 Reverse(u32 val) { return Reverse32(val); };
template<> static __forceinline u64 Reverse(u64 val) { return Reverse64(val); };
template<int size> static __forceinline u64 ReverseData(u64 val);
template<> static __forceinline u64 ReverseData<1>(u64 val) { return val; }
template<> static __forceinline u64 ReverseData<2>(u64 val) { return Reverse16(val); }
template<> static __forceinline u64 ReverseData<4>(u64 val) { return Reverse32(val); }
template<> static __forceinline u64 ReverseData<8>(u64 val) { return Reverse64(val); }
template<> static __forceinline s8 Reverse(s8 val) { return val; };
template<> static __forceinline s16 Reverse(s16 val) { return Reverse16(val); };
template<> static __forceinline s32 Reverse(s32 val) { return Reverse32(val); };
template<> static __forceinline s64 Reverse(s64 val) { return Reverse64(val); };
template<typename T> static __forceinline T Reverse(T val)
{
return (T)ReverseData<sizeof(T)>(val);
};
MemoryBlock& GetMemByNum(const u8 num)
{
@ -328,6 +328,32 @@ public:
return PRXMem.Free(addr);
}
bool Map(const u64 dst_addr, const u64 src_addr, const u32 size)
{
if(IsGoodAddr(dst_addr) || !IsGoodAddr(src_addr))
{
return false;
}
MemoryBlocks.Add((new MemoryMirror())->SetRange(GetMemFromAddr(src_addr), dst_addr, size));
ConLog.Warning("memory mapped 0x%llx to 0x%llx size=0x%x", src_addr, dst_addr, size);
return true;
}
bool Unmap(const u64 addr)
{
for(uint i=0; i<MemoryBlocks.GetCount(); ++i)
{
if(MemoryBlocks[i].IsMirror())
{
if(MemoryBlocks[i].GetStartAddr() == addr)
{
MemoryBlocks.RemoveFAt(i);
}
}
}
}
u8* operator + (const u64 vaddr)
{
u8* ret = GetMemFromAddr(vaddr);

View File

@ -1,14 +1,27 @@
#pragma once
struct MemBlockInfo
struct MemInfo
{
u64 addr;
u32 size;
MemInfo(u64 _addr, u32 _size)
: addr(_addr)
, size(_size)
{
}
MemInfo()
{
}
};
struct MemBlockInfo : public MemInfo
{
void* mem;
MemBlockInfo(u64 _addr, u32 _size)
: addr(_addr)
, size(_size)
: MemInfo(_addr, _size)
, mem(malloc(_size))
{
if(!mem)
@ -36,7 +49,7 @@ protected:
public:
MemoryBlock();
~MemoryBlock();
virtual ~MemoryBlock();
private:
void Init();
@ -46,6 +59,7 @@ public:
virtual void Delete();
virtual bool IsNULL() { return false; }
virtual bool IsMirror() { return false; }
u64 FixAddr(const u64 addr) const;
@ -88,6 +102,31 @@ public:
virtual u8* GetMem(u64 addr) const { return mem + addr; }
};
class MemoryMirror : public MemoryBlock
{
public:
virtual bool IsMirror() { return true; }
virtual MemoryBlock* SetRange(const u64 start, const u32 size)
{
range_start = start;
range_size = size;
return this;
}
void SetMemory(u8* memory)
{
mem = memory;
}
MemoryBlock* SetRange(u8* memory, const u64 start, const u32 size)
{
SetMemory(memory);
return SetRange(start, size);
}
};
class NullMemoryBlock : public MemoryBlock
{
virtual bool IsNULL() { return true; }

View File

@ -13,6 +13,31 @@ Callback::Callback(u32 slot, u64 addr)
{
}
u32 Callback::GetSlot() const
{
return m_slot;
}
u64 Callback::GetAddr() const
{
return m_addr;
}
void Callback::SetSlot(u32 slot)
{
m_slot = slot;
}
void Callback::SetAddr(u64 addr)
{
m_addr = addr;
}
bool Callback::HasData() const
{
return m_has_data;
}
void Callback::Handle(u64 _a1, u64 _a2, u64 _a3)
{
a1 = _a1;
@ -21,28 +46,31 @@ void Callback::Handle(u64 _a1, u64 _a2, u64 _a3)
m_has_data = true;
}
void Callback::Branch()
void Callback::Branch(bool wait)
{
m_has_data = false;
PPCThread& new_thread = Emu.GetCPU().AddThread(true);
PPCThread& new_thread = Emu.GetCPU().AddThread(PPC_THREAD_PPU);
new_thread.SetPc(m_addr);
new_thread.SetPrio(0x1001);
new_thread.SetEntry(m_addr);
new_thread.SetPrio(1001);
new_thread.stack_size = 0x10000;
new_thread.SetName("Callback");
new_thread.SetArg(0, a1);
new_thread.SetArg(1, a2);
new_thread.SetArg(2, a3);
new_thread.Run();
((PPUThread&)new_thread).LR = Emu.GetPPUThreadExit();
((PPUThread&)new_thread).GPR[3] = a1;
((PPUThread&)new_thread).GPR[4] = a2;
((PPUThread&)new_thread).GPR[5] = a3;
new_thread.Exec();
while(new_thread.IsAlive()) Sleep(1);
Emu.GetCPU().RemoveThread(new_thread.GetId());
if(wait)
GetCurrentPPCThread()->Wait(new_thread);
}
ConLog.Write("Callback EXIT!");
Callback::operator bool() const
{
return GetAddr() != 0;
}
Callback2::Callback2(u32 slot, u64 addr, u64 userdata) : Callback(slot, addr)

View File

@ -1,19 +1,29 @@
#pragma once
struct Callback
class Callback
{
protected:
u64 m_addr;
u32 m_slot;
bool m_has_data;
public:
u64 a1;
u64 a2;
u64 a3;
bool m_has_data;
u32 GetSlot() const;
u64 GetAddr() const;
void SetSlot(u32 slot);
void SetAddr(u64 addr);
bool HasData() const;
Callback(u32 slot, u64 addr);
void Handle(u64 a1, u64 a2, u64 a3);
void Branch();
Callback(u32 slot = 0, u64 addr = 0);
void Handle(u64 a1 = 0, u64 a2 = 0, u64 a3 = 0);
void Branch(bool wait);
operator bool() const;
};
struct Callback2 : public Callback
@ -46,7 +56,7 @@ struct Callbacks
{
for(u32 i=0; i<m_callbacks.GetCount(); ++i)
{
if(m_callbacks[i].m_slot == slot)
if(m_callbacks[i].GetSlot() == slot)
{
m_callbacks.RemoveAt(i);
break;
@ -62,10 +72,10 @@ struct Callbacks
for(u32 i=0; i<m_callbacks.GetCount(); ++i)
{
if(m_callbacks[i].m_has_data)
if(m_callbacks[i].HasData())
{
handled = true;
m_callbacks[i].Branch();
m_callbacks[i].Branch(true);
}
}

View File

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "SysCalls.h"
#define FUNC_LOG_ERROR(x) ConLog.Error(x); return SC_ARGS_1
#define FUNC_LOG_ERROR(x) ConLog.Error(x); return 0
s64 SysCalls::DoFunc(const u32 id)
{
switch(id)
@ -286,19 +286,19 @@ s64 SysCalls::DoFunc(const u32 id)
case 0x72cc6cf7: FUNC_LOG_ERROR("TODO: cellGameGetHomeDataImportPath");
case 0x94e9f81d: FUNC_LOG_ERROR("TODO: cellGameGetHomeLaunchOptionPath");
case 0xf6acd0bc: FUNC_LOG_ERROR("TODO: cellGameGetBootGameInfo");
case 0x055bd74d: return cellGcmGetTiledPitchSize(SC_ARGS_1); //FUNC_LOG_ERROR("TODO: cellGcmGetTiledPitchSize");
case 0x055bd74d: FUNC_LOG_ERROR("TODO: cellGcmGetTiledPitchSize");
case 0x06edea9e: FUNC_LOG_ERROR("TODO: cellGcmSetUserHandler");
case 0x0a862772: FUNC_LOG_ERROR("TODO: cellGcmSetQueueHandler");
case 0x0b4b62d5: FUNC_LOG_ERROR("TODO: cellGcmSetPrepareFlip");
case 0x0e6b0dae: FUNC_LOG_ERROR("TODO: cellGcmGetDisplayInfo");
case 0x107bf3a1: FUNC_LOG_ERROR("TODO: cellGcmInitCursor");
case 0x15bae46b: return cellGcmInit(SC_ARGS_4);//FUNC_LOG_ERROR("TODO: _cellGcmInitBody");
case 0x15bae46b: FUNC_LOG_ERROR("TODO: _cellGcmInitBody");
case 0x172c3197: FUNC_LOG_ERROR("TODO: cellGcmSetDefaultCommandBufferAndSegmentWordSize");
case 0x1a0de550: FUNC_LOG_ERROR("TODO: cellGcmSetCursorPosition");
case 0x1bd633f8: FUNC_LOG_ERROR("TODO: _cellGcmFunc3");
case 0x1f61b3ff: FUNC_LOG_ERROR("TODO: cellGcmDumpGraphicsError");
case 0x21397818: return cellGcmFlush(SC_ARGS_2); //FUNC_LOG_ERROR("TODO: _cellGcmSetFlipCommand");
case 0x21ac3697: return cellGcmAddressToOffset(SC_ARGS_2); //FUNC_LOG_ERROR("TODO: cellGcmAddressToOffset");
case 0x21397818: FUNC_LOG_ERROR("TODO: _cellGcmSetFlipCommand");
case 0x21ac3697: FUNC_LOG_ERROR("TODO: cellGcmAddressToOffset");
case 0x21cee035: FUNC_LOG_ERROR("TODO: cellGcmGetNotifyDataAddress");
case 0x23ae55a3: FUNC_LOG_ERROR("TODO: cellGcmGetLastSecondVTime");
case 0x25b40ab4: FUNC_LOG_ERROR("TODO: cellGcmSortRemapEaIoAddress");
@ -309,7 +309,7 @@ s64 SysCalls::DoFunc(const u32 id)
case 0x3a33c1fd: FUNC_LOG_ERROR("TODO: _cellGcmFunc15");
case 0x3b9bd5bd: FUNC_LOG_ERROR("TODO: cellGcmUnreserveIoMapSize");
case 0x4524cccd: FUNC_LOG_ERROR("TODO: cellGcmBindTile");
case 0x4ae8d215: return cellGcmSetFlipMode(SC_ARGS_1); //FUNC_LOG_ERROR("TODO: cellGcmSetFlipMode");
case 0x4ae8d215: FUNC_LOG_ERROR("TODO: cellGcmSetFlipMode");
case 0x4d7ce993: FUNC_LOG_ERROR("TODO: cellGcmSetSecondVFrequency");
case 0x51c9d62b: FUNC_LOG_ERROR("TODO: cellGcmSetDebugOutputLevel");
case 0x527c6439: FUNC_LOG_ERROR("TODO: cellGcmTerminate");
@ -324,7 +324,7 @@ s64 SysCalls::DoFunc(const u32 id)
case 0x688b8ac9: FUNC_LOG_ERROR("TODO: _cellGcmFunc38");
case 0x69c6cc82: FUNC_LOG_ERROR("TODO: cellGcmSetCursorDisable");
case 0x723bbc7e: FUNC_LOG_ERROR("TODO: cellGcmGetVBlankCount");
case 0x72a577ce: return cellGcmGetFlipStatus(); //FUNC_LOG_ERROR("TODO: cellGcmGetFlipStatus");
case 0x72a577ce: FUNC_LOG_ERROR("TODO: cellGcmGetFlipStatus");
case 0x7fc034bc: FUNC_LOG_ERROR("TODO: _cellGcmFunc4");
case 0x8572bce2: FUNC_LOG_ERROR("TODO: cellGcmGetReportDataAddressLocation");
case 0x8bde5ebf: FUNC_LOG_ERROR("TODO: cellGcmSetUserCommand");
@ -336,17 +336,17 @@ s64 SysCalls::DoFunc(const u32 id)
case 0x9a0159af: FUNC_LOG_ERROR("TODO: cellGcmGetReportDataAddress");
case 0x9ba451e4: FUNC_LOG_ERROR("TODO: cellGcmSetDefaultFifoSize");
case 0x9dc04436: FUNC_LOG_ERROR("TODO: cellGcmBindZcull");
case 0xa114ec67: return cellGcmMapMainMemory(SC_ARGS_3); //FUNC_LOG_ERROR("TODO: cellGcmMapMainMemory");
case 0xa114ec67: FUNC_LOG_ERROR("TODO: cellGcmMapMainMemory");
case 0xa41ef7e8: FUNC_LOG_ERROR("TODO: cellGcmSetFlipHandler");
case 0xa47c09ff: FUNC_LOG_ERROR("TODO: cellGcmSetFlipStatus");
case 0xa53d12ae: return cellGcmSetDisplayBuffer(SC_ARGS_5); //FUNC_LOG_ERROR("TODO: cellGcmSetDisplayBuffer");
case 0xa547adde: return cellGcmGetControlRegister();//FUNC_LOG_ERROR("TODO: cellGcmGetControlRegister");
case 0xa53d12ae: FUNC_LOG_ERROR("TODO: cellGcmSetDisplayBuffer");
case 0xa547adde: FUNC_LOG_ERROR("TODO: cellGcmGetControlRegister");
case 0xa6b180ac: FUNC_LOG_ERROR("TODO: cellGcmGetReportDataLocation");
case 0xa75640e8: FUNC_LOG_ERROR("TODO: cellGcmUnbindZcull");
case 0xa7ede268: FUNC_LOG_ERROR("TODO: cellGcmReserveIoMapSize");
case 0xa91b0402: FUNC_LOG_ERROR("TODO: cellGcmSetVBlankHandler");
case 0xacee8542: FUNC_LOG_ERROR("TODO: cellGcmSetFlipImmediate");
case 0xb2e761d4: return cellGcmResetFlipStatus(); //FUNC_LOG_ERROR("TODO: cellGcmResetFlipStatus");
case 0xb2e761d4: FUNC_LOG_ERROR("TODO: cellGcmResetFlipStatus");
case 0xbb42a9dd: FUNC_LOG_ERROR("TODO: _cellGcmFunc13");
case 0xbc982946: FUNC_LOG_ERROR("TODO: cellGcmSetDefaultCommandBuffer");
case 0xbd100dbc: FUNC_LOG_ERROR("TODO: cellGcmSetTileInfo");
@ -356,7 +356,7 @@ 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: cellGcmSetTile(SC_ARGS_8); return SC_ARGS_1;//FUNC_LOG_ERROR("TODO: cellGcmSetTile");
case 0xd0b1d189: ConLog.Error("TODO: cellGcmSetTile"); return SC_ARGS_1;
case 0xd34a420d: ConLog.Error("TODO: cellGcmSetZcull"); return SC_ARGS_1;
case 0xd8f88e1a: FUNC_LOG_ERROR("TODO: _cellGcmSetFlipCommandWithWaitLabel");
case 0xd9a0a879: FUNC_LOG_ERROR("TODO: cellGcmGetZcullInfo");
@ -366,10 +366,10 @@ s64 SysCalls::DoFunc(const u32 id)
case 0xdc09357e: FUNC_LOG_ERROR("TODO: cellGcmSetFlip");
case 0xdc494430: FUNC_LOG_ERROR("TODO: cellGcmSetSecondVHandler");
case 0xdf6476bd: FUNC_LOG_ERROR("TODO: cellGcmSetWaitFlipUnsafe");
case 0xe315a0b2: return cellGcmGetConfiguration(SC_ARGS_1); //FUNC_LOG_ERROR("TODO: cellGcmGetConfiguration");
case 0xe315a0b2: FUNC_LOG_ERROR("TODO: cellGcmGetConfiguration");
case 0xe44874f3: FUNC_LOG_ERROR("TODO: cellGcmSysGetLastVBlankTime");
case 0xefd00f54: FUNC_LOG_ERROR("TODO: cellGcmUnmapEaIoAddress");
case 0xf80196c1: return cellGcmGetLabelAddress(SC_ARGS_1); //FUNC_LOG_ERROR("TODO: cellGcmGetLabelAddress");
case 0xf80196c1: FUNC_LOG_ERROR("TODO: cellGcmGetLabelAddress");
case 0xf9bfdc72: FUNC_LOG_ERROR("TODO: cellGcmSetCursorImageOffset");
case 0xfb81c03e: FUNC_LOG_ERROR("TODO: cellGcmGetMaxIoMapSize");
case 0xfce9e764: FUNC_LOG_ERROR("TODO: cellGcmInitSystemMode");
@ -3583,7 +3583,7 @@ s64 SysCalls::DoFunc(const u32 id)
case 0x2f85c0ef: return sys_lwmutex_create(SC_ARGS_2);//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();//FUNC_LOG_ERROR("TODO: sys_ppu_thread_get_id");
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 0x3bd53c7b: FUNC_LOG_ERROR("TODO: _sys_memchr");
case 0x3dd4a957: FUNC_LOG_ERROR("TODO: sys_ppu_thread_register_atexit");
@ -3647,7 +3647,7 @@ s64 SysCalls::DoFunc(const u32 id)
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: FUNC_LOG_ERROR("TODO: sys_ppu_thread_once");
case 0xa3e3be68: sys_ppu_thread_once(SC_ARGS_2); return SC_ARGS_1;//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");

View File

@ -0,0 +1,459 @@
#include "stdafx.h"
#include "SysCalls.h"
#include "SC_FUNC.h"
Module* g_modules[3][0xff] = {0};
uint g_max_module_id = 0;
uint g_module_2_count = 0;
ArrayF<ModuleFunc> g_modules_funcs_list;
struct ModuleInfo
{
u32 id;
char* name;
}
static const g_module_list[] =
{
{0x0000, "sys_net"},
{0x0001, "sys_http"},
{0x0002, "cellHttpUtil"},
{0x0003, "cellSsl"},
{0x0004, "cellHttps"},
{0x0005, "cellVdec"},
{0x0006, "cellAdec"},
{0x0007, "cellDmux"},
{0x0008, "cellVpost"},
{0x0009, "cellRtc"},
{0x000a, "cellSpurs"},
{0x000b, "cellOvis"},
{0x000c, "cellSheap"},
{0x000d, "sys_sync"},
{0x000e, "sys_fs"},
{0x000f, "sys_jpgdec"},
{0x0010, "cellGcmSys"},
{0x0011, "cellAudio"},
{0x0012, "cellPamf"},
{0x0013, "cellAtrac"},
{0x0014, "cellNetCtl"},
{0x0015, "cellSysutil"},
{0x0016, "sceNp"},
{0x0017, "sys_io"},
{0x0018, "cellPngDec"},
{0x0019, "cellFont"},
{0x001a, "cellFontFt"},
{0x001b, "cellFreetype"},
{0x001c, "cellUsbd"},
{0x001d, "cellSail"},
{0x001e, "cellL10n"},
{0x001f, "cellResc"},
{0x0020, "cellDaisy"},
{0x0021, "cellKey2char"},
{0x0022, "cellMic"},
{0x0023, "cellCamera"},
{0x0024, "cellVdecMpeg2"},
{0x0025, "cellVdecAvc"},
{0x0026, "cellAdecLpcm"},
{0x0027, "cellAdecAc3"},
{0x0028, "cellAdecAtx"},
{0x0029, "cellAdecAt3"},
{0x002a, "cellDmuxPamf"},
{0x002e, "cellLv2dbg"},
{0x0030, "cellUsbpspcm"},
{0x0031, "cellAvconfExt"},
{0x0032, "cellSysutilUserinfo"},
{0x0033, "cellSysutilSavedata"},
{0x0034, "cellSubdisplay"},
{0x0035, "cellSysutilRec"},
{0x0036, "cellVideoExport"},
{0x0037, "cellGameExec"},
{0x0038, "sceNp2"},
{0x0039, "cellSysutilAp"},
{0x003a, "cellSysutilNpClans"},
{0x003b, "cellSysutilOskExt"},
{0x003c, "cellVdecDivx"},
{0x003d, "cellJpgEnc"},
{0x003e, "cellGame"},
{0x003f, "cellBgdl"},
{0x0040, "cellFreetypeTT"},
{0x0041, "cellSysutilVideoUpload"},
{0x0042, "cellSysutilSysconfExt"},
{0x0043, "cellFiber"},
{0x0044, "cellNpCommerce2"},
{0x0045, "cellNpTus"},
{0x0046, "cellVoice"},
{0x0047, "cellAdecCelp8"},
{0x0048, "cellCelp8Enc"},
{0x0049, "cellLicenseArea"},
{0x004a, "cellMusic2"},
{0x004e, "cellScreenshot"},
{0x004f, "cellMusicDecode"},
{0x0050, "cellSpursJq"},
{0x0052, "cellPngEnc"},
{0x0053, "cellMusicDecode2"},
{0x0055, "cellSync2"},
{0x0056, "cellNpUtil"},
{0x0057, "cellRudp"},
{0x0059, "cellNpSns"},
{0x005a, "cellGem"},
{0xf00a, "cellCelpEnc"},
{0xf010, "cellGifDec"},
{0xf019, "cellAdecCelp"},
{0xf01b, "cellAdecM2bc"},
{0xf01d, "cellAdecM4aac"},
{0xf01e, "cellAdecMp3"},
{0xf023, "cellImejp"},
{0xf028, "cellMusic"},
{0xf029, "cellPhotoExport"},
{0xf02a, "cellPrint"},
{0xf02b, "cellPhotoImport"},
{0xf02c, "cellMusicExport"},
{0xf02e, "cellPhotoDecode"},
{0xf02f, "cellSearch"},
{0xf030, "cellAvchat2"},
{0xf034, "cellSailRec"},
{0xf035, "sceNpTrophy"},
{0xf053, "cellAdecAt3multi"},
{0xf054, "cellLibatrac3multi"},
};
struct _InitNullModules
{
_InitNullModules()
{
for(auto& m : g_module_list)
{
new Module(m.id, m.name);
}
}
} InitNullModules;
bool IsLoadedFunc(u32 id)
{
for(u32 i=0; i<g_modules_funcs_list.GetCount(); ++i)
{
if(g_modules_funcs_list[i].id == id)
{
return true;
}
}
return false;
}
bool CallFunc(u32 num)
{
if(num - 1024 >= g_modules_funcs_list.GetCount())
return false;
(*g_modules_funcs_list[num - 1024].func)();
return true;
}
bool UnloadFunc(u32 id)
{
for(u32 i=0; i<g_modules_funcs_list.GetCount(); ++i)
{
if(g_modules_funcs_list[i].id == id)
{
g_modules_funcs_list.RemoveAt(i);
return true;
}
}
return false;
}
u32 GetFuncNumById(u32 id)
{
for(u32 i=0; i<g_modules_funcs_list.GetCount(); ++i)
{
if(g_modules_funcs_list[i].id == id)
{
return 1024 + i;
}
}
return id;
}
void UnloadModules()
{
for(u32 i=0; i<g_max_module_id; ++i)
{
if(g_modules[0][i])
{
g_modules[0][i]->SetLoaded(false);
}
if(g_modules[1][i])
{
g_modules[1][i]->SetLoaded(false);
}
if(g_modules[2][i])
{
g_modules[2][i]->SetLoaded(false);
}
}
g_modules_funcs_list.Clear();
}
Module* GetModuleByName(const wxString& name)
{
for(u32 i=0; i<g_max_module_id; ++i)
{
if(g_modules[0][i] && g_modules[0][i]->GetName().Cmp(name) == 0)
{
return g_modules[0][i];
}
if(g_modules[1][i] && g_modules[1][i]->GetName().Cmp(name) == 0)
{
return g_modules[1][i];
}
if(g_modules[2][i] && g_modules[2][i]->GetName().Cmp(name) == 0)
{
return g_modules[2][i];
}
}
return nullptr;
}
Module* GetModuleById(u16 id)
{
for(u32 i=0; i<g_max_module_id; ++i)
{
if(g_modules[0][i] && g_modules[0][i]->GetID() == id)
{
return g_modules[0][i];
}
if(g_modules[1][i] && g_modules[1][i]->GetID() == id)
{
return g_modules[1][i];
}
}
return nullptr;
}
void SetModule(int id, Module* module, bool with_data)
{
if(id != 0xffff)
{
if(u16((u8)id + 1) > g_max_module_id)
{
g_max_module_id = u16((u8)id + 1);
}
int index;
switch(id >> 8)
{
case 0x00: index = 0; break;
case 0xf0: index = 1; break;
default: assert(0); return;
}
if(g_modules[index][(u8)id])
{
if(with_data)
{
module->SetName(g_modules[index][(u8)id]->GetName());
delete g_modules[index][(u8)id];
g_modules[index][(u8)id] = module;
}
else
{
g_modules[index][(u8)id]->SetName(module->GetName());
delete module;
}
}
else
{
g_modules[index][(u8)id] = module;
}
}
else
{
g_modules[2][g_module_2_count++] = module;
if(g_module_2_count > g_max_module_id)
{
g_max_module_id = g_module_2_count;
}
}
}
Module::Module(u16 id, const char* name)
: m_is_loaded(false)
, m_name(name)
, m_id(id)
{
SetModule(m_id, this, false);
}
Module::Module(const char* name, void (*init)())
: m_is_loaded(false)
, m_name(name)
, m_id(-1)
{
SetModule(m_id, this, init != nullptr);
if(init) init();
}
Module::Module(u16 id, void (*init)())
: m_is_loaded(false)
, m_id(id)
{
SetModule(m_id, this, init != nullptr);
if(init) init();
}
void Module::Load()
{
for(u32 i=0; i<m_funcs_list.GetCount(); ++i)
{
if(IsLoadedFunc(m_funcs_list[i].id)) continue;
g_modules_funcs_list.Add(m_funcs_list[i]);
}
}
void Module::UnLoad()
{
for(u32 i=0; i<m_funcs_list.GetCount(); ++i)
{
UnloadFunc(m_funcs_list[i].id);
}
}
bool Module::Load(u32 id)
{
if(IsLoadedFunc(id)) return false;
for(u32 i=0; i<m_funcs_list.GetCount(); ++i)
{
if(m_funcs_list[i].id == id)
{
g_modules_funcs_list.Add(m_funcs_list[i]);
return true;
}
}
return false;
}
bool Module::UnLoad(u32 id)
{
return UnloadFunc(id);
}
void Module::SetLoaded(bool loaded)
{
m_is_loaded = loaded;
}
bool Module::IsLoaded() const
{
return m_is_loaded;
}
u16 Module::GetID() const
{
return m_id;
}
wxString Module::GetName() const
{
return m_name;
}
void Module::SetName(const wxString& name)
{
m_name = name;
}
void Module::Log(const u32 id, wxString fmt, ...)
{
if(enable_log)
{
va_list list;
va_start(list, fmt);
ConLog.Write(GetName() + wxString::Format("[%d]: ", id) + wxString::FormatV(fmt, list));
va_end(list);
}
}
void Module::Log(wxString fmt, ...)
{
if(enable_log)
{
va_list list;
va_start(list, fmt);
ConLog.Write(GetName() + ": " + wxString::FormatV(fmt, list));
va_end(list);
}
}
void Module::Warning(const u32 id, wxString fmt, ...)
{
va_list list;
va_start(list, fmt);
ConLog.Warning(GetName() + wxString::Format("[%d] warning: ", id) + wxString::FormatV(fmt, list));
va_end(list);
}
void Module::Warning(wxString fmt, ...)
{
va_list list;
va_start(list, fmt);
ConLog.Warning(GetName() + " warning: " + wxString::FormatV(fmt, list));
va_end(list);
}
void Module::Error(const u32 id, wxString fmt, ...)
{
va_list list;
va_start(list, fmt);
ConLog.Error(GetName() + wxString::Format("[%d] error: ", id) + wxString::FormatV(fmt, list));
va_end(list);
}
void Module::Error(wxString fmt, ...)
{
va_list list;
va_start(list, fmt);
ConLog.Error(GetName() + " error: " + wxString::FormatV(fmt, list));
va_end(list);
}
bool Module::CheckId(u32 id) const
{
return Emu.GetIdManager().CheckID(id) && !Emu.GetIdManager().GetIDData(id).m_name.Cmp(GetName());
}
bool Module::CheckId(u32 id, ID& _id) const
{
return Emu.GetIdManager().CheckID(id) && !(_id = Emu.GetIdManager().GetIDData(id)).m_name.Cmp(GetName());
}
template<typename T> bool Module::CheckId(u32 id, T*& data)
{
ID id_data;
if(!CheckId(id, id_data)) return false;
data = (T*)id_data.m_data;
return true;
}
u32 Module::GetNewId(void* data, u8 flags)
{
return Emu.GetIdManager().GetNewID(GetName(), data, flags);
}

View File

@ -0,0 +1,80 @@
#pragma once
#define declCPU PPUThread& CPU = GetCurrentPPUThread
class func_caller
{
public:
virtual void operator()() = 0;
};
//TODO
struct ModuleFunc
{
u32 id;
func_caller* func;
ModuleFunc(u32 id, func_caller* func)
: id(id)
, func(func)
{
}
};
class Module
{
wxString m_name;
const u16 m_id;
bool m_is_loaded;
public:
Array<ModuleFunc> m_funcs_list;
Module(u16 id, const char* name);
Module(const char* name, void (*init)());
Module(u16 id, void (*init)());
void Load();
void UnLoad();
bool Load(u32 id);
bool UnLoad(u32 id);
void SetLoaded(bool loaded = true);
bool IsLoaded() const;
u16 GetID() const;
wxString GetName() const;
void SetName(const wxString& name);
public:
void Log(const u32 id, wxString fmt, ...);
void Log(wxString fmt, ...);
void Warning(const u32 id, wxString fmt, ...);
void Warning(wxString fmt, ...);
void Error(const u32 id, wxString fmt, ...);
void Error(wxString fmt, ...);
bool CheckId(u32 id) const;
bool CheckId(u32 id, ID& _id) const;
template<typename T> bool CheckId(u32 id, T*& data);
u32 GetNewId(void* data = nullptr, u8 flags = 0);
template<typename T>
__forceinline void AddFunc(u32 id, T func)
{
m_funcs_list.Move(new ModuleFunc(id, bind_func(func)));
}
};
bool IsLoadedFunc(u32 id);
bool CallFunc(u32 num);
bool UnloadFunc(u32 id);
void UnloadModules();
u32 GetFuncNumById(u32 id);
Module* GetModuleByName(const wxString& name);
Module* GetModuleById(u16 id);

View File

@ -1,8 +1,344 @@
#include "stdafx.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/SC_FUNC.h"
#include "Emu/GS/GCM.h"
Module cellGcmSys("cellGcmSys", 0x0010);
void cellGcmSys_init();
Module cellGcmSys(0x0010, cellGcmSys_init);
enum
{
CELL_GCM_ERROR_FAILURE = 0x802100ff,
CELL_GCM_ERROR_INVALID_ENUM = 0x80210002,
CELL_GCM_ERROR_INVALID_VALUE = 0x80210003,
CELL_GCM_ERROR_INVALID_ALIGNMENT = 0x80210004,
};
CellGcmConfig current_config;
CellGcmContextData current_context;
gcmInfo gcm_info;
struct gcm_offset
{
u16 ea;
u16 offset;
};
u32 map_offset_addr = 0;
u32 map_offset_pos = 0;
int cellGcmMapMainMemory(u32 address, u32 size, u32 offset_addr)
{
cellGcmSys.Warning("cellGcmMapMainMemory(address=0x%x,size=0x%x,offset_addr=0x%x)", address, size, offset_addr);
if(!Memory.IsGoodAddr(offset_addr, sizeof(u32))) return CELL_EFAULT;
Emu.GetGSManager().GetRender().m_main_mem_addr = Emu.GetGSManager().GetRender().m_ioAddress;
u32 offset = address - Emu.GetGSManager().GetRender().m_main_mem_addr;
Emu.GetGSManager().GetRender().m_main_mem_info.AddCpy(MemInfo(address, size));
Memory.Write32(offset_addr, offset);
return CELL_OK;
}
int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress)
{
cellGcmSys.Log("cellGcmInit(context_addr=0x%x,cmdSize=0x%x,ioSize=0x%x,ioAddress=0x%x)", context_addr, cmdSize, ioSize, ioAddress);
const u32 local_size = 0xf900000; //TODO
const u32 local_addr = Memory.RSXFBMem.GetStartAddr();
map_offset_addr = 0;
map_offset_pos = 0;
current_config.ioSize = re32(ioSize);
current_config.ioAddress = re32(ioAddress);
current_config.localSize = re32(local_size);
current_config.localAddress = re32(local_addr);
current_config.memoryFrequency = re32(650000000);
current_config.coreFrequency = re32(500000000);
Memory.RSXFBMem.Alloc(local_size);
Memory.RSXCMDMem.Alloc(cmdSize);
u32 ctx_begin = ioAddress/* + 0x1000*/;
u32 ctx_size = 0x6ffc;
current_context.begin = re(ctx_begin);
current_context.end = re(ctx_begin + ctx_size);
current_context.current = current_context.begin;
current_context.callback = re32(Emu.GetRSXCallback() - 4);
gcm_info.context_addr = Memory.MainMem.Alloc(0x1000);
gcm_info.control_addr = gcm_info.context_addr + 0x40;
Memory.WriteData(gcm_info.context_addr, current_context);
Memory.Write32(context_addr, gcm_info.context_addr);
CellGcmControl& ctrl = (CellGcmControl&)Memory[gcm_info.control_addr];
ctrl.put = 0;
ctrl.get = 0;
ctrl.ref = -1;
auto& render = Emu.GetGSManager().GetRender();
render.m_ctxt_addr = context_addr;
render.m_gcm_buffers_addr = Memory.Alloc(sizeof(gcmBuffer) * 8, sizeof(gcmBuffer));
render.m_zculls_addr = Memory.Alloc(sizeof(CellGcmZcullInfo) * 8, sizeof(CellGcmZcullInfo));
render.m_tiles_addr = Memory.Alloc(sizeof(CellGcmTileInfo) * 15, sizeof(CellGcmTileInfo));
render.m_gcm_buffers_count = 0;
render.m_gcm_current_buffer = 0;
render.m_main_mem_info.Clear();
render.m_main_mem_addr = 0;
render.Init(ctx_begin, ctx_size, gcm_info.control_addr, local_addr);
return CELL_OK;
}
int cellGcmGetConfiguration(u32 config_addr)
{
cellGcmSys.Log("cellGcmGetConfiguration(config_addr=0x%x)", config_addr);
if(!Memory.IsGoodAddr(config_addr, sizeof(CellGcmConfig))) return CELL_EFAULT;
Memory.WriteData(config_addr, current_config);
return CELL_OK;
}
int cellGcmAddressToOffset(u32 address, u32 offset_addr)
{
cellGcmSys.Log("cellGcmAddressToOffset(address=0x%x,offset_addr=0x%x)", address, offset_addr);
if(!Memory.IsGoodAddr(offset_addr, sizeof(u32))) return CELL_EFAULT;
if(!map_offset_addr)
{
map_offset_addr = Memory.Alloc(4*50, 4);
}
u32 sa;
bool is_main_mem = false;
const auto& main_mem_info = Emu.GetGSManager().GetRender().m_main_mem_info;
for(u32 i=0; i<Emu.GetGSManager().GetRender().m_main_mem_info.GetCount(); ++i)
{
//main memory
if(address >= main_mem_info[i].addr && address < main_mem_info[i].addr + main_mem_info[i].size)
{
is_main_mem = true;
break;
}
}
if(is_main_mem)
{
//main
sa = Emu.GetGSManager().GetRender().m_main_mem_addr;
//ConLog.Warning("cellGcmAddressToOffset: main memory: offset = 0x%x - 0x%x = 0x%x", address, sa, address - sa);
}
else if(Memory.RSXFBMem.IsMyAddress(address))
{
//local
sa = Emu.GetGSManager().GetRender().m_local_mem_addr;
//ConLog.Warning("cellGcmAddressToOffset: local memory: offset = 0x%x - 0x%x = 0x%x", address, sa, address - sa);
}
else
{
//io
sa = Emu.GetGSManager().GetRender().m_ioAddress;
//ConLog.Warning("cellGcmAddressToOffset: io memory: offset = 0x%x - 0x%x = 0x%x", address, sa, address - sa);
}
u32 offset = address - sa;
//Memory.Write16(map_offset_addr + map_offset_pos + 0, ea);
//Memory.Write16(map_offset_addr + map_offset_pos + 2, offset);
//map_offset_pos += 4;
Memory.Write32(offset_addr, offset);
return CELL_OK;
}
int cellGcmSetDisplayBuffer(u32 id, u32 offset, u32 pitch, u32 width, u32 height)
{
cellGcmSys.Warning("cellGcmSetDisplayBuffer(id=0x%x,offset=0x%x,pitch=%d,width=%d,height=%d)",
id, offset, width ? pitch/width : pitch, width, height);
if(id > 7) return CELL_EINVAL;
gcmBuffer* buffers = (gcmBuffer*)Memory.GetMemFromAddr(Emu.GetGSManager().GetRender().m_gcm_buffers_addr);
buffers[id].offset = re(offset);
buffers[id].pitch = re(pitch);
buffers[id].width = re(width);
buffers[id].height = re(height);
if(id + 1 > Emu.GetGSManager().GetRender().m_gcm_buffers_count)
{
Emu.GetGSManager().GetRender().m_gcm_buffers_count = id + 1;
}
return CELL_OK;
}
u32 cellGcmGetLabelAddress(u8 index)
{
cellGcmSys.Log("cellGcmGetLabelAddress(index=%d)", index);
return Memory.RSXCMDMem.GetStartAddr() + 0x10 * index;
}
u32 cellGcmGetControlRegister()
{
cellGcmSys.Log("cellGcmGetControlRegister()");
return gcm_info.control_addr;
}
int cellGcmSetPrepareFlip(u32 ctx, u32 id)
{
cellGcmSys.Log("cellGcmSetPrepareFlip(ctx=0x%x, id=0x%x)", ctx, id);
if(id >= 8)
{
return CELL_GCM_ERROR_FAILURE;
}
GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH);
CellGcmContextData& ctxt = (CellGcmContextData&)Memory[ctx];
u32 current = re(ctxt.current);
u32 end = re(ctxt.end);
if(current + 8 >= end)
{
ConLog.Warning("bad flip!");
cellGcmCallback(ctx, current + 8 - end);
}
current = re(ctxt.current);
Memory.Write32(current, 0x3fead | (1 << 18));
Memory.Write32(current + 4, id);
re(ctxt.current, current + 8);
if(ctx == gcm_info.context_addr)
{
CellGcmControl& ctrl = (CellGcmControl&)Memory[gcm_info.control_addr];
re(ctrl.put, re(ctrl.put) + 8);
}
return id;
}
int cellGcmSetFlipCommand(u32 ctx, u32 id)
{
return cellGcmSetPrepareFlip(ctx, id);
}
int cellGcmSetZcull(u8 index, u32 offset, u32 width, u32 height, u32 cullStart, u32 zFormat, u32 aaFormat, u32 zCullDir, u32 zCullFormat, u32 sFunc, u32 sRef, u32 sMask)
{
cellGcmSys.Warning("TODO: cellGcmSetZcull(index=%d, offset=0x%x, width=%d, height=%d, cullStart=0x%x, zFormat=0x%x, aaFormat=0x%x, zCullDir=0x%x, zCullFormat=0x%x, sFunc=0x%x, sRef=0x%x, sMask=0x%x)",
index, offset, width, height, cullStart, zFormat, aaFormat, zCullDir, zCullFormat, sFunc, sRef, sMask);
return CELL_OK;
}
int cellGcmBindZcull(u8 index)
{
cellGcmSys.Warning("TODO: cellGcmBindZcull(index=%d)", index);
return CELL_OK;
}
u32 cellGcmGetZcullInfo()
{
cellGcmSys.Warning("cellGcmGetZcullInfo()");
return Emu.GetGSManager().GetRender().m_zculls_addr;
}
int cellGcmGetFlipStatus()
{
return Emu.GetGSManager().GetRender().m_flip_status;
}
int cellGcmResetFlipStatus()
{
Emu.GetGSManager().GetRender().m_flip_status = 1;
return CELL_OK;
}
int cellGcmSetFlipMode(u32 mode)
{
cellGcmSys.Warning("cellGcmSetFlipMode(mode=%d)", mode);
switch(mode)
{
case CELL_GCM_DISPLAY_HSYNC:
case CELL_GCM_DISPLAY_VSYNC:
case CELL_GCM_DISPLAY_HSYNC_WITH_NOISE:
Emu.GetGSManager().GetRender().m_flip_mode = mode;
break;
default:
return CELL_EINVAL;
}
return CELL_OK;
}
u32 cellGcmGetTiledPitchSize(u32 size)
{
//TODO
cellGcmSys.Warning("cellGcmGetTiledPitchSize(size=%d)", size);
return size;
}
u32 cellGcmGetDefaultCommandWordSize()
{
cellGcmSys.Warning("cellGcmGetDefaultCommandWordSize()");
return 0x400;
}
u32 cellGcmGetDefaultSegmentWordSize()
{
cellGcmSys.Warning("cellGcmGetDefaultSegmentWordSize()");
return 0x100;
}
int cellGcmSetDefaultFifoSize(u32 bufferSize, u32 segmentSize)
{
cellGcmSys.Warning("cellGcmSetDefaultFifoSize(bufferSize=0x%x, segmentSize=0x%x)", bufferSize, segmentSize);
return CELL_OK;
}
int cellGcmMapEaIoAddress(const u32 ea, const u32 io, const u32 size)
{
cellGcmSys.Warning("cellGcmMapEaIoAddress(ea=0x%x, io=0x%x, size=0x%x)", ea, io, size);
Memory.Map(io, ea, size);
Emu.GetGSManager().GetRender().m_report_main_addr = ea;
return CELL_OK;
}
int cellGcmUnbindZcull(u8 index)
{
cellGcmSys.Warning("cellGcmUnbindZcull(index=%d)", index);
if(index >= 8)
return CELL_EINVAL;
return CELL_OK;
}
u64 cellGcmGetTimeStamp(u32 index)
{
cellGcmSys.Log("cellGcmGetTimeStamp(index=%d)", index);
return Memory.Read64(Memory.RSXFBMem.GetStartAddr() + index * 0x10);
}
int cellGcmSetFlipHandler(u32 handler_addr)
{
cellGcmSys.Warning("cellGcmSetFlipHandler(handler_addr=%d)", handler_addr);
if(!Memory.IsGoodAddr(handler_addr) && handler_addr != 0)
{
return CELL_EFAULT;
}
Emu.GetGSManager().GetRender().m_flip_handler.SetAddr(handler_addr);
return 0;
}
s64 cellGcmFunc15()
{
@ -10,31 +346,216 @@ s64 cellGcmFunc15()
return 0;
}
s64 cellGcmSetFlipCommandWithWaitLabel()
int cellGcmSetFlipCommandWithWaitLabel(u32 ctx, u32 id, u32 label_index, u32 label_value)
{
cellGcmSys.Error("cellGcmSetFlipCommandWithWaitLabel()");
return 0;
int res = cellGcmSetPrepareFlip(ctx, id);
Memory.Write32(Memory.RSXCMDMem.GetStartAddr() + 0x10 * label_index, label_value);
return res == CELL_GCM_ERROR_FAILURE ? CELL_GCM_ERROR_FAILURE : CELL_OK;
}
struct _cellGcmSys_init
int cellGcmInitCursor()
{
_cellGcmSys_init()
UNIMPLEMENTED_FUNC(cellGcmSys);
return CELL_OK;
}
int cellGcmSetCursorPosition(s32 x, s32 y)
{
UNIMPLEMENTED_FUNC(cellGcmSys);
return CELL_OK;
}
int cellGcmSetCursorDisable()
{
UNIMPLEMENTED_FUNC(cellGcmSys);
return CELL_OK;
}
int cellGcmSetVBlankHandler()
{
UNIMPLEMENTED_FUNC(cellGcmSys);
return CELL_OK;
}
int cellGcmUpdateCursor()
{
UNIMPLEMENTED_FUNC(cellGcmSys);
return CELL_OK;
}
int cellGcmSetCursorEnable()
{
UNIMPLEMENTED_FUNC(cellGcmSys);
return CELL_OK;
}
int cellGcmSetCursorImageOffset(u32 offset)
{
UNIMPLEMENTED_FUNC(cellGcmSys);
return CELL_OK;
}
u32 cellGcmGetDisplayInfo()
{
cellGcmSys.Warning("cellGcmGetDisplayInfo() = 0x%x", Emu.GetGSManager().GetRender().m_gcm_buffers_addr);
return Emu.GetGSManager().GetRender().m_gcm_buffers_addr;
}
int cellGcmGetCurrentDisplayBufferId(u32 id_addr)
{
cellGcmSys.Warning("cellGcmGetCurrentDisplayBufferId(id_addr=0x%x)", id_addr);
if(!Memory.IsGoodAddr(id_addr))
{
cellGcmSys.AddFunc(0x055bd74d, bind_func(cellGcmGetTiledPitchSize));
cellGcmSys.AddFunc(0x15bae46b, bind_func(cellGcmInit));
cellGcmSys.AddFunc(0x21397818, bind_func(cellGcmFlush));
cellGcmSys.AddFunc(0x21ac3697, bind_func(cellGcmAddressToOffset));
cellGcmSys.AddFunc(0x3a33c1fd, bind_func(cellGcmFunc15));
cellGcmSys.AddFunc(0x4ae8d215, bind_func(cellGcmSetFlipMode));
cellGcmSys.AddFunc(0x5e2ee0f0, bind_func(cellGcmGetDefaultCommandWordSize));
cellGcmSys.AddFunc(0x72a577ce, bind_func(cellGcmGetFlipStatus));
cellGcmSys.AddFunc(0x8cdf8c70, bind_func(cellGcmGetDefaultSegmentWordSize));
cellGcmSys.AddFunc(0x9ba451e4, bind_func(cellGcmSetDefaultFifoSize));
cellGcmSys.AddFunc(0xa53d12ae, bind_func(cellGcmSetDisplayBuffer));
cellGcmSys.AddFunc(0xa547adde, bind_func(cellGcmGetControlRegister));
cellGcmSys.AddFunc(0xb2e761d4, bind_func(cellGcmResetFlipStatus));
cellGcmSys.AddFunc(0xd8f88e1a, bind_func(cellGcmSetFlipCommandWithWaitLabel));
cellGcmSys.AddFunc(0xe315a0b2, bind_func(cellGcmGetConfiguration));
cellGcmSys.AddFunc(0x9dc04436, bind_func(cellGcmBindZcull));
return CELL_EFAULT;
}
} _cellGcmSys_init;
Memory.Write32(id_addr, Emu.GetGSManager().GetRender().m_gcm_current_buffer);
return CELL_OK;
}
void cellGcmSetDefaultCommandBuffer()
{
cellGcmSys.Warning("cellGcmSetDefaultCommandBuffer()");
Memory.Write32(Emu.GetGSManager().GetRender().m_ctxt_addr, gcm_info.context_addr);
}
void cellGcmSetFlipStatus()
{
cellGcmSys.Warning("cellGcmSetFlipStatus()");
Emu.GetGSManager().GetRender().m_flip_status = 0;
}
int cellGcmSetTileInfo(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u8 comp, u16 base, u8 bank)
{
cellGcmSys.Warning("cellGcmSetTileInfo(index=%d, location=%d, offset=%d, size=%d, pitch=%d, comp=%d, base=%d, bank=%d)",
index, location, offset, size, pitch, comp, base, bank);
if(index >= g_tiles_count || base >= 800 || bank >= 4)
{
return CELL_GCM_ERROR_INVALID_VALUE;
}
if(offset & 0xffff || size & 0xffff || pitch & 0xf)
{
return CELL_GCM_ERROR_INVALID_ALIGNMENT;
}
if(location >= 2 || (comp != 0 && (comp < 7 || comp > 12)))
{
return CELL_GCM_ERROR_INVALID_ENUM;
}
if(comp)
{
cellGcmSys.Error("cellGcmSetTileInfo: bad comp! (%d)", comp);
}
auto& tile = Emu.GetGSManager().GetRender().m_tiles[index];
tile.m_location = location;
tile.m_offset = offset;
tile.m_size = size;
tile.m_pitch = pitch;
tile.m_comp = comp;
tile.m_base = base;
tile.m_bank = bank;
Memory.WriteData(Emu.GetGSManager().GetRender().m_tiles_addr + sizeof(CellGcmTileInfo) * index, tile.Pack());
return CELL_OK;
}
int cellGcmBindTile(u8 index)
{
cellGcmSys.Warning("cellGcmBindTile(index=%d)", index);
if(index >= g_tiles_count)
{
return CELL_GCM_ERROR_INVALID_VALUE;
}
auto& tile = Emu.GetGSManager().GetRender().m_tiles[index];
tile.m_binded = true;
return CELL_OK;
}
int cellGcmUnbindTile(u8 index)
{
cellGcmSys.Warning("cellGcmUnbindTile(index=%d)", index);
if(index >= g_tiles_count)
{
return CELL_GCM_ERROR_INVALID_VALUE;
}
auto& tile = Emu.GetGSManager().GetRender().m_tiles[index];
tile.m_binded = false;
return CELL_OK;
}
u32 cellGcmGetTileInfo()
{
cellGcmSys.Warning("cellGcmGetTileInfo()");
return Emu.GetGSManager().GetRender().m_tiles_addr;
}
int cellGcmInitDefaultFifoMode(int mode)
{
cellGcmSys.Warning("cellGcmInitDefaultFifoMode(mode=%d)", mode);
return CELL_OK;
}
u32 cellGcmGetReportDataAddressLocation(u8 location, u32 index)
{
ConLog.Warning("cellGcmGetReportDataAddressLocation(location=%d, index=%d)", location, index);
return Emu.GetGSManager().GetRender().m_report_main_addr;
}
void cellGcmSys_init()
{
cellGcmSys.AddFunc(0x055bd74d, cellGcmGetTiledPitchSize);
cellGcmSys.AddFunc(0x15bae46b, cellGcmInit);
cellGcmSys.AddFunc(0x21397818, cellGcmSetFlipCommand);
cellGcmSys.AddFunc(0x21ac3697, cellGcmAddressToOffset);
cellGcmSys.AddFunc(0x3a33c1fd, cellGcmFunc15);
cellGcmSys.AddFunc(0x4ae8d215, cellGcmSetFlipMode);
cellGcmSys.AddFunc(0x63441cb4, cellGcmMapEaIoAddress);
cellGcmSys.AddFunc(0x5e2ee0f0, cellGcmGetDefaultCommandWordSize);
cellGcmSys.AddFunc(0x72a577ce, cellGcmGetFlipStatus);
cellGcmSys.AddFunc(0x8cdf8c70, cellGcmGetDefaultSegmentWordSize);
cellGcmSys.AddFunc(0x9ba451e4, cellGcmSetDefaultFifoSize);
cellGcmSys.AddFunc(0xa53d12ae, cellGcmSetDisplayBuffer);
cellGcmSys.AddFunc(0xa547adde, cellGcmGetControlRegister);
cellGcmSys.AddFunc(0xb2e761d4, cellGcmResetFlipStatus);
cellGcmSys.AddFunc(0xd8f88e1a, cellGcmSetFlipCommandWithWaitLabel);
cellGcmSys.AddFunc(0xe315a0b2, cellGcmGetConfiguration);
cellGcmSys.AddFunc(0x9dc04436, cellGcmBindZcull);
cellGcmSys.AddFunc(0xd34a420d, cellGcmSetZcull);
cellGcmSys.AddFunc(0xd9a0a879, cellGcmGetZcullInfo);
cellGcmSys.AddFunc(0x5a41c10f, cellGcmGetTimeStamp);
cellGcmSys.AddFunc(0xd9b7653e, cellGcmUnbindTile);
cellGcmSys.AddFunc(0xa75640e8, cellGcmUnbindZcull);
cellGcmSys.AddFunc(0xa41ef7e8, cellGcmSetFlipHandler);
cellGcmSys.AddFunc(0xa114ec67, cellGcmMapMainMemory);
cellGcmSys.AddFunc(0xf80196c1, cellGcmGetLabelAddress);
cellGcmSys.AddFunc(0x107bf3a1, cellGcmInitCursor);
cellGcmSys.AddFunc(0x1a0de550, cellGcmSetCursorPosition);
cellGcmSys.AddFunc(0x69c6cc82, cellGcmSetCursorDisable);
cellGcmSys.AddFunc(0xa91b0402, cellGcmSetVBlankHandler);
cellGcmSys.AddFunc(0xbd2fa0a7, cellGcmUpdateCursor);
cellGcmSys.AddFunc(0xc47d0812, cellGcmSetCursorEnable);
cellGcmSys.AddFunc(0xf9bfdc72, cellGcmSetCursorImageOffset);
cellGcmSys.AddFunc(0x0e6b0dae, cellGcmGetDisplayInfo);
cellGcmSys.AddFunc(0x93806525, cellGcmGetCurrentDisplayBufferId);
cellGcmSys.AddFunc(0xbc982946, cellGcmSetDefaultCommandBuffer);
cellGcmSys.AddFunc(0xa47c09ff, cellGcmSetFlipStatus);
cellGcmSys.AddFunc(0xbd100dbc, cellGcmSetTileInfo);
cellGcmSys.AddFunc(0x4524cccd, cellGcmBindTile);
cellGcmSys.AddFunc(0x0b4b62d5, cellGcmSetPrepareFlip);
cellGcmSys.AddFunc(0x657571f7, cellGcmGetTileInfo);
cellGcmSys.AddFunc(0xcaabd992, cellGcmInitDefaultFifoMode);
cellGcmSys.AddFunc(0x8572bce2, cellGcmGetReportDataAddressLocation);
}

View File

@ -0,0 +1,39 @@
#include "stdafx.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/SC_FUNC.h"
#include "Emu/GS/GCM.h"
void cellRecs_init();
Module cellRecs(0x001f, cellRecs_init);
int cellRescSetConvertAndFlip(s32 indx)
{
cellRecs.Log("cellRescSetConvertAndFlip(indx=0x%x)", indx);
Emu.GetGSManager().GetRender().Draw();
return CELL_OK;
}
int cellRescSetWaitFlip()
{
return CELL_OK;
}
int cellRescSetFlipHandler(u32 handler_addr)
{
cellRecs.Warning("cellRescSetFlipHandler(handler_addr=%d)", handler_addr);
if(!Memory.IsGoodAddr(handler_addr) && handler_addr != 0)
{
return CELL_EFAULT;
}
Emu.GetGSManager().GetRender().m_flip_handler.SetAddr(handler_addr);
return 0;
}
void cellRecs_init()
{
cellRecs.AddFunc(0x25c107e6, cellRescSetConvertAndFlip);
cellRecs.AddFunc(0x0d3c22ce, cellRescSetWaitFlip);
cellRecs.AddFunc(0x2ea94661, cellRescSetFlipHandler);
}

View File

@ -0,0 +1,95 @@
#include "stdafx.h"
#include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/SC_FUNC.h"
void cellSysmodule_init();
Module cellSysmodule("cellSysmodule", cellSysmodule_init);
enum
{
CELL_SYSMODULE_LOADED = CELL_OK,
CELL_SYSMODULE_ERROR_DUPLICATED = 0x80012001,
CELL_SYSMODULE_ERROR_UNKNOWN = 0x80012002,
CELL_SYSMODULE_ERROR_UNLOADED = 0x80012003,
CELL_SYSMODULE_ERROR_INVALID_MEMCONTAINER = 0x80012004,
CELL_SYSMODULE_ERROR_FATAL = 0x800120ff,
};
int cellSysmoduleInitialize()
{
cellSysmodule.Log("cellSysmoduleInitialize()");
return CELL_OK;
}
int cellSysmoduleFinalize()
{
cellSysmodule.Log("cellSysmoduleFinalize()");
return CELL_OK;
}
int cellSysmoduleSetMemcontainer(u32 ct_id)
{
cellSysmodule.Warning("TODO: cellSysmoduleSetMemcontainer(ct_id=0x%x)", ct_id);
return CELL_OK;
}
int cellSysmoduleLoadModule(u16 id)
{
cellSysmodule.Warning("cellSysmoduleLoadModule(id=0x%04x)", id);
Module* m = GetModuleById(id);
if(!m)
{
return CELL_SYSMODULE_ERROR_UNKNOWN;
}
if(m->IsLoaded())
{
return CELL_SYSMODULE_ERROR_DUPLICATED;
}
m->Load();
return CELL_OK;
}
int cellSysmoduleUnloadModule(u16 id)
{
cellSysmodule.Warning("cellSysmoduleUnloadModule(id=0x%04x)", id);
Module* m = GetModuleById(id);
if(!m)
{
return CELL_SYSMODULE_ERROR_UNKNOWN;
}
if(!m->IsLoaded())
{
return CELL_SYSMODULE_ERROR_UNLOADED;
}
m->UnLoad();
return CELL_OK;
}
int cellSysmoduleIsLoaded(u16 id)
{
cellSysmodule.Warning("cellSysmoduleIsLoaded(id=0x%04x)", id);
Module* m = GetModuleById(id);
if(!m)
{
return CELL_SYSMODULE_ERROR_UNKNOWN;
}
return m->IsLoaded() ? CELL_SYSMODULE_LOADED : CELL_SYSMODULE_ERROR_UNLOADED;
}
void cellSysmodule_init()
{
cellSysmodule.AddFunc(0x63ff6ff9, cellSysmoduleInitialize);
cellSysmodule.AddFunc(0x96c07adf, cellSysmoduleFinalize);
cellSysmodule.AddFunc(0xa193143c, cellSysmoduleSetMemcontainer);
cellSysmodule.AddFunc(0x32267a31, cellSysmoduleLoadModule);
cellSysmodule.AddFunc(0x112a5ee9, cellSysmoduleUnloadModule);
cellSysmodule.AddFunc(0x5a59e258, cellSysmoduleIsLoaded);
}

View File

@ -0,0 +1,240 @@
#include "stdafx.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/SC_FUNC.h"
enum
{
CELL_SYSUTIL_SYSTEMPARAM_ID_LANG = 0x0111,
CELL_SYSUTIL_SYSTEMPARAM_ID_ENTER_BUTTON_ASSIGN = 0x0112,
CELL_SYSUTIL_SYSTEMPARAM_ID_DATE_FORMAT = 0x0114,
CELL_SYSUTIL_SYSTEMPARAM_ID_TIME_FORMAT = 0x0115,
CELL_SYSUTIL_SYSTEMPARAM_ID_TIMEZONE = 0x0116,
CELL_SYSUTIL_SYSTEMPARAM_ID_SUMMERTIME = 0x0117,
CELL_SYSUTIL_SYSTEMPARAM_ID_GAME_PARENTAL_LEVEL = 0x0121,
CELL_SYSUTIL_SYSTEMPARAM_ID_GAME_PARENTAL_LEVEL0_RESTRICT = 0x0123,
CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USER_HAS_NP_ACCOUNT = 0x0141,
CELL_SYSUTIL_SYSTEMPARAM_ID_CAMERA_PLFREQ = 0x0151,
CELL_SYSUTIL_SYSTEMPARAM_ID_PAD_RUMBLE = 0x0152,
CELL_SYSUTIL_SYSTEMPARAM_ID_KEYBOARD_TYPE = 0x0153,
CELL_SYSUTIL_SYSTEMPARAM_ID_JAPANESE_KEYBOARD_ENTRY_METHOD = 0x0154,
CELL_SYSUTIL_SYSTEMPARAM_ID_CHINESE_KEYBOARD_ENTRY_METHOD = 0x0155,
CELL_SYSUTIL_SYSTEMPARAM_ID_PAD_AUTOOFF = 0x0156,
};
enum
{
CELL_SYSUTIL_LANG_JAPANESE = 0,
CELL_SYSUTIL_LANG_ENGLISH_US = 1,
CELL_SYSUTIL_LANG_FRENCH = 2,
CELL_SYSUTIL_LANG_SPANISH = 3,
CELL_SYSUTIL_LANG_GERMAN = 4,
CELL_SYSUTIL_LANG_ITALIAN = 5,
CELL_SYSUTIL_LANG_DUTCH = 6,
CELL_SYSUTIL_LANG_PORTUGUESE_PT = 7,
CELL_SYSUTIL_LANG_RUSSIAN = 8,
CELL_SYSUTIL_LANG_KOREAN = 9,
CELL_SYSUTIL_LANG_CHINESE_T = 10,
CELL_SYSUTIL_LANG_CHINESE_S = 11,
CELL_SYSUTIL_LANG_FINNISH = 12,
CELL_SYSUTIL_LANG_SWEDISH = 13,
CELL_SYSUTIL_LANG_DANISH = 14,
CELL_SYSUTIL_LANG_NORWEGIAN = 15,
CELL_SYSUTIL_LANG_POLISH = 16,
CELL_SYSUTIL_LANG_PORTUGUESE_BR = 17,
CELL_SYSUTIL_LANG_ENGLISH_GB = 18,
};
enum
{
CELL_SYSUTIL_ENTER_BUTTON_ASSIGN_CIRCLE = 0,
CELL_SYSUTIL_ENTER_BUTTON_ASSIGN_CROSS = 1,
};
enum
{
CELL_SYSUTIL_DATE_FMT_YYYYMMDD = 0,
CELL_SYSUTIL_DATE_FMT_DDMMYYYY = 1,
CELL_SYSUTIL_DATE_FMT_MMDDYYYY = 2,
};
enum
{
CELL_SYSUTIL_TIME_FMT_CLOCK12 = 0,
CELL_SYSUTIL_TIME_FMT_CLOCK24 = 1,
};
enum
{
CELL_SYSUTIL_GAME_PARENTAL_OFF = 0,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL01 = 1,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL02 = 2,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL03 = 3,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL04 = 4,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL05 = 5,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL06 = 6,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL07 = 7,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL08 = 8,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL09 = 9,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL10 = 10,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL11 = 11,
};
enum
{
CELL_SYSUTIL_GAME_PARENTAL_LEVEL0_RESTRICT_OFF = 0,
CELL_SYSUTIL_GAME_PARENTAL_LEVEL0_RESTRICT_ON = 1,
};
enum
{
CELL_SYSUTIL_CAMERA_PLFREQ_DISABLED = 0,
CELL_SYSUTIL_CAMERA_PLFREQ_50HZ = 1,
CELL_SYSUTIL_CAMERA_PLFREQ_60HZ = 2,
CELL_SYSUTIL_CAMERA_PLFREQ_DEVCIE_DEPEND = 4,
};
enum
{
CELL_SYSUTIL_PAD_RUMBLE_OFF = 0,
CELL_SYSUTIL_PAD_RUMBLE_ON = 1,
};
enum
{
CELL_KB_MAPPING_101,
CELL_KB_MAPPING_106,
CELL_KB_MAPPING_106_KANA,
CELL_KB_MAPPING_GERMAN_GERMANY,
CELL_KB_MAPPING_SPANISH_SPAIN,
CELL_KB_MAPPING_FRENCH_FRANCE,
CELL_KB_MAPPING_ITALIAN_ITALY,
CELL_KB_MAPPING_DUTCH_NETHERLANDS,
CELL_KB_MAPPING_PORTUGUESE_PORTUGAL,
CELL_KB_MAPPING_RUSSIAN_RUSSIA,
CELL_KB_MAPPING_ENGLISH_UK,
CELL_KB_MAPPING_KOREAN_KOREA,
CELL_KB_MAPPING_NORWEGIAN_NORWAY,
CELL_KB_MAPPING_FINNISH_FINLAND,
CELL_KB_MAPPING_DANISH_DENMARK,
CELL_KB_MAPPING_SWEDISH_SWEDEN,
CELL_KB_MAPPING_CHINESE_TRADITIONAL,
CELL_KB_MAPPING_CHINESE_SIMPLIFIED,
CELL_KB_MAPPING_SWISS_FRENCH_SWITZERLAND,
CELL_KB_MAPPING_SWISS_GERMAN_SWITZERLAND,
CELL_KB_MAPPING_CANADIAN_FRENCH_CANADA,
CELL_KB_MAPPING_BELGIAN_BELGIUM,
CELL_KB_MAPPING_POLISH_POLAND,
CELL_KB_MAPPING_PORTUGUESE_BRAZIL,
};
void cellSysutil_init();
Module cellSysutil(0x0015, cellSysutil_init);
void cellVideoOutGetDeviceInfo()
{
UNIMPLEMENTED_FUNC(cellSysutil);
}
int cellSysutilGetSystemParamInt(int id, u32 value_addr)
{
cellSysutil.Log("cellSysutilGetSystemParamInt(id=0x%x, value_addr=0x%x)", id, value_addr);
if(!Memory.IsGoodAddr(value_addr))
{
return CELL_EFAULT;
}
switch(id)
{
case CELL_SYSUTIL_SYSTEMPARAM_ID_LANG:
cellSysutil.Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_LANG");
Memory.Write32(value_addr, CELL_SYSUTIL_LANG_ENGLISH_US);
break;
case CELL_SYSUTIL_SYSTEMPARAM_ID_ENTER_BUTTON_ASSIGN:
cellSysutil.Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_ENTER_BUTTON_ASSIGN");
Memory.Write32(value_addr, CELL_SYSUTIL_ENTER_BUTTON_ASSIGN_CROSS);
break;
case CELL_SYSUTIL_SYSTEMPARAM_ID_DATE_FORMAT:
cellSysutil.Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_DATE_FORMAT");
Memory.Write32(value_addr, CELL_SYSUTIL_DATE_FMT_DDMMYYYY);
break;
case CELL_SYSUTIL_SYSTEMPARAM_ID_TIME_FORMAT:
cellSysutil.Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_TIME_FORMAT");
Memory.Write32(value_addr, CELL_SYSUTIL_TIME_FMT_CLOCK24);
break;
case CELL_SYSUTIL_SYSTEMPARAM_ID_TIMEZONE:
cellSysutil.Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_TIMEZONE");
Memory.Write32(value_addr, 3);
break;
case CELL_SYSUTIL_SYSTEMPARAM_ID_SUMMERTIME:
cellSysutil.Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_SUMMERTIME");
Memory.Write32(value_addr, 1);
break;
case CELL_SYSUTIL_SYSTEMPARAM_ID_GAME_PARENTAL_LEVEL:
cellSysutil.Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_GAME_PARENTAL_LEVEL");
Memory.Write32(value_addr, CELL_SYSUTIL_GAME_PARENTAL_OFF);
break;
case CELL_SYSUTIL_SYSTEMPARAM_ID_GAME_PARENTAL_LEVEL0_RESTRICT:
cellSysutil.Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_GAME_PARENTAL_LEVEL0_RESTRICT");
Memory.Write32(value_addr, CELL_SYSUTIL_GAME_PARENTAL_LEVEL0_RESTRICT_OFF);
break;
case CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USER_HAS_NP_ACCOUNT:
cellSysutil.Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USER_HAS_NP_ACCOUNT");
Memory.Write32(value_addr, 0);
break;
case CELL_SYSUTIL_SYSTEMPARAM_ID_CAMERA_PLFREQ:
cellSysutil.Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_CAMERA_PLFREQ");
Memory.Write32(value_addr, CELL_SYSUTIL_CAMERA_PLFREQ_DISABLED);
break;
case CELL_SYSUTIL_SYSTEMPARAM_ID_PAD_RUMBLE:
cellSysutil.Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_PAD_RUMBLE");
Memory.Write32(value_addr, CELL_SYSUTIL_PAD_RUMBLE_OFF);
break;
case CELL_SYSUTIL_SYSTEMPARAM_ID_KEYBOARD_TYPE:
cellSysutil.Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_KEYBOARD_TYPE");
Memory.Write32(value_addr, 0);
break;
case CELL_SYSUTIL_SYSTEMPARAM_ID_JAPANESE_KEYBOARD_ENTRY_METHOD:
cellSysutil.Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_JAPANESE_KEYBOARD_ENTRY_METHOD");
Memory.Write32(value_addr, 0);
break;
case CELL_SYSUTIL_SYSTEMPARAM_ID_CHINESE_KEYBOARD_ENTRY_METHOD:
cellSysutil.Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_CHINESE_KEYBOARD_ENTRY_METHOD");
Memory.Write32(value_addr, 0);
break;
case CELL_SYSUTIL_SYSTEMPARAM_ID_PAD_AUTOOFF:
cellSysutil.Warning("cellSysutilGetSystemParamInt: CELL_SYSUTIL_SYSTEMPARAM_ID_PAD_AUTOOFF");
Memory.Write32(value_addr, 0);
break;
default:
return CELL_EINVAL;
}
return CELL_OK;
}
void cellSysutil_init()
{
cellSysutil.AddFunc(0x0bae8772, cellVideoOutConfigure);
cellSysutil.AddFunc(0x189a74da, cellSysutilCheckCallback);
cellSysutil.AddFunc(0x1e930eef, cellVideoOutGetDeviceInfo);
cellSysutil.AddFunc(0x40e895d3, cellSysutilGetSystemParamInt);
cellSysutil.AddFunc(0x887572d5, cellVideoOutGetState);
cellSysutil.AddFunc(0x9d98afa0, cellSysutilRegisterCallback);
cellSysutil.AddFunc(0xe558748d, cellVideoOutGetResolution);
}

View File

@ -2,7 +2,8 @@
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/SC_FUNC.h"
Module sysPrxForUser("sysPrxForUser", -1);
void sysPrxForUser_init();
Module sysPrxForUser("sysPrxForUser", sysPrxForUser_init);
void sys_initialize_tls()
{
@ -21,6 +22,12 @@ s64 sys_process_at_Exitspawn()
return 0;
}
int sys_spu_printf_initialize(int a1, int a2, int a3, int a4, int a5)
{
sysPrxForUser.Warning("sys_spu_printf_initialize(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)", a1, a2, a3, a4, a5);
return 0;
}
s64 sys_prx_register_library()
{
sysPrxForUser.Error("sys_prx_register_library()");
@ -40,36 +47,36 @@ s64 sys_strlen(u32 addr)
return str.Len();
}
struct _sysPrxForUser_init
void sysPrxForUser_init()
{
_sysPrxForUser_init()
{
sysPrxForUser.AddFunc(0x744680a2, bind_func(sys_initialize_tls));
sysPrxForUser.AddFunc(0x744680a2, sys_initialize_tls);
sysPrxForUser.AddFunc(0x2f85c0ef, sys_lwmutex_create);
sysPrxForUser.AddFunc(0xc3476d0c, sys_lwmutex_destroy);
sysPrxForUser.AddFunc(0x1573dc3f, sys_lwmutex_lock);
sysPrxForUser.AddFunc(0xaeb78725, sys_lwmutex_trylock);
sysPrxForUser.AddFunc(0x1bc200f4, sys_lwmutex_unlock);
sysPrxForUser.AddFunc(0x2f85c0ef, bind_func(sys_lwmutex_create));
sysPrxForUser.AddFunc(0xc3476d0c, bind_func(sys_lwmutex_destroy));
sysPrxForUser.AddFunc(0x1573dc3f, bind_func(sys_lwmutex_lock));
sysPrxForUser.AddFunc(0xaeb78725, bind_func(sys_lwmutex_trylock));
sysPrxForUser.AddFunc(0x1bc200f4, bind_func(sys_lwmutex_unlock));
sysPrxForUser.AddFunc(0x8461e528, sys_time_get_system_time);
sysPrxForUser.AddFunc(0x8461e528, bind_func(sys_time_get_system_time));
sysPrxForUser.AddFunc(0xe6f2c1e7, sys_process_exit);
sysPrxForUser.AddFunc(0x2c847572, sys_process_atexitspawn);
sysPrxForUser.AddFunc(0x96328741, sys_process_at_Exitspawn);
sysPrxForUser.AddFunc(0xe6f2c1e7, bind_func(sys_process_exit));
sysPrxForUser.AddFunc(0x2c847572, bind_func(sys_process_atexitspawn));
sysPrxForUser.AddFunc(0x96328741, bind_func(sys_process_at_Exitspawn));
sysPrxForUser.AddFunc(0x24a1ea07, sys_ppu_thread_create);
sysPrxForUser.AddFunc(0x350d454e, sys_ppu_thread_get_id);
sysPrxForUser.AddFunc(0xaff080a4, sys_ppu_thread_exit);
sysPrxForUser.AddFunc(0xa3e3be68, sys_ppu_thread_once);
sysPrxForUser.AddFunc(0x24a1ea07, bind_func(sys_ppu_thread_create));
sysPrxForUser.AddFunc(0x350d454e, bind_func(sys_ppu_thread_get_id));
sysPrxForUser.AddFunc(0xaff080a4, bind_func(sys_ppu_thread_exit));
sysPrxForUser.AddFunc(0x45fe2fce, sys_spu_printf_initialize);
sysPrxForUser.AddFunc(0x42b23552, bind_func(sys_prx_register_library));
sysPrxForUser.AddFunc(0xa2c7ba64, bind_func(sys_prx_exitspawn_with_level));
sysPrxForUser.AddFunc(0x42b23552, sys_prx_register_library);
sysPrxForUser.AddFunc(0xa2c7ba64, sys_prx_exitspawn_with_level);
sysPrxForUser.AddFunc(0x2d36462b, bind_func(sys_strlen));
sysPrxForUser.AddFunc(0x2d36462b, sys_strlen);
sysPrxForUser.AddFunc(0x35168520, bind_func(sys_heap_malloc));
//sysPrxForUser.AddFunc(0xaede4b03, bind_func(sys_heap_free>);
//sysPrxForUser.AddFunc(0x8a561d92, bind_func(sys_heap_delete_heap>);
sysPrxForUser.AddFunc(0xb2fcf2c8, bind_func(sys_heap_create_heap));
}
} sysPrxForUser_init;
sysPrxForUser.AddFunc(0x35168520, sys_heap_malloc);
//sysPrxForUser.AddFunc(0xaede4b03, sys_heap_free);
//sysPrxForUser.AddFunc(0x8a561d92, sys_heap_delete_heap);
sysPrxForUser.AddFunc(0xb2fcf2c8, sys_heap_create_heap);
}

View File

@ -2,25 +2,23 @@
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/SC_FUNC.h"
Module sys_fs("sys_fs", 0x000e);
void sys_fs_init();
Module sys_fs(0x000e, sys_fs_init);
struct _sys_fs_init
void sys_fs_init()
{
_sys_fs_init()
{
sys_fs.AddFunc(0x718bf5f8, bind_func(cellFsOpen));
sys_fs.AddFunc(0x4d5ff8e2, bind_func(cellFsRead));
sys_fs.AddFunc(0xecdcf2ab, bind_func(cellFsWrite));
sys_fs.AddFunc(0x2cb51f0d, bind_func(cellFsClose));
sys_fs.AddFunc(0x3f61245c, bind_func(cellFsOpendir));
sys_fs.AddFunc(0x5c74903d, bind_func(cellFsReaddir));
sys_fs.AddFunc(0xff42dcc3, bind_func(cellFsClosedir));
sys_fs.AddFunc(0x7de6dced, bind_func(cellFsStat));
sys_fs.AddFunc(0xef3efa34, bind_func(cellFsFstat));
sys_fs.AddFunc(0xba901fe6, bind_func(cellFsMkdir));
sys_fs.AddFunc(0xf12eecc8, bind_func(cellFsRename));
sys_fs.AddFunc(0x2796fdf3, bind_func(cellFsRmdir));
sys_fs.AddFunc(0x7f4677a8, bind_func(cellFsUnlink));
sys_fs.AddFunc(0xa397d042, bind_func(cellFsLseek));
}
} sys_fs_init;
sys_fs.AddFunc(0x718bf5f8, cellFsOpen);
sys_fs.AddFunc(0x4d5ff8e2, cellFsRead);
sys_fs.AddFunc(0xecdcf2ab, cellFsWrite);
sys_fs.AddFunc(0x2cb51f0d, cellFsClose);
sys_fs.AddFunc(0x3f61245c, cellFsOpendir);
sys_fs.AddFunc(0x5c74903d, cellFsReaddir);
sys_fs.AddFunc(0xff42dcc3, cellFsClosedir);
sys_fs.AddFunc(0x7de6dced, cellFsStat);
sys_fs.AddFunc(0xef3efa34, cellFsFstat);
sys_fs.AddFunc(0xba901fe6, cellFsMkdir);
sys_fs.AddFunc(0xf12eecc8, cellFsRename);
sys_fs.AddFunc(0x2796fdf3, cellFsRmdir);
sys_fs.AddFunc(0x7f4677a8, cellFsUnlink);
sys_fs.AddFunc(0xa397d042, cellFsLseek);
}

View File

@ -2,19 +2,17 @@
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/SC_FUNC.h"
Module sys_io("sys_io", 0x0017);
void sys_io_init();
Module sys_io(0x0017, sys_io_init);
struct _sys_io_init
void sys_io_init()
{
_sys_io_init()
{
sys_io.AddFunc(0x1cf98800, bind_func(cellPadInit));
sys_io.AddFunc(0x4d9b75d5, bind_func(cellPadEnd));
sys_io.AddFunc(0x0d5f2c14, bind_func(cellPadClearBuf));
sys_io.AddFunc(0x8b72cda1, bind_func(cellPadGetData));
sys_io.AddFunc(0x6bc09c61, bind_func(cellPadGetDataExtra));
sys_io.AddFunc(0xf65544ee, bind_func(cellPadSetActDirect));
sys_io.AddFunc(0xa703a51d, bind_func(cellPadGetInfo2));
sys_io.AddFunc(0x578e3c98, bind_func(cellPadSetPortSetting));
}
} sys_io_init;
sys_io.AddFunc(0x1cf98800, cellPadInit);
sys_io.AddFunc(0x4d9b75d5, cellPadEnd);
sys_io.AddFunc(0x0d5f2c14, cellPadClearBuf);
sys_io.AddFunc(0x8b72cda1, cellPadGetData);
sys_io.AddFunc(0x6bc09c61, cellPadGetDataExtra);
sys_io.AddFunc(0xf65544ee, cellPadSetActDirect);
sys_io.AddFunc(0xa703a51d, cellPadGetInfo2);
sys_io.AddFunc(0x578e3c98, cellPadSetPortSetting);
}

View File

@ -1,137 +1,10 @@
#include "stdafx.h"
#include "SysCalls.h"
#include "Modules.h"
#include "SC_FUNC.h"
#include <vector>
ArrayF<ModuleFunc> g_modules_funcs_list;
ArrayF<Module> g_modules_list;
bool IsLoadedFunc(u32 id)
{
for(u32 i=0; i<g_modules_funcs_list.GetCount(); ++i)
{
if(g_modules_funcs_list[i].id == id)
{
return true;
}
}
return false;
}
bool CallFunc(u32 id)
{
for(u32 i=0; i<g_modules_funcs_list.GetCount(); ++i)
{
if(g_modules_funcs_list[i].id == id)
{
(*g_modules_funcs_list[i].func)();
return true;
}
}
return false;
}
bool UnloadFunc(u32 id)
{
for(u32 i=0; i<g_modules_funcs_list.GetCount(); ++i)
{
if(g_modules_funcs_list[i].id == id)
{
g_modules_funcs_list.RemoveAt(i);
return true;
}
}
return false;
}
void UnloadModules()
{
for(u32 i=0; i<g_modules_list.GetCount(); ++i)
{
g_modules_list[i].SetLoaded(false);
}
g_modules_funcs_list.Clear();
}
Module* GetModuleByName(const wxString& name)
{
for(u32 i=0; i<g_modules_list.GetCount(); ++i)
{
if(g_modules_list[i].GetName().Cmp(name) == 0)
{
return &g_modules_list[i];
}
}
return nullptr;
}
Module* GetModuleById(u16 id)
{
for(u32 i=0; i<g_modules_list.GetCount(); ++i)
{
if(g_modules_list[i].GetID() == id)
{
return &g_modules_list[i];
}
}
return nullptr;
}
Module::Module(const char* name, u16 id)
: m_is_loaded(false)
, m_name(name)
, m_id(id)
{
g_modules_list.Add(this);
}
void Module::Load()
{
for(u32 i=0; i<m_funcs_list.GetCount(); ++i)
{
if(IsLoadedFunc(m_funcs_list[i].id)) continue;
g_modules_funcs_list.Add(m_funcs_list[i]);
}
}
void Module::UnLoad()
{
for(u32 i=0; i<m_funcs_list.GetCount(); ++i)
{
UnloadFunc(m_funcs_list[i].id);
}
}
bool Module::Load(u32 id)
{
if(IsLoadedFunc(id)) return false;
for(u32 i=0; i<m_funcs_list.GetCount(); ++i)
{
if(m_funcs_list[i].id == id)
{
g_modules_funcs_list.Add(m_funcs_list[i]);
return true;
}
}
return false;
}
bool Module::UnLoad(u32 id)
{
return UnloadFunc(id);
}
void default_syscall();
static func_caller *null_func = bind_func(default_syscall);
static func_caller* sc_table[1024] =
{
@ -144,7 +17,7 @@ static func_caller* sc_table[1024] =
null_func, null_func, null_func, null_func, null_func, //34
null_func, null_func, null_func, null_func, null_func, //39
null_func, bind_func(sys_ppu_thread_exit), null_func, bind_func(sys_ppu_thread_yield), bind_func(sys_ppu_thread_join), //44
bind_func(sys_ppu_thread_detach), bind_func(sys_ppu_thread_detach), bind_func(sys_ppu_thread_get_join_state), bind_func(sys_ppu_thread_set_priority), bind_func(sys_ppu_thread_get_priority), //49
bind_func(sys_ppu_thread_detach), bind_func(sys_ppu_thread_get_join_state), bind_func(sys_ppu_thread_set_priority), bind_func(sys_ppu_thread_get_priority), bind_func(sys_ppu_thread_get_stack_information), //49
bind_func(sys_ppu_thread_stop), bind_func(sys_ppu_thread_restart), bind_func(sys_ppu_thread_create), null_func, null_func, //54
null_func, null_func, null_func, null_func, null_func, //59
null_func, null_func, null_func, null_func, null_func, //64
@ -160,20 +33,20 @@ static func_caller* sc_table[1024] =
null_func, null_func, null_func, null_func, null_func, //114
null_func, null_func, null_func, null_func, null_func, //119
null_func, null_func, null_func, null_func, null_func, //124
null_func, null_func, null_func, null_func, null_func, //129
null_func, null_func, null_func, null_func, null_func, //134
null_func, null_func, null_func, null_func, null_func, //139
null_func, null_func, null_func, bind_func(sys_event_queue_create), null_func, //129
bind_func(sys_event_queue_receive), null_func, null_func, null_func, bind_func(sys_event_port_create), //134
null_func, bind_func(sys_event_port_connect_local), null_func, bind_func(sys_event_port_send), null_func, //139
null_func, null_func, null_func, null_func, null_func, //144
bind_func(sys_time_get_current_time), bind_func(sys_time_get_system_time), bind_func(sys_time_get_timebase_frequency), null_func, null_func, //149
null_func, null_func, null_func, null_func, null_func, //154
null_func, null_func, null_func, null_func, null_func, //159
null_func, bind_func(sys_spu_image_open), null_func, null_func, null_func, //159
bind_func(sys_raw_spu_create), null_func, null_func, null_func, null_func, //164
null_func, null_func, null_func, null_func, bind_func(sys_spu_initialize), //169
bind_func(sys_spu_thread_group_create), null_func, null_func, null_func, null_func, //174
bind_func(sys_spu_thread_group_create), bind_func(sys_spu_thread_set_argument), bind_func(sys_spu_thread_initialize), bind_func(sys_spu_thread_group_start), null_func, //174
null_func, null_func, null_func, null_func, null_func, //179
null_func, null_func, null_func, null_func, null_func, //184
null_func, bind_func(sys_spu_thread_write_ls), bind_func(sys_spu_thread_read_ls), null_func, null_func, //184
null_func, null_func, null_func, null_func, null_func, //189
null_func, null_func, null_func, null_func, null_func, //194
bind_func(sys_spu_thread_write_spu_mb), null_func, null_func, null_func, null_func, //194
null_func, null_func, null_func, null_func, null_func, //199
null_func, null_func, null_func, null_func, null_func, //204
null_func, null_func, null_func, null_func, null_func, //209
@ -185,7 +58,7 @@ static func_caller* sc_table[1024] =
null_func, null_func, null_func, null_func, null_func, //239
null_func, null_func, null_func, null_func, null_func, //244
null_func, null_func, null_func, null_func, null_func, //249
null_func, null_func, null_func, null_func, null_func, //254
null_func, bind_func(sys_spu_thread_group_connect_event_all_threads), null_func, null_func, null_func, //254
null_func, null_func, null_func, null_func, null_func, //259
null_func, null_func, null_func, null_func, null_func, //264
null_func, null_func, null_func, null_func, null_func, //269
@ -342,6 +215,58 @@ static func_caller* sc_table[1024] =
null_func, null_func, null_func, bind_func(cellGcmCallback), //1024
};
bool enable_log = false;
void default_syscall()
{
declCPU();
u32 code = CPU.GPR[11];
//TODO: remove this
switch(code)
{
/*
//process
case 2: RESULT(lv2ProcessWaitForChild(CPU)); return;
case 4: RESULT(lv2ProcessGetStatus(CPU)); return;
case 5: RESULT(lv2ProcessDetachChild(CPU)); return;
case 12: RESULT(lv2ProcessGetNumberOfObject(CPU)); return;
case 13: RESULT(lv2ProcessGetId(CPU)); return;
case 18: RESULT(lv2ProcessGetPpid(CPU)); return;
case 19: RESULT(lv2ProcessKill(CPU)); return;
case 23: RESULT(lv2ProcessWaitForChild2(CPU)); return;
case 25: RESULT(lv2ProcessGetSdkVersion(CPU)); return;
*/
//timer
case 141:
case 142:
std::this_thread::sleep_for(std::chrono::nanoseconds(SC_ARGS_1));
RESULT(0);
return;
//tty
case 988:
ConLog.Warning("SysCall 988! r3: 0x%llx, r4: 0x%llx, pc: 0x%llx",
CPU.GPR[3], CPU.GPR[4], CPU.PC);
RESULT(0);
return;
case 999:
dump_enable = !dump_enable;
Emu.Pause();
ConLog.Warning("Dump %s", dump_enable ? "enabled" : "disabled");
return;
case 1000:
enable_log = !enable_log;
ConLog.Warning("Log %s", enable_log ? "enabled" : "disabled");
return;
}
ConLog.Error("Unknown syscall: %d - %08x", code, code);
RESULT(0);
return;
}
SysCalls::SysCalls(PPUThread& cpu) : CPU(cpu)
{
}
@ -350,55 +275,21 @@ SysCalls::~SysCalls()
{
}
s64 SysCalls::DoSyscall(u32 code)
void SysCalls::DoSyscall(u32 code)
{
if(code < 0x400)
if(code < 1024)
{
if(sc_table[code])
{
(*sc_table[code])();
return SC_ARGS_1;
}
//TODO: remove this
switch(code)
{
//process
case 2: return lv2ProcessWaitForChild(CPU);
case 4: return lv2ProcessGetStatus(CPU);
case 5: return lv2ProcessDetachChild(CPU);
case 12: return lv2ProcessGetNumberOfObject(CPU);
case 13: return lv2ProcessGetId(CPU);
case 18: return lv2ProcessGetPpid(CPU);
case 19: return lv2ProcessKill(CPU);
case 23: return lv2ProcessWaitForChild2(CPU);
case 25: return lv2ProcessGetSdkVersion(CPU);
//timer
case 141:
case 142:
Sleep(SC_ARGS_1 / (1000 * 1000));
return 0;
//tty
case 988:
ConLog.Warning("SysCall 988! r3: 0x%llx, r4: 0x%llx, pc: 0x%llx",
CPU.GPR[3], CPU.GPR[4], CPU.PC);
return 0;
case 999:
dump_enable = !dump_enable;
ConLog.Warning("Dump %s", dump_enable ? "enabled" : "disabled");
return 0;
}
ConLog.Error("Unknown syscall: %d - %08x", code, code);
return 0;
(*sc_table[code])();
return;
}
if(CallFunc(code)) return SC_ARGS_1;
if(CallFunc(code))
{
return;
}
//ConLog.Error("Unknown function 0x%08x", code);
//return 0;
//TODO: remove this
return DoFunc(code);
RESULT(DoFunc(code));
}

View File

@ -5,161 +5,7 @@
#define declCPU PPUThread& CPU = GetCurrentPPUThread
class func_caller
{
public:
virtual void operator()() = 0;
};
static func_caller *null_func = nullptr;
//TODO
struct ModuleFunc
{
u32 id;
func_caller* func;
ModuleFunc(u32 id, func_caller* func)
: id(id)
, func(func)
{
}
};
class Module
{
const char* m_name;
const u16 m_id;
bool m_is_loaded;
public:
Array<ModuleFunc> m_funcs_list;
Module(const char* name, u16 id);
void Load();
void UnLoad();
bool Load(u32 id);
bool UnLoad(u32 id);
void SetLoaded(bool loaded = true)
{
m_is_loaded = loaded;
}
bool IsLoaded() const
{
return m_is_loaded;
}
u16 GetID() const
{
return m_id;
}
wxString GetName() const
{
return m_name;
}
public:
void Log(const u32 id, wxString fmt, ...)
{
#ifdef SYSCALLS_DEBUG
va_list list;
va_start(list, fmt);
ConLog.Write(GetName() + wxString::Format("[%d]: ", id) + wxString::FormatV(fmt, list));
va_end(list);
#endif
}
void Log(wxString fmt, ...)
{
#ifdef SYSCALLS_DEBUG
va_list list;
va_start(list, fmt);
ConLog.Write(GetName() + ": " + wxString::FormatV(fmt, list));
va_end(list);
#endif
}
void Warning(const u32 id, wxString fmt, ...)
{
//#ifdef SYSCALLS_DEBUG
va_list list;
va_start(list, fmt);
ConLog.Warning(GetName() + wxString::Format("[%d] warning: ", id) + wxString::FormatV(fmt, list));
va_end(list);
//#endif
}
void Warning(wxString fmt, ...)
{
//#ifdef SYSCALLS_DEBUG
va_list list;
va_start(list, fmt);
ConLog.Warning(GetName() + " warning: " + wxString::FormatV(fmt, list));
va_end(list);
//#endif
}
void Error(const u32 id, wxString fmt, ...)
{
va_list list;
va_start(list, fmt);
ConLog.Error(GetName() + wxString::Format("[%d] error: ", id) + wxString::FormatV(fmt, list));
va_end(list);
}
void Error(wxString fmt, ...)
{
va_list list;
va_start(list, fmt);
ConLog.Error(GetName() + " error: " + wxString::FormatV(fmt, list));
va_end(list);
}
bool CheckId(u32 id) const
{
return Emu.GetIdManager().CheckID(id) && !Emu.GetIdManager().GetIDData(id).m_name.Cmp(GetName());
}
bool CheckId(u32 id, ID& _id) const
{
return Emu.GetIdManager().CheckID(id) && !(_id = Emu.GetIdManager().GetIDData(id)).m_name.Cmp(GetName());
}
template<typename T> bool CheckId(u32 id, T*& data)
{
ID id_data;
if(!CheckId(id, id_data)) return false;
data = (T*)id_data.m_data;
return true;
}
u32 GetNewId(void* data = nullptr, u8 flags = 0)
{
return Emu.GetIdManager().GetNewID(GetName(), data, flags);
}
//protected:
__forceinline void AddFunc(u32 id, func_caller* func)
{
m_funcs_list.Move(new ModuleFunc(id, func));
}
};
static s64 null_function() { return 0; }
bool IsLoadedFunc(u32 id);
bool CallFunc(u32 id);
bool UnloadFunc(u32 id);
void UnloadModules();
Module* GetModuleByName(const wxString& name);
Module* GetModuleById(u16 id);
extern bool enable_log;
class SysCallBase //Module
{
@ -178,22 +24,24 @@ public:
void Log(const u32 id, wxString fmt, ...)
{
#ifdef SYSCALLS_DEBUG
if(enable_log)
{
va_list list;
va_start(list, fmt);
ConLog.Write(GetName() + wxString::Format("[%d]: ", id) + wxString::FormatV(fmt, list));
va_end(list);
#endif
}
}
void Log(wxString fmt, ...)
{
#ifdef SYSCALLS_DEBUG
if(enable_log)
{
va_list list;
va_start(list, fmt);
ConLog.Write(GetName() + ": " + wxString::FormatV(fmt, list));
va_end(list);
#endif
}
}
void Warning(const u32 id, wxString fmt, ...)
@ -259,40 +107,19 @@ public:
}
};
/*
static bool CmpPath(const wxString& path1, const wxString& path2)
{
return path1.Len() >= path2.Len() && path1(0, path2.Len()).CmpNoCase(path2) == 0;
}
static wxString GetWinPath(const wxString& path)
{
if(!CmpPath(path, "/") && CmpPath(path(1, 1), ":")) return path;
wxString ppath = wxFileName(Emu.m_path).GetPath() + '/' + wxFileName(path).GetFullName();
if(wxFileExists(ppath)) return ppath;
if (CmpPath(path, "/dev_hdd0/") ||
CmpPath(path, "/dev_hdd1/") ||
CmpPath(path, "/dev_bdvd/") ||
CmpPath(path, "/dev_usb001/") ||
CmpPath(path, "/ps3_home/") ||
CmpPath(path, "/app_home/") ||
CmpPath(path, "/dev_flash/") ||
CmpPath(path, "/dev_flash2/") ||
CmpPath(path, "/dev_flash3/")
) return wxGetCwd() + path;
return wxFileName(Emu.m_path).GetPath() + (path[0] == '/' ? path : "/" + path);
}
*/
//process
extern int sys_process_getpid();
extern int sys_process_exit(int errorcode);
extern int sys_game_process_exitspawn(u32 path_addr, u32 argv_addr, u32 envp_addr,
u32 data, u32 data_size, int prio, u64 flags );
//sys_event
extern int sys_event_queue_create(u32 equeue_id_addr, u32 attr_addr, u64 event_queue_key, int size);
extern int sys_event_queue_receive(u32 equeue_id, u32 event_addr, u32 timeout);
extern int sys_event_port_create(u32 eport_id_addr, int port_type, u64 name);
extern int sys_event_port_connect_local(u32 event_port_id, u32 event_queue_id);
extern int sys_event_port_send(u32 event_port_id, u64 data1, u64 data2, u64 data3);
//sys_semaphore
extern int sys_semaphore_create(u32 sem_addr, u32 attr_addr, int initial_val, int max_val);
extern int sys_semaphore_destroy(u32 sem);
@ -333,7 +160,9 @@ extern int sys_ppu_thread_get_stack_information(u32 info_addr);
extern int sys_ppu_thread_stop(u32 thread_id);
extern int sys_ppu_thread_restart(u32 thread_id);
extern int sys_ppu_thread_create(u32 thread_id_addr, u32 entry, u32 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr);
extern int sys_ppu_thread_get_id();
extern void sys_ppu_thread_once(u32 once_ctrl_addr, u32 entry);
extern int sys_ppu_thread_get_id(const u32 id_addr);
extern int sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32 spup_addr);
//memory
extern int sys_memory_container_create(u32 cid_addr, u32 yield_size);
@ -388,25 +217,7 @@ extern int cellPadGetInfo2(u32 info_addr);
extern int cellPadSetPortSetting(u32 port_no, u32 port_setting);
//cellGcm
extern int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress);
extern int cellGcmMapMainMemory(u32 address, u32 size, u32 offset_addr);
extern int cellGcmCallback(u32 context_addr, u32 count);
extern int cellGcmGetConfiguration(u32 config_addr);
extern int cellGcmAddressToOffset(u32 address, u32 offset_addr);
extern int cellGcmSetDisplayBuffer(u32 id, u32 offset, u32 pitch, u32 width, u32 height);
extern u32 cellGcmGetLabelAddress(u32 index);
extern u32 cellGcmGetControlRegister();
extern int cellGcmFlush(u32 ctx, u32 id);
extern void cellGcmSetTile(u32 index, u32 location, u32 offset, u32 size, u32 pitch, u32 comp, u32 base, u32 bank);
extern int cellGcmBindTile(u32 index);
extern int cellGcmBindZcull(u32 index, u32 offset, u32 width, u32 height, u32 cullStart, u32 zFormat, u32 aaFormat, u32 zCullDir, u32 zCullFormat, u32 sFunc, u32 sRef, u32 sMask);
extern int cellGcmGetFlipStatus();
extern int cellGcmResetFlipStatus();
extern u32 cellGcmGetTiledPitchSize(u32 size);
extern int cellGcmSetFlipMode(u32 mode);
extern u32 cellGcmGetDefaultCommandWordSize();
extern u32 cellGcmGetDefaultSegmentWordSize();
extern int cellGcmSetDefaultFifoSize(u32 bufferSize, u32 segmentSize);
//sys_tty
extern int sys_tty_read(u32 ch, u64 buf_addr, u32 len, u64 preadlen_addr);
@ -421,16 +232,25 @@ extern int sys_heap_create_heap(const u32 heap_addr, const u32 start_addr, const
extern int sys_heap_malloc(const u32 heap_addr, const u32 size);
//sys_spu
extern int sys_spu_image_open(u32 img_addr, u32 path_addr);
extern int sys_spu_thread_initialize(u32 thread_addr, u32 group, u32 spu_num, u32 img_addr, u32 attr_addr, u32 arg_addr);
extern int sys_spu_thread_set_argument(u32 id, u32 arg_addr);
extern int sys_spu_thread_group_start(u32 id);
extern int sys_spu_thread_group_create(u64 id_addr, u32 num, int prio, u64 attr_addr);
extern int sys_spu_thread_create(u64 thread_id_addr, u64 entry_addr, u64 arg, int prio, u32 stacksize, u64 flags, u64 threadname_addr);
extern int sys_raw_spu_create(u32 id_addr, u32 attr_addr);
extern int sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu);
extern int sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type);
extern int sys_spu_thread_read_ls(u32 id, u32 address, u32 value_addr, u32 type);
extern int sys_spu_thread_write_spu_mb(u32 id, u32 value);
//sys_time
extern int sys_time_get_current_time(u32 sec_addr, u32 nsec_addr);
extern s64 sys_time_get_system_time();
extern u64 sys_time_get_timebase_frequency();
#define UNIMPLEMENTED_FUNC(module) module.Error("Unimplemented function: "__FUNCTION__)
#define SC_ARGS_1 CPU.GPR[3]
#define SC_ARGS_2 SC_ARGS_1,CPU.GPR[4]
#define SC_ARGS_3 SC_ARGS_2,CPU.GPR[5]
@ -469,7 +289,7 @@ protected:
~SysCalls();
public:
s64 DoSyscall(u32 code);
void DoSyscall(u32 code);
s64 DoFunc(const u32 id);
};

View File

@ -0,0 +1,167 @@
#include "stdafx.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/Cell/SPUThread.h"
#include "Emu/event.h"
SysCallBase sys_event("sys_event");
//128
int sys_event_queue_create(u32 equeue_id_addr, u32 attr_addr, u64 event_queue_key, int size)
{
sys_event.Warning("sys_event_queue_create(equeue_id_addr=0x%x, attr_addr=0x%x, event_queue_key=0x%llx, size=%d)",
equeue_id_addr, attr_addr, event_queue_key, size);
if(size <= 0 || size > 127)
{
return CELL_EINVAL;
}
if(!Memory.IsGoodAddr(equeue_id_addr, 4) || !Memory.IsGoodAddr(attr_addr, sizeof(sys_event_queue_attr)))
{
return CELL_EFAULT;
}
auto& attr = (sys_event_queue_attr&)Memory[attr_addr];
sys_event.Warning("name = %s", attr.name);
sys_event.Warning("type = %d", re(attr.type));
EventQueue* equeue = new EventQueue();
equeue->size = size;
equeue->pos = 0;
equeue->type = re(attr.type);
strncpy(equeue->name, attr.name, 8);
Memory.Write32(equeue_id_addr, sys_event.GetNewId(equeue));
return CELL_OK;
}
int sys_event_queue_receive(u32 equeue_id, u32 event_addr, u32 timeout)
{
sys_event.Warning("sys_event_queue_receive(equeue_id=0x%x, event_addr=0x%x, timeout=0x%x)",
equeue_id, event_addr, timeout);
if(!sys_event.CheckId(equeue_id))
{
return CELL_ESRCH;
}
int result;
auto queue_receive = [&](int status) -> bool
{
if(status == PPCThread_Stopped)
{
result = CELL_ECANCELED;
return false;
}
EventQueue* equeue = (EventQueue*)Emu.GetIdManager().GetIDData(equeue_id).m_data;
for(int i=0; i<equeue->pos; ++i)
{
if(!equeue->ports[i]->has_data && equeue->ports[i]->thread)
{
SPUThread* thr = (SPUThread*)equeue->ports[i]->thread;
if(thr->SPU_OutIntr_Mbox.GetCount())
{
u32 val;
thr->SPU_OutIntr_Mbox.Pop(val);
if(!thr->mfc.SPU_Out_MBox.Pop(val)) val = 0;
equeue->ports[i]->data1 = val;
equeue->ports[i]->data2 = 0;
equeue->ports[i]->data3 = 0;
equeue->ports[i]->has_data = true;
}
}
}
for(int i=0; i<equeue->pos; i++)
{
if(equeue->ports[i]->has_data)
{
auto dst = (sys_event_data&)Memory[event_addr];
re(dst.source, equeue->ports[i]->name);
re(dst.data1, equeue->ports[i]->data1);
re(dst.data2, equeue->ports[i]->data2);
re(dst.data3, equeue->ports[i]->data3);
equeue->ports[i]->has_data = false;
result = CELL_OK;
return false;
}
}
return true;
};
GetCurrentPPUThread().WaitFor(queue_receive);
return result;
}
int sys_event_port_create(u32 eport_id_addr, int port_type, u64 name)
{
sys_event.Warning("sys_event_port_create(eport_id_addr=0x%x, port_type=0x%x, name=0x%llx)",
eport_id_addr, port_type, name);
if(!Memory.IsGoodAddr(eport_id_addr, 4))
{
return CELL_EFAULT;
}
EventPort* eport = new EventPort();
u32 id = sys_event.GetNewId(eport);
eport->pos = 0;
eport->has_data = false;
eport->name = name ? name : id;
Memory.Write32(eport_id_addr, id);
return CELL_OK;
}
int sys_event_port_connect_local(u32 event_port_id, u32 event_queue_id)
{
sys_event.Warning("sys_event_port_connect_local(event_port_id=0x%x, event_queue_id=0x%x)",
event_port_id, event_queue_id);
if(!sys_event.CheckId(event_port_id) || !sys_event.CheckId(event_queue_id))
{
return CELL_ESRCH;
}
EventPort* eport = (EventPort*)Emu.GetIdManager().GetIDData(event_port_id).m_data;
EventQueue* equeue = (EventQueue*)Emu.GetIdManager().GetIDData(event_queue_id).m_data;
equeue->ports[equeue->pos++] = eport;
eport->queue[eport->pos++] = equeue;
return CELL_OK;
}
int sys_event_port_send(u32 event_port_id, u64 data1, u64 data2, u64 data3)
{
sys_event.Warning("sys_event_port_send(event_port_id=0x%x, data1=0x%llx, data2=0x%llx, data3=0x%llx)",
event_port_id, data1, data2, data3);
if(!sys_event.CheckId(event_port_id))
{
return CELL_ESRCH;
}
EventPort* eport = (EventPort*)Emu.GetIdManager().GetIDData(event_port_id).m_data;
if(!eport->pos)
{
return CELL_ENOTCONN;
}
if(eport->has_data)
{
return CELL_EBUSY;
}
eport->has_data = true;
eport->data1 = data1;
eport->data2 = data2;
eport->data3 = data3;
return CELL_OK;
}

View File

@ -199,9 +199,14 @@ int cellFsWrite(u32 fd, u32 buf_addr, u64 nbytes, u32 nwrite_addr)
ID id;
if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
vfsStream& file = *(vfsStream*)id.m_data;
if(Memory.IsGoodAddr(buf_addr) && !Memory.IsGoodAddr(buf_addr, nbytes))
{
MemoryBlock& block = Memory.GetMemByAddr(buf_addr);
nbytes = block.GetSize() - (buf_addr - block.GetStartAddr());
}
Memory.Write64NN(nwrite_addr, file.Write(Memory.GetMemFromAddr(buf_addr), nbytes));
int count = nbytes ? file.Write(Memory.GetMemFromAddr(buf_addr), nbytes) : 0;
Memory.Write64NN(nwrite_addr, count);
return CELL_OK;
}
@ -242,7 +247,13 @@ int cellFsStat(const u32 path_addr, const u32 sb_addr)
const wxString& path = Memory.ReadString(path_addr);
sys_fs.Log("cellFsFstat(path: %s, sb_addr: 0x%x)", path, sb_addr);
if(!wxFileExists(path)) return CELL_ENOENT;
vfsStream* f = Emu.GetVFS().Open(path, vfsRead);
if(!f || !f->IsOpened())
{
sys_fs.Warning("cellFsFstat: '%s' not found.", path);
Emu.GetVFS().Close(f);
return CELL_ENOENT;
}
Lv2FsStat stat;
stat.st_mode =
@ -256,7 +267,7 @@ int cellFsStat(const u32 path_addr, const u32 sb_addr)
stat.st_atime = 0; //TODO
stat.st_mtime = 0; //TODO
stat.st_ctime = 0; //TODO
stat.st_size = wxFile(path).Length();
stat.st_size = f->GetSize();
stat.st_blksize = 4096;
mem_class_t stat_c(sb_addr);
@ -269,6 +280,8 @@ int cellFsStat(const u32 path_addr, const u32 sb_addr)
stat_c += stat.st_size;
stat_c += stat.st_blksize;
Emu.GetVFS().Close(f);
return CELL_OK;
}

View File

@ -3,59 +3,7 @@
#include "Emu/GS/GCM.h"
extern Module cellGcmSys;
CellGcmConfig current_config;
CellGcmContextData current_context;
gcmInfo gcm_info;
int cellGcmMapMainMemory(u32 address, u32 size, u32 offset_addr)
{
cellGcmSys.Warning("cellGcmMapMainMemory(address=0x%x,size=0x%x,offset_addr=0x%x)", address, size, offset_addr);
if(!Memory.IsGoodAddr(offset_addr, sizeof(u32))) return CELL_EFAULT;
Memory.Write32(offset_addr, address & 0xffff);
return CELL_OK;
}
int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress)
{
cellGcmSys.Log("cellGcmInit(context_addr=0x%x,cmdSize=0x%x,ioSize=0x%x,ioAddress=0x%x)", context_addr, cmdSize, ioSize, ioAddress);
const u32 local_size = 0xf900000; //TODO
const u32 local_addr = Memory.RSXFBMem.GetStartAddr();
current_config.ioSize = re32(ioSize);
current_config.ioAddress = re32(ioAddress);
current_config.localSize = re32(local_size);
current_config.localAddress = re32(local_addr);
current_config.memoryFrequency = re32(650000000);
current_config.coreFrequency = re32(500000000);
Memory.RSXFBMem.Alloc(local_size);
Memory.RSXCMDMem.Alloc(cmdSize);
u32 ctx_begin = ioAddress + 0x1000;
u32 ctx_size = 0x6ffc;
current_context.begin = re(ctx_begin);
current_context.end = re(ctx_begin + ctx_size);
current_context.current = current_context.begin;
current_context.callback = re32(Emu.GetRSXCallback() - 4);
gcm_info.context_addr = Memory.MainMem.Alloc(0x1000);
gcm_info.control_addr = gcm_info.context_addr + 0x40;
Memory.WriteData(gcm_info.context_addr, current_context);
Memory.Write32(context_addr, gcm_info.context_addr);
CellGcmControl& ctrl = (CellGcmControl&)Memory[gcm_info.control_addr];
ctrl.put = 0;
ctrl.get = 0;
ctrl.ref = -1;
Emu.GetGSManager().GetRender().Init(ctx_begin, ctx_size, gcm_info.control_addr, local_addr);
return CELL_OK;
}
extern gcmInfo gcm_info;
int cellGcmCallback(u32 context_addr, u32 count)
{
@ -75,143 +23,3 @@ int cellGcmCallback(u32 context_addr, u32 count)
return CELL_OK;
}
int cellGcmGetConfiguration(u32 config_addr)
{
cellGcmSys.Log("cellGcmGetConfiguration(config_addr=0x%x)", config_addr);
if(!Memory.IsGoodAddr(config_addr, sizeof(CellGcmConfig))) return CELL_EFAULT;
Memory.WriteData(config_addr, current_config);
return CELL_OK;
}
int cellGcmAddressToOffset(u32 address, u32 offset_addr)
{
cellGcmSys.Log("cellGcmAddressToOffset(address=0x%x,offset_addr=0x%x)", address, offset_addr);
if(!Memory.IsGoodAddr(offset_addr, sizeof(u32))) return CELL_EFAULT;
Memory.Write32(offset_addr,
Memory.RSXFBMem.IsInMyRange(address)
? address - Memory.RSXFBMem.GetStartAddr()
: address - re(current_context.begin));
return CELL_OK;
}
int cellGcmSetDisplayBuffer(u32 id, u32 offset, u32 pitch, u32 width, u32 height)
{
cellGcmSys.Warning("cellGcmSetDisplayBuffer(id=0x%x,offset=0x%x,pitch=%d,width=%d,height=%d)",
id, offset, width ? pitch/width : pitch, width, height);
if(id > 1) return CELL_EINVAL;
gcmBuffers[id].offset = offset;
gcmBuffers[id].pitch = pitch;
gcmBuffers[id].width = width;
gcmBuffers[id].height = height;
gcmBuffers[id].update = true;
return CELL_OK;
}
u32 cellGcmGetLabelAddress(u32 index)
{
cellGcmSys.Log("cellGcmGetLabelAddress(index=%d)", index);
return Memory.RSXCMDMem.GetStartAddr() + 0x10 * index;
}
u32 cellGcmGetControlRegister()
{
cellGcmSys.Log("cellGcmGetControlRegister()");
return gcm_info.control_addr;
}
int cellGcmFlush(u32 ctx, u32 id)
{
cellGcmSys.Log("cellGcmFlush(ctx=0x%x, id=0x%x)", ctx, id);
if(id > 1) return CELL_EINVAL;
Emu.GetGSManager().GetRender().Draw();
return CELL_OK;
}
void cellGcmSetTile(u32 index, u32 location, u32 offset, u32 size, u32 pitch, u32 comp, u32 base, u32 bank)
{
cellGcmSys.Warning("cellGcmSetTile(index=%d, location=%d, offset=0x%x, size=0x%x, pitch=0x%x, comp=0x%x, base=0x%x, bank=0x%x)",
index, location, offset, size, pitch, comp, base, bank);
//return CELL_OK;
}
int cellGcmBindTile(u32 index)
{
cellGcmSys.Warning("TODO: cellGcmBindTile(index=%d)", index);
return CELL_OK;
}
int cellGcmBindZcull(u32 index, u32 offset, u32 width, u32 height, u32 cullStart, u32 zFormat, u32 aaFormat, u32 zCullDir, u32 zCullFormat, u32 sFunc, u32 sRef, u32 sMask)
{
cellGcmSys.Warning("TODO: cellGcmBindZcull(index=%d, offset=0x%x, width=%d, height=%d, cullStart=0x%x, zFormat=0x%x, aaFormat=0x%x, zCullDir=0x%x, zCullFormat=0x%x, sFunc=0x%x, sRef=0x%x, sMask=0x%x)", index, offset, width, height, cullStart, zFormat, aaFormat, zCullDir, zCullFormat, sFunc, sRef, sMask);
return CELL_OK;
}
int cellGcmGetFlipStatus()
{
return Emu.GetGSManager().GetRender().m_flip_status;
}
int cellGcmResetFlipStatus()
{
Emu.GetGSManager().GetRender().m_flip_status = 1;
return CELL_OK;
}
int cellGcmSetFlipMode(u32 mode)
{
cellGcmSys.Warning("cellGcmSetFlipMode(mode=%d)", mode);
switch(mode)
{
case CELL_GCM_DISPLAY_HSYNC:
case CELL_GCM_DISPLAY_VSYNC:
case CELL_GCM_DISPLAY_HSYNC_WITH_NOISE:
Emu.GetGSManager().GetRender().m_flip_mode = mode;
break;
default:
return CELL_EINVAL;
}
return CELL_OK;
}
u32 cellGcmGetTiledPitchSize(u32 size)
{
//TODO
cellGcmSys.Warning("cellGcmGetTiledPitchSize(size=%d)", size);
return size;
}
u32 cellGcmGetDefaultCommandWordSize()
{
cellGcmSys.Warning("cellGcmGetDefaultCommandWordSize()");
return 0x400;
}
u32 cellGcmGetDefaultSegmentWordSize()
{
cellGcmSys.Warning("cellGcmGetDefaultSegmentWordSize()");
return 0x100;
}
int cellGcmSetDefaultFifoSize(u32 bufferSize, u32 segmentSize)
{
cellGcmSys.Warning("cellGcmSetDefaultFifoSize(bufferSize=0x%x, segmentSize=0x%x)", bufferSize, segmentSize);
return CELL_OK;
}

View File

@ -33,26 +33,15 @@ SysCallBase sc_lwmutex("sys_wmutex");
int sys_lwmutex_create(u64 lwmutex_addr, u64 lwmutex_attr_addr)
{
if(!Memory.IsGoodAddr(lwmutex_addr, 4) || !Memory.IsGoodAddr(lwmutex_attr_addr))
{
return CELL_EFAULT;
}
lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr];
lmtx.lock_var.all_info = 0;
lwmutex_attr& lmtx_attr = (lwmutex_attr&)Memory[lwmutex_attr_addr];
//sc_lwmutex.Warning("sys_lwmutex_create(lwmutex_addr = 0x%llx, lwmutex_attr_addr = 0x%llx)", lwmutex_addr, lwmutex_attr_addr);
lmtx.lock_var.info.owner = 0;
lmtx.lock_var.info.waiter = 0;
lmtx.attribute = Emu.GetIdManager().GetNewID(wxString::Format("lwmutex[%s]", lmtx_attr.name), nullptr, lwmutex_addr);
/*
ConLog.Write("r3:");
ConLog.Write("*** lock_var[owner: 0x%x, waiter: 0x%x]", re(lmtx.lock_var.info.owner), re(lmtx.lock_var.info.waiter));
ConLog.Write("*** attribute: 0x%x", re(lmtx.attribute));
ConLog.Write("*** recursive_count: 0x%x", re(lmtx.recursive_count));
ConLog.Write("*** sleep_queue: 0x%x", re(lmtx.sleep_queue));
ConLog.Write("r4:");
ConLog.Write("*** attr_protocol: 0x%x", re(lmtx_attr.attr_protocol));
ConLog.Write("*** attr_recursive: 0x%x", re(lmtx_attr.attr_recursive));
ConLog.Write("*** name: %s", lmtx_attr.name);
*/
return CELL_OK;
}
@ -60,39 +49,46 @@ int sys_lwmutex_destroy(u64 lwmutex_addr)
{
//sc_lwmutex.Warning("sys_lwmutex_destroy(lwmutex_addr = 0x%llx)", lwmutex_addr);
lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr];
Emu.GetIdManager().RemoveID(lmtx.attribute);
//lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr];
//Emu.GetIdManager().RemoveID(lmtx.attribute);
return CELL_OK;
}
int sys_lwmutex_lock(u64 lwmutex_addr, u64 timeout)
{
//sc_lwmutex.Warning("sys_lwmutex_lock(lwmutex_addr = 0x%llx, timeout = 0x%llx)", lwmutex_addr, timeout);
lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr];
PPCThread& thr = GetCurrentPPUThread();
if(thr.GetId() == re(lmtx.lock_var.info.owner))
{
re(lmtx.recursive_count, re(lmtx.recursive_count) + 1);
return CELL_OK;
}
if(!lmtx.lock_var.info.owner)
{
re(lmtx.lock_var.info.owner, GetCurrentPPUThread().GetId());
re(lmtx.recursive_count, 1);
}
else if(!lmtx.lock_var.info.waiter)
{
re(lmtx.lock_var.info.waiter, GetCurrentPPUThread().GetId());
while(re(lmtx.lock_var.info.owner) != GetCurrentPPUThread().GetId()) Sleep(1);
thr.Wait(true);
re(lmtx.lock_var.info.waiter, thr.GetId());
}
else
{
return -1;
ConLog.Warning("lwmutex has waiter!");
return CELL_EBUSY;
}
return CELL_OK;
}
int sys_lwmutex_trylock(u64 lwmutex_addr)
{
//sc_lwmutex.Warning("sys_lwmutex_trylock(lwmutex_addr = 0x%llx)", lwmutex_addr);
lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr];
if(lmtx.lock_var.info.owner) return CELL_EBUSY;
@ -105,8 +101,21 @@ int sys_lwmutex_unlock(u64 lwmutex_addr)
//sc_lwmutex.Warning("sys_lwmutex_unlock(lwmutex_addr = 0x%llx)", lwmutex_addr);
lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr];
lmtx.lock_var.info.owner = lmtx.lock_var.info.waiter;
lmtx.lock_var.info.waiter = 0;
re(lmtx.recursive_count, re(lmtx.recursive_count) - 1);
if(!lmtx.recursive_count)
{
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);
if(thr)
{
thr->Wait(false);
}
}
}
return CELL_OK;
}

View File

@ -1,158 +1,5 @@
#include "stdafx.h"
#include "Emu/SysCalls/SysCalls.h"
/*
struct MemContiner
{
u8* continer;
u32 num;
void Create(u32 size)
{
continer = new u8[size];
}
void Delete()
{
if(continer != NULL) free(continer);
}
~MemContiner()
{
Delete();
}
};
class MemContiners : private SysCallBase
{
SysCallsArraysList<MemContiner> continers;
public:
MemContiners() : SysCallBase("MemContainers")
{
}
u64 AddContiner(const u64 size)
{
const u64 id = continers.Add();
bool error;
MemContiner& data = *continers.GetDataById(id, &error);
if(error)
{
ConLog.Error("%s error: id [%d] is not found!", module_name, id);
return 0;
}
data.Create(size);
return id;
}
void DeleteContiner(const u64 id)
{
bool error;
MemContiner& data = *continers.GetDataById(id, &error);
if(error)
{
ConLog.Error("%s error: id [%d] is not found!", module_name, id);
return;
}
data.Delete();
continers.RemoveById(id);
}
};
MemContiners continers;
*/
/*
int SysCalls::lv2MemContinerCreate(PPUThread& CPU)
{
u64& continer = CPU.GPR[3];
u32 size = CPU.GPR[4];
ConLog.Warning("lv2MemContinerCreate[size: 0x%x]", size);
//continer = continers.AddContiner(size);
return 0;
}
int SysCalls::lv2MemContinerDestroy(PPUThread& CPU)
{
u32 container = CPU.GPR[3];
ConLog.Warning("lv2MemContinerDestroy[container: 0x%x]", container);
//continers.DeleteContiner(container);
return 0;
}*/
/*
static const u32 max_user_mem = 0x0d500000; //100mb
u32 free_user_mem = max_user_mem;
static u64 addr_user_mem = 0;
struct MemoryInfo
{
u32 free_user_mem;
u32 aviable_user_mem;
};
enum
{
SYS_MEMORY_PAGE_SIZE_1M = 0x400,
SYS_MEMORY_PAGE_SIZE_64K = 0x200,
};
int SysCalls::sys_memory_allocate(u32 size, u64 flags, u64 alloc_addr)
{
//int sys_memory_allocate(size_t size, uint64_t flags, sys_addr_t * alloc_addr);
const u64 size = CPU.GPR[3];
const u64 flags = CPU.GPR[4];
const u64 alloc_addr = CPU.GPR[5];
ConLog.Write("lv2MemAllocate: size: 0x%llx, flags: 0x%llx, alloc_addr: 0x%llx", size, flags, alloc_addr);
//u32 addr = 0;
switch(flags)
{
case SYS_MEMORY_PAGE_SIZE_1M:
if(size & 0xfffff) return CELL_EALIGN;
//addr = Memory.Alloc(size, 0x100000);
break;
case SYS_MEMORY_PAGE_SIZE_64K:
if(size & 0xffff) return CELL_EALIGN;
//addr = Memory.Alloc(size, 0x10000);
break;
default: return CELL_EINVAL;
}
u32 num = Memory.MemoryBlocks.GetCount();
Memory.MemoryBlocks.Add(new MemoryBlock());
Memory.MemoryBlocks[num].SetRange(Memory.MemoryBlocks[num - 1].GetEndAddr(), size);
Memory.Write32(alloc_addr, Memory.MemoryBlocks[num].GetStartAddr());
ConLog.Write("Test...");
Memory.Write32(Memory.MemoryBlocks[num].GetStartAddr(), 0xfff);
if(Memory.Read32(Memory.MemoryBlocks[num].GetStartAddr()) != 0xfff)
{
ConLog.Write("Test faild");
}
else
{
ConLog.Write("Test OK");
Memory.Write32(Memory.MemoryBlocks[num].GetStartAddr(), 0x0);
}
return CELL_OK;
}
int SysCalls::sys_memory_get_user_memory_size(PPUThread& CPU)
{
ConLog.Write("lv2MemGetUserMemorySize: r3=0x%llx", CPU.GPR[3]);
//int sys_memory_get_user_memory_size(sys_memory_info_t * mem_info);
MemoryInfo& memoryinfo = *(MemoryInfo*)Memory.GetMemFromAddr(CPU.GPR[3]);
memoryinfo.aviable_user_mem = Memory.Reverse32(free_user_mem);
memoryinfo.free_user_mem = Memory.Reverse32(free_user_mem);
return CELL_OK;
}*/
SysCallBase sc_mem("memory");
@ -162,15 +9,51 @@ enum
SYS_MEMORY_PAGE_SIZE_64K = 0x200,
};
struct MemoryContainerInfo
{
u64 addr;
u32 size;
MemoryContainerInfo(u64 addr, u32 size)
: addr(addr)
, size(size)
{
}
};
int sys_memory_container_create(u32 cid_addr, u32 yield_size)
{
sc_mem.Warning("TODO: sys_memory_container_create(cid_addr=0x%x,yield_size=0x%x)", cid_addr, yield_size);
sc_mem.Warning("sys_memory_container_create(cid_addr=0x%x,yield_size=0x%x)", cid_addr, yield_size);
if(!Memory.IsGoodAddr(cid_addr, 4))
{
return CELL_EFAULT;
}
u64 addr = Memory.Alloc(yield_size, 1);
if(!addr)
{
return CELL_ENOMEM;
}
Memory.Write32(cid_addr, sc_mem.GetNewId(new MemoryContainerInfo(addr, yield_size)));
return CELL_OK;
}
int sys_memory_container_destroy(u32 cid)
{
sc_mem.Warning("TODO: sys_memory_container_destroy(cid=0x%x)", cid);
sc_mem.Warning("sys_memory_container_destroy(cid=0x%x)", cid);
MemoryContainerInfo* ct;
if(!sc_mem.CheckId(cid, ct))
{
return CELL_ESRCH;
}
Memory.Free(ct->addr);
Emu.GetIdManager().RemoveID(cid);
return CELL_OK;
}
@ -212,11 +95,13 @@ int sys_memory_free(u32 start_addr)
struct mmapper_info
{
u64 addr;
u32 size;
u32 flags;
mmapper_info(u32 _size, u32 _flags)
: size(_size)
mmapper_info(u64 _addr, u32 _size, u32 _flags)
: addr(_addr)
, size(_size)
, flags(_flags)
{
}
@ -240,7 +125,13 @@ int sys_mmapper_allocate_memory(u32 size, u64 flags, u32 mem_id_addr)
sc_mem.Warning("sys_mmapper_allocate_memory(size=0x%x, flags=0x%llx, mem_id_addr=0x%x)", size, flags, mem_id_addr);
if(!Memory.IsGoodAddr(mem_id_addr)) return CELL_EFAULT;
Memory.Write32(mem_id_addr, sc_mem.GetNewId(new mmapper_info(size, flags)));
u64 addr = Memory.Alloc(size, 1);
if(!addr)
return CELL_ENOMEM;
Memory.Write32(mem_id_addr, sc_mem.GetNewId(new mmapper_info(addr, size, flags)));
return CELL_OK;
}
@ -252,6 +143,10 @@ int sys_mmapper_map_memory(u32 start_addr, u32 mem_id, u64 flags)
mmapper_info* info;
if(!sc_mem.CheckId(mem_id, info)) return CELL_ESRCH;
if(!Memory.Map(start_addr, info->addr, info->size))
{
sc_mem.Error("sys_mmapper_map_memory failed!");
}
//Memory.MemoryBlocks.Add((new MemoryBlock())->SetRange(start_addr, info->size));
return CELL_OK;

View File

@ -3,28 +3,45 @@
extern Module sysPrxForUser;
#define PPU_THREAD_ID_INVALID 0xFFFFFFFFU
static const u32 PPU_THREAD_ID_INVALID = 0xFFFFFFFFU;
enum
{
SYS_PPU_THREAD_ONCE_INIT,
SYS_PPU_THREAD_DONE_INIT,
};
int sys_ppu_thread_exit(int errorcode)
{
sysPrxForUser.Log("sys_ppu_thread_exit(errorcode=%d)", errorcode);
Emu.GetCPU().RemoveThread(GetCurrentPPUThread().GetId());
if(errorcode == 0)
{
sysPrxForUser.Log("sys_ppu_thread_exit(errorcode=%d)", errorcode);
}
else
{
sysPrxForUser.Warning("sys_ppu_thread_exit(errorcode=%d)", errorcode);
}
PPUThread& thr = GetCurrentPPUThread();
thr.SetExitStatus(errorcode);
Emu.GetCPU().RemoveThread(thr.GetId());
return CELL_OK;
}
int sys_ppu_thread_yield()
{
sysPrxForUser.Log("sys_ppu_thread_yield()");
wxThread::Yield();
sysPrxForUser.Log("sys_ppu_thread_yield()");
return CELL_OK;
}
int sys_ppu_thread_join(u32 thread_id, u32 vptr_addr)
{
sysPrxForUser.Error("sys_ppu_thread_join(thread_id=%d, vptr_addr=0x%x)", thread_id, 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);
if(!thr) return CELL_ESRCH;
GetCurrentPPUThread().Wait(*thr);
return CELL_OK;
}
@ -110,13 +127,16 @@ int sys_ppu_thread_create(u32 thread_id_addr, u32 entry, u32 arg, int prio, u32
sysPrxForUser.Log("sys_ppu_thread_create(thread_id_addr=0x%x, entry=0x%x, arg=0x%x, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x('%s'))",
thread_id_addr, entry, arg, prio, stacksize, flags, threadname_addr, Memory.ReadString(threadname_addr));
if(!Memory.IsGoodAddr(entry) || !Memory.IsGoodAddr(thread_id_addr) || !Memory.IsGoodAddr(threadname_addr)) return CELL_EFAULT;
if(!Memory.IsGoodAddr(entry) || !Memory.IsGoodAddr(thread_id_addr) || !Memory.IsGoodAddr(threadname_addr))
{
return CELL_EFAULT;
}
PPCThread& new_thread = Emu.GetCPU().AddThread(true);
PPCThread& new_thread = Emu.GetCPU().AddThread(PPC_THREAD_PPU);
Memory.Write32(thread_id_addr, new_thread.GetId());
new_thread.SetEntry(entry);
new_thread.SetArg(arg);
new_thread.SetArg(0, arg);
new_thread.SetPrio(prio);
new_thread.stack_size = stacksize;
//new_thread.flags = flags;
@ -127,9 +147,27 @@ int sys_ppu_thread_create(u32 thread_id_addr, u32 entry, u32 arg, int prio, u32
return CELL_OK;
}
int sys_ppu_thread_get_id()
void sys_ppu_thread_once(u32 once_ctrl_addr, u32 entry)
{
sysPrxForUser.Log("sys_ppu_thread_get_id()");
sysPrxForUser.Warning("sys_ppu_thread_once(once_ctrl_addr=0x%x, entry=0x%x)", once_ctrl_addr, entry);
return GetCurrentPPUThread().GetId();
if(Memory.IsGoodAddr(once_ctrl_addr, 4) && Memory.Read32(once_ctrl_addr) == SYS_PPU_THREAD_ONCE_INIT)
{
Memory.Write32(once_ctrl_addr, SYS_PPU_THREAD_DONE_INIT);
PPCThread& new_thread = Emu.GetCPU().AddThread(PPC_THREAD_PPU);
new_thread.SetEntry(entry);
new_thread.Run();
new_thread.Exec();
GetCurrentPPUThread().Wait(new_thread);
}
}
int sys_ppu_thread_get_id(const u32 id_addr)
{
sysPrxForUser.Log("sys_ppu_thread_get_id(id_addr=0x%x)", id_addr);
Memory.Write32(id_addr, GetCurrentPPUThread().GetId());
return CELL_OK;
}

View File

@ -87,6 +87,12 @@ int cellPadGetData(u32 port_no, u32 data_addr)
case CELL_PAD_BTN_OFFSET_DIGITAL1: if(!(d1 & buttons[i].m_outKeyCode)){d1 |= buttons[i].m_outKeyCode; len++;} break;
case CELL_PAD_BTN_OFFSET_DIGITAL2: if(!(d2 & buttons[i].m_outKeyCode)){d2 |= buttons[i].m_outKeyCode; len++;} break;
}
if(buttons[i].m_flush)
{
buttons[i].m_pressed = false;
buttons[i].m_flush = false;
}
}
data.len = re(len);

View File

@ -11,7 +11,11 @@ int sys_process_getpid()
int sys_process_exit(int errorcode)
{
ConLog.Warning("sys_process_exit(%d)", errorcode);
#ifdef _DEBUG
Emu.Pause();
#else
Emu.Stop();
#endif
return CELL_OK;
}
@ -37,7 +41,6 @@ int SysCalls::lv2ProcessWaitForChild(PPUThread& CPU)
int SysCalls::lv2ProcessGetStatus(PPUThread& CPU)
{
ConLog.Warning("lv2ProcessGetStatus");
if(CPU.IsSPU()) return CELL_UNKNOWN_ERROR;
//Memory.Write32(CPU.GPR[4], GetPPUThreadStatus(CPU));
return CELL_OK;
}

View File

@ -1,6 +1,7 @@
#include "stdafx.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Loader/ELF.h"
#include "Emu/Cell/SPUThread.h"
SysCallBase sc_spu("sys_spu");
@ -12,6 +13,21 @@ struct sys_spu_thread_group_attribute
union{u32 ct;} option;
};
struct sys_spu_thread_attribute
{
u32 name_addr;
u32 name_len;
u32 option;
};
struct sys_spu_thread_argument
{
u64 arg1;
u64 arg2;
u64 arg3;
u64 arg4;
};
struct sys_spu_image
{
u32 type;
@ -20,25 +36,185 @@ struct sys_spu_image
int nsegs;
};
u32 LoadImage(vfsStream& stream)
static const u32 g_spu_group_thr_count = 255;
struct SpuGroupInfo
{
PPCThread* 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);
}
};
u64 g_spu_offset = 0;
u32 LoadSpuImage(vfsStream& stream)
{
ELFLoader l(stream);
l.LoadInfo();
l.LoadData(Memory.MainMem.Alloc(stream.GetSize()));
g_spu_offset = Memory.MainMem.Alloc(0xFFFFED - stream.GetSize());
l.LoadData(g_spu_offset);
return l.GetEntry();
return g_spu_offset + l.GetEntry();
}
int sys_spu_image_open(u32 img_addr, u32 path_addr)
{
//156
int sys_spu_image_open(u32 img_addr, u32 path_addr)
{
const wxString& path = Memory.ReadString(path_addr);
sc_spu.Warning("sys_spu_image_open(img_addr=0x%x, path_addr=0x%x [%s])", img_addr, path_addr, path);
vfsLocalFile stream(path);
LoadImage(stream);
if(!Memory.IsGoodAddr(img_addr, sizeof(sys_spu_image)) || !Memory.IsGoodAddr(path_addr))
{
return CELL_EFAULT;
}
vfsStream* stream = Emu.GetVFS().Open(path, vfsRead);
if(!stream || !stream->IsOpened())
{
sc_spu.Error("sys_spu_image_open error: '%s' not found!", path);
delete stream;
return CELL_ENOENT;
}
u32 entry = LoadSpuImage(*stream);
delete stream;
auto& ret = (sys_spu_image&)Memory[img_addr];
re(ret.type, 1);
re(ret.entry_point, entry);
re(ret.segs_addr, 0x0);
re(ret.nsegs, 0);
return CELL_OK;
}
}
//172
int sys_spu_thread_initialize(u32 thread_addr, u32 group, u32 spu_num, u32 img_addr, u32 attr_addr, u32 arg_addr)
{
sc_spu.Warning("sys_spu_thread_initialize(thread_addr=0x%x, group=0x%x, spu_num=%d, img_addr=0x%x, attr_addr=0x%x, arg_addr=0x%x)",
thread_addr, group, spu_num, img_addr, attr_addr, arg_addr);
if(!Emu.GetIdManager().CheckID(group))
{
return CELL_ESRCH;
}
SpuGroupInfo& group_info = *(SpuGroupInfo*)Emu.GetIdManager().GetIDData(group).m_data;
if(
!Memory.IsGoodAddr(img_addr, sizeof(sys_spu_image)) ||
!Memory.IsGoodAddr(attr_addr, sizeof(sys_spu_thread_attribute)) ||
!Memory.IsGoodAddr(arg_addr, sizeof(sys_spu_thread_argument)))
{
return CELL_EFAULT;
}
auto& img = (sys_spu_image&)Memory[img_addr];
auto& attr = (sys_spu_thread_attribute&)Memory[attr_addr];
auto& arg = (sys_spu_thread_argument&)Memory[arg_addr];
if(!Memory.IsGoodAddr(re(attr.name_addr), re(attr.name_len)))
{
return CELL_EFAULT;
}
if(spu_num >= g_spu_group_thr_count)
{
return CELL_EINVAL;
}
if(group_info.threads[spu_num])
{
return CELL_EBUSY;
}
u32 entry = re(img.entry_point);
wxString name = Memory.ReadString(re(attr.name_addr), re(attr.name_len));
u64 a1 = re(arg.arg1);
u64 a2 = re(arg.arg2);
u64 a3 = re(arg.arg3);
u64 a4 = re(arg.arg4);
ConLog.Write("New SPU Thread:");
ConLog.Write("entry = 0x%x", entry);
ConLog.Write("name = %s", name);
ConLog.Write("a1 = 0x%x", a1);
ConLog.Write("a2 = 0x%x", a2);
ConLog.Write("a3 = 0x%x", a3);
ConLog.Write("a4 = 0x%x", a4);
ConLog.SkipLn();
PPCThread& new_thread = Emu.GetCPU().AddThread(PPC_THREAD_SPU);
new_thread.SetOffset(g_spu_offset);
new_thread.SetEntry(entry - g_spu_offset);
new_thread.SetName(name);
new_thread.Run();
new_thread.Pause();
new_thread.SetArg(0, a1);
new_thread.SetArg(1, a2);
new_thread.SetArg(2, a3);
new_thread.SetArg(3, a4);
group_info.threads[spu_num] = &new_thread;
return CELL_OK;
}
//166
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);
if(!thr || thr->GetType() == PPC_THREAD_PPU)
{
return CELL_ESRCH;
}
if(!Memory.IsGoodAddr(arg_addr, sizeof(sys_spu_thread_argument)))
{
return CELL_EFAULT;
}
auto& arg = (sys_spu_thread_argument&)Memory[arg_addr];
thr->SetArg(0, re(arg.arg1));
thr->SetArg(1, re(arg.arg2));
thr->SetArg(2, re(arg.arg3));
thr->SetArg(3, re(arg.arg4));
return CELL_OK;
}
//173
int sys_spu_thread_group_start(u32 id)
{
sc_spu.Warning("sys_spu_thread_group_start(id=0x%x)", id);
if(!Emu.GetIdManager().CheckID(id))
{
return CELL_ESRCH;
}
ID& id_data = Emu.GetIdManager().GetIDData(id);
SpuGroupInfo& group_info = *(SpuGroupInfo*)id_data.m_data;
Emu.Pause();
for(int i=0; i<g_spu_group_thr_count; i++)
{
if(group_info.threads[i])
{
group_info.threads[i]->Exec();
}
}
return CELL_OK;
}
//170
int sys_spu_thread_group_create(u64 id_addr, u32 num, int prio, u64 attr_addr)
@ -49,7 +225,7 @@ int sys_spu_thread_group_create(u64 id_addr, u32 num, int prio, u64 attr_addr)
ConLog.Write("*** prio=%d", prio);
ConLog.Write("*** attr_addr=0x%llx", attr_addr);
sys_spu_thread_group_attribute& attr = *new sys_spu_thread_group_attribute(*(sys_spu_thread_group_attribute*)&Memory[attr_addr]);
sys_spu_thread_group_attribute& attr = (sys_spu_thread_group_attribute&)Memory[attr_addr];
ConLog.Write("*** attr.name_len=%d", re(attr.name_len));
ConLog.Write("*** attr.name_addr=0x%x", re(attr.name_addr));
@ -60,7 +236,7 @@ int sys_spu_thread_group_create(u64 id_addr, u32 num, int prio, u64 attr_addr)
ConLog.Write("*** name='%s'", name);
Memory.Write32(id_addr,
Emu.GetIdManager().GetNewID(wxString::Format("sys_spu_thread_group %s", name), &attr, 0));
Emu.GetIdManager().GetNewID(wxString::Format("sys_spu_thread_group '%s'", name), new SpuGroupInfo(attr)));
return CELL_OK;
}
@ -71,14 +247,31 @@ int sys_spu_thread_create(u64 thread_id_addr, u64 entry_addr, u64 arg,
return CELL_OK;
}
int sys_spu_thread_connect_event(u32 id, u32 eq, u32 et, u8 spup)
{
if(!Emu.GetIdManager().CheckID(id))
{
return CELL_ESRCH;
}
if(spup > 63)
{
return CELL_EINVAL;
}
return CELL_OK;
}
//160
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);
//PPCThread& new_thread = Emu.GetCPU().AddThread(false);
//Emu.GetIdManager().GetNewID("sys_raw_spu", new u32(attr_addr));
//Memory.Write32(id_addr, Emu.GetCPU().GetThreadNumById(false, new_thread.GetId()));
PPCThread& new_thread = Emu.GetCPU().AddThread(PPC_THREAD_RAW_SPU);
Memory.Write32(id_addr, Emu.GetCPU().GetThreadNumById(PPC_THREAD_RAW_SPU, new_thread.GetId()));
new_thread.Run();
new_thread.Exec();
return CELL_OK;
}
@ -88,10 +281,123 @@ int sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu)
{
sc_spu.Warning("sys_spu_initialize(max_usable_spu=%d, max_raw_spu=%d)", max_usable_spu, max_raw_spu);
if(max_raw_spu > 5)
{
return CELL_EINVAL;
}
if(!Memory.InitSpuRawMem(max_raw_spu))
{
return CELL_UNKNOWN_ERROR;
return CELL_ENOMEM;
}
//enable_log = true;
//dump_enable = true;
return CELL_OK;
}
//181
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);
if(!thr || thr->GetType() == PPC_THREAD_PPU)
{
return CELL_ESRCH;
}
(*(SPUThread*)thr).WriteLS64(address, value);
return CELL_OK;
}
//182
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);
if(!thr || thr->GetType() == PPC_THREAD_PPU)
{
return CELL_ESRCH;
}
if(!(*(SPUThread*)thr).IsGoodLSA(address))
{
return CELL_EFAULT;
}
Memory.Write64(value_addr, (*(SPUThread*)thr).ReadLS64(address));
return CELL_OK;
}
//190
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);
if(!thr || !thr->GetType() == PPC_THREAD_PPU)
{
return CELL_ESRCH;
}
if(!(*(SPUThread*)thr).mfc.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; //?
}
return CELL_OK;
}
extern SysCallBase sys_event;
int sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32 spup_addr)
{
sc_spu.Warning("sys_spu_thread_group_connect_event_all_threads(id=0x%x, eq=0x%x, req=0x%llx, spup_addr=0x%x)",
id, eq, req, spup_addr);
if(!Emu.GetIdManager().CheckID(id) || !sys_event.CheckId(eq))
{
return CELL_ESRCH;
}
if(!req)
{
return CELL_EINVAL;
}
SpuGroupInfo* group = (SpuGroupInfo*)Emu.GetIdManager().GetIDData(id).m_data;
EventQueue* equeue = (EventQueue*)Emu.GetIdManager().GetIDData(eq).m_data;
for(int i=0; i<g_spu_group_thr_count; ++i)
{
if(group->threads[i])
{
bool finded_port = false;
for(int j=0; j<equeue->pos; ++j)
{
if(!equeue->ports[j]->thread)
{
finded_port = true;
equeue->ports[j]->thread = group->threads[i];
}
}
if(!finded_port)
{
return CELL_EISCONN;
}
}
}
return CELL_OK;
}

View File

@ -201,4 +201,4 @@ int cellSysutilUnregisterCallback(int slot)
wxGetApp().SendDbgCommand(DID_UNREGISTRED_CALLBACK);
return CELL_OK;
}
}

View File

@ -70,7 +70,7 @@ int cellMsgDialogOpen2(u32 type, u32 msgString_addr, u32 callback_addr, u32 user
Callback2 callback(0, callback_addr, userData);
callback.Handle(status);
callback.Branch();
callback.Branch(true);
return CELL_OK;
}

View File

@ -12,7 +12,10 @@ using namespace PPU_instr;
static const wxString& BreakPointsDBName = "BreakPoints.dat";
static const u16 bpdb_version = 0x1000;
//SysCalls SysCallsManager;
ModuleInitializer::ModuleInitializer()
{
Emu.AddModuleInit(this);
}
Emulator::Emulator()
: m_status(Stopped)
@ -24,6 +27,11 @@ Emulator::Emulator()
void Emulator::Init()
{
while(m_modules_init.GetCount())
{
m_modules_init[0].Init();
m_modules_init.RemoveAt(0);
}
//if(m_memory_viewer) m_memory_viewer->Close();
//m_memory_viewer = new MemoryViewerPanel(wxGetApp().m_MainFrame);
}
@ -77,8 +85,6 @@ void Emulator::Load()
Memory.Init();
GetInfo().Reset();
Memory.Write64(Memory.PRXMem.Alloc(8), 0xDEADBEEFABADCAFE);
bool is_error;
vfsLocalFile f(m_path);
Loader l(f);
@ -106,29 +112,40 @@ void Emulator::Load()
}
LoadPoints(BreakPointsDBName);
PPCThread& thread = GetCPU().AddThread(l.GetMachine() == MACHINE_PPC64);
PPCThread& thread = GetCPU().AddThread(l.GetMachine() == MACHINE_PPC64 ? PPC_THREAD_PPU : PPC_THREAD_SPU);
thread.SetEntry(l.GetEntry());
thread.SetArg(thread.GetId());
Memory.StackMem.Alloc(0x1000);
thread.InitStack();
thread.AddArgv(m_path);
//thread.AddArgv("-emu");
if(l.GetMachine() == 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
{
thread.SetEntry(l.GetEntry());
Memory.StackMem.Alloc(0x1000);
thread.InitStack();
thread.AddArgv(m_path);
//thread.AddArgv("-emu");
m_rsx_callback = Memory.MainMem.Alloc(4 * 4) + 4;
Memory.Write32(m_rsx_callback - 4, m_rsx_callback);
m_rsx_callback = Memory.MainMem.Alloc(4 * 4) + 4;
Memory.Write32(m_rsx_callback - 4, m_rsx_callback);
mem32_t callback_data(m_rsx_callback);
callback_data += ADDI(11, 0, 0x3ff);
callback_data += SC(2);
callback_data += BCLR(0x10 | 0x04, 0, 0, 0);
mem32_t callback_data(m_rsx_callback);
callback_data += ADDI(11, 0, 0x3ff);
callback_data += SC(2);
callback_data += BCLR(0x10 | 0x04, 0, 0, 0);
m_ppu_thr_exit = Memory.MainMem.Alloc(4 * 3);
mem32_t ppu_thr_exit_data(m_ppu_thr_exit);
ppu_thr_exit_data += ADDI(11, 0, 41);
ppu_thr_exit_data += SC(2);
ppu_thr_exit_data += BCLR(0x10 | 0x04, 0, 0, 0);
m_ppu_thr_exit = Memory.MainMem.Alloc(4 * 4);
mem32_t ppu_thr_exit_data(m_ppu_thr_exit);
ppu_thr_exit_data += ADDI(3, 0, 0);
ppu_thr_exit_data += ADDI(11, 0, 41);
ppu_thr_exit_data += SC(2);
ppu_thr_exit_data += BCLR(0x10 | 0x04, 0, 0, 0);
}
thread.Run();
@ -158,10 +175,11 @@ void Emulator::Run()
//ConLog.Write("run...");
m_status = Runned;
m_vfs.Mount("/", vfsDevice::GetRoot(m_path), new vfsLocalFile());
m_vfs.Mount("/dev_hdd0/", wxGetCwd() + "\\dev_hdd0\\", new vfsLocalFile());
m_vfs.Mount("/app_home/", vfsDevice::GetRoot(m_path), new vfsLocalFile());
m_vfs.Mount(vfsDevice::GetRootPs3(m_path), vfsDevice::GetRoot(m_path), new vfsLocalFile());
m_vfs.Init(m_path);
//m_vfs.Mount("/", vfsDevice::GetRoot(m_path), new vfsLocalFile());
//m_vfs.Mount("/dev_hdd0/", wxGetCwd() + "\\dev_hdd0\\", new vfsLocalFile());
//m_vfs.Mount("/app_home/", vfsDevice::GetRoot(m_path), new vfsLocalFile());
//m_vfs.Mount(vfsDevice::GetRootPs3(m_path), vfsDevice::GetRoot(m_path), new vfsLocalFile());
ConLog.SkipLn();
ConLog.Write("Mount info:");
@ -178,7 +196,14 @@ void Emulator::Run()
//m_memory_viewer->ShowPC();
if(!m_dbg_console)
{
m_dbg_console = new DbgConsole();
}
else
{
GetDbgCon().Close();
GetDbgCon().Clear();
}
GetGSManager().Init();
GetCallbackManager().Init();
@ -229,6 +254,8 @@ void Emulator::Stop()
m_break_points.Clear();
m_marked_points.Clear();
m_vfs.UnMountAll();
GetGSManager().Close();
GetCPU().Close();
//SysCallsManager.Close();
@ -240,12 +267,6 @@ void Emulator::Stop()
CurGameInfo.Reset();
Memory.Close();
if(m_dbg_console)
{
GetDbgCon().Close();
GetDbgCon().Clear();
}
//if(m_memory_viewer && m_memory_viewer->IsShown()) m_memory_viewer->Hide();
wxGetApp().SendDbgCommand(DID_STOPED_EMU);
}

View File

@ -8,6 +8,7 @@
#include "Emu/DbgConsole.h"
#include "Loader/Loader.h"
#include "SysCalls/Callback.h"
#include "SysCalls/Modules.h"
struct EmuInfo
{
@ -45,6 +46,14 @@ public:
u64 GetTLSMemsz() const { return tls_memsz; }
};
class ModuleInitializer
{
public:
ModuleInitializer();
virtual void Init() = 0;
};
class Emulator
{
enum Mode
@ -62,6 +71,7 @@ class Emulator
u32 m_ppu_thr_exit;
MemoryViewerPanel* m_memory_viewer;
//ArrayF<CPUThread> m_cpu_threads;
ArrayF<ModuleInitializer> m_modules_init;
Array<u64> m_break_points;
Array<u64> m_marked_points;
@ -93,6 +103,11 @@ public:
VFS& GetVFS() { return m_vfs; }
Array<u64>& GetBreakPoints() { return m_break_points; }
Array<u64>& GetMarkedPoints() { return m_marked_points; }
void AddModuleInit(ModuleInitializer* m)
{
m_modules_init.Add(m);
}
void SetTLSData(const u64 addr, const u64 filesz, const u64 memsz)
{

39
rpcs3/Emu/event.h Normal file
View File

@ -0,0 +1,39 @@
#pragma once
struct sys_event_queue_attr
{
u32 attr_protocol;
int type;
char name[8];
};
struct sys_event_data
{
u64 source;
u64 data1;
u64 data2;
u64 data3;
};
struct EventQueue;
struct EventPort
{
u64 name;
u64 data1;
u64 data2;
u64 data3;
bool has_data;
PPCThread* thread;
EventQueue* queue[127];
int pos;
};
struct EventQueue
{
EventPort* ports[127];
int size;
int pos;
int type;
char name[8];
};

View File

@ -74,6 +74,8 @@ public:
void HandleCommand(wxCommandEvent& event)
{
event.Skip();
switch(event.GetId())
{
case DID_STOP_EMU:
@ -88,10 +90,13 @@ public:
case DID_RESUME_EMU:
m_btn_run->SetLabel("Pause");
break;
case DID_EXIT_THR_SYSCALL:
Emu.GetCPU().RemoveThread(((PPCThread*)event.GetClientData())->GetId());
break;
}
UpdateUI();
event.Skip();
}
};
@ -99,16 +104,9 @@ DebuggerPanel::DebuggerPanel(wxWindow* parent) : wxPanel(parent, wxID_ANY, wxDef
{
m_aui_mgr.SetManagedWindow(this);
m_nb = new wxAuiNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxAUI_NB_TOP | wxAUI_NB_TAB_SPLIT |
wxAUI_NB_TAB_EXTERNAL_MOVE | wxAUI_NB_SCROLL_BUTTONS |
wxAUI_NB_WINDOWLIST_BUTTON | wxAUI_NB_TAB_MOVE | wxNO_BORDER);
m_aui_mgr.AddPane(new DbgEmuPanel(this), wxAuiPaneInfo().Top());
m_aui_mgr.AddPane(m_nb, wxAuiPaneInfo().Center().CaptionVisible(false).CloseButton().MaximizeButton());
m_aui_mgr.AddPane(new InterpreterDisAsmFrame(this), wxAuiPaneInfo().Center().CaptionVisible(false).CloseButton().MaximizeButton());
m_aui_mgr.Update();
m_app_connector.Connect(wxEVT_DBG_COMMAND, wxCommandEventHandler(DebuggerPanel::HandleCommand), (wxObject*)0, this);
}
DebuggerPanel::~DebuggerPanel()
@ -119,30 +117,3 @@ DebuggerPanel::~DebuggerPanel()
void DebuggerPanel::UpdateUI()
{
}
void DebuggerPanel::HandleCommand(wxCommandEvent& event)
{
PPCThread* thr = (PPCThread*)event.GetClientData();
switch(event.GetId())
{
case DID_CREATE_THREAD:
m_nb->AddPage(new InterpreterDisAsmFrame(m_nb, thr), thr->GetFName());
break;
case DID_REMOVE_THREAD:
for(uint i=0; i<m_nb->GetPageCount(); ++i)
{
InterpreterDisAsmFrame* page = (InterpreterDisAsmFrame*)m_nb->GetPage(i);
if(page->CPU.GetId() == thr->GetId())
{
m_nb->DeletePage(i);
break;
}
}
break;
}
event.Skip();
}

View File

@ -5,13 +5,10 @@
class DebuggerPanel : public wxPanel
{
wxAuiManager m_aui_mgr;
wxAuiNotebook* m_nb;
AppConnector m_app_connector;
public:
DebuggerPanel(wxWindow* parent);
~DebuggerPanel();
void UpdateUI();
void HandleCommand(wxCommandEvent& event);
};

View File

@ -135,7 +135,7 @@ public:
*done = false;
if(Emu.GetCPU().GetThreads()[0].IsSPU())
if(Emu.GetCPU().GetThreads()[0].GetType() != PPC_THREAD_PPU)
{
SPU_DisAsm& dis_asm = *new SPU_DisAsm(*(PPCThread*)NULL, DumpMode);
decoder = new SPU_Decoder(dis_asm);
@ -341,7 +341,7 @@ void DisAsmFrame::Dump(wxCommandEvent& WXUNUSED(event))
PPC_DisAsm* disasm;
PPC_Decoder* decoder;
if(Emu.GetCPU().GetThreads()[0].IsSPU())
if(Emu.GetCPU().GetThreads()[0].GetType() != PPC_THREAD_PPU)
{
SPU_DisAsm& dis_asm = *new SPU_DisAsm(*(PPCThread*)NULL, DumpMode);
decoder = new SPU_Decoder(dis_asm);

View File

@ -3,48 +3,39 @@
//static const int show_lines = 30;
u32 InterpreterDisAsmFrame::CentrePc(const u32 pc) const
u64 InterpreterDisAsmFrame::CentrePc(const u64 pc) const
{
return pc - ((m_item_count / 2) * 4);
}
InterpreterDisAsmFrame::InterpreterDisAsmFrame(wxWindow* parent, PPCThread* cpu)
InterpreterDisAsmFrame::InterpreterDisAsmFrame(wxWindow* parent)
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(500, 700), wxTAB_TRAVERSAL)
, ThreadBase(false, "DisAsmFrame Thread")
, CPU(*cpu)
, PC(0)
, CPU(nullptr)
, m_item_count(30)
, decoder(nullptr)
, disasm(nullptr)
{
if(CPU.IsSPU())
{
SPU_DisAsm& dis_asm = *new SPU_DisAsm(CPU, InterpreterMode);
decoder = new SPU_Decoder(dis_asm);
disasm = &dis_asm;
}
else
{
PPU_DisAsm& dis_asm = *new PPU_DisAsm(CPU, InterpreterMode);
decoder = new PPU_Decoder(dis_asm);
disasm = &dis_asm;
}
wxBoxSizer& s_p_main = *new wxBoxSizer(wxVERTICAL);
wxBoxSizer& s_b_main = *new wxBoxSizer(wxHORIZONTAL);
m_list = new wxListView(this);
m_choice_units = new wxChoice(this, wxID_ANY);
wxButton& b_go_to_addr = *new wxButton(this, wxID_ANY, "Go To Address");
wxButton& b_go_to_pc = *new wxButton(this, wxID_ANY, "Go To PC");
m_btn_step = new wxButton(this, wxID_ANY, "Step");
m_btn_run = new wxButton(this, wxID_ANY, "Run");
m_btn_pause = new wxButton(this, wxID_ANY, "Pause");
m_btn_step = new wxButton(this, wxID_ANY, "Step");
m_btn_run = new wxButton(this, wxID_ANY, "Run");
m_btn_pause = new wxButton(this, wxID_ANY, "Pause");
s_b_main.Add(&b_go_to_addr, wxSizerFlags().Border(wxALL, 5));
s_b_main.Add(&b_go_to_pc, wxSizerFlags().Border(wxALL, 5));
s_b_main.Add(m_btn_step, wxSizerFlags().Border(wxALL, 5));
s_b_main.Add(m_btn_run, wxSizerFlags().Border(wxALL, 5));
s_b_main.Add(m_btn_pause, wxSizerFlags().Border(wxALL, 5));
s_b_main.Add(&b_go_to_addr, wxSizerFlags().Border(wxALL, 5));
s_b_main.Add(&b_go_to_pc, wxSizerFlags().Border(wxALL, 5));
s_b_main.Add(m_btn_step, wxSizerFlags().Border(wxALL, 5));
s_b_main.Add(m_btn_run, wxSizerFlags().Border(wxALL, 5));
s_b_main.Add(m_btn_pause, wxSizerFlags().Border(wxALL, 5));
s_b_main.Add(m_choice_units, wxSizerFlags().Border(wxALL, 5));
m_regs = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_DONTWRAP|wxNO_BORDER|wxTE_RICH2);
@ -77,12 +68,14 @@ InterpreterDisAsmFrame::InterpreterDisAsmFrame(wxWindow* parent, PPCThread* cpu)
Connect(m_btn_run->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(InterpreterDisAsmFrame::DoRun));
Connect(m_btn_pause->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(InterpreterDisAsmFrame::DoPause));
Connect(m_list->GetId(), wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler(InterpreterDisAsmFrame::DClick));
Connect(m_choice_units->GetId(),wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(InterpreterDisAsmFrame::OnSelectUnit));
Connect(wxEVT_SIZE, wxSizeEventHandler(InterpreterDisAsmFrame::OnResize));
m_app_connector.Connect(m_list->GetId(), wxEVT_MOUSEWHEEL, wxMouseEventHandler(InterpreterDisAsmFrame::MouseWheel), (wxObject*)0, this);
m_app_connector.Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(InterpreterDisAsmFrame::OnKeyDown), (wxObject*)0, this);
m_app_connector.Connect(wxEVT_DBG_COMMAND, wxCommandEventHandler(InterpreterDisAsmFrame::HandleCommand), (wxObject*)0, this);
WriteRegs();
ShowAddr(CentrePc(PC));
UpdateUnitList();
}
InterpreterDisAsmFrame::~InterpreterDisAsmFrame()
@ -90,6 +83,48 @@ InterpreterDisAsmFrame::~InterpreterDisAsmFrame()
ThreadBase::Stop();
}
void InterpreterDisAsmFrame::UpdateUnitList()
{
m_choice_units->Freeze();
m_choice_units->Clear();
auto& thrs = Emu.GetCPU().GetThreads();
for(uint i=0; i<thrs.GetCount(); ++i)
{
m_choice_units->Append(thrs[i].GetFName(), &thrs[i]);
}
m_choice_units->Thaw();
}
void InterpreterDisAsmFrame::OnSelectUnit(wxCommandEvent& event)
{
CPU = (PPCThread*)event.GetClientData();
delete decoder;
//delete disasm;
decoder = nullptr;
disasm = nullptr;
if(CPU)
{
if(CPU->GetType() != PPC_THREAD_PPU)
{
SPU_DisAsm& dis_asm = *new SPU_DisAsm(*CPU, InterpreterMode);
decoder = new SPU_Decoder(dis_asm);
disasm = &dis_asm;
}
else
{
PPU_DisAsm& dis_asm = *new PPU_DisAsm(*CPU, InterpreterMode);
decoder = new PPU_Decoder(dis_asm);
disasm = &dis_asm;
}
}
DoUpdate();
}
void InterpreterDisAsmFrame::OnKeyDown(wxKeyEvent& event)
{
if(wxGetActiveWindow() != wxGetTopLevelParent(this))
@ -164,47 +199,59 @@ void InterpreterDisAsmFrame::ShowAddr(const u64 addr)
{
PC = addr;
m_list->Freeze();
for(uint i=0; i<m_item_count; ++i, PC += 4)
if(!CPU)
{
if(!Memory.IsGoodAddr(PC, 4))
for(uint i=0; i<m_item_count; ++i, PC += 4)
{
m_list->SetItem(i, 0, wxString::Format("[%08llx] illegal address", PC));
continue;
}
disasm->dump_pc = PC;
decoder->Decode(Memory.Read32(PC));
if(IsBreakPoint(PC))
}
else
{
disasm->offset = CPU->GetOffset();
for(uint i=0; i<m_item_count; ++i, PC += 4)
{
m_list->SetItem(i, 0, ">>> " + disasm->last_opcode);
}
else
{
m_list->SetItem(i, 0, " " + disasm->last_opcode);
}
wxColour colour;
if((!CPU.IsRunned() || !Emu.IsRunned()) && PC == CPU.PC)
{
colour = wxColour("Green");
}
else
{
colour = wxColour("White");
for(u32 i=0; i<Emu.GetMarkedPoints().GetCount(); ++i)
if(!Memory.IsGoodAddr(CPU->GetOffset() + PC, 4))
{
if(Emu.GetMarkedPoints()[i] == PC)
m_list->SetItem(i, 0, wxString::Format("[%08llx] illegal address", PC));
continue;
}
disasm->dump_pc = PC;
decoder->Decode(Memory.Read32(CPU->GetOffset() + PC));
if(IsBreakPoint(PC))
{
m_list->SetItem(i, 0, ">>> " + disasm->last_opcode);
}
else
{
m_list->SetItem(i, 0, " " + disasm->last_opcode);
}
wxColour colour;
if((!CPU->IsRunned() || !Emu.IsRunned()) && PC == CPU->PC)
{
colour = wxColour("Green");
}
else
{
colour = wxColour("White");
for(u32 i=0; i<Emu.GetMarkedPoints().GetCount(); ++i)
{
colour = wxColour("Wheat");
break;
if(Emu.GetMarkedPoints()[i] == PC)
{
colour = wxColour("Wheat");
break;
}
}
}
}
m_list->SetItemBackgroundColour( i, colour );
m_list->SetItemBackgroundColour( i, colour );
}
}
while(remove_markedPC.GetCount())
@ -231,9 +278,17 @@ void InterpreterDisAsmFrame::ShowAddr(const u64 addr)
void InterpreterDisAsmFrame::WriteRegs()
{
if(!CPU)
{
m_regs->Clear();
return;
}
const wxString data = CPU->RegsToString();
m_regs->Freeze();
m_regs->Clear();
m_regs->WriteText(CPU.RegsToString());
m_regs->WriteText(data);
m_regs->Thaw();
}
@ -246,37 +301,38 @@ void InterpreterDisAsmFrame::HandleCommand(wxCommandEvent& event)
{
switch(event.GetId())
{
case DID_STOP_EMU:
case DID_PAUSE_EMU:
DoUpdate();
case DID_STOPED_EMU:
UpdateUnitList();
break;
case DID_PAUSED_EMU:
//DoUpdate();
break;
}
}
else if(thr->GetId() == CPU.GetId())
else if(CPU && thr->GetId() == CPU->GetId())
{
switch(event.GetId())
{
case DID_PAUSE_THREAD:
m_btn_run->Disable();
m_btn_step->Disable();
m_btn_pause->Disable();
break;
case DID_PAUSED_THREAD:
m_btn_run->Enable();
m_btn_step->Enable();
m_btn_pause->Disable();
case DID_CREATE_THREAD:
DoUpdate();
break;
case DID_START_THREAD:
case DID_EXEC_THREAD:
case DID_RESUME_THREAD:
m_btn_run->Disable();
m_btn_step->Disable();
m_btn_pause->Enable();
if(event.GetId() == DID_START_THREAD)
{
DoUpdate();
}
break;
case DID_REMOVE_THREAD:
@ -284,6 +340,38 @@ void InterpreterDisAsmFrame::HandleCommand(wxCommandEvent& event)
m_btn_run->Disable();
m_btn_step->Disable();
m_btn_pause->Disable();
if(event.GetId() == DID_REMOVE_THREAD)
{
//m_choice_units->SetSelection(-1);
//wxCommandEvent event;
//event.SetInt(-1);
//event.SetClientData(nullptr);
//OnSelectUnit(event);
UpdateUnitList();
//DoUpdate();
}
break;
}
}
else
{
switch(event.GetId())
{
case DID_CREATE_THREAD:
UpdateUnitList();
if(m_choice_units->GetSelection() == -1)
{
//m_choice_units->SetSelection(0);
//wxCommandEvent event;
//event.SetInt(0);
//event.SetClientData(&Emu.GetCPU().GetThreads()[0]);
//OnSelectUnit(event);
}
break;
case DID_REMOVED_THREAD:
UpdateUnitList();
break;
}
}
@ -312,11 +400,11 @@ void InterpreterDisAsmFrame::Show_Val(wxCommandEvent& WXUNUSED(event))
diag->SetSizerAndFit( s_panel );
p_pc->SetLabel(wxString::Format("%llx", CPU.PC));
if(CPU) p_pc->SetLabel(wxString::Format("%llx", CPU->PC));
if(diag->ShowModal() == wxID_OK)
{
u64 pc = CPU.PC;
u64 pc = CPU ? CPU->PC : 0x0;
sscanf(p_pc->GetLabel(), "%llx", &pc);
remove_markedPC.AddCpy(Emu.GetMarkedPoints().AddCpy(pc));
ShowAddr(CentrePc(pc));
@ -325,17 +413,19 @@ void InterpreterDisAsmFrame::Show_Val(wxCommandEvent& WXUNUSED(event))
void InterpreterDisAsmFrame::Show_PC(wxCommandEvent& WXUNUSED(event))
{
ShowAddr(CentrePc(CPU.PC));
if(CPU) ShowAddr(CentrePc(CPU->PC));
}
extern bool dump_enable;
void InterpreterDisAsmFrame::DoRun(wxCommandEvent& WXUNUSED(event))
{
if(CPU.IsPaused()) CPU.Resume();
if(!CPU) return;
if(CPU->IsPaused()) CPU->Resume();
if(!Emu.IsPaused())
{
CPU.Exec();
CPU->Exec();
}
//ThreadBase::Start();
@ -343,7 +433,8 @@ void InterpreterDisAsmFrame::DoRun(wxCommandEvent& WXUNUSED(event))
void InterpreterDisAsmFrame::DoPause(wxCommandEvent& WXUNUSED(event))
{
CPU.Pause();
//DoUpdate();
if(CPU) CPU->Pause();
}
void InterpreterDisAsmFrame::DoStep(wxCommandEvent& WXUNUSED(event))
@ -417,8 +508,9 @@ bool InterpreterDisAsmFrame::RemoveBreakPoint(u64 pc)
void InterpreterDisAsmFrame::Task()
{
wxGetApp().SendDbgCommand(DID_RESUME_THREAD, &CPU);
if(!CPU) return;
wxGetApp().SendDbgCommand(DID_RESUME_THREAD, CPU);
wxGetApp().SendDbgCommand(DID_RESUMED_THREAD, CPU);
bool dump_status = dump_enable;
//CPU.InitTls();
@ -427,9 +519,9 @@ void InterpreterDisAsmFrame::Task()
{
do
{
CPU.ExecOnce();
CPU->ExecOnce();
}
while(CPU.IsRunned() && Emu.IsRunned() && !TestDestroy() && !IsBreakPoint(CPU.PC) && dump_status == dump_enable);
while(CPU->IsRunned() && Emu.IsRunned() && !TestDestroy() && !IsBreakPoint(CPU->PC) && dump_status == dump_enable);
}
catch(const wxString& e)
{
@ -442,5 +534,6 @@ void InterpreterDisAsmFrame::Task()
//CPU.FreeTls();
wxGetApp().SendDbgCommand(DID_PAUSE_THREAD, &CPU);
wxGetApp().SendDbgCommand(DID_PAUSE_THREAD, CPU);
wxGetApp().SendDbgCommand(DID_PAUSED_THREAD, CPU);
}

View File

@ -20,16 +20,19 @@ class InterpreterDisAsmFrame
wxButton* m_btn_pause;
AppConnector m_app_connector;
u32 m_item_count;
wxChoice* m_choice_units;
public:
PPCThread& CPU;
PPCThread* CPU;
public:
InterpreterDisAsmFrame(wxWindow* parent, PPCThread* cpu);
InterpreterDisAsmFrame(wxWindow* parent);
~InterpreterDisAsmFrame();
u32 CentrePc(const u32 pc) const;
void UpdateUnitList();
u64 CentrePc(const u64 pc) const;
void OnSelectUnit(wxCommandEvent& event);
void OnKeyDown(wxKeyEvent& event);
void OnResize(wxSizeEvent& event);
void DoUpdate();

View File

@ -5,6 +5,8 @@
#include "Emu/System.h"
#include "Ini.h"
#include "Emu/GS/sysutil_video.h"
#include "Gui/VHDDManager.h"
#include "Gui/VFSManager.h"
#include <wx/dynlib.h>
BEGIN_EVENT_TABLE(MainFrame, FrameBase)
@ -18,8 +20,11 @@ enum IDs
id_boot_game,
id_sys_pause,
id_sys_stop,
id_sys_send_open_menu,
id_sys_send_exit,
id_config_emu,
id_config_vfs_manager,
id_config_vhdd_manager,
id_update_dbg,
};
@ -31,8 +36,9 @@ wxString GetPaneName()
}
MainFrame::MainFrame()
: FrameBase(NULL, wxID_ANY, "", "MainFrame", wxSize(280, 180))
: FrameBase(nullptr, wxID_ANY, "", "MainFrame", wxSize(800, 600))
, m_aui_mgr(this)
, m_sys_menu_opened(false)
{
SetLabel(wxString::Format(_PRGNAME_ " " _PRGVER_));
wxMenuBar& menubar(*new wxMenuBar());
@ -53,25 +59,34 @@ MainFrame::MainFrame()
menu_sys.Append(id_sys_pause, "Pause")->Enable(false);
menu_sys.Append(id_sys_stop, "Stop\tCtrl + S")->Enable(false);
menu_sys.AppendSeparator();
menu_sys.Append(id_sys_send_open_menu, "Send open system menu cmd")->Enable(false);
menu_sys.Append(id_sys_send_exit, "Send exit cmd")->Enable(false);
menu_conf.Append(id_config_emu, "Settings");
menu_conf.AppendSeparator();
menu_conf.Append(id_config_vfs_manager, "Virtual File System Manager");
menu_conf.Append(id_config_vhdd_manager, "Virtual HDD Manager");
SetMenuBar(&menubar);
m_game_viewer = new GameViewer(this);
AddPane(m_game_viewer, "Game List", wxAUI_DOCK_BOTTOM);
Connect( id_boot_game, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::BootGame) );
Connect( id_boot_elf, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::BootElf) );
Connect( id_boot_self, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::BootSelf) );
Connect( id_boot_game, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::BootGame) );
Connect( id_boot_elf, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::BootElf) );
Connect( id_boot_self, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::BootSelf) );
Connect( id_sys_pause, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Pause) );
Connect( id_sys_stop, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Stop) );
Connect( id_sys_send_exit, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::SendExit) );
Connect( id_update_dbg, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::UpdateUI) );
Connect( id_sys_pause, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Pause) );
Connect( id_sys_stop, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Stop) );
Connect( id_sys_send_open_menu, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::SendOpenCloseSysMenu) );
Connect( id_sys_send_exit, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::SendExit) );
Connect( id_config_emu, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Config) );
Connect( id_config_vfs_manager, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::ConfigVFS) );
Connect( id_config_vhdd_manager,wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::ConfigVHDD) );
Connect( id_update_dbg, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::UpdateUI) );
Connect( id_config_emu, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Config) );
m_app_connector.Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainFrame::OnKeyDown), (wxObject*)0, this);
m_app_connector.Connect(wxEVT_DBG_COMMAND, wxCommandEventHandler(MainFrame::UpdateUI), (wxObject*)0, this);
}
@ -83,6 +98,7 @@ MainFrame::~MainFrame()
void MainFrame::AddPane(wxWindow* wind, const wxString& caption, int flags)
{
wind->SetSize(-1, 300);
m_aui_mgr.AddPane(wind, wxAuiPaneInfo().Name(GetPaneName()).Caption(caption).Direction(flags).CloseButton(false).MaximizeButton());
}
@ -260,6 +276,13 @@ void MainFrame::SendExit(wxCommandEvent& event)
Emu.GetCallbackManager().m_exit_callback.Handle(0x0101, 0);
}
void MainFrame::SendOpenCloseSysMenu(wxCommandEvent& event)
{
Emu.GetCallbackManager().m_exit_callback.Handle(m_sys_menu_opened ? 0x0132 : 0x0131, 0);
m_sys_menu_opened = !m_sys_menu_opened;
UpdateUI(wxCommandEvent());
}
void MainFrame::Config(wxCommandEvent& WXUNUSED(event))
{
//TODO
@ -366,6 +389,16 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event))
if(paused) Emu.Resume();
}
void MainFrame::ConfigVFS(wxCommandEvent& WXUNUSED(event))
{
VFSManagerDialog(this).ShowModal();
}
void MainFrame::ConfigVHDD(wxCommandEvent& WXUNUSED(event))
{
VHDDManagerDialog(this).ShowModal();
}
void MainFrame::UpdateUI(wxCommandEvent& event)
{
event.Skip();
@ -388,6 +421,7 @@ void MainFrame::UpdateUI(wxCommandEvent& event)
is_runned = false;
is_stopped = true;
is_ready = false;
m_sys_menu_opened = false;
break;
case DID_PAUSE_EMU:
@ -410,11 +444,14 @@ void MainFrame::UpdateUI(wxCommandEvent& event)
is_ready = true;
break;
default:
case DID_REGISTRED_CALLBACK:
is_runned = Emu.IsRunned();
is_stopped = Emu.IsStopped();
is_ready = Emu.IsReady();
break;
default:
return;
}
}
else
@ -427,15 +464,19 @@ void MainFrame::UpdateUI(wxCommandEvent& event)
wxMenuBar& menubar( *GetMenuBar() );
wxMenuItem& pause = *menubar.FindItem( id_sys_pause );
wxMenuItem& stop = *menubar.FindItem( id_sys_stop );
wxMenuItem& send_exit = *menubar.FindItem( id_sys_send_exit );
wxMenuItem& send_exit = *menubar.FindItem( id_sys_send_exit );
wxMenuItem& send_open_menu = *menubar.FindItem( id_sys_send_open_menu );
pause.SetText(is_runned ? "Pause\tCtrl + P" : is_ready ? "Start\tCtrl + C" : "Resume\tCtrl + C");
pause.Enable(!is_stopped);
stop.Enable(!is_stopped);
//send_exit.Enable(false);
send_exit.Enable(!is_stopped && Emu.GetCallbackManager().m_exit_callback.m_callbacks.GetCount());
bool enable_commands = !is_stopped && Emu.GetCallbackManager().m_exit_callback.m_callbacks.GetCount();
m_aui_mgr.Update();
send_open_menu.SetText(wxString::Format("Send %s system menu cmd", m_sys_menu_opened ? "close" : "open"));
send_open_menu.Enable(enable_commands);
send_exit.Enable(enable_commands);
//m_aui_mgr.Update();
//wxCommandEvent refit( wxEVT_COMMAND_MENU_SELECTED, id_update_dbg );
//GetEventHandler()->AddPendingEvent( refit );

View File

@ -7,6 +7,7 @@ class MainFrame : public FrameBase
GameViewer* m_game_viewer;
wxAuiManager m_aui_mgr;
AppConnector m_app_connector;
bool m_sys_menu_opened;
public:
MainFrame();
@ -24,7 +25,10 @@ private:
void Pause(wxCommandEvent& event);
void Stop(wxCommandEvent& event);
void SendExit(wxCommandEvent& event);
void SendOpenCloseSysMenu(wxCommandEvent& event);
void Config(wxCommandEvent& event);
void ConfigVFS(wxCommandEvent& event);
void ConfigVHDD(wxCommandEvent& event);
void UpdateUI(wxCommandEvent& event);
void OnKeyDown(wxKeyEvent& event);

View File

@ -0,0 +1,37 @@
#include "stdafx.h"
#include "TextInputDialog.h"
TextInputDialog::TextInputDialog(wxWindow* parent, const wxString& defvalue)
: wxDialog(parent, wxID_ANY, "Input text", wxDefaultPosition)
{
m_tctrl_text = new wxTextCtrl(this, wxID_ANY, defvalue);
wxBoxSizer& s_text(*new wxBoxSizer(wxVERTICAL));
s_text.Add(m_tctrl_text, 1, wxEXPAND);
wxBoxSizer& s_btns(*new wxBoxSizer(wxHORIZONTAL));
s_btns.Add(new wxButton(this, wxID_OK));
s_btns.AddSpacer(30);
s_btns.Add(new wxButton(this, wxID_CANCEL));
wxBoxSizer& s_main(*new wxBoxSizer(wxVERTICAL));
s_main.Add(&s_text, 1, wxEXPAND | wxUP | wxLEFT | wxRIGHT, 5);
s_main.AddSpacer(30);
s_main.Add(&s_btns, 0, wxCENTER | wxDOWN | wxLEFT | wxRIGHT, 5);
SetSizerAndFit(&s_main);
SetSize(250, -1);
Connect(wxID_OK, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(TextInputDialog::OnOk));
}
void TextInputDialog::OnOk(wxCommandEvent& event)
{
m_result = m_tctrl_text->GetValue();
EndModal(wxID_OK);
}
wxString& TextInputDialog::GetResult()
{
return m_result;
}

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