mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
commit
555ad9472a
2014
GL/glext.h
2014
GL/glext.h
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
|
@ -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);
|
||||
|
BIN
bin/dev_hdd0/game/TEST12345/USRDIR/cube.elf
Normal file
BIN
bin/dev_hdd0/game/TEST12345/USRDIR/cube.elf
Normal file
Binary file not shown.
BIN
bin/dev_hdd0/game/TEST12345/USRDIR/hello_world.elf
Normal file
BIN
bin/dev_hdd0/game/TEST12345/USRDIR/hello_world.elf
Normal file
Binary file not shown.
2
rpcs3/Emu/Cell/MFC.cpp
Normal file
2
rpcs3/Emu/Cell/MFC.cpp
Normal file
@ -0,0 +1,2 @@
|
||||
#include "stdafx.h"
|
||||
#include "MFC.h"
|
252
rpcs3/Emu/Cell/MFC.h
Normal file
252
rpcs3/Emu/Cell/MFC.h
Normal 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);
|
||||
}
|
||||
}
|
||||
};
|
@ -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>
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
};
|
@ -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);
|
||||
|
@ -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
|
||||
};
|
@ -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]);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
131
rpcs3/Emu/Cell/RawSPUThread.cpp
Normal file
131
rpcs3/Emu/Cell/RawSPUThread.cpp
Normal 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());
|
||||
}
|
71
rpcs3/Emu/Cell/RawSPUThread.h
Normal file
71
rpcs3/Emu/Cell/RawSPUThread.h
Normal 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();
|
@ -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
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
};
|
@ -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();
|
||||
}
|
@ -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();
|
||||
}
|
||||
};
|
@ -40,4 +40,4 @@ wxString vfsFileBase::GetPath() const
|
||||
vfsOpenMode vfsFileBase::GetOpenMode() const
|
||||
{
|
||||
return m_mode;
|
||||
}
|
||||
}
|
||||
|
@ -21,4 +21,4 @@ public:
|
||||
*/
|
||||
wxString GetPath() const;
|
||||
vfsOpenMode GetOpenMode() const;
|
||||
};
|
||||
};
|
||||
|
@ -92,4 +92,4 @@ u64 vfsLocalFile::Tell() const
|
||||
bool vfsLocalFile::IsOpened() const
|
||||
{
|
||||
return m_file.IsOpened() && vfsFileBase::IsOpened();
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
@ -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
@ -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);
|
||||
|
@ -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);
|
@ -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();
|
||||
}
|
@ -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();
|
||||
};
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 ¶ms[i];
|
||||
if(type.Cmp(params[i].type.GetPtr()) == 0) return ¶ms[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;
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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
3
rpcs3/Emu/HDD/HDD.cpp
Normal file
@ -0,0 +1,3 @@
|
||||
#include "stdafx.h"
|
||||
#include "HDD.h"
|
||||
|
864
rpcs3/Emu/HDD/HDD.h
Normal file
864
rpcs3/Emu/HDD/HDD.h
Normal 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();
|
||||
}
|
||||
};
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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())
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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; }
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
459
rpcs3/Emu/SysCalls/Modules.cpp
Normal file
459
rpcs3/Emu/SysCalls/Modules.cpp
Normal 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);
|
||||
}
|
80
rpcs3/Emu/SysCalls/Modules.h
Normal file
80
rpcs3/Emu/SysCalls/Modules.h
Normal 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);
|
@ -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);
|
||||
}
|
||||
|
39
rpcs3/Emu/SysCalls/Modules/cellResc.cpp
Normal file
39
rpcs3/Emu/SysCalls/Modules/cellResc.cpp
Normal 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);
|
||||
}
|
95
rpcs3/Emu/SysCalls/Modules/cellSysmodule.cpp
Normal file
95
rpcs3/Emu/SysCalls/Modules/cellSysmodule.cpp
Normal 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);
|
||||
}
|
240
rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp
Normal file
240
rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp
Normal 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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
@ -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);
|
||||
};
|
||||
|
||||
|
167
rpcs3/Emu/SysCalls/lv2/SC_Event.cpp
Normal file
167
rpcs3/Emu/SysCalls/lv2/SC_Event.cpp
Normal 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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -201,4 +201,4 @@ int cellSysutilUnregisterCallback(int slot)
|
||||
wxGetApp().SendDbgCommand(DID_UNREGISTRED_CALLBACK);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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
39
rpcs3/Emu/event.h
Normal 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];
|
||||
};
|
@ -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();
|
||||
}
|
@ -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);
|
||||
};
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
@ -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();
|
||||
|
@ -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 );
|
||||
|
@ -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);
|
||||
|
||||
|
37
rpcs3/Gui/TextInputDialog.cpp
Normal file
37
rpcs3/Gui/TextInputDialog.cpp
Normal 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
Loading…
Reference in New Issue
Block a user