mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-08 07:51:28 +12:00
commit
3642b267a0
39 changed files with 882 additions and 1010 deletions
|
@ -11,6 +11,7 @@ using std::max;
|
||||||
#define re64(val) MemoryBase::Reverse64(val)
|
#define re64(val) MemoryBase::Reverse64(val)
|
||||||
#define re32(val) MemoryBase::Reverse32(val)
|
#define re32(val) MemoryBase::Reverse32(val)
|
||||||
#define re16(val) MemoryBase::Reverse16(val)
|
#define re16(val) MemoryBase::Reverse16(val)
|
||||||
|
#define re128(val) MemoryBase::Reverse128(val)
|
||||||
|
|
||||||
template<typename T, int size = sizeof(T)> struct se_t;
|
template<typename T, int size = sizeof(T)> struct se_t;
|
||||||
template<typename T> struct se_t<T, 1> { static __forceinline void func(T& dst, const T src) { (u8&)dst = (u8&)src; } };
|
template<typename T> struct se_t<T, 1> { static __forceinline void func(T& dst, const T src) { (u8&)dst = (u8&)src; } };
|
||||||
|
|
|
@ -195,7 +195,7 @@ void LogManager::log(LogMessage msg)
|
||||||
}
|
}
|
||||||
if (NamedThreadBase* thr = GetCurrentNamedThread())
|
if (NamedThreadBase* thr = GetCurrentNamedThread())
|
||||||
{
|
{
|
||||||
prefix += thr->GetThreadName();
|
prefix += "{" + thr->GetThreadName() + "} ";
|
||||||
}
|
}
|
||||||
msg.mText.insert(0, prefix);
|
msg.mText.insert(0, prefix);
|
||||||
msg.mText.append(1,'\n');
|
msg.mText.append(1,'\n');
|
||||||
|
|
|
@ -52,7 +52,22 @@ void ThreadBase::Start()
|
||||||
g_tls_this_thread = this;
|
g_tls_this_thread = this;
|
||||||
g_thread_count++;
|
g_thread_count++;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
Task();
|
Task();
|
||||||
|
}
|
||||||
|
catch (const std::string& e)
|
||||||
|
{
|
||||||
|
LOG_ERROR(GENERAL, "Exception: %s", e.c_str());
|
||||||
|
}
|
||||||
|
catch (const char* e)
|
||||||
|
{
|
||||||
|
LOG_ERROR(GENERAL, "Exception: %s", e);
|
||||||
|
}
|
||||||
|
catch (int exitcode)
|
||||||
|
{
|
||||||
|
LOG_SUCCESS(GENERAL, "Exit Code: %d", exitcode);
|
||||||
|
}
|
||||||
|
|
||||||
m_alive = false;
|
m_alive = false;
|
||||||
g_thread_count--;
|
g_thread_count--;
|
||||||
|
|
|
@ -280,14 +280,33 @@ void CPUThread::ExecOnce()
|
||||||
SendDbgCommand(DID_PAUSED_THREAD, this);
|
SendDbgCommand(DID_PAUSED_THREAD, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp)
|
||||||
|
{
|
||||||
|
const u64 addr = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)Memory.GetBaseAddr();
|
||||||
|
if (addr < 0x100000000 && u == EXCEPTION_ACCESS_VIOLATION)
|
||||||
|
{
|
||||||
|
// TODO: allow recovering from a page fault
|
||||||
|
//GetCurrentPPUThread().Stop();
|
||||||
|
Emu.Pause();
|
||||||
|
throw fmt::Format("Access violation: addr = 0x%x", (u32)addr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// some fatal error (should crash)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// TODO: linux version
|
||||||
|
#endif
|
||||||
|
|
||||||
void CPUThread::Task()
|
void CPUThread::Task()
|
||||||
{
|
{
|
||||||
if (Ini.HLELogging.GetValue()) LOG_NOTICE(PPU, "%s enter", CPUThread::GetFName().c_str());
|
if (Ini.HLELogging.GetValue()) LOG_NOTICE(PPU, "%s enter", CPUThread::GetFName().c_str());
|
||||||
|
|
||||||
const std::vector<u64>& bp = Emu.GetBreakPoints();
|
const std::vector<u64>& bp = Emu.GetBreakPoints();
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
for (uint i = 0; i<bp.size(); ++i)
|
for (uint i = 0; i<bp.size(); ++i)
|
||||||
{
|
{
|
||||||
if (bp[i] == m_offset + PC)
|
if (bp[i] == m_offset + PC)
|
||||||
|
@ -297,6 +316,12 @@ void CPUThread::Task()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
_set_se_translator(_se_translator);
|
||||||
|
#else
|
||||||
|
// TODO: linux version
|
||||||
|
#endif
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
int status = ThreadStatus();
|
int status = ThreadStatus();
|
||||||
|
@ -330,19 +355,6 @@ void CPUThread::Task()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch(const std::string& e)
|
|
||||||
{
|
|
||||||
LOG_ERROR(PPU, "Exception: %s", e.c_str());
|
|
||||||
}
|
|
||||||
catch(const char* e)
|
|
||||||
{
|
|
||||||
LOG_ERROR(PPU, "Exception: %s", e);
|
|
||||||
}
|
|
||||||
catch(int exitcode)
|
|
||||||
{
|
|
||||||
LOG_SUCCESS(PPU, "Exit Code: %d", exitcode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Ini.HLELogging.GetValue()) LOG_NOTICE(PPU, "%s leave", CPUThread::GetFName().c_str());
|
if (Ini.HLELogging.GetValue()) LOG_NOTICE(PPU, "%s leave", CPUThread::GetFName().c_str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,23 +110,15 @@ CPUThread* CPUThreadManager::GetThread(u32 id)
|
||||||
|
|
||||||
RawSPUThread* CPUThreadManager::GetRawSPUThread(u32 num)
|
RawSPUThread* CPUThreadManager::GetRawSPUThread(u32 num)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_mtx_thread);
|
if (num < sizeof(Memory.RawSPUMem) / sizeof(Memory.RawSPUMem[0]))
|
||||||
|
|
||||||
for (u32 i = 0; i < m_threads.size(); i++)
|
|
||||||
{
|
{
|
||||||
if (m_threads[i]->GetType() == CPU_THREAD_RAW_SPU)
|
return (RawSPUThread*)Memory.RawSPUMem[num];
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
RawSPUThread* t = (RawSPUThread*)m_threads[i];
|
|
||||||
|
|
||||||
if (t->GetIndex() == num)
|
|
||||||
{
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CPUThreadManager::NotifyThread(const u32 id)
|
void CPUThreadManager::NotifyThread(const u32 id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,9 +5,8 @@
|
||||||
|
|
||||||
u8 PPCDecoder::DecodeMemory(const u64 address)
|
u8 PPCDecoder::DecodeMemory(const u64 address)
|
||||||
{
|
{
|
||||||
u32 instr;
|
u32 instr = Memory.Read32(address);
|
||||||
Memory.Read32ByAddr(address, &instr);
|
|
||||||
Decode(instr);
|
Decode(instr);
|
||||||
|
|
||||||
return 4;
|
return sizeof(u32);
|
||||||
}
|
}
|
|
@ -12,48 +12,13 @@ RawSPUThread::RawSPUThread(u32 index, CPUThreadType type)
|
||||||
, MemoryBlock()
|
, MemoryBlock()
|
||||||
, m_index(index)
|
, m_index(index)
|
||||||
{
|
{
|
||||||
Memory.MemoryBlocks.push_back(SetRange(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index, RAW_SPU_OFFSET));
|
Memory.InitRawSPU(SetRange(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index, RAW_SPU_PROB_OFFSET), m_index);
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
RawSPUThread::~RawSPUThread()
|
RawSPUThread::~RawSPUThread()
|
||||||
{
|
{
|
||||||
for(int i=0; i<Memory.MemoryBlocks.size(); ++i)
|
Memory.CloseRawSPU(this, m_index);
|
||||||
{
|
|
||||||
if(Memory.MemoryBlocks[i]->GetStartAddr() == GetStartAddr())
|
|
||||||
{
|
|
||||||
Memory.MemoryBlocks.erase(Memory.MemoryBlocks.begin() + i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RawSPUThread::Read8(const u64 addr, u8* value)
|
|
||||||
{
|
|
||||||
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
|
|
||||||
{
|
|
||||||
return MemoryBlock::Read8(addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
|
|
||||||
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read8(0x%x)", m_index, offset);
|
|
||||||
Emu.Pause();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RawSPUThread::Read16(const u64 addr, u16* value)
|
|
||||||
{
|
|
||||||
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
|
|
||||||
{
|
|
||||||
return MemoryBlock::Read16(addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
|
|
||||||
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read16(0x%x)", m_index, offset);
|
|
||||||
Emu.Pause();
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RawSPUThread::Read32(const u64 addr, u32* value)
|
bool RawSPUThread::Read32(const u64 addr, u32* value)
|
||||||
|
@ -63,101 +28,141 @@ bool RawSPUThread::Read32(const u64 addr, u32* value)
|
||||||
return MemoryBlock::Read32(addr, value);
|
return MemoryBlock::Read32(addr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
|
const u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
|
||||||
|
|
||||||
switch(offset)
|
switch(offset)
|
||||||
{
|
{
|
||||||
case MFC_LSA_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(MFC_LSA)", m_index); *value = MFC2.LSA.GetValue(); break;
|
case MFC_LSA_offs:
|
||||||
case MFC_EAH_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(MFC_EAH)", m_index); *value = MFC2.EAH.GetValue(); break;
|
{
|
||||||
case MFC_EAL_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(MFC_EAL)", m_index); *value = MFC2.EAL.GetValue(); break;
|
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(MFC_LSA)", m_index);
|
||||||
case MFC_Size_Tag_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(MFC_Size_Tag)", m_index); *value = MFC2.Size_Tag.GetValue(); break;
|
*value = MFC2.LSA.GetValue();
|
||||||
case MFC_CMDStatus_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(MFC_CMDStatus)", m_index); *value = MFC2.CMDStatus.GetValue(); break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MFC_EAH_offs:
|
||||||
|
{
|
||||||
|
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(MFC_EAH)", m_index);
|
||||||
|
*value = MFC2.EAH.GetValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MFC_EAL_offs:
|
||||||
|
{
|
||||||
|
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(MFC_EAL)", m_index);
|
||||||
|
*value = MFC2.EAL.GetValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MFC_Size_Tag_offs:
|
||||||
|
{
|
||||||
|
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(MFC_Size_Tag)", m_index);
|
||||||
|
*value = MFC2.Size_Tag.GetValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MFC_CMDStatus_offs:
|
||||||
|
{
|
||||||
|
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(MFC_CMDStatus)", m_index);
|
||||||
|
*value = MFC2.CMDStatus.GetValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case MFC_QStatus_offs:
|
case MFC_QStatus_offs:
|
||||||
|
{
|
||||||
LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(MFC_QStatus)", m_index);
|
LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(MFC_QStatus)", m_index);
|
||||||
*value = MFC2.QStatus.GetValue();
|
*value = MFC2.QStatus.GetValue();
|
||||||
break;
|
break;
|
||||||
case Prxy_QueryType_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(Prxy_QueryType)", m_index); *value = Prxy.QueryType.GetValue(); break;
|
}
|
||||||
case Prxy_QueryMask_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(Prxy_QueryMask)", m_index); *value = Prxy.QueryMask.GetValue(); break;
|
|
||||||
case Prxy_TagStatus_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(Prxy_TagStatus)", m_index); *value = Prxy.TagStatus.GetValue(); break;
|
case Prxy_QueryType_offs:
|
||||||
case SPU_Out_MBox_offs:
|
{
|
||||||
//LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(SPU_Out_MBox)", m_index);
|
LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(Prxy_QueryType)", m_index);
|
||||||
SPU.Out_MBox.PopUncond(*value); //if Out_MBox is empty yet, the result will be undefined
|
*value = Prxy.QueryType.GetValue();
|
||||||
break;
|
break;
|
||||||
case SPU_In_MBox_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(SPU_In_MBox)", m_index); while(!SPU.In_MBox.Pop(*value) && !Emu.IsStopped()) Sleep(1); break;
|
}
|
||||||
case SPU_MBox_Status_offs: //LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(SPU_MBox_Status)", m_index);
|
|
||||||
|
case Prxy_QueryMask_offs:
|
||||||
|
{
|
||||||
|
LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(Prxy_QueryMask)", m_index);
|
||||||
|
*value = Prxy.QueryMask.GetValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Prxy_TagStatus_offs:
|
||||||
|
{
|
||||||
|
LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(Prxy_TagStatus)", m_index);
|
||||||
|
*value = Prxy.TagStatus.GetValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SPU_Out_MBox_offs:
|
||||||
|
{
|
||||||
|
// if Out_MBox is empty, the result is undefined
|
||||||
|
SPU.Out_MBox.PopUncond(*value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SPU_In_MBox_offs:
|
||||||
|
{
|
||||||
|
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(SPU_In_MBox)", m_index);
|
||||||
|
while (!SPU.In_MBox.Pop(*value) && !Emu.IsStopped()) Sleep(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SPU_MBox_Status_offs:
|
||||||
|
{
|
||||||
|
//LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(SPU_MBox_Status)", m_index);
|
||||||
//SPU.MBox_Status.SetValue(SPU.Out_MBox.GetCount() ? SPU.MBox_Status.GetValue() | 1 : SPU.MBox_Status.GetValue() & ~1);
|
//SPU.MBox_Status.SetValue(SPU.Out_MBox.GetCount() ? SPU.MBox_Status.GetValue() | 1 : SPU.MBox_Status.GetValue() & ~1);
|
||||||
SPU.MBox_Status.SetValue((SPU.Out_MBox.GetCount() & 0xff) | (SPU.In_MBox.GetFreeCount() << 8));
|
SPU.MBox_Status.SetValue((SPU.Out_MBox.GetCount() & 0xff) | (SPU.In_MBox.GetFreeCount() << 8));
|
||||||
*value = SPU.MBox_Status.GetValue();
|
*value = SPU.MBox_Status.GetValue();
|
||||||
break;
|
break;
|
||||||
case SPU_RunCntl_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(SPU_RunCntl)", m_index); *value = SPU.RunCntl.GetValue(); break;
|
}
|
||||||
|
|
||||||
|
case SPU_RunCntl_offs:
|
||||||
|
{
|
||||||
|
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(SPU_RunCntl)", m_index);
|
||||||
|
*value = (u32)IsRunning();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case SPU_Status_offs:
|
case SPU_Status_offs:
|
||||||
//LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(SPU_Status)", m_index);
|
{
|
||||||
*value = SPU.Status.GetValue();
|
*value = SPU.Status.GetValue();
|
||||||
break;
|
break;
|
||||||
case SPU_NPC_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(SPU_NPC)", m_index); *value = SPU.NPC.GetValue(); break;
|
}
|
||||||
case SPU_RdSigNotify1_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(SPU_RdSigNotify1)", m_index); *value = SPU.SNR[0].GetValue(); break;
|
|
||||||
case SPU_RdSigNotify2_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(SPU_RdSigNotify2)", m_index); *value = SPU.SNR[1].GetValue(); break;
|
case SPU_NPC_offs:
|
||||||
|
{
|
||||||
|
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(SPU_NPC)", m_index);
|
||||||
|
*value = SPU.NPC.GetValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SPU_RdSigNotify1_offs:
|
||||||
|
{
|
||||||
|
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(SPU_RdSigNotify1)", m_index);
|
||||||
|
*value = SPU.SNR[0].GetValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SPU_RdSigNotify2_offs:
|
||||||
|
{
|
||||||
|
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(SPU_RdSigNotify2)", m_index);
|
||||||
|
*value = SPU.SNR[1].GetValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
{
|
||||||
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(0x%x)", m_index, offset);
|
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(0x%x)", m_index, offset);
|
||||||
Emu.Pause();
|
Emu.Pause();
|
||||||
break;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RawSPUThread::Read64(const u64 addr, u64* value)
|
|
||||||
{
|
|
||||||
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
|
|
||||||
{
|
|
||||||
return MemoryBlock::Read64(addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
|
|
||||||
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read64(0x%x)", m_index, offset);
|
|
||||||
Emu.Pause();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RawSPUThread::Read128(const u64 addr, u128* value)
|
|
||||||
{
|
|
||||||
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
|
|
||||||
{
|
|
||||||
return MemoryBlock::Read128(addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
|
|
||||||
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read128(0x%x)", m_index, offset);
|
|
||||||
Emu.Pause();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RawSPUThread::Write8(const u64 addr, const u8 value)
|
|
||||||
{
|
|
||||||
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
|
|
||||||
{
|
|
||||||
return MemoryBlock::Write8(addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
|
|
||||||
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Write8(0x%x, 0x%x)", m_index, offset, value);
|
|
||||||
Emu.Pause();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RawSPUThread::Write16(const u64 addr, const u16 value)
|
|
||||||
{
|
|
||||||
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
|
|
||||||
{
|
|
||||||
return MemoryBlock::Write16(addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
|
|
||||||
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Write16(0x%x, 0x%x)", m_index, offset, value);
|
|
||||||
Emu.Pause();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RawSPUThread::Write32(const u64 addr, const u32 value)
|
bool RawSPUThread::Write32(const u64 addr, const u32 value)
|
||||||
{
|
{
|
||||||
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
|
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
|
||||||
|
@ -165,19 +170,48 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value)
|
||||||
return MemoryBlock::Write32(addr, value);
|
return MemoryBlock::Write32(addr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
|
const u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
|
||||||
|
|
||||||
switch(offset)
|
switch(offset)
|
||||||
{
|
{
|
||||||
case MFC_LSA_offs: MFC2.LSA.SetValue(value); break;
|
case MFC_LSA_offs:
|
||||||
case MFC_EAH_offs: MFC2.EAH.SetValue(value); break;
|
{
|
||||||
case MFC_EAL_offs: MFC2.EAL.SetValue(value); break;
|
MFC2.LSA.SetValue(value);
|
||||||
case MFC_Size_Tag_offs: MFC2.Size_Tag.SetValue(value); break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MFC_EAH_offs:
|
||||||
|
{
|
||||||
|
MFC2.EAH.SetValue(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MFC_EAL_offs:
|
||||||
|
{
|
||||||
|
MFC2.EAL.SetValue(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MFC_Size_Tag_offs:
|
||||||
|
{
|
||||||
|
MFC2.Size_Tag.SetValue(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case MFC_CMDStatus_offs:
|
case MFC_CMDStatus_offs:
|
||||||
|
{
|
||||||
MFC2.CMDStatus.SetValue(value);
|
MFC2.CMDStatus.SetValue(value);
|
||||||
EnqMfcCmd(MFC2);
|
EnqMfcCmd(MFC2);
|
||||||
break;
|
break;
|
||||||
case MFC_QStatus_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(MFC_QStatus, 0x%x)", m_index, value); MFC2.QStatus.SetValue(value); break;
|
}
|
||||||
|
|
||||||
|
case MFC_QStatus_offs:
|
||||||
|
{
|
||||||
|
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Write32(MFC_QStatus, 0x%x)", m_index, value);
|
||||||
|
//MFC2.QStatus.SetValue(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case Prxy_QueryType_offs:
|
case Prxy_QueryType_offs:
|
||||||
{
|
{
|
||||||
LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(Prxy_QueryType, 0x%x)", m_index, value);
|
LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(Prxy_QueryType, 0x%x)", m_index, value);
|
||||||
|
@ -196,57 +230,103 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value)
|
||||||
|
|
||||||
Prxy.QueryType.SetValue(0);
|
Prxy.QueryType.SetValue(0);
|
||||||
MFC2.QStatus.SetValue(Prxy.QueryMask.GetValue());
|
MFC2.QStatus.SetValue(Prxy.QueryMask.GetValue());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Prxy_QueryMask_offs:
|
||||||
|
{
|
||||||
|
LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(Prxy_QueryMask, 0x%x)", m_index, value);
|
||||||
|
Prxy.QueryMask.SetValue(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Prxy_TagStatus_offs:
|
||||||
|
{
|
||||||
|
LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(Prxy_TagStatus, 0x%x)", m_index, value);
|
||||||
|
Prxy.TagStatus.SetValue(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SPU_Out_MBox_offs:
|
||||||
|
{
|
||||||
|
LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_Out_MBox, 0x%x)", m_index, value);
|
||||||
|
while (!SPU.Out_MBox.Push(value) && !Emu.IsStopped()) Sleep(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SPU_In_MBox_offs:
|
||||||
|
{
|
||||||
|
// if In_MBox is already full, the last message is overwritten
|
||||||
|
SPU.In_MBox.PushUncond(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SPU_MBox_Status_offs:
|
||||||
|
{
|
||||||
|
LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_MBox_Status, 0x%x)", m_index, value);
|
||||||
|
SPU.MBox_Status.SetValue(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SPU_RunCntl_offs:
|
||||||
|
{
|
||||||
|
if (value == SPU_RUNCNTL_RUNNABLE)
|
||||||
|
{
|
||||||
|
SPU.Status.SetValue(SPU_STATUS_RUNNING);
|
||||||
|
Exec();
|
||||||
|
}
|
||||||
|
else if (value == SPU_RUNCNTL_STOP)
|
||||||
|
{
|
||||||
|
SPU.Status.SetValue(SPU_STATUS_STOPPED);
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Write32(SPU_RunCtrl, 0x%x): unknown value", m_index, value);
|
||||||
|
Emu.Pause();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Prxy_QueryMask_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(Prxy_QueryMask, 0x%x)", m_index, value); Prxy.QueryMask.SetValue(value); break;
|
}
|
||||||
case Prxy_TagStatus_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(Prxy_TagStatus, 0x%x)", m_index, value); Prxy.TagStatus.SetValue(value); break;
|
|
||||||
case SPU_Out_MBox_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_Out_MBox, 0x%x)", m_index, value); while(!SPU.Out_MBox.Push(value) && !Emu.IsStopped()) Sleep(1); break;
|
case SPU_Status_offs:
|
||||||
case SPU_In_MBox_offs:
|
{
|
||||||
//LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_In_MBox, 0x%x)", m_index, value);
|
LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_Status, 0x%x)", m_index, value);
|
||||||
SPU.In_MBox.PushUncond(value); //if In_MBox is already full, the last message will be overwritten
|
SPU.Status.SetValue(value);
|
||||||
break;
|
break;
|
||||||
case SPU_MBox_Status_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_MBox_Status, 0x%x)", m_index, value); SPU.MBox_Status.SetValue(value); break;
|
}
|
||||||
case SPU_RunCntl_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_RunCntl, 0x%x)", m_index, value); SPU.RunCntl.SetValue(value); break;
|
|
||||||
case SPU_Status_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_Status, 0x%x)", m_index, value); SPU.Status.SetValue(value); break;
|
case SPU_NPC_offs:
|
||||||
case SPU_NPC_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_NPC, 0x%x)", m_index, value); SPU.NPC.SetValue(value); break;
|
{
|
||||||
case SPU_RdSigNotify1_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_RdSigNotify1, 0x%x)", m_index, value); SPU.SNR[0].SetValue(value); break;
|
LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_NPC, 0x%x)", m_index, value);
|
||||||
case SPU_RdSigNotify2_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_RdSigNotify2, 0x%x)", m_index, value); SPU.SNR[1].SetValue(value); break;
|
SPU.NPC.SetValue(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SPU_RdSigNotify1_offs:
|
||||||
|
{
|
||||||
|
LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_RdSigNotify1, 0x%x)", m_index, value);
|
||||||
|
SPU.SNR[0].SetValue(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SPU_RdSigNotify2_offs:
|
||||||
|
{
|
||||||
|
LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_RdSigNotify2, 0x%x)", m_index, value);
|
||||||
|
SPU.SNR[1].SetValue(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
{
|
||||||
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Write32(0x%x, 0x%x)", m_index, offset, value);
|
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Write32(0x%x, 0x%x)", m_index, offset, value);
|
||||||
Emu.Pause();
|
Emu.Pause();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RawSPUThread::Write64(const u64 addr, const u64 value)
|
|
||||||
{
|
|
||||||
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
|
|
||||||
{
|
|
||||||
return MemoryBlock::Write64(addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
|
|
||||||
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Write64(0x%x, 0x%llx)", m_index, offset, value);
|
|
||||||
Emu.Pause();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RawSPUThread::Write128(const u64 addr, const u128 value)
|
|
||||||
{
|
|
||||||
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
|
|
||||||
{
|
|
||||||
return MemoryBlock::Write128(addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
|
|
||||||
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Write128(0x%x, 0x%llx_%llx)", m_index, offset, value._u64[1], value._u64[0]);
|
|
||||||
Emu.Pause();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RawSPUThread::InitRegs()
|
void RawSPUThread::InitRegs()
|
||||||
{
|
{
|
||||||
dmac.ls_offset = m_offset = GetStartAddr() + RAW_SPU_LS_OFFSET;
|
dmac.ls_offset = m_offset = GetStartAddr() + RAW_SPU_LS_OFFSET;
|
||||||
|
@ -260,88 +340,9 @@ u32 RawSPUThread::GetIndex() const
|
||||||
|
|
||||||
void RawSPUThread::Task()
|
void RawSPUThread::Task()
|
||||||
{
|
{
|
||||||
if (Ini.HLELogging.GetValue()) LOG_NOTICE(Log::SPU, "%s enter", PPCThread::GetFName().c_str());
|
|
||||||
|
|
||||||
const std::vector<u64>& bp = Emu.GetBreakPoints();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
for(uint i=0; i<bp.size(); ++i)
|
|
||||||
{
|
|
||||||
if(bp[i] == m_offset + PC)
|
|
||||||
{
|
|
||||||
Emu.Pause();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_last_paused = true;
|
|
||||||
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
int status = ThreadStatus();
|
|
||||||
|
|
||||||
if(status == CPUThread_Stopped || status == CPUThread_Break)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(status == CPUThread_Sleeping)
|
|
||||||
{
|
|
||||||
Sleep(1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//dmac.DoCmd();
|
|
||||||
|
|
||||||
if(SPU.RunCntl.GetValue() != SPU_RUNCNTL_RUNNABLE)
|
|
||||||
{
|
|
||||||
if(!is_last_paused)
|
|
||||||
{
|
|
||||||
is_last_paused = true;
|
|
||||||
SPU.NPC.SetValue(PC);
|
|
||||||
SPU.Status.SetValue(SPU_STATUS_WAITING_FOR_CHANNEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
Sleep(1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(is_last_paused)
|
|
||||||
{
|
|
||||||
is_last_paused = false;
|
|
||||||
PC = SPU.NPC.GetValue();
|
PC = SPU.NPC.GetValue();
|
||||||
SPU.Status.SetValue(SPU_STATUS_RUNNING);
|
|
||||||
LOG_WARNING(Log::SPU, "Starting RawSPU...");
|
|
||||||
}
|
|
||||||
|
|
||||||
Step();
|
CPUThread::Task();
|
||||||
NextPc(m_dec->DecodeMemory(PC + m_offset));
|
|
||||||
|
|
||||||
if(status == CPUThread_Step)
|
SPU.NPC.SetValue(PC);
|
||||||
{
|
|
||||||
m_is_step = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(uint i=0; i<bp.size(); ++i)
|
|
||||||
{
|
|
||||||
if(bp[i] == PC)
|
|
||||||
{
|
|
||||||
Emu.Pause();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(const std::string& e)
|
|
||||||
{
|
|
||||||
LOG_ERROR(Log::SPU, "Exception: %s", e.c_str());
|
|
||||||
}
|
|
||||||
catch(const char* e)
|
|
||||||
{
|
|
||||||
LOG_ERROR(Log::SPU, "Exception: %s", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Ini.HLELogging.GetValue()) LOG_NOTICE(Log::SPU, "%s leave", PPCThread::GetFName().c_str());
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,17 +22,9 @@ public:
|
||||||
RawSPUThread(u32 index, CPUThreadType type = CPU_THREAD_RAW_SPU);
|
RawSPUThread(u32 index, CPUThreadType type = CPU_THREAD_RAW_SPU);
|
||||||
virtual ~RawSPUThread();
|
virtual ~RawSPUThread();
|
||||||
|
|
||||||
virtual bool Read8(const u64 addr, u8* value) override;
|
|
||||||
virtual bool Read16(const u64 addr, u16* value) override;
|
|
||||||
virtual bool Read32(const u64 addr, u32* value) override;
|
virtual bool Read32(const u64 addr, u32* value) override;
|
||||||
virtual bool Read64(const u64 addr, u64* value) override;
|
|
||||||
virtual bool Read128(const u64 addr, u128* value) override;
|
|
||||||
|
|
||||||
virtual bool Write8(const u64 addr, const u8 value) override;
|
|
||||||
virtual bool Write16(const u64 addr, const u16 value) override;
|
|
||||||
virtual bool Write32(const u64 addr, const u32 value) override;
|
virtual bool Write32(const u64 addr, const u32 value) override;
|
||||||
virtual bool Write64(const u64 addr, const u64 value) override;
|
|
||||||
virtual bool Write128(const u64 addr, const u128 value) override;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void InitRegs();
|
virtual void InitRegs();
|
||||||
|
|
|
@ -61,8 +61,7 @@ void SPUThread::InitRegs()
|
||||||
dmac.proxy_lock = 0;
|
dmac.proxy_lock = 0;
|
||||||
dmac.queue_lock = 0;*/
|
dmac.queue_lock = 0;*/
|
||||||
|
|
||||||
SPU.RunCntl.SetValue(SPU_RUNCNTL_STOP);
|
SPU.Status.SetValue(SPU_STATUS_STOPPED);
|
||||||
SPU.Status.SetValue(SPU_STATUS_RUNNING);
|
|
||||||
Prxy.QueryType.SetValue(0);
|
Prxy.QueryType.SetValue(0);
|
||||||
MFC1.CMDStatus.SetValue(0);
|
MFC1.CMDStatus.SetValue(0);
|
||||||
MFC2.CMDStatus.SetValue(0);
|
MFC2.CMDStatus.SetValue(0);
|
||||||
|
|
|
@ -151,14 +151,6 @@ enum
|
||||||
SPU_RdSigNotify2_offs = 0x1C00C,
|
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,
|
|
||||||
};
|
|
||||||
|
|
||||||
//Floating point status and control register. Unsure if this is one of the GPRs or SPRs
|
//Floating point status and control register. Unsure if this is one of the GPRs or SPRs
|
||||||
//Is 128 bits, but bits 0-19, 24-28, 32-49, 56-60, 64-81, 88-92, 96-115, 120-124 are unused
|
//Is 128 bits, but bits 0-19, 24-28, 32-49, 56-60, 64-81, 88-92, 96-115, 120-124 are unused
|
||||||
class FPSCR
|
class FPSCR
|
||||||
|
@ -318,7 +310,7 @@ class SPUThread : public PPCThread
|
||||||
public:
|
public:
|
||||||
SPU_GPR_hdr GPR[128]; //General-Purpose Register
|
SPU_GPR_hdr GPR[128]; //General-Purpose Register
|
||||||
SPU_SPR_hdr SPR[128]; //Special-Purpose Registers
|
SPU_SPR_hdr SPR[128]; //Special-Purpose Registers
|
||||||
// FPSCR fpscr; //Unused
|
//FPSCR FPSCR;
|
||||||
SPU_SNRConfig_hdr cfg; //Signal Notification Registers Configuration (OR-mode enabled: 0x1 for SNR1, 0x2 for SNR2)
|
SPU_SNRConfig_hdr cfg; //Signal Notification Registers Configuration (OR-mode enabled: 0x1 for SNR1, 0x2 for SNR2)
|
||||||
|
|
||||||
EventPort SPUPs[64]; // SPU Thread Event Ports
|
EventPort SPUPs[64]; // SPU Thread Event Ports
|
||||||
|
@ -562,7 +554,6 @@ public:
|
||||||
Channel<1> Out_IntrMBox;
|
Channel<1> Out_IntrMBox;
|
||||||
Channel<4> In_MBox;
|
Channel<4> In_MBox;
|
||||||
Channel<1> MBox_Status;
|
Channel<1> MBox_Status;
|
||||||
Channel<1> RunCntl;
|
|
||||||
Channel<1> Status;
|
Channel<1> Status;
|
||||||
Channel<1> NPC;
|
Channel<1> NPC;
|
||||||
Channel<1> SNR[2];
|
Channel<1> SNR[2];
|
||||||
|
@ -590,19 +581,26 @@ public:
|
||||||
|
|
||||||
DMAC dmac;
|
DMAC dmac;
|
||||||
|
|
||||||
|
#define LOG_DMAC(type, text) type(Log::SPU, "DMAC::ProcessCmd(cmd=0x%x, tag=0x%x, lsa=0x%x, ea=0x%llx, size=0x%x): " text, cmd, tag, lsa, ea, size)
|
||||||
|
|
||||||
bool ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
|
bool ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
|
||||||
{
|
{
|
||||||
if (cmd & (MFC_BARRIER_MASK | MFC_FENCE_MASK)) _mm_mfence();
|
if (cmd & (MFC_BARRIER_MASK | MFC_FENCE_MASK)) _mm_mfence();
|
||||||
|
|
||||||
if (ea >= SYS_SPU_THREAD_BASE_LOW)
|
if (ea >= SYS_SPU_THREAD_BASE_LOW)
|
||||||
{
|
{
|
||||||
if (group)
|
if (ea >= 0x100000000)
|
||||||
|
{
|
||||||
|
LOG_DMAC(LOG_ERROR, "Invalid external address");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (group)
|
||||||
{
|
{
|
||||||
// SPU Thread Group MMIO (LS and SNR)
|
// SPU Thread Group MMIO (LS and SNR)
|
||||||
u32 num = (ea & SYS_SPU_THREAD_BASE_MASK) / SYS_SPU_THREAD_OFFSET; // thread number in group
|
u32 num = (ea & SYS_SPU_THREAD_BASE_MASK) / SYS_SPU_THREAD_OFFSET; // thread number in group
|
||||||
if (num >= group->list.size() || !group->list[num])
|
if (num >= group->list.size() || !group->list[num])
|
||||||
{
|
{
|
||||||
LOG_ERROR(Log::SPU, "DMAC::ProcessCmd(): SPU Thread Group MMIO Access (ea=0x%llx): invalid thread", ea);
|
LOG_DMAC(LOG_ERROR, "Invalid thread (SPU Thread Group MMIO)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -621,13 +619,13 @@ public:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_ERROR(Log::SPU, "DMAC::ProcessCmd(): SPU Thread Group MMIO Access (ea=0x%llx, size=%d, cmd=0x%x): invalid command", ea, size, cmd);
|
LOG_DMAC(LOG_ERROR, "Invalid register (SPU Thread Group MMIO)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_ERROR(Log::SPU, "DMAC::ProcessCmd(): SPU Thread Group MMIO Access (ea=0x%llx): group not set", ea);
|
LOG_DMAC(LOG_ERROR, "Thread group not set (SPU Thread Group MMIO)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -649,14 +647,12 @@ public:
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
LOG_ERROR(Log::SPU, "DMAC::ProcessCmd(): Unknown DMA cmd.");
|
LOG_DMAC(LOG_ERROR, "Unknown DMA command");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Sleep(1); // hack
|
|
||||||
|
|
||||||
switch (cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK | MFC_RESULT_MASK))
|
switch (cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK | MFC_RESULT_MASK))
|
||||||
{
|
{
|
||||||
case MFC_PUT_CMD:
|
case MFC_PUT_CMD:
|
||||||
|
@ -667,7 +663,7 @@ public:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_ERROR(Log::SPU, "DMAC::ProcessCmd(): PUT* cmd failed (ea=0x%llx, lsa=0x%x, size=%d)", ea, lsa, size);
|
LOG_DMAC(LOG_ERROR, "PUT* cmd failed");
|
||||||
return false; // TODO: page fault (?)
|
return false; // TODO: page fault (?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -680,19 +676,21 @@ public:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_ERROR(Log::SPU, "DMAC::ProcessCmd(): GET* cmd failed (ea=0x%llx, lsa=0x%x, size=%d)", ea, lsa, size);
|
LOG_DMAC(LOG_ERROR, "GET* cmd failed");
|
||||||
return false; // TODO: page fault (?)
|
return false; // TODO: page fault (?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
LOG_ERROR(Log::SPU, "DMAC::ProcessCmd(): Unknown DMA cmd.");
|
LOG_DMAC(LOG_ERROR, "Unknown DMA command");
|
||||||
return false; // ???
|
return false; // ???
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef LOG_CMD
|
||||||
|
|
||||||
u32 dmacCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
|
u32 dmacCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
|
||||||
{
|
{
|
||||||
/*if(proxy_pos >= MFC_PPU_MAX_QUEUE_SPACE)
|
/*if(proxy_pos >= MFC_PPU_MAX_QUEUE_SPACE)
|
||||||
|
|
|
@ -32,12 +32,15 @@ u64 vfsStreamMemory::Write(const void* src, u64 size)
|
||||||
size = GetSize() - Tell();
|
size = GetSize() - Tell();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!size || !Memory.IsGoodAddr(m_addr + Tell(), size)) return 0;
|
if (!Memory.CopyFromReal(m_addr + Tell(), (void*)src, size))
|
||||||
|
{
|
||||||
Memory.CopyFromReal(m_addr + Tell(), (void*)src, size);
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
return vfsStream::Write(src, size);
|
return vfsStream::Write(src, size);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
u64 vfsStreamMemory::Read(void* dst, u64 size)
|
u64 vfsStreamMemory::Read(void* dst, u64 size)
|
||||||
{
|
{
|
||||||
|
@ -46,9 +49,12 @@ u64 vfsStreamMemory::Read(void* dst, u64 size)
|
||||||
size = GetSize() - Tell();
|
size = GetSize() - Tell();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!size || !Memory.IsGoodAddr(m_addr + Tell(), size)) return 0;
|
if (!Memory.CopyToReal(dst, m_addr + Tell(), size))
|
||||||
|
{
|
||||||
Memory.CopyToReal(dst, m_addr + Tell(), size);
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
return vfsStream::Read(dst, size);
|
return vfsStream::Read(dst, size);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "RSXThread.h"
|
#include "RSXThread.h"
|
||||||
#include "Emu/SysCalls/lv2/sys_time.h"
|
#include "Emu/SysCalls/lv2/sys_time.h"
|
||||||
|
|
||||||
#define ARGS(x) (x >= count ? OutOfArgsCount(x, cmd, count) : Memory.Read32(Memory.RSXIOMem.GetStartAddr() + m_ctrl->get + (4*(x+1))))
|
#define ARGS(x) (x >= count ? OutOfArgsCount(x, cmd, count, args) : args[x].ToLE())
|
||||||
|
|
||||||
u32 methodRegisters[0xffff];
|
u32 methodRegisters[0xffff];
|
||||||
|
|
||||||
|
@ -45,10 +45,7 @@ u32 GetAddress(u32 offset, u8 location)
|
||||||
switch(location)
|
switch(location)
|
||||||
{
|
{
|
||||||
case CELL_GCM_LOCATION_LOCAL: return Memory.RSXFBMem.GetStartAddr() + offset;
|
case CELL_GCM_LOCATION_LOCAL: return Memory.RSXFBMem.GetStartAddr() + offset;
|
||||||
case CELL_GCM_LOCATION_MAIN:
|
case CELL_GCM_LOCATION_MAIN: return Memory.RSXIOMem.RealAddr(Memory.RSXIOMem.GetStartAddr() + offset); // TODO: Error Check?
|
||||||
u64 realAddr;
|
|
||||||
Memory.RSXIOMem.getRealAddr(Memory.RSXIOMem.GetStartAddr() + offset, realAddr); // TODO: Error Check?
|
|
||||||
return realAddr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_ERROR(RSX, "GetAddress(offset=0x%x, location=0x%x)", location);
|
LOG_ERROR(RSX, "GetAddress(offset=0x%x, location=0x%x)", location);
|
||||||
|
@ -140,7 +137,7 @@ u32 RSXVertexData::GetTypeSize()
|
||||||
#define CMD_LOG(...)
|
#define CMD_LOG(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
u32 RSXThread::OutOfArgsCount(const uint x, const u32 cmd, const u32 count)
|
u32 RSXThread::OutOfArgsCount(const uint x, const u32 cmd, const u32 count, mem32_ptr_t args)
|
||||||
{
|
{
|
||||||
std::string debug = GetMethodName(cmd);
|
std::string debug = GetMethodName(cmd);
|
||||||
debug += "(";
|
debug += "(";
|
||||||
|
@ -206,7 +203,7 @@ u32 RSXThread::OutOfArgsCount(const uint x, const u32 cmd, const u32 count)
|
||||||
index = (cmd - a) / m; \
|
index = (cmd - a) / m; \
|
||||||
case a \
|
case a \
|
||||||
|
|
||||||
void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u32 count)
|
void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t args, const u32 count)
|
||||||
{
|
{
|
||||||
#if CMD_DEBUG
|
#if CMD_DEBUG
|
||||||
std::string debug = GetMethodName(cmd);
|
std::string debug = GetMethodName(cmd);
|
||||||
|
@ -2454,7 +2451,7 @@ void RSXThread::Task()
|
||||||
}
|
}
|
||||||
|
|
||||||
//ConLog.Write("addr = 0x%x", m_ioAddress + get);
|
//ConLog.Write("addr = 0x%x", m_ioAddress + get);
|
||||||
const u32 cmd = Memory.Read32(Memory.RSXIOMem.GetStartAddr() + get);
|
const u32 cmd = ReadIO32(get);
|
||||||
const u32 count = (cmd >> 18) & 0x7ff;
|
const u32 count = (cmd >> 18) & 0x7ff;
|
||||||
//if(cmd == 0) continue;
|
//if(cmd == 0) continue;
|
||||||
|
|
||||||
|
@ -2469,7 +2466,7 @@ void RSXThread::Task()
|
||||||
{
|
{
|
||||||
m_call_stack.push(get + 4);
|
m_call_stack.push(get + 4);
|
||||||
u32 offs = cmd & ~CELL_GCM_METHOD_FLAG_CALL;
|
u32 offs = cmd & ~CELL_GCM_METHOD_FLAG_CALL;
|
||||||
u32 addr = Memory.RSXIOMem.GetStartAddr() + offs;
|
//u32 addr = Memory.RSXIOMem.GetStartAddr() + offs;
|
||||||
//LOG_WARNING(RSX, "rsx call(0x%x) #0x%x - 0x%x - 0x%x", offs, addr, cmd, get);
|
//LOG_WARNING(RSX, "rsx call(0x%x) #0x%x - 0x%x - 0x%x", offs, addr, cmd, get);
|
||||||
m_ctrl->get = offs;
|
m_ctrl->get = offs;
|
||||||
continue;
|
continue;
|
||||||
|
@ -2498,12 +2495,13 @@ void RSXThread::Task()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mem32_ptr_t args((u32)Memory.RSXIOMem.RealAddr(Memory.RSXIOMem.GetStartAddr() + get + 4));
|
||||||
|
|
||||||
for(u32 i=0; i<count; i++)
|
for(u32 i=0; i<count; i++)
|
||||||
{
|
{
|
||||||
methodRegisters[(cmd & 0xffff) + (i*4*inc)] = ARGS(i);
|
methodRegisters[(cmd & 0xffff) + (i*4*inc)] = ARGS(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
mem32_ptr_t args(Memory.RSXIOMem.GetStartAddr() + get + 4);
|
|
||||||
DoCmd(cmd, cmd & 0x3ffff, args, count);
|
DoCmd(cmd, cmd & 0x3ffff, args, count);
|
||||||
|
|
||||||
m_ctrl->get = get + (count + 1) * 4;
|
m_ctrl->get = get + (count + 1) * 4;
|
||||||
|
|
|
@ -608,8 +608,8 @@ protected:
|
||||||
void Begin(u32 draw_mode);
|
void Begin(u32 draw_mode);
|
||||||
void End();
|
void End();
|
||||||
|
|
||||||
u32 OutOfArgsCount(const uint x, const u32 cmd, const u32 count);
|
u32 OutOfArgsCount(const uint x, const u32 cmd, const u32 count, mem32_ptr_t args);
|
||||||
void DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u32 count);
|
void DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t args, const u32 count);
|
||||||
void nativeRescale(float width, float height);
|
void nativeRescale(float width, float height);
|
||||||
|
|
||||||
virtual void OnInit() = 0;
|
virtual void OnInit() = 0;
|
||||||
|
@ -649,4 +649,16 @@ public:
|
||||||
OnInit();
|
OnInit();
|
||||||
ThreadBase::Start();
|
ThreadBase::Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 ReadIO32(u32 addr)
|
||||||
|
{
|
||||||
|
u32 value;
|
||||||
|
Memory.RSXIOMem.Read32(Memory.RSXIOMem.GetStartAddr() + addr, &value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteIO32(u32 addr, u32 value)
|
||||||
|
{
|
||||||
|
Memory.RSXIOMem.Write32(Memory.RSXIOMem.GetStartAddr() + addr, value);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -41,7 +41,7 @@ bool DynamicMemoryBlockBase<PT>::IsMyAddress(const u64 addr)
|
||||||
|
|
||||||
const u32 index = MemoryBlock::FixAddr(addr) >> 12;
|
const u32 index = MemoryBlock::FixAddr(addr) >> 12;
|
||||||
|
|
||||||
return m_pages[index] && !m_locked[index];
|
return m_pages[index] != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename PT>
|
template<typename PT>
|
||||||
|
@ -54,9 +54,7 @@ MemoryBlock* DynamicMemoryBlockBase<PT>::SetRange(const u64 start, const u32 siz
|
||||||
|
|
||||||
const u32 page_count = m_max_size >> 12;
|
const u32 page_count = m_max_size >> 12;
|
||||||
m_pages.resize(page_count);
|
m_pages.resize(page_count);
|
||||||
m_locked.resize(page_count);
|
|
||||||
memset(m_pages.data(), 0, sizeof(u8*) * page_count);
|
memset(m_pages.data(), 0, sizeof(u8*) * page_count);
|
||||||
memset(m_locked.data(), 0, sizeof(u8*) * page_count);
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -70,7 +68,6 @@ void DynamicMemoryBlockBase<PT>::Delete()
|
||||||
m_max_size = 0;
|
m_max_size = 0;
|
||||||
|
|
||||||
m_pages.clear();
|
m_pages.clear();
|
||||||
m_locked.clear();
|
|
||||||
|
|
||||||
MemoryBlock::Delete();
|
MemoryBlock::Delete();
|
||||||
}
|
}
|
||||||
|
@ -90,6 +87,7 @@ bool DynamicMemoryBlockBase<PT>::AllocFixed(u64 addr, u32 size)
|
||||||
|
|
||||||
if (IsMyAddress(addr) || IsMyAddress(addr + size - 1))
|
if (IsMyAddress(addr) || IsMyAddress(addr + size - 1))
|
||||||
{
|
{
|
||||||
|
assert(0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +106,6 @@ bool DynamicMemoryBlockBase<PT>::AllocFixed(u64 addr, u32 size)
|
||||||
template<typename PT>
|
template<typename PT>
|
||||||
void DynamicMemoryBlockBase<PT>::AppendMem(u64 addr, u32 size) /* private */
|
void DynamicMemoryBlockBase<PT>::AppendMem(u64 addr, u32 size) /* private */
|
||||||
{
|
{
|
||||||
//u8* pointer = (u8*)m_allocated[m_allocated.Move(new MemBlockInfo(addr, size))].mem;
|
|
||||||
m_allocated.emplace_back(addr, size);
|
m_allocated.emplace_back(addr, size);
|
||||||
u8* pointer = (u8*) m_allocated.back().mem;
|
u8* pointer = (u8*) m_allocated.back().mem;
|
||||||
|
|
||||||
|
@ -119,7 +116,6 @@ void DynamicMemoryBlockBase<PT>::AppendMem(u64 addr, u32 size) /* private */
|
||||||
for (u32 i = first; i <= last; i++)
|
for (u32 i = first; i <= last; i++)
|
||||||
{
|
{
|
||||||
m_pages[i] = pointer;
|
m_pages[i] = pointer;
|
||||||
m_locked[i] = nullptr;
|
|
||||||
pointer += 4096;
|
pointer += 4096;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,6 +161,8 @@ u64 DynamicMemoryBlockBase<PT>::AllocAlign(u32 size, u32 align)
|
||||||
addr = (addr + (align - 1)) & ~(align - 1);
|
addr = (addr + (align - 1)) & ~(align - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//LOG_NOTICE(MEMORY, "AllocAlign(size=0x%x) -> 0x%llx", size, addr);
|
||||||
|
|
||||||
AppendMem(addr, size);
|
AppendMem(addr, size);
|
||||||
|
|
||||||
return addr;
|
return addr;
|
||||||
|
@ -195,18 +193,19 @@ bool DynamicMemoryBlockBase<PT>::Free(u64 addr)
|
||||||
const u32 last = first + ((m_allocated[num].size - 1) >> 12);
|
const u32 last = first + ((m_allocated[num].size - 1) >> 12);
|
||||||
|
|
||||||
// check if locked:
|
// check if locked:
|
||||||
for (u32 i = first; i <= last; i++)
|
//for (u32 i = first; i <= last; i++)
|
||||||
{
|
//{
|
||||||
if (!m_pages[i] || m_locked[i]) return false;
|
// if (!m_pages[i]) return false;
|
||||||
}
|
//}
|
||||||
|
|
||||||
// clear pointers:
|
// clear pointers:
|
||||||
for (u32 i = first; i <= last; i++)
|
for (u32 i = first; i <= last; i++)
|
||||||
{
|
{
|
||||||
m_pages[i] = nullptr;
|
m_pages[i] = nullptr;
|
||||||
m_locked[i] = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//LOG_NOTICE(MEMORY, "Free(0x%llx)", addr);
|
||||||
|
|
||||||
m_allocated.erase(m_allocated.begin() + num);
|
m_allocated.erase(m_allocated.begin() + num);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -217,6 +216,7 @@ bool DynamicMemoryBlockBase<PT>::Free(u64 addr)
|
||||||
{
|
{
|
||||||
LOG_NOTICE(MEMORY, "*** Memory Block: addr = 0x%llx, size = 0x%x", m_allocated[i].addr, m_allocated[i].size);
|
LOG_NOTICE(MEMORY, "*** Memory Block: addr = 0x%llx, size = 0x%x", m_allocated[i].addr, m_allocated[i].size);
|
||||||
}
|
}
|
||||||
|
assert(0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,97 +233,34 @@ u8* DynamicMemoryBlockBase<PT>::GetMem(u64 addr) const // lock-free, addr is fix
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_ERROR(MEMORY, "GetMem(%llx) from not allocated address.", addr);
|
LOG_ERROR(MEMORY, "GetMem(0x%llx) from not allocated address.", addr);
|
||||||
assert(0);
|
assert(0);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename PT>
|
template<typename PT>
|
||||||
bool DynamicMemoryBlockBase<PT>::IsLocked(u64 addr) // lock-free
|
bool DynamicMemoryBlockBase<PT>::IsLocked(u64 addr)
|
||||||
{
|
{
|
||||||
if (IsInMyRange(addr))
|
// TODO
|
||||||
{
|
LOG_ERROR(MEMORY, "IsLocked(0x%llx) not implemented", addr);
|
||||||
const u32 index = MemoryBlock::FixAddr(addr) >> 12;
|
assert(0);
|
||||||
|
|
||||||
if (index < m_locked.size())
|
|
||||||
{
|
|
||||||
if (m_locked[index]) return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename PT>
|
template<typename PT>
|
||||||
bool DynamicMemoryBlockBase<PT>::Lock(u64 addr, u32 size)
|
bool DynamicMemoryBlockBase<PT>::Lock(u64 addr, u32 size)
|
||||||
{
|
{
|
||||||
size = PAGE_4K(size); // align size
|
// TODO
|
||||||
|
LOG_ERROR(MEMORY, "Lock(0x%llx, 0x%x) not implemented", addr, size);
|
||||||
addr &= ~4095; // align start address
|
|
||||||
|
|
||||||
if (!IsInMyRange(addr, size))
|
|
||||||
{
|
|
||||||
assert(0);
|
assert(0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsMyAddress(addr) || IsMyAddress(addr + size - 1))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const u32 first = MemoryBlock::FixAddr(addr) >> 12;
|
|
||||||
|
|
||||||
const u32 last = first + ((size - 1) >> 12);
|
|
||||||
|
|
||||||
for (u32 i = first; i <= last; i++)
|
|
||||||
{
|
|
||||||
if (u8* pointer = m_pages[i])
|
|
||||||
{
|
|
||||||
m_locked[i] = pointer;
|
|
||||||
m_pages[i] = nullptr;
|
|
||||||
}
|
|
||||||
else // already locked or empty
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename PT>
|
template<typename PT>
|
||||||
bool DynamicMemoryBlockBase<PT>::Unlock(u64 addr, u32 size)
|
bool DynamicMemoryBlockBase<PT>::Unlock(u64 addr, u32 size)
|
||||||
{
|
{
|
||||||
size = PAGE_4K(size); // align size
|
// TODO
|
||||||
|
LOG_ERROR(MEMORY, "Unlock(0x%llx, 0x%x) not implemented", addr, size);
|
||||||
addr &= ~4095; // align start address
|
|
||||||
|
|
||||||
if (!IsInMyRange(addr, size))
|
|
||||||
{
|
|
||||||
assert(0);
|
assert(0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsMyAddress(addr) || IsMyAddress(addr + size - 1))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const u32 first = MemoryBlock::FixAddr(addr) >> 12;
|
|
||||||
|
|
||||||
const u32 last = first + ((size - 1) >> 12);
|
|
||||||
|
|
||||||
for (u32 i = first; i <= last; i++)
|
|
||||||
{
|
|
||||||
if (u8* pointer = m_locked[i])
|
|
||||||
{
|
|
||||||
m_pages[i] = pointer;
|
|
||||||
m_locked[i] = nullptr;
|
|
||||||
}
|
|
||||||
else // already unlocked or empty
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,8 +6,53 @@
|
||||||
|
|
||||||
MemoryBase Memory;
|
MemoryBase Memory;
|
||||||
|
|
||||||
|
MemBlockInfo::MemBlockInfo(u64 _addr, u32 _size)
|
||||||
|
: MemInfo(_addr, PAGE_4K(_size))
|
||||||
|
{
|
||||||
|
void* real_addr = (void*)((u64)Memory.GetBaseAddr() + _addr);
|
||||||
|
#ifdef _WIN32
|
||||||
|
mem = VirtualAlloc(real_addr, size, MEM_COMMIT, PAGE_READWRITE);
|
||||||
|
#else
|
||||||
|
if (::mprotect(real_addr, size, PROT_READ | PROT_WRITE))
|
||||||
|
{
|
||||||
|
mem = nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mem = real_addr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (mem != real_addr)
|
||||||
|
{
|
||||||
|
LOG_ERROR(MEMORY, "Memory allocation failed (addr=0x%llx, size=0x%llx)", addr, size);
|
||||||
|
Emu.Pause();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Memory.RegisterPages(_addr, PAGE_4K(_size));
|
||||||
|
memset(mem, 0, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemBlockInfo::Free()
|
||||||
|
{
|
||||||
|
if (mem)
|
||||||
|
{
|
||||||
|
Memory.UnregisterPages(addr, size);
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (!VirtualFree(mem, size, MEM_DECOMMIT))
|
||||||
|
#else
|
||||||
|
if (::mprotect(mem, size, PROT_NONE))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
LOG_ERROR(MEMORY, "Memory deallocation failed (addr=0x%llx, size=0x%llx)", addr, size);
|
||||||
|
Emu.Pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//MemoryBlock
|
//MemoryBlock
|
||||||
MemoryBlock::MemoryBlock()
|
MemoryBlock::MemoryBlock() : mem_inf(nullptr)
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
@ -29,14 +74,24 @@ void MemoryBlock::InitMemory()
|
||||||
{
|
{
|
||||||
if (!range_size) return;
|
if (!range_size) return;
|
||||||
|
|
||||||
if(mem) safe_free(mem);
|
Free();
|
||||||
mem = (u8*)malloc(range_size);
|
mem_inf = new MemBlockInfo(range_start, range_size);
|
||||||
memset(mem, 0, range_size);
|
mem = (u8*)mem_inf->mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryBlock::Free()
|
||||||
|
{
|
||||||
|
if (mem_inf)
|
||||||
|
{
|
||||||
|
delete mem_inf;
|
||||||
|
mem_inf = nullptr;
|
||||||
|
}
|
||||||
|
mem = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryBlock::Delete()
|
void MemoryBlock::Delete()
|
||||||
{
|
{
|
||||||
if(mem) safe_free(mem);
|
Free();
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,16 +104,14 @@ bool MemoryBlock::GetMemFromAddr(void* dst, const u64 addr, const u32 size)
|
||||||
{
|
{
|
||||||
if(!IsMyAddress(addr) || FixAddr(addr) + size > GetSize()) return false;
|
if(!IsMyAddress(addr) || FixAddr(addr) + size > GetSize()) return false;
|
||||||
|
|
||||||
// mem cpy(dst, GetMem(FixAddr(addr)), size);
|
return Memory.CopyToReal(dst, addr, size);
|
||||||
return Memory.CopyToReal(dst, (u32)addr, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemoryBlock::SetMemFromAddr(void* src, const u64 addr, const u32 size)
|
bool MemoryBlock::SetMemFromAddr(void* src, const u64 addr, const u32 size)
|
||||||
{
|
{
|
||||||
if(!IsMyAddress(addr) || FixAddr(addr) + size > GetSize()) return false;
|
if(!IsMyAddress(addr) || FixAddr(addr) + size > GetSize()) return false;
|
||||||
|
|
||||||
// mem cpy(GetMem(FixAddr(addr)), src, size);
|
return Memory.CopyFromReal(addr, src, size);
|
||||||
return Memory.CopyFromReal((u32)addr, src, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemoryBlock::GetMemFFromAddr(void* dst, const u64 addr)
|
bool MemoryBlock::GetMemFFromAddr(void* dst, const u64 addr)
|
||||||
|
@ -116,7 +169,6 @@ bool MemoryBlock::Read8(const u64 addr, u8* value)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//*value = std::atomic_load((volatile std::atomic<u8>*)GetMem(FixAddr(addr)));
|
|
||||||
*value = FastRead<u8>(FixAddr(addr));
|
*value = FastRead<u8>(FixAddr(addr));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -129,7 +181,6 @@ bool MemoryBlock::Read16(const u64 addr, u16* value)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//se_t<u16>::func(*value, std::atomic_load((volatile std::atomic<u16>*)GetMem(FixAddr(addr))));
|
|
||||||
*value = FastRead<u16>(FixAddr(addr));
|
*value = FastRead<u16>(FixAddr(addr));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -142,7 +193,6 @@ bool MemoryBlock::Read32(const u64 addr, u32* value)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//se_t<u32>::func(*value, std::atomic_load((volatile std::atomic<u32>*)GetMem(FixAddr(addr))));
|
|
||||||
*value = FastRead<u32>(FixAddr(addr));
|
*value = FastRead<u32>(FixAddr(addr));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -155,7 +205,6 @@ bool MemoryBlock::Read64(const u64 addr, u64* value)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//se_t<u64>::func(*value, std::atomic_load((volatile std::atomic<u64>*)GetMem(FixAddr(addr))));
|
|
||||||
*value = FastRead<u64>(FixAddr(addr));
|
*value = FastRead<u64>(FixAddr(addr));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -168,9 +217,6 @@ bool MemoryBlock::Read128(const u64 addr, u128* value)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//u64 f_addr = FixAddr(addr);
|
|
||||||
//se_t<u64>::func(value->lo, std::atomic_load((volatile std::atomic<u64>*)GetMem(f_addr)));
|
|
||||||
//se_t<u64>::func(value->hi, std::atomic_load((volatile std::atomic<u64>*)GetMem(f_addr + 8)));
|
|
||||||
*value = FastRead<u128>(FixAddr(addr));
|
*value = FastRead<u128>(FixAddr(addr));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -194,7 +240,6 @@ bool MemoryBlock::Write8(const u64 addr, const u8 value)
|
||||||
{
|
{
|
||||||
if(!IsMyAddress(addr) || IsLocked(addr)) return false;
|
if(!IsMyAddress(addr) || IsLocked(addr)) return false;
|
||||||
|
|
||||||
//std::atomic_store((std::atomic<u8>*)GetMem(FixAddr(addr)), value);
|
|
||||||
FastWrite<u8>(FixAddr(addr), value);
|
FastWrite<u8>(FixAddr(addr), value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -203,9 +248,6 @@ bool MemoryBlock::Write16(const u64 addr, const u16 value)
|
||||||
{
|
{
|
||||||
if(!IsMyAddress(addr) || IsLocked(addr)) return false;
|
if(!IsMyAddress(addr) || IsLocked(addr)) return false;
|
||||||
|
|
||||||
//u16 re_value;
|
|
||||||
//se_t<u16>::func(re_value, value);
|
|
||||||
//std::atomic_store((std::atomic<u16>*)GetMem(FixAddr(addr)), re_value);
|
|
||||||
FastWrite<u16>(FixAddr(addr), value);
|
FastWrite<u16>(FixAddr(addr), value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -214,9 +256,6 @@ bool MemoryBlock::Write32(const u64 addr, const u32 value)
|
||||||
{
|
{
|
||||||
if(!IsMyAddress(addr) || IsLocked(addr)) return false;
|
if(!IsMyAddress(addr) || IsLocked(addr)) return false;
|
||||||
|
|
||||||
//u32 re_value;
|
|
||||||
//se_t<u32>::func(re_value, value);
|
|
||||||
//std::atomic_store((std::atomic<u32>*)GetMem(FixAddr(addr)), re_value);
|
|
||||||
FastWrite<u32>(FixAddr(addr), value);
|
FastWrite<u32>(FixAddr(addr), value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -225,9 +264,6 @@ bool MemoryBlock::Write64(const u64 addr, const u64 value)
|
||||||
{
|
{
|
||||||
if(!IsMyAddress(addr) || IsLocked(addr)) return false;
|
if(!IsMyAddress(addr) || IsLocked(addr)) return false;
|
||||||
|
|
||||||
//u64 re_value;
|
|
||||||
//se_t<u64>::func(re_value, value);
|
|
||||||
//std::atomic_store((std::atomic<u64>*)GetMem(FixAddr(addr)), re_value);
|
|
||||||
FastWrite<u64>(FixAddr(addr), value);
|
FastWrite<u64>(FixAddr(addr), value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -236,12 +272,6 @@ bool MemoryBlock::Write128(const u64 addr, const u128 value)
|
||||||
{
|
{
|
||||||
if(!IsMyAddress(addr) || IsLocked(addr)) return false;
|
if(!IsMyAddress(addr) || IsLocked(addr)) return false;
|
||||||
|
|
||||||
//u64 f_addr = FixAddr(addr);
|
|
||||||
//u64 re_value;
|
|
||||||
//se_t<u64>::func(re_value, value.lo);
|
|
||||||
//std::atomic_store((std::atomic<u64>*)GetMem(f_addr), re_value);
|
|
||||||
//se_t<u64>::func(re_value, value.hi);
|
|
||||||
//std::atomic_store((std::atomic<u64>*)GetMem(f_addr + 8), re_value);
|
|
||||||
FastWrite<u128>(FixAddr(addr), value);
|
FastWrite<u128>(FixAddr(addr), value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -326,111 +356,77 @@ bool MemoryBlockLE::Write128(const u64 addr, const u128 value)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//NullMemoryBlock
|
|
||||||
bool NullMemoryBlock::Read8(const u64 addr, u8* )
|
|
||||||
{
|
|
||||||
LOG_ERROR(MEMORY, "Read8 from null block: [%08llx]", addr);
|
|
||||||
if (!Ini.CPUIgnoreRWErrors.GetValue())
|
|
||||||
Emu.Pause();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NullMemoryBlock::Read16(const u64 addr, u16* )
|
|
||||||
{
|
|
||||||
LOG_ERROR(MEMORY, "Read16 from null block: [%08llx]", addr);
|
|
||||||
if (!Ini.CPUIgnoreRWErrors.GetValue())
|
|
||||||
Emu.Pause();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NullMemoryBlock::Read32(const u64 addr, u32* )
|
|
||||||
{
|
|
||||||
LOG_ERROR(MEMORY, "Read32 from null block: [%08llx]", addr);
|
|
||||||
if (!Ini.CPUIgnoreRWErrors.GetValue())
|
|
||||||
Emu.Pause();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NullMemoryBlock::Read64(const u64 addr, u64* )
|
|
||||||
{
|
|
||||||
LOG_ERROR(MEMORY, "Read64 from null block: [%08llx]", addr);
|
|
||||||
if (!Ini.CPUIgnoreRWErrors.GetValue())
|
|
||||||
Emu.Pause();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NullMemoryBlock::Read128(const u64 addr, u128* )
|
|
||||||
{
|
|
||||||
LOG_ERROR(MEMORY, "Read128 from null block: [%08llx]", addr);
|
|
||||||
if (!Ini.CPUIgnoreRWErrors.GetValue())
|
|
||||||
Emu.Pause();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NullMemoryBlock::Write8(const u64 addr, const u8 value)
|
|
||||||
{
|
|
||||||
LOG_ERROR(MEMORY, "Write8 to null block: [%08llx]: %x", addr, value);
|
|
||||||
if (!Ini.CPUIgnoreRWErrors.GetValue())
|
|
||||||
Emu.Pause();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NullMemoryBlock::Write16(const u64 addr, const u16 value)
|
|
||||||
{
|
|
||||||
LOG_ERROR(MEMORY, "Write16 to null block: [%08llx]: %x", addr, value);
|
|
||||||
if (!Ini.CPUIgnoreRWErrors.GetValue())
|
|
||||||
Emu.Pause();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NullMemoryBlock::Write32(const u64 addr, const u32 value)
|
|
||||||
{
|
|
||||||
LOG_ERROR(MEMORY, "Write32 to null block: [%08llx]: %x", addr, value);
|
|
||||||
if (!Ini.CPUIgnoreRWErrors.GetValue())
|
|
||||||
Emu.Pause();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NullMemoryBlock::Write64(const u64 addr, const u64 value)
|
|
||||||
{
|
|
||||||
LOG_ERROR(MEMORY, "Write64 to null block: [%08llx]: %llx", addr, value);
|
|
||||||
if (!Ini.CPUIgnoreRWErrors.GetValue())
|
|
||||||
Emu.Pause();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NullMemoryBlock::Write128(const u64 addr, const u128 value)
|
|
||||||
{
|
|
||||||
LOG_ERROR(MEMORY, "Write128 to null block: [%08llx]: %llx_%llx", addr, value.hi, value.lo);
|
|
||||||
if (!Ini.CPUIgnoreRWErrors.GetValue())
|
|
||||||
Emu.Pause();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//MemoryBase
|
//MemoryBase
|
||||||
void MemoryBase::Write8(u64 addr, const u8 data)
|
void MemoryBase::Write8(u64 addr, const u8 data)
|
||||||
{
|
{
|
||||||
GetMemByAddr(addr).Write8(addr, data);
|
if ((u32)addr == addr)
|
||||||
|
{
|
||||||
|
*(u8*)((u64)GetBaseAddr() + addr) = data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr);
|
||||||
|
Emu.Pause();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryBase::Write16(u64 addr, const u16 data)
|
void MemoryBase::Write16(u64 addr, const u16 data)
|
||||||
{
|
{
|
||||||
GetMemByAddr(addr).Write16(addr, data);
|
if ((u32)addr == addr)
|
||||||
|
{
|
||||||
|
*(u16*)((u64)GetBaseAddr() + addr) = re16(data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr);
|
||||||
|
Emu.Pause();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryBase::Write32(u64 addr, const u32 data)
|
void MemoryBase::Write32(u64 addr, const u32 data)
|
||||||
{
|
{
|
||||||
GetMemByAddr(addr).Write32(addr, data);
|
if ((u32)addr == addr)
|
||||||
|
{
|
||||||
|
if (addr < RAW_SPU_BASE_ADDR || (addr % RAW_SPU_OFFSET) < RAW_SPU_PROB_OFFSET || !RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET])
|
||||||
|
{
|
||||||
|
*(u32*)((u64)GetBaseAddr() + addr) = re32(data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET]->Write32(addr, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr);
|
||||||
|
Emu.Pause();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryBase::Write64(u64 addr, const u64 data)
|
void MemoryBase::Write64(u64 addr, const u64 data)
|
||||||
{
|
{
|
||||||
GetMemByAddr(addr).Write64(addr, data);
|
if ((u32)addr == addr)
|
||||||
|
{
|
||||||
|
*(u64*)((u64)GetBaseAddr() + addr) = re64(data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr);
|
||||||
|
Emu.Pause();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryBase::Write128(u64 addr, const u128 data)
|
void MemoryBase::Write128(u64 addr, const u128 data)
|
||||||
{
|
{
|
||||||
GetMemByAddr(addr).Write128(addr, data);
|
if ((u32)addr == addr)
|
||||||
|
{
|
||||||
|
*(u128*)((u64)GetBaseAddr() + addr) = re128(data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr);
|
||||||
|
Emu.Pause();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemoryBase::Write8NN(u64 addr, const u8 data)
|
bool MemoryBase::Write8NN(u64 addr, const u8 data)
|
||||||
|
@ -470,37 +466,81 @@ bool MemoryBase::Write128NN(u64 addr, const u128 data)
|
||||||
|
|
||||||
u8 MemoryBase::Read8(u64 addr)
|
u8 MemoryBase::Read8(u64 addr)
|
||||||
{
|
{
|
||||||
u8 res;
|
if ((u32)addr == addr)
|
||||||
Read8ByAddr(addr, &res);
|
{
|
||||||
return res;
|
return *(u8*)((u64)GetBaseAddr() + addr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr);
|
||||||
|
Emu.Pause();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 MemoryBase::Read16(u64 addr)
|
u16 MemoryBase::Read16(u64 addr)
|
||||||
{
|
{
|
||||||
u16 res;
|
if ((u32)addr == addr)
|
||||||
Read16ByAddr(addr, &res);
|
{
|
||||||
return res;
|
return re16(*(u16*)((u64)GetBaseAddr() + addr));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr);
|
||||||
|
Emu.Pause();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 MemoryBase::Read32(u64 addr)
|
u32 MemoryBase::Read32(u64 addr)
|
||||||
|
{
|
||||||
|
if ((u32)addr == addr)
|
||||||
|
{
|
||||||
|
if (addr < RAW_SPU_BASE_ADDR || (addr % RAW_SPU_OFFSET) < RAW_SPU_PROB_OFFSET || !RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET])
|
||||||
|
{
|
||||||
|
return re32(*(u32*)((u64)GetBaseAddr() + addr));
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
u32 res;
|
u32 res;
|
||||||
Read32ByAddr(addr, &res);
|
RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET]->Read32(addr, &res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr);
|
||||||
|
Emu.Pause();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
u64 MemoryBase::Read64(u64 addr)
|
u64 MemoryBase::Read64(u64 addr)
|
||||||
{
|
{
|
||||||
u64 res;
|
if ((u32)addr == addr)
|
||||||
Read64ByAddr(addr, &res);
|
{
|
||||||
return res;
|
return re64(*(u64*)((u64)GetBaseAddr() + addr));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr);
|
||||||
|
Emu.Pause();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u128 MemoryBase::Read128(u64 addr)
|
u128 MemoryBase::Read128(u64 addr)
|
||||||
{
|
{
|
||||||
u128 res;
|
if ((u32)addr == addr)
|
||||||
Read128ByAddr(addr, &res);
|
{
|
||||||
return res;
|
return re128(*(u128*)((u64)GetBaseAddr() + addr));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr);
|
||||||
|
Emu.Pause();
|
||||||
|
return u128::From128(0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> __forceinline u64 MemoryBase::ReverseData<1>(u64 val) { return val; }
|
template<> __forceinline u64 MemoryBase::ReverseData<1>(u64 val) { return val; }
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "MemoryBlock.h"
|
#include "MemoryBlock.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -14,12 +19,22 @@ enum MemoryType
|
||||||
Memory_PSP,
|
Memory_PSP,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum : u64
|
||||||
|
{
|
||||||
|
RAW_SPU_OFFSET = 0x0000000000100000,
|
||||||
|
RAW_SPU_BASE_ADDR = 0x00000000E0000000,
|
||||||
|
RAW_SPU_LS_OFFSET = 0x0000000000000000,
|
||||||
|
RAW_SPU_PROB_OFFSET = 0x0000000000040000,
|
||||||
|
};
|
||||||
|
|
||||||
class MemoryBase
|
class MemoryBase
|
||||||
{
|
{
|
||||||
NullMemoryBlock NullMem;
|
void* m_base_addr;
|
||||||
|
std::vector<MemoryBlock*> MemoryBlocks;
|
||||||
|
u32 m_pages[0x100000000 / 4096]; // information about every page
|
||||||
|
std::recursive_mutex m_mutex;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::vector<MemoryBlock*> MemoryBlocks;
|
|
||||||
MemoryBlock* UserMemory;
|
MemoryBlock* UserMemory;
|
||||||
|
|
||||||
DynamicMemoryBlock MainMem;
|
DynamicMemoryBlock MainMem;
|
||||||
|
@ -28,8 +43,7 @@ public:
|
||||||
DynamicMemoryBlock MmaperMem;
|
DynamicMemoryBlock MmaperMem;
|
||||||
DynamicMemoryBlock RSXFBMem;
|
DynamicMemoryBlock RSXFBMem;
|
||||||
DynamicMemoryBlock StackMem;
|
DynamicMemoryBlock StackMem;
|
||||||
MemoryBlock SpuRawMem;
|
MemoryBlock* RawSPUMem[(0x100000000 - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET];
|
||||||
MemoryBlock SpuThrMem;
|
|
||||||
VirtualMemoryBlock RSXIOMem;
|
VirtualMemoryBlock RSXIOMem;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
|
@ -59,38 +73,64 @@ public:
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* GetBaseAddr() const
|
||||||
|
{
|
||||||
|
return m_base_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterPages(u64 addr, u32 size)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||||
|
|
||||||
|
//LOG_NOTICE(MEMORY, "RegisterPages(addr=0x%llx, size=0x%x)", addr, size);
|
||||||
|
for (u32 i = addr / 4096; i < (addr + size) / 4096; i++)
|
||||||
|
{
|
||||||
|
if (i >= sizeof(m_pages) / sizeof(m_pages[0])) break;
|
||||||
|
if (m_pages[i])
|
||||||
|
{
|
||||||
|
LOG_ERROR(MEMORY, "Page already registered (page=0x%x)", i * 4096);
|
||||||
|
}
|
||||||
|
m_pages[i] = 1; // TODO: define page parameters
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnregisterPages(u64 addr, u32 size)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||||
|
|
||||||
|
//LOG_NOTICE(MEMORY, "UnregisterPages(addr=0x%llx, size=0x%x)", addr, size);
|
||||||
|
for (u32 i = addr / 4096; i < (addr + size) / 4096; i++)
|
||||||
|
{
|
||||||
|
if (i >= sizeof(m_pages) / sizeof(m_pages[0])) break;
|
||||||
|
if (!m_pages[i])
|
||||||
|
{
|
||||||
|
LOG_ERROR(MEMORY, "Page not registered (page=0x%x)", i * 4096);
|
||||||
|
}
|
||||||
|
m_pages[i] = 0; // TODO: define page parameters
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static __forceinline u16 Reverse16(const u16 val)
|
static __forceinline u16 Reverse16(const u16 val)
|
||||||
{
|
{
|
||||||
return _byteswap_ushort(val);
|
return _byteswap_ushort(val);
|
||||||
//return ((val >> 8) & 0xff) | ((val << 8) & 0xff00);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static __forceinline u32 Reverse32(const u32 val)
|
static __forceinline u32 Reverse32(const u32 val)
|
||||||
{
|
{
|
||||||
return _byteswap_ulong(val);
|
return _byteswap_ulong(val);
|
||||||
/*
|
|
||||||
return
|
|
||||||
((val >> 24) & 0x000000ff) |
|
|
||||||
((val >> 8) & 0x0000ff00) |
|
|
||||||
((val << 8) & 0x00ff0000) |
|
|
||||||
((val << 24) & 0xff000000);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static __forceinline u64 Reverse64(const u64 val)
|
static __forceinline u64 Reverse64(const u64 val)
|
||||||
{
|
{
|
||||||
return _byteswap_uint64(val);
|
return _byteswap_uint64(val);
|
||||||
/*
|
}
|
||||||
return
|
|
||||||
((val >> 56) & 0x00000000000000ff) |
|
static __forceinline u128 Reverse128(const u128 val)
|
||||||
((val >> 40) & 0x000000000000ff00) |
|
{
|
||||||
((val >> 24) & 0x0000000000ff0000) |
|
u128 ret;
|
||||||
((val >> 8) & 0x00000000ff000000) |
|
ret.lo = _byteswap_uint64(val.hi);
|
||||||
((val << 8) & 0x000000ff00000000) |
|
ret.hi = _byteswap_uint64(val.lo);
|
||||||
((val << 24) & 0x0000ff0000000000) |
|
return ret;
|
||||||
((val << 40) & 0x00ff000000000000) |
|
|
||||||
((val << 56) & 0xff00000000000000);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int size> static __forceinline u64 ReverseData(u64 val);
|
template<int size> static __forceinline u64 ReverseData(u64 val);
|
||||||
|
@ -100,81 +140,9 @@ public:
|
||||||
return (T)ReverseData<sizeof(T)>(val);
|
return (T)ReverseData<sizeof(T)>(val);
|
||||||
};
|
};
|
||||||
|
|
||||||
MemoryBlock& GetMemByNum(const u8 num)
|
|
||||||
{
|
|
||||||
if(num >= MemoryBlocks.size()) return NullMem;
|
|
||||||
return *MemoryBlocks[num];
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryBlock& GetMemByAddr(const u64 addr)
|
|
||||||
{
|
|
||||||
for (auto block : MemoryBlocks)
|
|
||||||
{
|
|
||||||
if (block->IsMyAddress(addr))
|
|
||||||
return *block;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NullMem;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Read8ByAddr(const u64 addr, u8 *value)
|
|
||||||
{
|
|
||||||
for (auto block : MemoryBlocks)
|
|
||||||
{
|
|
||||||
if (block->Read8(addr, value))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NullMem.Read8(addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Read16ByAddr(const u64 addr, u16 *value)
|
|
||||||
{
|
|
||||||
for (auto block : MemoryBlocks)
|
|
||||||
{
|
|
||||||
if (block->Read16(addr, value))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NullMem.Read16(addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Read32ByAddr(const u64 addr, u32 *value)
|
|
||||||
{
|
|
||||||
for (auto block : MemoryBlocks)
|
|
||||||
{
|
|
||||||
if (block->Read32(addr, value))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NullMem.Read32(addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Read64ByAddr(const u64 addr, u64 *value)
|
|
||||||
{
|
|
||||||
for (auto block : MemoryBlocks)
|
|
||||||
{
|
|
||||||
if (block->Read64(addr, value))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NullMem.Read64(addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Read128ByAddr(const u64 addr, u128 *value)
|
|
||||||
{
|
|
||||||
for (auto block : MemoryBlocks)
|
|
||||||
{
|
|
||||||
if (block->Read128(addr, value))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NullMem.Read128(addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
u8* GetMemFromAddr(const u64 addr)
|
u8* GetMemFromAddr(const u64 addr)
|
||||||
{
|
{
|
||||||
return GetMemByAddr(addr).GetMemFromAddr(addr);
|
return (u8*)GetBaseAddr() + addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* VirtualToRealAddr(const u64 vaddr)
|
void* VirtualToRealAddr(const u64 vaddr)
|
||||||
|
@ -184,36 +152,68 @@ public:
|
||||||
|
|
||||||
u64 RealToVirtualAddr(const void* addr)
|
u64 RealToVirtualAddr(const void* addr)
|
||||||
{
|
{
|
||||||
const u64 raddr = (u64)addr;
|
const u64 res = (u64)addr - (u64)GetBaseAddr();
|
||||||
for (auto block : MemoryBlocks)
|
|
||||||
{
|
|
||||||
MemoryBlock& b = *block;
|
|
||||||
const u64 baddr = (u64)b.GetMem();
|
|
||||||
|
|
||||||
if(raddr >= baddr && raddr < baddr + b.GetSize())
|
if (res < 0x100000000)
|
||||||
{
|
{
|
||||||
return b.GetStartAddr() + (raddr - baddr);
|
return res;
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool InitSpuRawMem(const u32 max_spu_raw)
|
void InitRawSPU(MemoryBlock* raw_spu, const u32 num)
|
||||||
{
|
{
|
||||||
//if(SpuRawMem.GetSize()) return false;
|
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||||
|
|
||||||
MemoryBlocks.push_back(SpuRawMem.SetRange(0xe0000000, 0x100000 * max_spu_raw));
|
MemoryBlocks.push_back(raw_spu);
|
||||||
|
if (num < sizeof(RawSPUMem) / sizeof(RawSPUMem[0])) RawSPUMem[num] = raw_spu;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
void CloseRawSPU(MemoryBlock* raw_spu, const u32 num)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||||
|
|
||||||
|
for (int i = 0; i < MemoryBlocks.size(); ++i)
|
||||||
|
{
|
||||||
|
if (MemoryBlocks[i] == raw_spu)
|
||||||
|
{
|
||||||
|
MemoryBlocks.erase(MemoryBlocks.begin() + i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (num < sizeof(RawSPUMem) / sizeof(RawSPUMem[0])) RawSPUMem[num] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init(MemoryType type)
|
void Init(MemoryType type)
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||||
|
|
||||||
if(m_inited) return;
|
if(m_inited) return;
|
||||||
m_inited = true;
|
m_inited = true;
|
||||||
|
|
||||||
LOG_NOTICE(MEMORY, "Initing memory...");
|
memset(m_pages, 0, sizeof(m_pages));
|
||||||
|
memset(RawSPUMem, 0, sizeof(RawSPUMem));
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
m_base_addr = VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS);
|
||||||
|
if (!m_base_addr)
|
||||||
|
#else
|
||||||
|
m_base_addr = ::mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
|
||||||
|
if (m_base_addr == (void*)-1)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
m_base_addr = nullptr;
|
||||||
|
LOG_ERROR(MEMORY, "Initing memory failed");
|
||||||
|
assert(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_NOTICE(MEMORY, "Initing memory: m_base_addr = 0x%llx", (u64)m_base_addr);
|
||||||
|
}
|
||||||
|
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
|
@ -224,8 +224,6 @@ public:
|
||||||
MemoryBlocks.push_back(MmaperMem.SetRange(0xB0000000, 0x10000000));
|
MemoryBlocks.push_back(MmaperMem.SetRange(0xB0000000, 0x10000000));
|
||||||
MemoryBlocks.push_back(RSXFBMem.SetRange(0xC0000000, 0x10000000));
|
MemoryBlocks.push_back(RSXFBMem.SetRange(0xC0000000, 0x10000000));
|
||||||
MemoryBlocks.push_back(StackMem.SetRange(0xD0000000, 0x10000000));
|
MemoryBlocks.push_back(StackMem.SetRange(0xD0000000, 0x10000000));
|
||||||
//MemoryBlocks.push_back(SpuRawMem.SetRange(0xE0000000, 0x10000000));
|
|
||||||
//MemoryBlocks.push_back(SpuThrMem.SetRange(0xF0000000, 0x10000000));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Memory_PSV:
|
case Memory_PSV:
|
||||||
|
@ -247,29 +245,36 @@ public:
|
||||||
|
|
||||||
bool IsGoodAddr(const u64 addr)
|
bool IsGoodAddr(const u64 addr)
|
||||||
{
|
{
|
||||||
for (auto block : MemoryBlocks)
|
if (addr >= 0x100000000 || !m_pages[addr / 4096]) // TODO: define page parameters
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (block->IsMyAddress(addr))
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsGoodAddr(const u64 addr, const u32 size)
|
bool IsGoodAddr(const u64 addr, const u32 size)
|
||||||
{
|
{
|
||||||
const u64 end = addr + size - 1;
|
if (addr + size > 0x100000000)
|
||||||
for (auto block : MemoryBlocks)
|
|
||||||
{
|
{
|
||||||
if (block->IsMyAddress(addr) && block->IsMyAddress(end))
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (u32 i = addr / 4096; i <= (addr + size - 1) / 4096; i++)
|
||||||
|
{
|
||||||
|
if (!m_pages[i]) return false; // TODO: define page parameters
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Close()
|
void Close()
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||||
|
|
||||||
if(!m_inited) return;
|
if(!m_inited) return;
|
||||||
m_inited = false;
|
m_inited = false;
|
||||||
|
|
||||||
|
@ -281,6 +286,18 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryBlocks.clear();
|
MemoryBlocks.clear();
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (!VirtualFree(m_base_addr, 0, MEM_RELEASE))
|
||||||
|
{
|
||||||
|
LOG_ERROR(MEMORY, "VirtualFree(0x%llx) failed", (u64)m_base_addr);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (::munmap(m_base_addr, 0x100000000))
|
||||||
|
{
|
||||||
|
LOG_ERROR(MEMORY, "::munmap(0x%llx) failed", (u64)m_base_addr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write8(const u64 addr, const u8 data);
|
void Write8(const u64 addr, const u8 data);
|
||||||
|
@ -301,156 +318,51 @@ public:
|
||||||
u64 Read64(const u64 addr);
|
u64 Read64(const u64 addr);
|
||||||
u128 Read128(const u64 addr);
|
u128 Read128(const u64 addr);
|
||||||
|
|
||||||
bool CopyToReal(void* real, u32 from, u32 count) // (4K pages) copy from virtual to real memory
|
bool CopyToReal(void* real, u64 from, u32 count)
|
||||||
{
|
{
|
||||||
if (!count) return true;
|
if (!IsGoodAddr(from, count)) return false;
|
||||||
|
|
||||||
u8* to = (u8*)real;
|
memcpy(real, GetMemFromAddr(from), count);
|
||||||
|
|
||||||
if (u32 frag = from & 4095)
|
|
||||||
{
|
|
||||||
if (!IsGoodAddr(from)) return false;
|
|
||||||
u32 num = 4096 - frag;
|
|
||||||
if (count < num) num = count;
|
|
||||||
memcpy(to, GetMemFromAddr(from), num);
|
|
||||||
to += num;
|
|
||||||
from += num;
|
|
||||||
count -= num;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 page = count / 4096; page > 0; page--)
|
|
||||||
{
|
|
||||||
if (!IsGoodAddr(from)) return false;
|
|
||||||
memcpy(to, GetMemFromAddr(from), 4096);
|
|
||||||
to += 4096;
|
|
||||||
from += 4096;
|
|
||||||
count -= 4096;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count)
|
|
||||||
{
|
|
||||||
if (!IsGoodAddr(from)) return false;
|
|
||||||
memcpy(to, GetMemFromAddr(from), count);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CopyFromReal(u32 to, const void* real, u32 count) // (4K pages) copy from real to virtual memory
|
bool CopyFromReal(u64 to, const void* real, u32 count)
|
||||||
{
|
{
|
||||||
if (!count) return true;
|
if (!IsGoodAddr(to, count)) return false;
|
||||||
|
|
||||||
const u8* from = (const u8*)real;
|
memcpy(GetMemFromAddr(to), real, count);
|
||||||
|
|
||||||
if (u32 frag = to & 4095)
|
|
||||||
{
|
|
||||||
if (!IsGoodAddr(to)) return false;
|
|
||||||
u32 num = 4096 - frag;
|
|
||||||
if (count < num) num = count;
|
|
||||||
memcpy(GetMemFromAddr(to), from, num);
|
|
||||||
to += num;
|
|
||||||
from += num;
|
|
||||||
count -= num;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 page = count / 4096; page > 0; page--)
|
|
||||||
{
|
|
||||||
if (!IsGoodAddr(to)) return false;
|
|
||||||
memcpy(GetMemFromAddr(to), from, 4096);
|
|
||||||
to += 4096;
|
|
||||||
from += 4096;
|
|
||||||
count -= 4096;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count)
|
|
||||||
{
|
|
||||||
if (!IsGoodAddr(to)) return false;
|
|
||||||
memcpy(GetMemFromAddr(to), from, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Copy(u32 to, u32 from, u32 count) // (4K pages) copy from virtual to virtual memory through real
|
bool Copy(u64 to, u64 from, u32 count)
|
||||||
{
|
{
|
||||||
if (u8* buf = (u8*)malloc(count))
|
if (!IsGoodAddr(to, count) || !IsGoodAddr(from, count)) return false;
|
||||||
{
|
|
||||||
if (CopyToReal(buf, from, count))
|
memmove(GetMemFromAddr(to), GetMemFromAddr(from), count);
|
||||||
{
|
|
||||||
if (CopyFromReal(to, buf, count))
|
|
||||||
{
|
|
||||||
free(buf);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
free(buf);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
free(buf);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReadLeft(u8* dst, const u64 addr, const u32 size)
|
void ReadLeft(u8* dst, const u64 addr, const u32 size)
|
||||||
{
|
{
|
||||||
MemoryBlock& mem = GetMemByAddr(addr);
|
for (u32 i = 0; i < size; ++i) dst[size - 1 - i] = Read8(addr + i);
|
||||||
|
|
||||||
if(mem.IsNULL())
|
|
||||||
{
|
|
||||||
LOG_ERROR(MEMORY, "ReadLeft[%d] from null block (0x%llx)", size, addr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(u32 i=0; i<size; ++i) mem.Read8(addr + i, dst + size - 1 - i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteLeft(const u64 addr, const u32 size, const u8* src)
|
void WriteLeft(const u64 addr, const u32 size, const u8* src)
|
||||||
{
|
{
|
||||||
MemoryBlock& mem = GetMemByAddr(addr);
|
for (u32 i = 0; i < size; ++i) Write8(addr + i, src[size - 1 - i]);
|
||||||
|
|
||||||
if(mem.IsNULL())
|
|
||||||
{
|
|
||||||
LOG_ERROR(MEMORY, "WriteLeft[%d] to null block (0x%llx)", size, addr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(u32 i=0; i<size; ++i) mem.Write8(addr + i, src[size - 1 - i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadRight(u8* dst, const u64 addr, const u32 size)
|
void ReadRight(u8* dst, const u64 addr, const u32 size)
|
||||||
{
|
{
|
||||||
MemoryBlock& mem = GetMemByAddr(addr);
|
for (u32 i = 0; i < size; ++i) dst[i] = Read8(addr + (size - 1 - i));
|
||||||
|
|
||||||
if(mem.IsNULL())
|
|
||||||
{
|
|
||||||
LOG_ERROR(MEMORY, "ReadRight[%d] from null block (0x%llx)", size, addr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(u32 i=0; i<size; ++i) mem.Read8(addr + (size - 1 - i), dst + i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteRight(const u64 addr, const u32 size, const u8* src)
|
void WriteRight(const u64 addr, const u32 size, const u8* src)
|
||||||
{
|
{
|
||||||
MemoryBlock& mem = GetMemByAddr(addr);
|
for (u32 i = 0; i < size; ++i) Write8(addr + (size - 1 - i), src[i]);
|
||||||
|
|
||||||
if(mem.IsNULL())
|
|
||||||
{
|
|
||||||
LOG_ERROR(MEMORY, "WriteRight[%d] to null block (0x%llx)", size, addr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(u32 i=0; i<size; ++i) mem.Write8(addr + (size - 1 - i), src[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> void WriteData(const u64 addr, const T* data)
|
template<typename T> void WriteData(const u64 addr, const T* data)
|
||||||
|
@ -477,12 +389,6 @@ public:
|
||||||
|
|
||||||
void WriteString(const u64 addr, const std::string& str)
|
void WriteString(const u64 addr, const std::string& str)
|
||||||
{
|
{
|
||||||
if(!IsGoodAddr(addr, str.length()))
|
|
||||||
{
|
|
||||||
LOG_ERROR(MEMORY,"Memory::WriteString error: bad address (0x%llx)", addr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy((char*)GetMemFromAddr(addr), str.c_str());
|
strcpy((char*)GetMemFromAddr(addr), str.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -523,6 +429,8 @@ public:
|
||||||
|
|
||||||
bool Map(const u64 dst_addr, const u64 src_addr, const u32 size)
|
bool Map(const u64 dst_addr, const u64 src_addr, const u32 size)
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||||
|
|
||||||
if(IsGoodAddr(dst_addr) || !IsGoodAddr(src_addr))
|
if(IsGoodAddr(dst_addr) || !IsGoodAddr(src_addr))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -535,6 +443,8 @@ public:
|
||||||
|
|
||||||
bool Unmap(const u64 addr)
|
bool Unmap(const u64 addr)
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
for(uint i=0; i<MemoryBlocks.size(); ++i)
|
for(uint i=0; i<MemoryBlocks.size(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -554,8 +464,6 @@ public:
|
||||||
u8* operator + (const u64 vaddr)
|
u8* operator + (const u64 vaddr)
|
||||||
{
|
{
|
||||||
u8* ret = GetMemFromAddr(vaddr);
|
u8* ret = GetMemFromAddr(vaddr);
|
||||||
if(ret == nullptr)
|
|
||||||
throw fmt::Format("GetMemFromAddr(0x%x)", vaddr);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -869,7 +777,7 @@ public:
|
||||||
|
|
||||||
u32 AppendRawBytes(const u8 *bytes, size_t count)
|
u32 AppendRawBytes(const u8 *bytes, size_t count)
|
||||||
{
|
{
|
||||||
Memory.CopyFromReal(this->m_addr, bytes, count);
|
memmove(Memory + this->m_addr, bytes, count);
|
||||||
this->m_addr += count;
|
this->m_addr += count;
|
||||||
return this->m_addr;
|
return this->m_addr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -209,28 +209,26 @@ struct MemBlockInfo : public MemInfo
|
||||||
{
|
{
|
||||||
void *mem;
|
void *mem;
|
||||||
|
|
||||||
MemBlockInfo(u64 _addr, u32 _size)
|
MemBlockInfo(u64 _addr, u32 _size);
|
||||||
: MemInfo(_addr, PAGE_4K(_size))
|
|
||||||
, mem(_aligned_malloc(PAGE_4K(_size), 128))
|
void Free();
|
||||||
{
|
|
||||||
if(!mem)
|
|
||||||
{
|
|
||||||
LOG_ERROR(MEMORY, "Not enough free memory.");
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
memset(mem, 0, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
MemBlockInfo(MemBlockInfo &other) = delete;
|
MemBlockInfo(MemBlockInfo &other) = delete;
|
||||||
MemBlockInfo(MemBlockInfo &&other) : MemInfo(other.addr,other.size) ,mem(other.mem)
|
|
||||||
|
MemBlockInfo(MemBlockInfo &&other)
|
||||||
|
: MemInfo(other.addr,other.size)
|
||||||
|
, mem(other.mem)
|
||||||
{
|
{
|
||||||
other.mem = nullptr;
|
other.mem = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemBlockInfo& operator =(MemBlockInfo &other) = delete;
|
MemBlockInfo& operator =(MemBlockInfo &other) = delete;
|
||||||
MemBlockInfo& operator =(MemBlockInfo &&other){
|
|
||||||
|
MemBlockInfo& operator =(MemBlockInfo &&other)
|
||||||
|
{
|
||||||
|
this->Free();
|
||||||
this->addr = other.addr;
|
this->addr = other.addr;
|
||||||
this->size = other.size;
|
this->size = other.size;
|
||||||
if (this->mem) _aligned_free(mem);
|
|
||||||
this->mem = other.mem;
|
this->mem = other.mem;
|
||||||
other.mem = nullptr;
|
other.mem = nullptr;
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -238,7 +236,7 @@ struct MemBlockInfo : public MemInfo
|
||||||
|
|
||||||
~MemBlockInfo()
|
~MemBlockInfo()
|
||||||
{
|
{
|
||||||
if(mem) _aligned_free(mem);
|
Free();
|
||||||
mem = nullptr;
|
mem = nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -272,7 +270,9 @@ public:
|
||||||
virtual ~MemoryBlock();
|
virtual ~MemoryBlock();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
MemBlockInfo* mem_inf;
|
||||||
void Init();
|
void Init();
|
||||||
|
void Free();
|
||||||
void InitMemory();
|
void InitMemory();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -391,7 +391,6 @@ class DynamicMemoryBlockBase : public PT
|
||||||
mutable std::mutex m_lock;
|
mutable std::mutex m_lock;
|
||||||
std::vector<MemBlockInfo> m_allocated; // allocation info
|
std::vector<MemBlockInfo> m_allocated; // allocation info
|
||||||
std::vector<u8*> m_pages; // real addresses of every 4096 byte pages (array size should be fixed)
|
std::vector<u8*> m_pages; // real addresses of every 4096 byte pages (array size should be fixed)
|
||||||
std::vector<u8*> m_locked; // locked pages should be moved here
|
|
||||||
|
|
||||||
u32 m_max_size;
|
u32 m_max_size;
|
||||||
|
|
||||||
|
@ -472,6 +471,13 @@ public:
|
||||||
// return true for success
|
// return true for success
|
||||||
bool getRealAddr(u64 addr, u64& result);
|
bool getRealAddr(u64 addr, u64& result);
|
||||||
|
|
||||||
|
u64 RealAddr(u64 addr)
|
||||||
|
{
|
||||||
|
u64 realAddr = 0;
|
||||||
|
getRealAddr(addr, realAddr);
|
||||||
|
return realAddr;
|
||||||
|
}
|
||||||
|
|
||||||
// return the mapped address given a real address, if not mapped return 0
|
// return the mapped address given a real address, if not mapped return 0
|
||||||
u64 getMappedAddress(u64 realAddress);
|
u64 getMappedAddress(u64 realAddress);
|
||||||
};
|
};
|
||||||
|
|
|
@ -724,33 +724,11 @@ int cellAdecGetPcm(u32 handle, u32 outBuffer_addr)
|
||||||
|
|
||||||
if (!af.data) // fake: empty data
|
if (!af.data) // fake: empty data
|
||||||
{
|
{
|
||||||
/*u8* buf = (u8*)malloc(4096);
|
|
||||||
memset(buf, 0, 4096);
|
|
||||||
Memory.CopyFromReal(outBuffer_addr, buf, 4096);
|
|
||||||
free(buf);*/
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy data
|
// copy data
|
||||||
SwrContext* swr = nullptr;
|
|
||||||
|
|
||||||
/*swr = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_FLT, 48000,
|
|
||||||
frame->channel_layout, (AVSampleFormat)frame->format, frame->sample_rate, 0, NULL);
|
|
||||||
|
|
||||||
if (!swr)
|
|
||||||
{
|
|
||||||
LOG_ERROR(HLE, "cellAdecGetPcm(%d): swr_alloc_set_opts() failed", handle);
|
|
||||||
Emu.Pause();
|
|
||||||
free(out);
|
|
||||||
if (af.data)
|
|
||||||
{
|
|
||||||
av_frame_unref(af.data);
|
|
||||||
av_frame_free(&af.data);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}*/
|
|
||||||
u8* out = (u8*)malloc(af.size);
|
u8* out = (u8*)malloc(af.size);
|
||||||
// something is wrong
|
|
||||||
//swr_convert(swr, &out, frame->nb_samples, (const u8**)frame->extended_data, frame->nb_samples);
|
|
||||||
|
|
||||||
// reverse byte order, extract data:
|
// reverse byte order, extract data:
|
||||||
float* in_f[2];
|
float* in_f[2];
|
||||||
|
@ -770,7 +748,6 @@ int cellAdecGetPcm(u32 handle, u32 outBuffer_addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
free(out);
|
free(out);
|
||||||
if (swr) swr_free(&swr);
|
|
||||||
|
|
||||||
if (af.data)
|
if (af.data)
|
||||||
{
|
{
|
||||||
|
|
|
@ -315,17 +315,16 @@ int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress)
|
||||||
if (system_mode == CELL_GCM_SYSTEM_MODE_IOMAP_512MB)
|
if (system_mode == CELL_GCM_SYSTEM_MODE_IOMAP_512MB)
|
||||||
{
|
{
|
||||||
cellGcmSys->Warning("cellGcmInit(): 512MB io address space used");
|
cellGcmSys->Warning("cellGcmInit(): 512MB io address space used");
|
||||||
Memory.MemoryBlocks.push_back(Memory.RSXIOMem.SetRange(0x50000000, 0x20000000/*512MB*/));//TODO: implement allocateAdressSpace in memoryBase
|
Memory.RSXIOMem.SetRange(0x50000000, 0x20000000 /*512MB*/);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cellGcmSys->Warning("cellGcmInit(): 256MB io address space used");
|
cellGcmSys->Warning("cellGcmInit(): 256MB io address space used");
|
||||||
Memory.MemoryBlocks.push_back(Memory.RSXIOMem.SetRange(0x50000000, 0x10000000/*256MB*/));//TODO: implement allocateAdressSpace in memoryBase
|
Memory.RSXIOMem.SetRange(0x50000000, 0x10000000 /*256MB*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cellGcmMapEaIoAddress(ioAddress, 0, ioSize) != CELL_OK)
|
if(cellGcmMapEaIoAddress(ioAddress, 0, ioSize) != CELL_OK)
|
||||||
{
|
{
|
||||||
Memory.MemoryBlocks.pop_back();
|
|
||||||
cellGcmSys->Error("cellGcmInit : CELL_GCM_ERROR_FAILURE");
|
cellGcmSys->Error("cellGcmInit : CELL_GCM_ERROR_FAILURE");
|
||||||
return CELL_GCM_ERROR_FAILURE;
|
return CELL_GCM_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -495,7 +494,12 @@ int cellGcmSetPrepareFlip(mem_ptr_t<CellGcmContextData> ctxt, u32 id)
|
||||||
|
|
||||||
const s32 res = ctxt->current - ctxt->begin - ctrl.put;
|
const s32 res = ctxt->current - ctxt->begin - ctrl.put;
|
||||||
|
|
||||||
if(res > 0) Memory.Copy(ctxt->begin, ctxt->current - res, res);
|
if (res > 0 && !Memory.Copy(ctxt->begin, ctxt->current - res, res))
|
||||||
|
{
|
||||||
|
cellGcmSys->Error("cellGcmSetPrepareFlip(): Memory.Copy(0x%x, 0x%x, 0x%x) failed", (u32)ctxt->begin, (u32)ctxt->current - res, res);
|
||||||
|
Emu.Pause();
|
||||||
|
return CELL_EFAULT;
|
||||||
|
}
|
||||||
ctxt->current = ctxt->begin + res;
|
ctxt->current = ctxt->begin + res;
|
||||||
|
|
||||||
//InterlockedExchange64((volatile long long*)((u8*)&ctrl + offsetof(CellGcmControl, put)), (u64)(u32)re(res));
|
//InterlockedExchange64((volatile long long*)((u8*)&ctrl + offsetof(CellGcmControl, put)), (u64)(u32)re(res));
|
||||||
|
@ -1161,7 +1165,12 @@ int cellGcmCallback(u32 context_addr, u32 count)
|
||||||
|
|
||||||
const s32 res = ctx.current - ctx.begin - ctrl.put;
|
const s32 res = ctx.current - ctx.begin - ctrl.put;
|
||||||
|
|
||||||
if(res > 0) Memory.Copy(ctx.begin, ctx.current - res, res);
|
if (res > 0 && !Memory.Copy(ctx.begin, ctx.current - res, res))
|
||||||
|
{
|
||||||
|
cellGcmSys->Error("cellGcmCallback(): Memory.Copy(0x%x, 0x%x, 0x%x) failed", (u32)ctx.begin, (u32)ctx.current - res, res);
|
||||||
|
Emu.Pause();
|
||||||
|
return CELL_EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
ctx.current = ctx.begin + res;
|
ctx.current = ctx.begin + res;
|
||||||
|
|
||||||
|
|
|
@ -182,7 +182,11 @@ int cellGifDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, const m
|
||||||
switch((u32)current_outParam.outputColorSpace)
|
switch((u32)current_outParam.outputColorSpace)
|
||||||
{
|
{
|
||||||
case CELL_GIFDEC_RGBA:
|
case CELL_GIFDEC_RGBA:
|
||||||
Memory.CopyFromReal(data.GetAddr(), image.get(), image_size);
|
if (!Memory.CopyFromReal(data.GetAddr(), image.get(), image_size))
|
||||||
|
{
|
||||||
|
cellGifDec->Error("cellGifDecDecodeData() failed (dataa_addr=0x%x)", data.GetAddr());
|
||||||
|
return CELL_EFAULT;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CELL_GIFDEC_ARGB:
|
case CELL_GIFDEC_ARGB:
|
||||||
|
|
|
@ -164,7 +164,11 @@ int cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, const m
|
||||||
case CELL_JPG_RGBA:
|
case CELL_JPG_RGBA:
|
||||||
case CELL_JPG_RGB:
|
case CELL_JPG_RGB:
|
||||||
image_size *= current_outParam.outputColorSpace == CELL_JPG_RGBA ? 4 : 3;
|
image_size *= current_outParam.outputColorSpace == CELL_JPG_RGBA ? 4 : 3;
|
||||||
Memory.CopyFromReal(data.GetAddr(), image.get(), image_size);
|
if (!Memory.CopyFromReal(data.GetAddr(), image.get(), image_size))
|
||||||
|
{
|
||||||
|
cellJpgDec->Error("cellJpgDecDecodeData() failed (data_addr=0x%x)", data.GetAddr());
|
||||||
|
return CELL_EFAULT;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CELL_JPG_ARGB:
|
case CELL_JPG_ARGB:
|
||||||
|
|
|
@ -148,7 +148,11 @@ int cellPngDecReadHeader(u32 mainHandle, u32 subHandle, mem_ptr_t<CellPngDecInfo
|
||||||
switch(subHandle_data->src.srcSelect.ToBE())
|
switch(subHandle_data->src.srcSelect.ToBE())
|
||||||
{
|
{
|
||||||
case se32(CELL_PNGDEC_BUFFER):
|
case se32(CELL_PNGDEC_BUFFER):
|
||||||
Memory.Copy(buffer.GetAddr(), subHandle_data->src.streamPtr.ToLE(), buffer.GetSize());
|
if (!Memory.Copy(buffer.GetAddr(), subHandle_data->src.streamPtr.ToLE(), buffer.GetSize()))
|
||||||
|
{
|
||||||
|
cellPngDec->Error("cellPngDecReadHeader() failed ()");
|
||||||
|
return CELL_EFAULT;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case se32(CELL_PNGDEC_FILE):
|
case se32(CELL_PNGDEC_FILE):
|
||||||
cellFsLseek(fd, 0, CELL_SEEK_SET, pos.GetAddr());
|
cellFsLseek(fd, 0, CELL_SEEK_SET, pos.GetAddr());
|
||||||
|
@ -213,7 +217,11 @@ int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, const m
|
||||||
switch(subHandle_data->src.srcSelect.ToLE())
|
switch(subHandle_data->src.srcSelect.ToLE())
|
||||||
{
|
{
|
||||||
case CELL_PNGDEC_BUFFER:
|
case CELL_PNGDEC_BUFFER:
|
||||||
Memory.Copy(png.GetAddr(), subHandle_data->src.streamPtr.ToLE(), png.GetSize());
|
if (!Memory.Copy(png.GetAddr(), subHandle_data->src.streamPtr.ToLE(), png.GetSize()))
|
||||||
|
{
|
||||||
|
cellPngDec->Error("cellPngDecDecodeData() failed (I)");
|
||||||
|
return CELL_EFAULT;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CELL_PNGDEC_FILE:
|
case CELL_PNGDEC_FILE:
|
||||||
cellFsLseek(fd, 0, CELL_SEEK_SET, pos.GetAddr());
|
cellFsLseek(fd, 0, CELL_SEEK_SET, pos.GetAddr());
|
||||||
|
@ -249,12 +257,20 @@ int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, const m
|
||||||
{
|
{
|
||||||
const int dstOffset = i * bytesPerLine;
|
const int dstOffset = i * bytesPerLine;
|
||||||
const int srcOffset = width * nComponents * (flip ? height - i - 1 : i);
|
const int srcOffset = width * nComponents * (flip ? height - i - 1 : i);
|
||||||
Memory.CopyFromReal(data.GetAddr() + dstOffset, &image.get()[srcOffset], linesize);
|
if (!Memory.CopyFromReal(data.GetAddr() + dstOffset, &image.get()[srcOffset], linesize))
|
||||||
|
{
|
||||||
|
cellPngDec->Error("cellPngDecDecodeData() failed (II)");
|
||||||
|
return CELL_EFAULT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Memory.CopyFromReal(data.GetAddr(), image.get(), image_size);
|
if (!Memory.CopyFromReal(data.GetAddr(), image.get(), image_size))
|
||||||
|
{
|
||||||
|
cellPngDec->Error("cellPngDecDecodeData() failed (III)");
|
||||||
|
return CELL_EFAULT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -279,7 +295,11 @@ int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, const m
|
||||||
output[j + 2] = image.get()[srcOffset + j + 1];
|
output[j + 2] = image.get()[srcOffset + j + 1];
|
||||||
output[j + 3] = image.get()[srcOffset + j + 2];
|
output[j + 3] = image.get()[srcOffset + j + 2];
|
||||||
}
|
}
|
||||||
Memory.CopyFromReal(data.GetAddr() + dstOffset, output, linesize);
|
if (!Memory.CopyFromReal(data.GetAddr() + dstOffset, output, linesize))
|
||||||
|
{
|
||||||
|
cellPngDec->Error("cellPngDecDecodeData() failed (IV)");
|
||||||
|
return CELL_EFAULT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free(output);
|
free(output);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1135,7 +1135,7 @@ int cellRescSetBufferAddress(mem32_t colorBuffers, mem32_t vertexArray, mem32_t
|
||||||
|
|
||||||
if(colorBuffers.GetAddr() % COLOR_BUFFER_ALIGNMENT || vertexArray.GetAddr() % VERTEX_BUFFER_ALIGNMENT || fragmentShader.GetAddr() % FRAGMENT_SHADER_ALIGNMENT)
|
if(colorBuffers.GetAddr() % COLOR_BUFFER_ALIGNMENT || vertexArray.GetAddr() % VERTEX_BUFFER_ALIGNMENT || fragmentShader.GetAddr() % FRAGMENT_SHADER_ALIGNMENT)
|
||||||
{
|
{
|
||||||
cellResc->Error("cellRescSetBufferAddress : CELL_RESC_ERROR_BAD_ARGUMENT");
|
cellResc->Error("cellRescSetBufferAddress : CELL_RESC_ERROR_BAD_ARGUMENT (alignment)");
|
||||||
return CELL_RESC_ERROR_BAD_ARGUMENT;
|
return CELL_RESC_ERROR_BAD_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -335,9 +335,6 @@ int cellVideoOutGetResolutionAvailability(u32 videoOut, u32 resolutionId, u32 as
|
||||||
return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT;
|
return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern std::atomic<u32> g_FsAioReadID;
|
|
||||||
extern std::atomic<u32> g_FsAioReadCur;
|
|
||||||
|
|
||||||
int cellSysutilCheckCallback()
|
int cellSysutilCheckCallback()
|
||||||
{
|
{
|
||||||
cellSysutil->Log("cellSysutilCheckCallback()");
|
cellSysutil->Log("cellSysutilCheckCallback()");
|
||||||
|
@ -346,7 +343,7 @@ int cellSysutilCheckCallback()
|
||||||
|
|
||||||
CPUThread& thr = Emu.GetCallbackThread();
|
CPUThread& thr = Emu.GetCallbackThread();
|
||||||
|
|
||||||
while (thr.IsAlive() || (g_FsAioReadCur < g_FsAioReadID))
|
while (thr.IsAlive())
|
||||||
{
|
{
|
||||||
Sleep(1);
|
Sleep(1);
|
||||||
if (Emu.IsStopped())
|
if (Emu.IsStopped())
|
||||||
|
|
|
@ -361,7 +361,7 @@ int cellSurMixerCreate(const mem_ptr_t<CellSurMixerConfig> config)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mixcount > (port.tag + 15)) // preemptive buffer filling (probably hack)
|
if (mixcount > (port.tag + 14)) // preemptive buffer filling (probably hack)
|
||||||
{
|
{
|
||||||
Sleep(1);
|
Sleep(1);
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -168,9 +168,12 @@ int sys_raw_spu_image_load(int id, mem_ptr_t<sys_spu_image> img)
|
||||||
{
|
{
|
||||||
sysPrxForUser->Warning("sys_raw_spu_image_load(id=0x%x, img_addr=0x%x)", id, img.GetAddr());
|
sysPrxForUser->Warning("sys_raw_spu_image_load(id=0x%x, img_addr=0x%x)", id, img.GetAddr());
|
||||||
|
|
||||||
Memory.Copy(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id, (u32)img->segs_addr, 256 * 1024);
|
if (!Memory.Copy(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id, (u32)img->segs_addr, 256 * 1024))
|
||||||
Memory.Write32(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id + RAW_SPU_PROB_OFFSET + SPU_NPC_offs,
|
{
|
||||||
(u32)img->entry_point);
|
sysPrxForUser->Error("sys_raw_spu_image_load() failed");
|
||||||
|
return CELL_EFAULT;
|
||||||
|
}
|
||||||
|
Memory.Write32(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id + RAW_SPU_PROB_OFFSET + SPU_NPC_offs, (u32)img->entry_point);
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,56 +162,28 @@ void fsAioRead(u32 fd, mem_ptr_t<CellFsAio> aio, int xid, mem_func_ptr_t<void (*
|
||||||
u64 nbytes = aio->size;
|
u64 nbytes = aio->size;
|
||||||
u32 buf_addr = aio->buf_addr;
|
u32 buf_addr = aio->buf_addr;
|
||||||
|
|
||||||
u32 res = 0;
|
|
||||||
u32 error = CELL_OK;
|
u32 error = CELL_OK;
|
||||||
|
|
||||||
vfsStream& file = *(vfsStream*)orig_file;
|
vfsStream& file = *(vfsStream*)orig_file;
|
||||||
const u64 old_pos = file.Tell();
|
const u64 old_pos = file.Tell();
|
||||||
file.Seek((u64)aio->offset);
|
file.Seek((u64)aio->offset);
|
||||||
|
|
||||||
u32 count = nbytes;
|
// TODO: use code from cellFsRead or something
|
||||||
if (nbytes != (u64)count)
|
|
||||||
|
u64 res = 0;
|
||||||
|
if (nbytes != (u32)nbytes)
|
||||||
{
|
{
|
||||||
error = CELL_ENOMEM;
|
error = CELL_ENOMEM;
|
||||||
goto fin;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (!Memory.IsGoodAddr(buf_addr))
|
|
||||||
{
|
{
|
||||||
error = CELL_EFAULT;
|
res = nbytes ? file.Read(Memory.GetMemFromAddr(buf_addr), nbytes) : 0;
|
||||||
goto fin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count) if (u32 frag = buf_addr & 4095) // memory page fragment
|
|
||||||
{
|
|
||||||
u32 req = std::min(count, 4096 - frag);
|
|
||||||
u32 read = file.Read(Memory + buf_addr, req);
|
|
||||||
buf_addr += req;
|
|
||||||
res += read;
|
|
||||||
count -= req;
|
|
||||||
if (read < req) goto fin;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 pages = count / 4096; pages > 0; pages--) // full pages
|
|
||||||
{
|
|
||||||
if (!Memory.IsGoodAddr(buf_addr)) goto fin; // ??? (probably EFAULT)
|
|
||||||
u32 read = file.Read(Memory + buf_addr, 4096);
|
|
||||||
buf_addr += 4096;
|
|
||||||
res += read;
|
|
||||||
count -= 4096;
|
|
||||||
if (read < 4096) goto fin;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count) // last fragment
|
|
||||||
{
|
|
||||||
if (!Memory.IsGoodAddr(buf_addr)) goto fin;
|
|
||||||
res += file.Read(Memory + buf_addr, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
fin:
|
|
||||||
file.Seek(old_pos);
|
file.Seek(old_pos);
|
||||||
|
|
||||||
LOG_WARNING(HLE, "*** fsAioRead(fd=%d, offset=0x%llx, buf_addr=0x%x, size=0x%x, error=0x%x, res=0x%x, xid=0x%x [%s])",
|
if (Ini.HLELogging.GetValue())
|
||||||
|
LOG_NOTICE(HLE, "*** fsAioRead(fd=%d, offset=0x%llx, buf_addr=0x%x, size=0x%x, error=0x%x, res=0x%x, xid=0x%x [%s])",
|
||||||
fd, (u64)aio->offset, buf_addr, (u64)aio->size, error, res, xid, orig_file->GetPath().c_str());
|
fd, (u64)aio->offset, buf_addr, (u64)aio->size, error, res, xid, orig_file->GetPath().c_str());
|
||||||
|
|
||||||
if (func) // start callback thread
|
if (func) // start callback thread
|
||||||
|
@ -219,17 +191,6 @@ fin:
|
||||||
func.async(aio, error, xid, res);
|
func.async(aio, error, xid, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*CPUThread& thr = Emu.GetCallbackThread();
|
|
||||||
while (thr.IsAlive())
|
|
||||||
{
|
|
||||||
Sleep(1);
|
|
||||||
if (Emu.IsStopped())
|
|
||||||
{
|
|
||||||
LOG_WARNING(HLE, "fsAioRead() aborted");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
g_FsAioReadCur++;
|
g_FsAioReadCur++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,41 +144,17 @@ s32 cellFsRead(u32 fd, u32 buf_addr, u64 nbytes, mem64_t nread)
|
||||||
vfsStream* file;
|
vfsStream* file;
|
||||||
if(!sys_fs->CheckId(fd, file)) return CELL_ESRCH;
|
if(!sys_fs->CheckId(fd, file)) return CELL_ESRCH;
|
||||||
|
|
||||||
if (nread.GetAddr() && !nread.IsGood()) return CELL_EFAULT;
|
if (nread.GetAddr() && !nread.IsGood())
|
||||||
|
|
||||||
u32 res = 0;
|
|
||||||
u32 count = nbytes;
|
|
||||||
if (nbytes != (u64)count) return CELL_ENOMEM;
|
|
||||||
|
|
||||||
if (!Memory.IsGoodAddr(buf_addr)) return CELL_EFAULT;
|
|
||||||
|
|
||||||
if (count) if (u32 frag = buf_addr & 4095) // memory page fragment
|
|
||||||
{
|
{
|
||||||
u32 req = std::min(count, 4096 - frag);
|
sys_fs->Error("cellFsRead(): bad nread_addr(0x%x)", nread.GetAddr());
|
||||||
u32 read = file->Read(Memory + buf_addr, req);
|
return CELL_EFAULT;
|
||||||
buf_addr += req;
|
|
||||||
res += read;
|
|
||||||
count -= req;
|
|
||||||
if (read < req) goto fin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u32 pages = count / 4096; pages > 0; pages--) // full pages
|
if (nbytes != (u32)nbytes) return CELL_ENOMEM;
|
||||||
{
|
|
||||||
if (!Memory.IsGoodAddr(buf_addr)) goto fin; // ??? (probably EFAULT)
|
|
||||||
u32 read = file->Read(Memory + buf_addr, 4096);
|
|
||||||
buf_addr += 4096;
|
|
||||||
res += read;
|
|
||||||
count -= 4096;
|
|
||||||
if (read < 4096) goto fin;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count) // last fragment
|
// TODO: checks
|
||||||
{
|
|
||||||
if (!Memory.IsGoodAddr(buf_addr)) goto fin;
|
|
||||||
res += file->Read(Memory + buf_addr, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
fin:
|
const u64 res = nbytes ? file->Read(Memory.GetMemFromAddr(buf_addr), nbytes) : 0;
|
||||||
|
|
||||||
if (nread.GetAddr()) nread = res; // write value if not NULL
|
if (nread.GetAddr()) nread = res; // write value if not NULL
|
||||||
|
|
||||||
|
@ -192,16 +168,15 @@ s32 cellFsWrite(u32 fd, u32 buf_addr, u64 nbytes, mem64_t nwrite)
|
||||||
vfsStream* file;
|
vfsStream* file;
|
||||||
if(!sys_fs->CheckId(fd, file)) return CELL_ESRCH;
|
if(!sys_fs->CheckId(fd, file)) return CELL_ESRCH;
|
||||||
|
|
||||||
if(Memory.IsGoodAddr(buf_addr) && !Memory.IsGoodAddr(buf_addr, nbytes))
|
if (nwrite.GetAddr() && !nwrite.IsGood()) return CELL_EFAULT;
|
||||||
{
|
|
||||||
MemoryBlock& block = Memory.GetMemByAddr(buf_addr);
|
if (nbytes != (u32)nbytes) return CELL_ENOMEM;
|
||||||
nbytes = block.GetSize() - (buf_addr - block.GetStartAddr());
|
|
||||||
}
|
// TODO: checks
|
||||||
|
|
||||||
const u64 res = nbytes ? file->Write(Memory.GetMemFromAddr(buf_addr), nbytes) : 0;
|
const u64 res = nbytes ? file->Write(Memory.GetMemFromAddr(buf_addr), nbytes) : 0;
|
||||||
|
|
||||||
if(nwrite.IsGood())
|
if (nwrite.GetAddr()) nwrite = res; // write value if not NULL
|
||||||
nwrite = res;
|
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@ enum cellFsStStatus
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(4)
|
#pragma pack(push, 4)
|
||||||
|
|
||||||
struct CellFsStat
|
struct CellFsStat
|
||||||
{
|
{
|
||||||
|
@ -98,7 +98,7 @@ struct CellFsDirent
|
||||||
char d_name[CELL_MAX_FS_FILE_NAME_LENGTH + 1];
|
char d_name[CELL_MAX_FS_FILE_NAME_LENGTH + 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack(pop)
|
||||||
|
|
||||||
struct CellFsAio
|
struct CellFsAio
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Emu/SysCalls/SysCalls.h"
|
#include "Emu/SysCalls/SysCalls.h"
|
||||||
#include "sys_process.h"
|
#include "sys_process.h"
|
||||||
|
#include "rpcs3.h"
|
||||||
|
|
||||||
SysCallBase sc_p("Process");
|
SysCallBase sc_p("Process");
|
||||||
|
|
||||||
|
@ -23,14 +24,16 @@ s32 sys_process_getppid()
|
||||||
s32 sys_process_exit(s32 errorcode)
|
s32 sys_process_exit(s32 errorcode)
|
||||||
{
|
{
|
||||||
sc_p.Warning("sys_process_exit(%d)", errorcode);
|
sc_p.Warning("sys_process_exit(%d)", errorcode);
|
||||||
Emu.Pause(); // Emu.Stop() does crash
|
Emu.Pause();
|
||||||
LOG_SUCCESS(HLE, "Process finished");
|
LOG_SUCCESS(HLE, "Process finished");
|
||||||
|
wxGetApp().CallAfter([]()
|
||||||
|
{
|
||||||
|
Emu.Stop();
|
||||||
if (Ini.HLEExitOnStop.GetValue())
|
if (Ini.HLEExitOnStop.GetValue())
|
||||||
{
|
{
|
||||||
Ini.HLEExitOnStop.SetValue(false);
|
wxGetApp().Exit();
|
||||||
// TODO: Find a way of calling Emu.Stop() and/or exiting RPCS3 (that is, TheApp->Exit()) without crashes
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,6 @@ struct sys_rwlock_attribute_t
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack()
|
|
||||||
|
|
||||||
struct RWLock
|
struct RWLock
|
||||||
{
|
{
|
||||||
std::mutex m_lock; // internal lock
|
std::mutex m_lock; // internal lock
|
||||||
|
|
|
@ -136,10 +136,14 @@ s32 sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t<
|
||||||
u64 a3 = arg->arg3;
|
u64 a3 = arg->arg3;
|
||||||
u64 a4 = arg->arg4;
|
u64 a4 = arg->arg4;
|
||||||
|
|
||||||
CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_SPU);
|
|
||||||
//copy SPU image:
|
//copy SPU image:
|
||||||
u32 spu_offset = Memory.MainMem.AllocAlign(256 * 1024);
|
auto spu_offset = Memory.MainMem.AllocAlign(256 * 1024);
|
||||||
Memory.CopyToReal(Memory + spu_offset, (u32)img->segs_addr, 256 * 1024);
|
if (!Memory.Copy(spu_offset, (u32)img->segs_addr, 256 * 1024))
|
||||||
|
{
|
||||||
|
return CELL_EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_SPU);
|
||||||
//initialize from new place:
|
//initialize from new place:
|
||||||
new_thread.SetOffset(spu_offset);
|
new_thread.SetOffset(spu_offset);
|
||||||
new_thread.SetEntry(spu_ep);
|
new_thread.SetEntry(spu_ep);
|
||||||
|
@ -391,14 +395,6 @@ s32 sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu)
|
||||||
return CELL_EINVAL;
|
return CELL_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if(!Memory.InitSpuRawMem(max_raw_spu))
|
|
||||||
//{
|
|
||||||
// return CELL_ENOMEM;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//Ini.HLELogging.SetValue(true);
|
|
||||||
//dump_enable = true;
|
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,7 +769,6 @@ s32 sys_raw_spu_create(mem32_t id, u32 attr_addr)
|
||||||
CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_RAW_SPU);
|
CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_RAW_SPU);
|
||||||
id = ((RawSPUThread&)new_thread).GetIndex();
|
id = ((RawSPUThread&)new_thread).GetIndex();
|
||||||
new_thread.Run();
|
new_thread.Run();
|
||||||
new_thread.Exec();
|
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,6 @@ struct timer
|
||||||
sys_timer_information_t timer_information_t;
|
sys_timer_information_t timer_information_t;
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack()
|
|
||||||
|
|
||||||
s32 sys_timer_create(mem32_t timer_id);
|
s32 sys_timer_create(mem32_t timer_id);
|
||||||
s32 sys_timer_destroy(u32 timer_id);
|
s32 sys_timer_destroy(u32 timer_id);
|
||||||
s32 sys_timer_get_information(u32 timer_id, mem_ptr_t<sys_timer_information_t> info);
|
s32 sys_timer_get_information(u32 timer_id, mem_ptr_t<sys_timer_information_t> info);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#pragma pack
|
#pragma once
|
||||||
|
|
||||||
#define SYS_VM_TEST_INVALID 0x0000ULL
|
#define SYS_VM_TEST_INVALID 0x0000ULL
|
||||||
#define SYS_VM_TEST_UNUSED 0x0001ULL
|
#define SYS_VM_TEST_UNUSED 0x0001ULL
|
||||||
|
|
|
@ -201,6 +201,10 @@ void Emulator::Load()
|
||||||
switch(l.GetMachine())
|
switch(l.GetMachine())
|
||||||
{
|
{
|
||||||
case MACHINE_SPU:
|
case MACHINE_SPU:
|
||||||
|
Memory.Init(Memory_PS3);
|
||||||
|
Memory.MainMem.AllocFixed(Memory.MainMem.GetStartAddr(), 0x40000);
|
||||||
|
break;
|
||||||
|
|
||||||
case MACHINE_PPC64:
|
case MACHINE_PPC64:
|
||||||
Memory.Init(Memory_PS3);
|
Memory.Init(Memory_PS3);
|
||||||
break;
|
break;
|
||||||
|
@ -263,7 +267,6 @@ void Emulator::Load()
|
||||||
LOG_NOTICE(LOADER, "offset = 0x%llx", Memory.MainMem.GetStartAddr());
|
LOG_NOTICE(LOADER, "offset = 0x%llx", Memory.MainMem.GetStartAddr());
|
||||||
LOG_NOTICE(LOADER, "max addr = 0x%x", l.GetMaxAddr());
|
LOG_NOTICE(LOADER, "max addr = 0x%x", l.GetMaxAddr());
|
||||||
thread.SetOffset(Memory.MainMem.GetStartAddr());
|
thread.SetOffset(Memory.MainMem.GetStartAddr());
|
||||||
Memory.MainMem.AllocFixed(Memory.MainMem.GetStartAddr() + l.GetMaxAddr(), 0xFFFFED - l.GetMaxAddr());
|
|
||||||
thread.SetEntry(l.GetEntry() - Memory.MainMem.GetStartAddr());
|
thread.SetEntry(l.GetEntry() - Memory.MainMem.GetStartAddr());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -236,7 +236,7 @@ bool ELF32Loader::LoadPhdrData(u64 _offset)
|
||||||
|
|
||||||
switch(machine)
|
switch(machine)
|
||||||
{
|
{
|
||||||
case MACHINE_SPU: Memory.MainMem.AllocFixed(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break;
|
case MACHINE_SPU: break;
|
||||||
case MACHINE_MIPS: Memory.PSPMemory.RAM.AllocFixed(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break;
|
case MACHINE_MIPS: Memory.PSPMemory.RAM.AllocFixed(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break;
|
||||||
case MACHINE_ARM: Memory.PSVMemory.RAM.AllocFixed(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break;
|
case MACHINE_ARM: Memory.PSVMemory.RAM.AllocFixed(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break;
|
||||||
|
|
||||||
|
|
|
@ -312,6 +312,7 @@
|
||||||
<ClInclude Include="Emu\Io\Windows\WindowsKeyboardHandler.h" />
|
<ClInclude Include="Emu\Io\Windows\WindowsKeyboardHandler.h" />
|
||||||
<ClInclude Include="Emu\Io\Windows\WindowsMouseHandler.h" />
|
<ClInclude Include="Emu\Io\Windows\WindowsMouseHandler.h" />
|
||||||
<ClInclude Include="Emu\Io\Windows\WindowsPadHandler.h" />
|
<ClInclude Include="Emu\Io\Windows\WindowsPadHandler.h" />
|
||||||
|
<ClInclude Include="Emu\Memory\DynamicMemoryBlockBase.h" />
|
||||||
<ClInclude Include="Emu\Memory\Memory.h" />
|
<ClInclude Include="Emu\Memory\Memory.h" />
|
||||||
<ClInclude Include="Emu\Memory\MemoryBlock.h" />
|
<ClInclude Include="Emu\Memory\MemoryBlock.h" />
|
||||||
<ClInclude Include="Emu\SysCalls\Callback.h" />
|
<ClInclude Include="Emu\SysCalls\Callback.h" />
|
||||||
|
@ -505,6 +506,7 @@
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
<PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
|
||||||
|
<ExceptionHandling>Async</ExceptionHandling>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
@ -518,6 +520,7 @@
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
<PreprocessorDefinitions>_UNICODE;UNICODE;MSVC_CRT_MEMLEAK_DETECTION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_UNICODE;UNICODE;MSVC_CRT_MEMLEAK_DETECTION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
|
||||||
|
<ExceptionHandling>Async</ExceptionHandling>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
@ -548,6 +551,7 @@
|
||||||
<SDLCheck>false</SDLCheck>
|
<SDLCheck>false</SDLCheck>
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
|
||||||
|
<ExceptionHandling>Async</ExceptionHandling>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
|
|
@ -1093,5 +1093,8 @@
|
||||||
<ClInclude Include="Emu\SysCalls\Modules\cellMsgDialog.h">
|
<ClInclude Include="Emu\SysCalls\Modules\cellMsgDialog.h">
|
||||||
<Filter>Emu\SysCalls\Modules</Filter>
|
<Filter>Emu\SysCalls\Modules</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Emu\Memory\DynamicMemoryBlockBase.h">
|
||||||
|
<Filter>Emu\Memory</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -81,6 +81,7 @@
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
<AdditionalIncludeDirectories>..\wxWidgets\include\msvc</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\wxWidgets\include\msvc</AdditionalIncludeDirectories>
|
||||||
|
<ExceptionHandling>Async</ExceptionHandling>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
@ -104,6 +105,7 @@
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
<AdditionalIncludeDirectories>..\wxWidgets\include\msvc</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\wxWidgets\include\msvc</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>_UNICODE;UNICODE;MSVC_CRT_MEMLEAK_DETECTION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_UNICODE;UNICODE;MSVC_CRT_MEMLEAK_DETECTION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ExceptionHandling>Async</ExceptionHandling>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
@ -131,7 +133,7 @@
|
||||||
<DisableLanguageExtensions>false</DisableLanguageExtensions>
|
<DisableLanguageExtensions>false</DisableLanguageExtensions>
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||||
<ExceptionHandling>Sync</ExceptionHandling>
|
<ExceptionHandling>Async</ExceptionHandling>
|
||||||
<EnablePREfast>false</EnablePREfast>
|
<EnablePREfast>false</EnablePREfast>
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue