diff --git a/Utilities/BEType.h b/Utilities/BEType.h index e87e62379a..8322b804f8 100644 --- a/Utilities/BEType.h +++ b/Utilities/BEType.h @@ -5,11 +5,10 @@ using std::min; using std::max; -//#define re(val) MemoryBase::Reverse(val) -#define re64(val) MemoryBase::Reverse64(val) -#define re32(val) MemoryBase::Reverse32(val) -#define re16(val) MemoryBase::Reverse16(val) -#define re128(val) MemoryBase::Reverse128(val) +#define re16(val) _byteswap_ushort(val) +#define re32(val) _byteswap_ulong(val) +#define re64(val) _byteswap_uint64(val) +#define re128(val) u128::byteswap(val) template struct se_t; template struct se_t { static __forceinline void func(T& dst, const T src) { (u8&)dst = (u8&)src; } }; diff --git a/rpcs3/Emu/ARMv7/ARMv7DisAsm.h b/rpcs3/Emu/ARMv7/ARMv7DisAsm.h index 03f99be552..ba59fc0a26 100644 --- a/rpcs3/Emu/ARMv7/ARMv7DisAsm.h +++ b/rpcs3/Emu/ARMv7/ARMv7DisAsm.h @@ -1,7 +1,6 @@ #pragma once #include "Emu/ARMv7/ARMv7Opcodes.h" #include "Emu/CPU/CPUDisAsm.h" -#include "Emu/Memory/Memory.h" static const char* g_arm_cond_name[16] = { diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp index d4cdddc2c9..95b355b0e4 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp @@ -2,7 +2,6 @@ #include "Utilities/Log.h" #include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/Cell/PPCThread.h" #include "ARMv7Thread.h" #include "ARMv7Decoder.h" diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index 9cfa145da7..0f04d99f9d 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -5,7 +5,6 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/DbgCommand.h" -#include "rpcs3/Ini.h" #include "CPUThread.h" diff --git a/rpcs3/Emu/CPU/CPUThreadManager.cpp b/rpcs3/Emu/CPU/CPUThreadManager.cpp index d162bc493b..7d8c5c6072 100644 --- a/rpcs3/Emu/CPU/CPUThreadManager.cpp +++ b/rpcs3/Emu/CPU/CPUThreadManager.cpp @@ -1,5 +1,4 @@ #include "stdafx.h" -#include "Utilities/Log.h" #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/DbgCommand.h" diff --git a/rpcs3/Emu/Cell/PPCDecoder.cpp b/rpcs3/Emu/Cell/PPCDecoder.cpp index 3b60ece5a2..a5df4c7f8c 100644 --- a/rpcs3/Emu/Cell/PPCDecoder.cpp +++ b/rpcs3/Emu/Cell/PPCDecoder.cpp @@ -1,5 +1,4 @@ #include "stdafx.h" -#include "Utilities/Log.h" #include "Emu/Memory/Memory.h" #include "PPCDecoder.h" diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 94cc1cde92..89524cfd27 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -1,9 +1,7 @@ #pragma once #include "Emu/Cell/PPUOpcodes.h" -#include "Emu/Memory/Memory.h" -#include "Emu/Cell/PPUThread.h" -#include "Emu/SysCalls/SysCalls.h" + #include #ifdef _MSC_VER #include diff --git a/rpcs3/Emu/Cell/PPUProgramCompiler.cpp b/rpcs3/Emu/Cell/PPUProgramCompiler.cpp index 6c239fe1cc..5e64958d0b 100644 --- a/rpcs3/Emu/Cell/PPUProgramCompiler.cpp +++ b/rpcs3/Emu/Cell/PPUProgramCompiler.cpp @@ -1,7 +1,4 @@ #include "stdafx.h" -#include "Utilities/Log.h" -#include "Emu/Memory/Memory.h" - #include "PPUProgramCompiler.h" using namespace PPU_instr; @@ -83,7 +80,7 @@ SectionInfo::SectionInfo(const std::string& _name) void SectionInfo::SetDataSize(u32 size, u32 align) { if(align) shdr.sh_addralign = align; - if(shdr.sh_addralign) size = Memory.AlignAddr(size, shdr.sh_addralign); + if(shdr.sh_addralign) size = AlignAddr(size, shdr.sh_addralign); if(!code.empty()) { @@ -987,7 +984,7 @@ void CompilePPUProgram::Compile() elf_info.e_shnum = 15; elf_info.e_shstrndx = elf_info.e_shnum - 1; elf_info.e_phoff = elf_info.e_ehsize; - u32 section_offset = Memory.AlignAddr(elf_info.e_phoff + elf_info.e_phnum * elf_info.e_phentsize, 0x100); + u32 section_offset = AlignAddr(elf_info.e_phoff + elf_info.e_phnum * elf_info.e_phentsize, 0x100); static const u32 sceStub_text_block = 8 * 4; @@ -1145,7 +1142,7 @@ void CompilePPUProgram::Compile() Elf64_Shdr s_sceStub_text; memset(&s_sceStub_text, 0, sizeof(Elf64_Shdr)); s_sceStub_text.sh_addralign = 4; - section_offset = Memory.AlignAddr(section_offset, s_sceStub_text.sh_addralign); + section_offset = AlignAddr(section_offset, s_sceStub_text.sh_addralign); s_sceStub_text.sh_type = 1; s_sceStub_text.sh_offset = section_offset; s_sceStub_text.sh_addr = section_offset + 0x10000; @@ -1169,7 +1166,7 @@ void CompilePPUProgram::Compile() Elf64_Shdr s_lib_stub_top; memset(&s_lib_stub_top, 0, sizeof(Elf64_Shdr)); s_lib_stub_top.sh_addralign = 4; - section_offset = Memory.AlignAddr(section_offset, s_lib_stub_top.sh_addralign); + section_offset = AlignAddr(section_offset, s_lib_stub_top.sh_addralign); s_lib_stub_top.sh_type = 1; s_lib_stub_top.sh_name = section_name_offset; s_lib_stub_top.sh_offset = section_offset; @@ -1209,7 +1206,7 @@ void CompilePPUProgram::Compile() Elf64_Shdr s_rodata_sceFNID; memset(&s_rodata_sceFNID, 0, sizeof(Elf64_Shdr)); s_rodata_sceFNID.sh_addralign = 4; - section_offset = Memory.AlignAddr(section_offset, s_rodata_sceFNID.sh_addralign); + section_offset = AlignAddr(section_offset, s_rodata_sceFNID.sh_addralign); s_rodata_sceFNID.sh_type = 1; s_rodata_sceFNID.sh_name = section_name_offset; s_rodata_sceFNID.sh_offset = section_offset; @@ -1223,7 +1220,7 @@ void CompilePPUProgram::Compile() Elf64_Shdr s_rodata_sceResident; memset(&s_rodata_sceResident, 0, sizeof(Elf64_Shdr)); s_rodata_sceResident.sh_addralign = 4; - section_offset = Memory.AlignAddr(section_offset, s_rodata_sceResident.sh_addralign); + section_offset = AlignAddr(section_offset, s_rodata_sceResident.sh_addralign); s_rodata_sceResident.sh_type = 1; s_rodata_sceResident.sh_name = section_name_offset; s_rodata_sceResident.sh_offset = section_offset; @@ -1234,7 +1231,7 @@ void CompilePPUProgram::Compile() { s_rodata_sceResident.sh_size += module.m_name.length() + 1; } - s_rodata_sceResident.sh_size = Memory.AlignAddr(s_rodata_sceResident.sh_size, s_rodata_sceResident.sh_addralign); + s_rodata_sceResident.sh_size = AlignAddr(s_rodata_sceResident.sh_size, s_rodata_sceResident.sh_addralign); sections_names.push_back(".rodata.sceResident"); section_name_offset += std::string(".rodata.sceResident").length() + 1; section_offset += s_rodata_sceResident.sh_size; @@ -1242,7 +1239,7 @@ void CompilePPUProgram::Compile() Elf64_Shdr s_lib_ent_top; memset(&s_lib_ent_top, 0, sizeof(Elf64_Shdr)); s_lib_ent_top.sh_addralign = 4; - section_offset = Memory.AlignAddr(section_offset, s_lib_ent_top.sh_addralign); + section_offset = AlignAddr(section_offset, s_lib_ent_top.sh_addralign); s_lib_ent_top.sh_size = 4; s_lib_ent_top.sh_flags = 2; s_lib_ent_top.sh_type = 1; @@ -1269,7 +1266,7 @@ void CompilePPUProgram::Compile() Elf64_Shdr s_sys_proc_prx_param; memset(&s_sys_proc_prx_param, 0, sizeof(Elf64_Shdr)); s_sys_proc_prx_param.sh_addralign = 4; - section_offset = Memory.AlignAddr(section_offset, s_sys_proc_prx_param.sh_addralign); + section_offset = AlignAddr(section_offset, s_sys_proc_prx_param.sh_addralign); s_sys_proc_prx_param.sh_type = 1; s_sys_proc_prx_param.sh_size = sizeof(sys_proc_prx_param); s_sys_proc_prx_param.sh_name = section_name_offset; @@ -1282,14 +1279,14 @@ void CompilePPUProgram::Compile() const u32 prog_load_0_end = section_offset; - section_offset = Memory.AlignAddr(section_offset + 0x10000, 0x10000); + section_offset = AlignAddr(section_offset + 0x10000, 0x10000); const u32 prog_load_1_start = section_offset; Elf64_Shdr s_data_sceFStub; memset(&s_data_sceFStub, 0, sizeof(Elf64_Shdr)); s_data_sceFStub.sh_name = section_name_offset; s_data_sceFStub.sh_addralign = 4; - section_offset = Memory.AlignAddr(section_offset, s_data_sceFStub.sh_addralign); + section_offset = AlignAddr(section_offset, s_data_sceFStub.sh_addralign); s_data_sceFStub.sh_flags = 3; s_data_sceFStub.sh_type = 1; s_data_sceFStub.sh_offset = section_offset; @@ -1302,7 +1299,7 @@ void CompilePPUProgram::Compile() Elf64_Shdr s_tbss; memset(&s_tbss, 0, sizeof(Elf64_Shdr)); s_tbss.sh_addralign = 4; - section_offset = Memory.AlignAddr(section_offset, s_tbss.sh_addralign); + section_offset = AlignAddr(section_offset, s_tbss.sh_addralign); s_tbss.sh_size = 4; s_tbss.sh_flags = 0x403; s_tbss.sh_type = 8; @@ -1316,7 +1313,7 @@ void CompilePPUProgram::Compile() Elf64_Shdr s_opd; memset(&s_opd, 0, sizeof(Elf64_Shdr)); s_opd.sh_addralign = 8; - section_offset = Memory.AlignAddr(section_offset, s_opd.sh_addralign); + section_offset = AlignAddr(section_offset, s_opd.sh_addralign); s_opd.sh_size = 2*4; s_opd.sh_type = 1; s_opd.sh_offset = section_offset; @@ -1477,7 +1474,7 @@ void CompilePPUProgram::Compile() if(!m_file_path.empty() && !m_analyze && !m_error) { - s_opd.sh_size = Memory.AlignAddr(s_opd.sh_size, s_opd.sh_addralign); + s_opd.sh_size = AlignAddr(s_opd.sh_size, s_opd.sh_addralign); section_offset += s_opd.sh_size; const u32 prog_load_1_end = section_offset; @@ -1485,7 +1482,7 @@ void CompilePPUProgram::Compile() Elf64_Shdr s_shstrtab; memset(&s_shstrtab, 0, sizeof(Elf64_Shdr)); s_shstrtab.sh_addralign = 1; - section_offset = Memory.AlignAddr(section_offset, s_shstrtab.sh_addralign); + section_offset = AlignAddr(section_offset, s_shstrtab.sh_addralign); s_shstrtab.sh_name = section_name_offset; s_shstrtab.sh_type = 3; s_shstrtab.sh_offset = section_offset; @@ -1507,7 +1504,7 @@ void CompilePPUProgram::Compile() elf_info.e_machine = MACHINE_PPC64; //PowerPC64 elf_info.e_version = 1; //ver 1 elf_info.e_flags = 0x0; - elf_info.e_shoff = Memory.AlignAddr(section_offset, 4); + elf_info.e_shoff = AlignAddr(section_offset, 4); u8* opd_data = new u8[s_opd.sh_size]; u32 entry_point = s_text.sh_addr; diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 47d09f6090..8996dad702 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -6,7 +6,6 @@ #include "Emu/SysCalls/Modules.h" #include "Emu/Cell/PPUDecoder.h" #include "Emu/Cell/PPUInterpreter.h" -#include "Emu/Cell/PPUDisAsm.h" #include #include @@ -57,7 +56,7 @@ void PPUThread::DoReset() void PPUThread::AddArgv(const std::string& arg) { m_stack_point -= arg.length() + 1; - m_stack_point = Memory.AlignAddr(m_stack_point, 0x10) - 0x10; + m_stack_point = AlignAddr(m_stack_point, 0x10) - 0x10; m_argv_addr.push_back(m_stack_point); Memory.WriteString(m_stack_point, arg); } @@ -94,7 +93,7 @@ void PPUThread::InitRegs() } */ - m_stack_point = Memory.AlignAddr(m_stack_point, 0x200) - 0x200; + m_stack_point = AlignAddr(m_stack_point, 0x200) - 0x200; GPR[1] = m_stack_point; GPR[2] = rtoc; diff --git a/rpcs3/Emu/Cell/RawSPUThread.cpp b/rpcs3/Emu/Cell/RawSPUThread.cpp index a1ad6c258a..023a946ea7 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.cpp +++ b/rpcs3/Emu/Cell/RawSPUThread.cpp @@ -1,7 +1,6 @@ #include "stdafx.h" #include "Utilities/Log.h" #include "Emu/Memory/Memory.h" -#include "Emu/System.h" #include "Emu/Cell/RawSPUThread.h" @@ -149,7 +148,7 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value) else { LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Write32(SPU_RunCtrl, 0x%x): unknown value", m_index, value); - Emu.Pause(); + return false; } break; } diff --git a/rpcs3/Emu/Cell/RawSPUThread.h b/rpcs3/Emu/Cell/RawSPUThread.h index ec40d69ab4..cfea40b0bf 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.h +++ b/rpcs3/Emu/Cell/RawSPUThread.h @@ -6,11 +6,6 @@ __forceinline static u32 GetRawSPURegAddrByNum(int num, int offset) return RAW_SPU_OFFSET * num + RAW_SPU_BASE_ADDR + RAW_SPU_PROB_OFFSET + offset; } -__forceinline static u32 GetRawSPURegAddrById(int id, int offset) -{ - return GetRawSPURegAddrByNum(Emu.GetCPU().GetThreadNumById(CPU_THREAD_RAW_SPU, id), offset); -} - class RawSPUThread : public SPUThread , public MemoryBlock diff --git a/rpcs3/Emu/Cell/SPUInstrTable.h b/rpcs3/Emu/Cell/SPUInstrTable.h index 18b4a72b75..267db8df8d 100644 --- a/rpcs3/Emu/Cell/SPUInstrTable.h +++ b/rpcs3/Emu/Cell/SPUInstrTable.h @@ -1,5 +1,4 @@ #pragma once -#include "PPCInstrTable.h" #include "PPCDecoder.h" #include "SPUOpcodes.h" diff --git a/rpcs3/Emu/Cell/SPUInterpreter.h b/rpcs3/Emu/Cell/SPUInterpreter.h index 78d8b9a280..be42be1d3e 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.h +++ b/rpcs3/Emu/Cell/SPUInterpreter.h @@ -1,20 +1,7 @@ #pragma once -#include "Emu/Cell/SPUOpcodes.h" -#include "Emu/Memory/Memory.h" -#include "Emu/Cell/SPUThread.h" -#include "Emu/SysCalls/SysCalls.h" -#include "Crypto/sha1.h" - #define UNIMPLEMENTED() UNK(__FUNCTION__) -/* typedef union _CRT_ALIGN(16) __u32x4 { - u32 _u32[4]; - __m128i m128i; - __m128 m128; - __m128d m128d; - } __u32x4; */ - #define MEM_AND_REG_HASH() \ unsigned char mem_h[20]; sha1(&Memory[CPU.dmac.ls_offset], 256*1024, mem_h); \ unsigned char reg_h[20]; sha1((const unsigned char*)CPU.GPR, sizeof(CPU.GPR), reg_h); \ diff --git a/rpcs3/Emu/Cell/SPURecompilerCore.cpp b/rpcs3/Emu/Cell/SPURecompilerCore.cpp index 5d9524475b..04997c8c39 100644 --- a/rpcs3/Emu/Cell/SPURecompilerCore.cpp +++ b/rpcs3/Emu/Cell/SPURecompilerCore.cpp @@ -3,8 +3,12 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" +#include "Emu/SysCalls/lv2/sys_time.h" + #include "SPUInstrTable.h" #include "SPUDisAsm.h" + +#include "SPUThread.h" #include "SPUInterpreter.h" #include "SPURecompiler.h" diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index b7a0c6787b..fbaf6805d3 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -2,6 +2,13 @@ #include "Utilities/Log.h" #include "Emu/System.h" +#include "Emu/SysCalls/ErrorCodes.h" +#include "Emu/SysCalls/lv2/sys_spu.h" +#include "Emu/SysCalls/lv2/sys_event_flag.h" +#include "Emu/SysCalls/lv2/sys_time.h" +#include "Emu/Event.h" + +#include "Emu/Cell/PPUThread.h" #include "Emu/Cell/SPUThread.h" #include "Emu/Cell/SPUDecoder.h" #include "Emu/Cell/SPUInterpreter.h" @@ -140,3 +147,908 @@ void SPUThread::DoClose() } } } + +void SPUThread::WriteSNR(bool number, u32 value) +{ + if (cfg.value & ((u64)1 << (u64)number)) + { + SPU.SNR[number].PushUncond_OR(value); // logical OR + } + else + { + SPU.SNR[number].PushUncond(value); // overwrite + } +} + +#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) + +void SPUThread::ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size) +{ + if (cmd & (MFC_BARRIER_MASK | MFC_FENCE_MASK)) _mm_mfence(); + + if (ea >= SYS_SPU_THREAD_BASE_LOW) + { + if (ea >= 0x100000000) + { + LOG_DMAC(LOG_ERROR, "Invalid external address"); + Emu.Pause(); + return; + } + else if (group) + { + // SPU Thread Group MMIO (LS and SNR) + u32 num = (ea & SYS_SPU_THREAD_BASE_MASK) / SYS_SPU_THREAD_OFFSET; // thread number in group + if (num >= group->list.size() || !group->list[num]) + { + LOG_DMAC(LOG_ERROR, "Invalid thread (SPU Thread Group MMIO)"); + Emu.Pause(); + return; + } + + SPUThread* spu = (SPUThread*)Emu.GetCPU().GetThread(group->list[num]); + + u32 addr = (ea & SYS_SPU_THREAD_BASE_MASK) % SYS_SPU_THREAD_OFFSET; + if ((addr <= 0x3ffff) && (addr + size <= 0x40000)) + { + // LS access + ea = spu->dmac.ls_offset + addr; + } + else if ((cmd & MFC_PUT_CMD) && size == 4 && (addr == SYS_SPU_THREAD_SNR1 || addr == SYS_SPU_THREAD_SNR2)) + { + spu->WriteSNR(SYS_SPU_THREAD_SNR2 == addr, Memory.Read32(dmac.ls_offset + lsa)); + return; + } + else + { + LOG_DMAC(LOG_ERROR, "Invalid register (SPU Thread Group MMIO)"); + Emu.Pause(); + return; + } + } + else + { + LOG_DMAC(LOG_ERROR, "Thread group not set (SPU Thread Group MMIO)"); + Emu.Pause(); + return; + } + } + else if (ea >= RAW_SPU_BASE_ADDR && size == 4) + { + switch (cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK | MFC_RESULT_MASK)) + { + case MFC_PUT_CMD: + { + Memory.Write32(ea, ReadLS32(lsa)); + return; + } + + case MFC_GET_CMD: + { + WriteLS32(lsa, Memory.Read32(ea)); + return; + } + + default: + { + LOG_DMAC(LOG_ERROR, "Unknown DMA command"); + Emu.Pause(); + return; + } + } + } + + switch (cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK | MFC_RESULT_MASK)) + { + case MFC_PUT_CMD: + { + memcpy(Memory + ea, Memory + (dmac.ls_offset + lsa), size); + return; + } + + case MFC_GET_CMD: + { + memcpy(Memory + (dmac.ls_offset + lsa), Memory + ea, size); + return; + } + + default: + { + LOG_DMAC(LOG_ERROR, "Unknown DMA command"); + Emu.Pause(); + return; + } + } +} + +#undef LOG_CMD + +void SPUThread::ListCmd(u32 lsa, u64 ea, u16 tag, u16 size, u32 cmd, MFCReg& MFCArgs) +{ + u32 list_addr = ea & 0x3ffff; + u32 list_size = size / 8; + lsa &= 0x3fff0; + + struct list_element + { + be_t s; // Stall-and-Notify bit (0x8000) + be_t ts; // List Transfer Size + be_t ea; // External Address Low + }; + + u32 result = MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL; + + for (u32 i = 0; i < list_size; i++) + { + mem_ptr_t rec(dmac.ls_offset + list_addr + i * 8); + + u32 size = rec->ts; + if (size < 16 && size != 1 && size != 2 && size != 4 && size != 8) + { + LOG_ERROR(Log::SPU, "DMA List: invalid transfer size(%d)", size); + result = MFC_PPU_DMA_CMD_SEQUENCE_ERROR; + break; + } + + u32 addr = rec->ea; + ProcessCmd(cmd, tag, lsa | (addr & 0xf), addr, size); + + if (Ini.HLELogging.GetValue() || rec->s) + LOG_NOTICE(Log::SPU, "*** list element(%d/%d): s = 0x%x, ts = 0x%x, low ea = 0x%x (lsa = 0x%x)", + i, list_size, (u16)rec->s, (u16)rec->ts, (u32)rec->ea, lsa | (addr & 0xf)); + + lsa += std::max(size, (u32)16); + + if (rec->s & se16(0x8000)) + { + StallStat.PushUncond_OR(1 << tag); + + if (StallList[tag].MFCArgs) + { + LOG_ERROR(Log::SPU, "DMA List: existing stalled list found (tag=%d)", tag); + result = MFC_PPU_DMA_CMD_SEQUENCE_ERROR; + break; + } + StallList[tag].MFCArgs = &MFCArgs; + StallList[tag].cmd = cmd; + StallList[tag].ea = (ea & ~0xffffffff) | (list_addr + (i + 1) * 8); + StallList[tag].lsa = lsa; + StallList[tag].size = (list_size - i - 1) * 8; + + break; + } + } + + MFCArgs.CMDStatus.SetValue(result); +} + +void SPUThread::EnqMfcCmd(MFCReg& MFCArgs) +{ + u32 cmd = MFCArgs.CMDStatus.GetValue(); + u16 op = cmd & MFC_MASK_CMD; + + u32 lsa = MFCArgs.LSA.GetValue(); + u64 ea = (u64)MFCArgs.EAL.GetValue() | ((u64)MFCArgs.EAH.GetValue() << 32); + u32 size_tag = MFCArgs.Size_Tag.GetValue(); + u16 tag = (u16)size_tag; + u16 size = size_tag >> 16; + + switch (op & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK)) + { + case MFC_PUT_CMD: + case MFC_PUTR_CMD: // ??? + case MFC_GET_CMD: + { + if (Ini.HLELogging.GetValue()) LOG_NOTICE(Log::SPU, "DMA %s%s%s%s: lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x", + (op & MFC_PUT_CMD ? "PUT" : "GET"), + (op & MFC_RESULT_MASK ? "R" : ""), + (op & MFC_BARRIER_MASK ? "B" : ""), + (op & MFC_FENCE_MASK ? "F" : ""), + lsa, ea, tag, size, cmd); + + ProcessCmd(cmd, tag, lsa, ea, size); + MFCArgs.CMDStatus.SetValue(MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL); + } + break; + + case MFC_PUTL_CMD: + case MFC_PUTRL_CMD: // ??? + case MFC_GETL_CMD: + { + if (Ini.HLELogging.GetValue()) LOG_NOTICE(Log::SPU, "DMA %s%s%s%s: lsa = 0x%x, list = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x", + (op & MFC_PUT_CMD ? "PUT" : "GET"), + (op & MFC_RESULT_MASK ? "RL" : "L"), + (op & MFC_BARRIER_MASK ? "B" : ""), + (op & MFC_FENCE_MASK ? "F" : ""), + lsa, ea, tag, size, cmd); + + ListCmd(lsa, ea, tag, size, cmd, MFCArgs); + } + break; + + case MFC_GETLLAR_CMD: + case MFC_PUTLLC_CMD: + case MFC_PUTLLUC_CMD: + case MFC_PUTQLLUC_CMD: + { + if (Ini.HLELogging.GetValue() || size != 128) LOG_NOTICE(Log::SPU, "DMA %s: lsa=0x%x, ea = 0x%llx, (tag) = 0x%x, (size) = 0x%x, cmd = 0x%x", + (op == MFC_GETLLAR_CMD ? "GETLLAR" : + op == MFC_PUTLLC_CMD ? "PUTLLC" : + op == MFC_PUTLLUC_CMD ? "PUTLLUC" : "PUTQLLUC"), + lsa, ea, tag, size, cmd); + + if (op == MFC_GETLLAR_CMD) // get reservation + { + if (R_ADDR) + { + m_events |= SPU_EVENT_LR; + } + + R_ADDR = ea; + for (u32 i = 0; i < 16; i++) + { + R_DATA[i] = *(u64*)&Memory[R_ADDR + i * 8]; + *(u64*)&Memory[dmac.ls_offset + lsa + i * 8] = R_DATA[i]; + } + MFCArgs.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS); + } + else if (op == MFC_PUTLLC_CMD) // store conditional + { + MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS); + + if (R_ADDR == ea) + { + u32 changed = 0, mask = 0; + u64 buf[16]; + for (u32 i = 0; i < 16; i++) + { + buf[i] = *(u64*)&Memory[dmac.ls_offset + lsa + i * 8]; + if (buf[i] != R_DATA[i]) + { + changed++; + mask |= (0x3 << (i * 2)); + if (*(u64*)&Memory[R_ADDR + i * 8] != R_DATA[i]) + { + m_events |= SPU_EVENT_LR; + MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE); + R_ADDR = 0; + return; + } + } + } + + for (u32 i = 0; i < 16; i++) + { + if (buf[i] != R_DATA[i]) + { + if (InterlockedCompareExchange64((volatile long long*)(Memory + (ea + i * 8)), buf[i], R_DATA[i]) != R_DATA[i]) + { + m_events |= SPU_EVENT_LR; + MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE); + + if (changed > 1) + { + LOG_ERROR(Log::SPU, "MFC_PUTLLC_CMD: Memory corrupted (~x%d (mask=0x%x)) (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)", + changed, mask, op, cmd, lsa, ea, tag, size); + Emu.Pause(); + } + + break; + } + } + } + + if (changed > 1) + { + LOG_WARNING(Log::SPU, "MFC_PUTLLC_CMD: Reservation impossibru (~x%d (mask=0x%x)) (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)", + changed, mask, op, cmd, lsa, ea, tag, size); + + SPUDisAsm dis_asm(CPUDisAsm_InterpreterMode); + for (s32 i = PC; i < PC + 4 * 7; i += 4) + { + dis_asm.dump_pc = i; + dis_asm.offset = Memory.GetMemFromAddr(dmac.ls_offset); + const u32 opcode = Memory.Read32(i + dmac.ls_offset); + (*SPU_instr::rrr_list)(&dis_asm, opcode); + if (i >= 0 && i < 0x40000) + { + LOG_NOTICE(Log::SPU, "*** %s", dis_asm.last_opcode.c_str()); + } + } + } + } + else + { + MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE); + } + R_ADDR = 0; + } + else // store unconditional + { + if (R_ADDR) + { + m_events |= SPU_EVENT_LR; + } + + ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128); + if (op == MFC_PUTLLUC_CMD) + { + MFCArgs.AtomicStat.PushUncond(MFC_PUTLLUC_SUCCESS); + } + R_ADDR = 0; + } + } + break; + + default: + LOG_ERROR(Log::SPU, "Unknown MFC cmd. (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)", + op, cmd, lsa, ea, tag, size); + break; + } +} + +bool SPUThread::CheckEvents() +{ + // checks events: + // SPU_EVENT_LR: + { + for (u32 i = 0; i < 16; i++) + { + if (*(u64*)&Memory[R_ADDR + i * 8] != R_DATA[i]) + { + m_events |= SPU_EVENT_LR; + R_ADDR = 0; + break; + } + } + } + + return (m_events & m_event_mask) != 0; +} + +u32 SPUThread::GetChannelCount(u32 ch) +{ + switch (ch) + { + case SPU_WrOutMbox: return SPU.Out_MBox.GetFreeCount(); + case SPU_WrOutIntrMbox: return SPU.Out_IntrMBox.GetFreeCount(); + case SPU_RdInMbox: return SPU.In_MBox.GetCount(); + case MFC_RdTagStat: return MFC1.TagStatus.GetCount(); + case MFC_RdListStallStat: return StallStat.GetCount(); + case MFC_WrTagUpdate: return MFC1.TagStatus.GetCount(); // hack + case SPU_RdSigNotify1: return SPU.SNR[0].GetCount(); + case SPU_RdSigNotify2: return SPU.SNR[1].GetCount(); + case MFC_RdAtomicStat: return MFC1.AtomicStat.GetCount(); + case SPU_RdEventStat: return CheckEvents() ? 1 : 0; + + default: + { + LOG_ERROR(Log::SPU, "%s error: unknown/illegal channel (%d [%s]).", + __FUNCTION__, ch, spu_ch_name[ch]); + return 0; + } + } +} + +void SPUThread::WriteChannel(u32 ch, const SPU_GPR_hdr& r) +{ + const u32 v = r._u32[3]; + + switch (ch) + { + case SPU_WrOutIntrMbox: + { + if (!group) // if RawSPU + { + if (Ini.HLELogging.GetValue()) LOG_NOTICE(Log::SPU, "SPU_WrOutIntrMbox: interrupt(v=0x%x)", v); + while (!SPU.Out_IntrMBox.Push(v)) + { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + if (Emu.IsStopped()) + { + LOG_WARNING(Log::SPU, "%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]); + return; + } + } + m_intrtag[2].stat |= 1; + if (CPUThread* t = Emu.GetCPU().GetThread(m_intrtag[2].thread)) + { + if (t->GetType() == CPU_THREAD_PPU && !t->IsAlive()) + { + PPUThread& ppu = *(PPUThread*)t; + ppu.FastStop(); + ppu.Run(); + ppu.FastCall(ppu.PC, ppu.GPR[2], ppu.m_interrupt_arg); + } + } + } + else + { + const u8 code = v >> 24; + if (code < 64) + { + /* ===== sys_spu_thread_send_event (used by spu_printf) ===== */ + + u8 spup = code & 63; + + u32 data; + if (!SPU.Out_MBox.Pop(data)) + { + LOG_ERROR(Log::SPU, "sys_spu_thread_send_event(v=0x%x, spup=%d): Out_MBox is empty", v, spup); + return; + } + + if (Ini.HLELogging.GetValue()) + { + LOG_NOTICE(Log::SPU, "sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x)", spup, v & 0x00ffffff, data); + } + + EventPort& port = SPUPs[spup]; + + std::lock_guard lock(port.m_mutex); + + if (!port.eq) + { + LOG_WARNING(Log::SPU, "sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x): event queue not connected", spup, (v & 0x00ffffff), data); + SPU.In_MBox.PushUncond(CELL_ENOTCONN); // TODO: check error passing + return; + } + + if (!port.eq->events.push(SYS_SPU_THREAD_EVENT_USER_KEY, GetCurrentCPUThread()->GetId(), ((u64)spup << 32) | (v & 0x00ffffff), data)) + { + SPU.In_MBox.PushUncond(CELL_EBUSY); + return; + } + + SPU.In_MBox.PushUncond(CELL_OK); + return; + } + else if (code < 128) + { + /* ===== sys_spu_thread_throw_event ===== */ + + const u8 spup = code & 63; + + u32 data; + if (!SPU.Out_MBox.Pop(data)) + { + LOG_ERROR(Log::SPU, "sys_spu_thread_throw_event(v=0x%x, spup=%d): Out_MBox is empty", v, spup); + return; + } + + //if (Ini.HLELogging.GetValue()) + { + LOG_WARNING(Log::SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x)", spup, v & 0x00ffffff, data); + } + + EventPort& port = SPUPs[spup]; + + std::lock_guard lock(port.m_mutex); + + if (!port.eq) + { + LOG_WARNING(Log::SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x): event queue not connected", spup, (v & 0x00ffffff), data); + return; + } + + // TODO: check passing spup value + if (!port.eq->events.push(SYS_SPU_THREAD_EVENT_USER_KEY, GetCurrentCPUThread()->GetId(), ((u64)spup << 32) | (v & 0x00ffffff), data)) + { + LOG_WARNING(Log::SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x) failed (queue is full)", spup, (v & 0x00ffffff), data); + return; + } + + return; + } + else if (code == 128) + { + /* ===== sys_event_flag_set_bit ===== */ + u32 flag = v & 0xffffff; + + u32 data; + if (!SPU.Out_MBox.Pop(data)) + { + LOG_ERROR(Log::SPU, "sys_event_flag_set_bit(v=0x%x (flag=%d)): Out_MBox is empty", v, flag); + return; + } + + if (flag > 63) + { + LOG_ERROR(Log::SPU, "sys_event_flag_set_bit(id=%d, v=0x%x): flag > 63", data, v, flag); + return; + } + + //if (Ini.HLELogging.GetValue()) + { + LOG_WARNING(Log::SPU, "sys_event_flag_set_bit(id=%d, v=0x%x (flag=%d))", data, v, flag); + } + + EventFlag* ef; + if (!Emu.GetIdManager().GetIDData(data, ef)) + { + LOG_ERROR(Log::SPU, "sys_event_flag_set_bit(id=%d, v=0x%x (flag=%d)): EventFlag not found", data, v, flag); + SPU.In_MBox.PushUncond(CELL_ESRCH); + return; + } + + u32 tid = GetCurrentCPUThread()->GetId(); + + ef->m_mutex.lock(tid); + ef->flags |= (u64)1 << flag; + if (u32 target = ef->check()) + { + // if signal, leave both mutexes locked... + ef->signal.lock(target); + ef->m_mutex.unlock(tid, target); + } + else + { + ef->m_mutex.unlock(tid); + } + + SPU.In_MBox.PushUncond(CELL_OK); + return; + } + else if (code == 192) + { + /* ===== sys_event_flag_set_bit_impatient ===== */ + u32 flag = v & 0xffffff; + + u32 data; + if (!SPU.Out_MBox.Pop(data)) + { + LOG_ERROR(Log::SPU, "sys_event_flag_set_bit_impatient(v=0x%x (flag=%d)): Out_MBox is empty", v, flag); + return; + } + + if (flag > 63) + { + LOG_ERROR(Log::SPU, "sys_event_flag_set_bit_impatient(id=%d, v=0x%x): flag > 63", data, v, flag); + return; + } + + //if (Ini.HLELogging.GetValue()) + { + LOG_WARNING(Log::SPU, "sys_event_flag_set_bit_impatient(id=%d, v=0x%x (flag=%d))", data, v, flag); + } + + EventFlag* ef; + if (!Emu.GetIdManager().GetIDData(data, ef)) + { + LOG_WARNING(Log::SPU, "sys_event_flag_set_bit_impatient(id=%d, v=0x%x (flag=%d)): EventFlag not found", data, v, flag); + return; + } + + u32 tid = GetCurrentCPUThread()->GetId(); + + ef->m_mutex.lock(tid); + ef->flags |= (u64)1 << flag; + if (u32 target = ef->check()) + { + // if signal, leave both mutexes locked... + ef->signal.lock(target); + ef->m_mutex.unlock(tid, target); + } + else + { + ef->m_mutex.unlock(tid); + } + + return; + } + else + { + u32 data; + if (SPU.Out_MBox.Pop(data)) + { + LOG_ERROR(Log::SPU, "SPU_WrOutIntrMbox: unknown data (v=0x%x); Out_MBox = 0x%x", v, data); + } + else + { + LOG_ERROR(Log::SPU, "SPU_WrOutIntrMbox: unknown data (v=0x%x)", v); + } + SPU.In_MBox.PushUncond(CELL_EINVAL); // ??? + return; + } + } + break; + } + + case SPU_WrOutMbox: + { + while (!SPU.Out_MBox.Push(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + break; + } + + case MFC_WrTagMask: + { + MFC1.QueryMask.SetValue(v); + break; + } + + case MFC_WrTagUpdate: + { + MFC1.TagStatus.PushUncond(MFC1.QueryMask.GetValue()); + break; + } + + case MFC_LSA: + { + MFC1.LSA.SetValue(v); + break; + } + + case MFC_EAH: + { + MFC1.EAH.SetValue(v); + break; + } + + case MFC_EAL: + { + MFC1.EAL.SetValue(v); + break; + } + + case MFC_Size: + { + MFC1.Size_Tag.SetValue((MFC1.Size_Tag.GetValue() & 0xffff) | (v << 16)); + break; + } + + case MFC_TagID: + { + MFC1.Size_Tag.SetValue((MFC1.Size_Tag.GetValue() & ~0xffff) | (v & 0xffff)); + break; + } + + + case MFC_Cmd: + { + MFC1.CMDStatus.SetValue(v); + EnqMfcCmd(MFC1); + break; + } + + case MFC_WrListStallAck: + { + if (v >= 32) + { + LOG_ERROR(Log::SPU, "MFC_WrListStallAck error: invalid tag(%d)", v); + return; + } + StalledList temp = StallList[v]; + if (!temp.MFCArgs) + { + LOG_ERROR(Log::SPU, "MFC_WrListStallAck error: empty tag(%d)", v); + return; + } + StallList[v].MFCArgs = nullptr; + ListCmd(temp.lsa, temp.ea, temp.tag, temp.size, temp.cmd, *temp.MFCArgs); + break; + } + + case SPU_WrDec: + { + m_dec_start = get_time(); + m_dec_value = v; + break; + } + + case SPU_WrEventMask: + { + m_event_mask = v; + if (v & ~(SPU_EVENT_IMPLEMENTED)) LOG_ERROR(Log::SPU, "SPU_WrEventMask: unsupported event masked (0x%x)"); + break; + } + + case SPU_WrEventAck: + { + m_events &= ~v; + break; + } + + default: + { + LOG_ERROR(Log::SPU, "%s error (v=0x%x): unknown/illegal channel (%d [%s]).", __FUNCTION__, v, ch, spu_ch_name[ch]); + break; + } + } + + if (Emu.IsStopped()) LOG_WARNING(Log::SPU, "%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]); +} + +void SPUThread::ReadChannel(SPU_GPR_hdr& r, u32 ch) +{ + r.Reset(); + u32& v = r._u32[3]; + + switch (ch) + { + case SPU_RdInMbox: + { + while (!SPU.In_MBox.Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + break; + } + + case MFC_RdTagStat: + { + while (!MFC1.TagStatus.Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + break; + } + + case MFC_RdTagMask: + { + v = MFC1.QueryMask.GetValue(); + break; + } + + case SPU_RdSigNotify1: + { + while (!SPU.SNR[0].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + break; + } + + case SPU_RdSigNotify2: + { + while (!SPU.SNR[1].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + break; + } + + case MFC_RdAtomicStat: + { + while (!MFC1.AtomicStat.Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + break; + } + + case MFC_RdListStallStat: + { + while (!StallStat.Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + break; + } + + case SPU_RdDec: + { + v = m_dec_value - (u32)(get_time() - m_dec_start); + break; + } + + case SPU_RdEventMask: + { + v = m_event_mask; + break; + } + + case SPU_RdEventStat: + { + while (!CheckEvents() && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + v = m_events & m_event_mask; + break; + } + + case SPU_RdMachStat: + { + v = 1; // hack (not isolated, interrupts enabled) + // TODO: check value + break; + } + + default: + { + LOG_ERROR(Log::SPU, "%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); + break; + } + } + + if (Emu.IsStopped()) LOG_WARNING(Log::SPU, "%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]); +} + +void SPUThread::StopAndSignal(u32 code) +{ + SetExitStatus(code); // exit code (not status) + + switch (code) + { + case 0x110: /* ===== sys_spu_thread_receive_event ===== */ + { + u32 spuq = 0; + if (!SPU.Out_MBox.Pop(spuq)) + { + LOG_ERROR(Log::SPU, "sys_spu_thread_receive_event: cannot read Out_MBox"); + SPU.In_MBox.PushUncond(CELL_EINVAL); // ??? + return; + } + + if (SPU.In_MBox.GetCount()) + { + LOG_ERROR(Log::SPU, "sys_spu_thread_receive_event(spuq=0x%x): In_MBox is not empty", spuq); + SPU.In_MBox.PushUncond(CELL_EBUSY); // ??? + return; + } + + if (Ini.HLELogging.GetValue()) + { + LOG_NOTICE(Log::SPU, "sys_spu_thread_receive_event(spuq=0x%x)", spuq); + } + + EventQueue* eq; + if (!SPUQs.GetEventQueue(FIX_SPUQ(spuq), eq)) + { + SPU.In_MBox.PushUncond(CELL_EINVAL); // TODO: check error value + return; + } + + u32 tid = GetId(); + + eq->sq.push(tid); // add thread to sleep queue + + while (true) + { + switch (eq->owner.trylock(tid)) + { + case SMR_OK: + if (!eq->events.count()) + { + eq->owner.unlock(tid); + break; + } + else + { + u32 next = (eq->protocol == SYS_SYNC_FIFO) ? eq->sq.pop() : eq->sq.pop_prio(); + if (next != tid) + { + eq->owner.unlock(tid, next); + break; + } + } + case SMR_SIGNAL: + { + sys_event_data event; + eq->events.pop(event); + eq->owner.unlock(tid); + SPU.In_MBox.PushUncond(CELL_OK); + SPU.In_MBox.PushUncond(event.data1); + SPU.In_MBox.PushUncond(event.data2); + SPU.In_MBox.PushUncond(event.data3); + return; + } + case SMR_FAILED: break; + default: eq->sq.invalidate(tid); SPU.In_MBox.PushUncond(CELL_ECANCELED); return; + } + + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + if (Emu.IsStopped()) + { + LOG_WARNING(Log::SPU, "sys_spu_thread_receive_event(spuq=0x%x) aborted", spuq); + eq->sq.invalidate(tid); + return; + } + } + } + break; + case 0x102: + if (!SPU.Out_MBox.GetCount()) + { + LOG_ERROR(Log::SPU, "sys_spu_thread_exit (no status, code 0x102)"); + } + else if (Ini.HLELogging.GetValue()) + { + // the real exit status + LOG_NOTICE(Log::SPU, "sys_spu_thread_exit (status=0x%x)", SPU.Out_MBox.GetValue()); + } + SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_STOP); + Stop(); + break; + default: + if (!SPU.Out_MBox.GetCount()) + { + LOG_ERROR(Log::SPU, "Unknown STOP code: 0x%x (no message)", code); + } + else + { + LOG_ERROR(Log::SPU, "Unknown STOP code: 0x%x (message=0x%x)", code, SPU.Out_MBox.GetValue()); + } + SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_STOP); + Stop(); + break; + } +} \ No newline at end of file diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 1b9e4555db..3829db3c65 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -1,13 +1,7 @@ #pragma once -#include "PPUThread.h" -#include "SPUInstrTable.h" -#include "SPUDisAsm.h" +#include "PPCThread.h" #include "Emu/Event.h" -#include "Emu/SysCalls/lv2/sys_spu.h" -#include "Emu/SysCalls/lv2/sys_event_flag.h" -#include "Emu/SysCalls/lv2/sys_time.h" #include "MFC.h" -#include "Emu/SysCalls/ErrorCodes.h" #include enum SPUchannels @@ -163,7 +157,7 @@ public: return this->low >> 22 & 0x3; default: - LOG_ERROR(SPU, "Unexpected slice value in FPSCR::checkSliceRounding(): %d", slice); + throw fmt::Format("Unexpected slice value in FPSCR::checkSliceRounding(): %d", slice); return 0; } } @@ -246,6 +240,8 @@ union SPU_SNRConfig_hdr } }; +struct SpuGroupInfo; + class SPUThread : public PPCThread { public: @@ -499,17 +495,7 @@ public: Channel<1> SNR[2]; } SPU; - void WriteSNR(bool number, u32 value) - { - if (cfg.value & ((u64)1 << (u64)number)) - { - SPU.SNR[number].PushUncond_OR(value); // logical OR - } - else - { - SPU.SNR[number].PushUncond(value); // overwrite - } - } + void WriteSNR(bool number, u32 value); u32 LSA; @@ -521,897 +507,21 @@ public: 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) + void ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size); - void ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size) - { - if (cmd & (MFC_BARRIER_MASK | MFC_FENCE_MASK)) _mm_mfence(); + void ListCmd(u32 lsa, u64 ea, u16 tag, u16 size, u32 cmd, MFCReg& MFCArgs); - if (ea >= SYS_SPU_THREAD_BASE_LOW) - { - if (ea >= 0x100000000) - { - LOG_DMAC(LOG_ERROR, "Invalid external address"); - Emu.Pause(); - return; - } - else if (group) - { - // SPU Thread Group MMIO (LS and SNR) - u32 num = (ea & SYS_SPU_THREAD_BASE_MASK) / SYS_SPU_THREAD_OFFSET; // thread number in group - if (num >= group->list.size() || !group->list[num]) - { - LOG_DMAC(LOG_ERROR, "Invalid thread (SPU Thread Group MMIO)"); - Emu.Pause(); - return; - } + void EnqMfcCmd(MFCReg& MFCArgs); - SPUThread* spu = (SPUThread*)Emu.GetCPU().GetThread(group->list[num]); + bool CheckEvents(); - u32 addr = (ea & SYS_SPU_THREAD_BASE_MASK) % SYS_SPU_THREAD_OFFSET; - if ((addr <= 0x3ffff) && (addr + size <= 0x40000)) - { - // LS access - ea = spu->dmac.ls_offset + addr; - } - else if ((cmd & MFC_PUT_CMD) && size == 4 && (addr == SYS_SPU_THREAD_SNR1 || addr == SYS_SPU_THREAD_SNR2)) - { - spu->WriteSNR(SYS_SPU_THREAD_SNR2 == addr, Memory.Read32(dmac.ls_offset + lsa)); - return; - } - else - { - LOG_DMAC(LOG_ERROR, "Invalid register (SPU Thread Group MMIO)"); - Emu.Pause(); - return; - } - } - else - { - LOG_DMAC(LOG_ERROR, "Thread group not set (SPU Thread Group MMIO)"); - Emu.Pause(); - return; - } - } - else if (ea >= RAW_SPU_BASE_ADDR && size == 4) - { - switch (cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK | MFC_RESULT_MASK)) - { - case MFC_PUT_CMD: - { - Memory.Write32(ea, ReadLS32(lsa)); - return; - } + u32 GetChannelCount(u32 ch); - case MFC_GET_CMD: - { - WriteLS32(lsa, Memory.Read32(ea)); - return; - } + void WriteChannel(u32 ch, const SPU_GPR_hdr& r); - default: - { - LOG_DMAC(LOG_ERROR, "Unknown DMA command"); - Emu.Pause(); - return; - } - } - } + void ReadChannel(SPU_GPR_hdr& r, u32 ch); - switch (cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK | MFC_RESULT_MASK)) - { - case MFC_PUT_CMD: - { - memcpy(Memory + ea, Memory + (dmac.ls_offset + lsa), size); - return; - } - - case MFC_GET_CMD: - { - memcpy(Memory + (dmac.ls_offset + lsa), Memory + ea, size); - return; - } - - default: - { - LOG_DMAC(LOG_ERROR, "Unknown DMA command"); - Emu.Pause(); - return; - } - } - } - -#undef LOG_CMD - - void ListCmd(u32 lsa, u64 ea, u16 tag, u16 size, u32 cmd, MFCReg& MFCArgs) - { - u32 list_addr = ea & 0x3ffff; - u32 list_size = size / 8; - lsa &= 0x3fff0; - - struct list_element - { - be_t s; // Stall-and-Notify bit (0x8000) - be_t ts; // List Transfer Size - be_t ea; // External Address Low - }; - - u32 result = MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL; - - for (u32 i = 0; i < list_size; i++) - { - mem_ptr_t rec(dmac.ls_offset + list_addr + i * 8); - - u32 size = rec->ts; - if (size < 16 && size != 1 && size != 2 && size != 4 && size != 8) - { - LOG_ERROR(Log::SPU, "DMA List: invalid transfer size(%d)", size); - result = MFC_PPU_DMA_CMD_SEQUENCE_ERROR; - break; - } - - u32 addr = rec->ea; - ProcessCmd(cmd, tag, lsa | (addr & 0xf), addr, size); - - if (Ini.HLELogging.GetValue() || rec->s) - LOG_NOTICE(Log::SPU, "*** list element(%d/%d): s = 0x%x, ts = 0x%x, low ea = 0x%x (lsa = 0x%x)", - i, list_size, (u16)rec->s, (u16)rec->ts, (u32)rec->ea, lsa | (addr & 0xf)); - - lsa += std::max(size, (u32)16); - - if (rec->s & se16(0x8000)) - { - StallStat.PushUncond_OR(1 << tag); - - if (StallList[tag].MFCArgs) - { - LOG_ERROR(Log::SPU, "DMA List: existing stalled list found (tag=%d)", tag); - result = MFC_PPU_DMA_CMD_SEQUENCE_ERROR; - break; - } - StallList[tag].MFCArgs = &MFCArgs; - StallList[tag].cmd = cmd; - StallList[tag].ea = (ea & ~0xffffffff) | (list_addr + (i + 1) * 8); - StallList[tag].lsa = lsa; - StallList[tag].size = (list_size - i - 1) * 8; - - break; - } - } - - MFCArgs.CMDStatus.SetValue(result); - } - - void EnqMfcCmd(MFCReg& MFCArgs) - { - u32 cmd = MFCArgs.CMDStatus.GetValue(); - u16 op = cmd & MFC_MASK_CMD; - - u32 lsa = MFCArgs.LSA.GetValue(); - u64 ea = (u64)MFCArgs.EAL.GetValue() | ((u64)MFCArgs.EAH.GetValue() << 32); - u32 size_tag = MFCArgs.Size_Tag.GetValue(); - u16 tag = (u16)size_tag; - u16 size = size_tag >> 16; - - switch(op & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK)) - { - case MFC_PUT_CMD: - case MFC_PUTR_CMD: // ??? - case MFC_GET_CMD: - { - if (Ini.HLELogging.GetValue()) LOG_NOTICE(Log::SPU, "DMA %s%s%s%s: lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x", - (op & MFC_PUT_CMD ? "PUT" : "GET"), - (op & MFC_RESULT_MASK ? "R" : ""), - (op & MFC_BARRIER_MASK ? "B" : ""), - (op & MFC_FENCE_MASK ? "F" : ""), - lsa, ea, tag, size, cmd); - - ProcessCmd(cmd, tag, lsa, ea, size); - MFCArgs.CMDStatus.SetValue(MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL); - } - break; - - case MFC_PUTL_CMD: - case MFC_PUTRL_CMD: // ??? - case MFC_GETL_CMD: - { - if (Ini.HLELogging.GetValue()) LOG_NOTICE(Log::SPU, "DMA %s%s%s%s: lsa = 0x%x, list = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x", - (op & MFC_PUT_CMD ? "PUT" : "GET"), - (op & MFC_RESULT_MASK ? "RL" : "L"), - (op & MFC_BARRIER_MASK ? "B" : ""), - (op & MFC_FENCE_MASK ? "F" : ""), - lsa, ea, tag, size, cmd); - - ListCmd(lsa, ea, tag, size, cmd, MFCArgs); - } - break; - - case MFC_GETLLAR_CMD: - case MFC_PUTLLC_CMD: - case MFC_PUTLLUC_CMD: - case MFC_PUTQLLUC_CMD: - { - if (Ini.HLELogging.GetValue() || size != 128) LOG_NOTICE(Log::SPU, "DMA %s: lsa=0x%x, ea = 0x%llx, (tag) = 0x%x, (size) = 0x%x, cmd = 0x%x", - (op == MFC_GETLLAR_CMD ? "GETLLAR" : - op == MFC_PUTLLC_CMD ? "PUTLLC" : - op == MFC_PUTLLUC_CMD ? "PUTLLUC" : "PUTQLLUC"), - lsa, ea, tag, size, cmd); - - if (op == MFC_GETLLAR_CMD) // get reservation - { - if (R_ADDR) - { - m_events |= SPU_EVENT_LR; - } - - R_ADDR = ea; - for (u32 i = 0; i < 16; i++) - { - R_DATA[i] = *(u64*)&Memory[R_ADDR + i * 8]; - *(u64*)&Memory[dmac.ls_offset + lsa + i * 8] = R_DATA[i]; - } - MFCArgs.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS); - } - else if (op == MFC_PUTLLC_CMD) // store conditional - { - MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS); - - if (R_ADDR == ea) - { - u32 changed = 0, mask = 0; - u64 buf[16]; - for (u32 i = 0; i < 16; i++) - { - buf[i] = *(u64*)&Memory[dmac.ls_offset + lsa + i * 8]; - if (buf[i] != R_DATA[i]) - { - changed++; - mask |= (0x3 << (i * 2)); - if (*(u64*)&Memory[R_ADDR + i * 8] != R_DATA[i]) - { - m_events |= SPU_EVENT_LR; - MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE); - R_ADDR = 0; - return; - } - } - } - - for (u32 i = 0; i < 16; i++) - { - if (buf[i] != R_DATA[i]) - { - if (InterlockedCompareExchange64((volatile long long*)(Memory + (ea + i * 8)), buf[i], R_DATA[i]) != R_DATA[i]) - { - m_events |= SPU_EVENT_LR; - MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE); - - if (changed > 1) - { - LOG_ERROR(Log::SPU, "MFC_PUTLLC_CMD: Memory corrupted (~x%d (mask=0x%x)) (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)", - changed, mask, op, cmd, lsa, ea, tag, size); - Emu.Pause(); - } - - break; - } - } - } - - if (changed > 1) - { - LOG_WARNING(Log::SPU, "MFC_PUTLLC_CMD: Reservation impossibru (~x%d (mask=0x%x)) (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)", - changed, mask, op, cmd, lsa, ea, tag, size); - - SPUDisAsm dis_asm(CPUDisAsm_InterpreterMode); - for (s32 i = PC; i < PC + 4 * 7; i += 4) - { - dis_asm.dump_pc = i; - dis_asm.offset = Memory.GetMemFromAddr(dmac.ls_offset); - const u32 opcode = Memory.Read32(i + dmac.ls_offset); - (*SPU_instr::rrr_list)(&dis_asm, opcode); - if (i >= 0 && i < 0x40000) - { - LOG_NOTICE(Log::SPU, "*** %s", dis_asm.last_opcode.c_str()); - } - } - } - } - else - { - MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE); - } - R_ADDR = 0; - } - else // store unconditional - { - if (R_ADDR) - { - m_events |= SPU_EVENT_LR; - } - - ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128); - if (op == MFC_PUTLLUC_CMD) - { - MFCArgs.AtomicStat.PushUncond(MFC_PUTLLUC_SUCCESS); - } - R_ADDR = 0; - } - } - break; - - default: - LOG_ERROR( Log::SPU, "Unknown MFC cmd. (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)", - op, cmd, lsa, ea, tag, size); - break; - } - } - - bool CheckEvents() // checks events - { - // SPU_EVENT_LR: - { - for (u32 i = 0; i < 16; i++) - { - if (*(u64*)&Memory[R_ADDR + i * 8] != R_DATA[i]) - { - m_events |= SPU_EVENT_LR; - R_ADDR = 0; - break; - } - } - } - - return (m_events & m_event_mask) != 0; - } - - u32 GetChannelCount(u32 ch) - { - switch(ch) - { - case SPU_WrOutMbox: return SPU.Out_MBox.GetFreeCount(); - case SPU_WrOutIntrMbox: return SPU.Out_IntrMBox.GetFreeCount(); - case SPU_RdInMbox: return SPU.In_MBox.GetCount(); - case MFC_RdTagStat: return MFC1.TagStatus.GetCount(); - case MFC_RdListStallStat: return StallStat.GetCount(); - case MFC_WrTagUpdate: return MFC1.TagStatus.GetCount(); // hack - case SPU_RdSigNotify1: return SPU.SNR[0].GetCount(); - case SPU_RdSigNotify2: return SPU.SNR[1].GetCount(); - case MFC_RdAtomicStat: return MFC1.AtomicStat.GetCount(); - case SPU_RdEventStat: return CheckEvents() ? 1 : 0; - - default: - { - LOG_ERROR(Log::SPU, "%s error: unknown/illegal channel (%d [%s]).", - __FUNCTION__, ch, spu_ch_name[ch]); - return 0; - } - } - } - - void WriteChannel(u32 ch, const SPU_GPR_hdr& r) - { - const u32 v = r._u32[3]; - - switch(ch) - { - case SPU_WrOutIntrMbox: - { - if (!group) // if RawSPU - { - if (Ini.HLELogging.GetValue()) LOG_NOTICE(Log::SPU, "SPU_WrOutIntrMbox: interrupt(v=0x%x)", v); - while (!SPU.Out_IntrMBox.Push(v)) - { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - if (Emu.IsStopped()) - { - LOG_WARNING(Log::SPU, "%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]); - return; - } - } - m_intrtag[2].stat |= 1; - if (CPUThread* t = Emu.GetCPU().GetThread(m_intrtag[2].thread)) - { - if (t->GetType() == CPU_THREAD_PPU && !t->IsAlive()) - { - PPUThread& ppu = *(PPUThread*)t; - ppu.FastStop(); - ppu.Run(); - ppu.FastCall(ppu.PC, ppu.GPR[2], ppu.m_interrupt_arg); - } - } - } - else - { - const u8 code = v >> 24; - if (code < 64) - { - /* ===== sys_spu_thread_send_event (used by spu_printf) ===== */ - - u8 spup = code & 63; - - u32 data; - if (!SPU.Out_MBox.Pop(data)) - { - LOG_ERROR(Log::SPU, "sys_spu_thread_send_event(v=0x%x, spup=%d): Out_MBox is empty", v, spup); - return; - } - - if (Ini.HLELogging.GetValue()) - { - LOG_NOTICE(Log::SPU, "sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x)", spup, v & 0x00ffffff, data); - } - - EventPort& port = SPUPs[spup]; - - std::lock_guard lock(port.m_mutex); - - if (!port.eq) - { - LOG_WARNING(Log::SPU, "sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x): event queue not connected", spup, (v & 0x00ffffff), data); - SPU.In_MBox.PushUncond(CELL_ENOTCONN); // TODO: check error passing - return; - } - - if (!port.eq->events.push(SYS_SPU_THREAD_EVENT_USER_KEY, GetCurrentCPUThread()->GetId(), ((u64)spup << 32) | (v & 0x00ffffff), data)) - { - SPU.In_MBox.PushUncond(CELL_EBUSY); - return; - } - - SPU.In_MBox.PushUncond(CELL_OK); - return; - } - else if (code < 128) - { - /* ===== sys_spu_thread_throw_event ===== */ - - const u8 spup = code & 63; - - u32 data; - if (!SPU.Out_MBox.Pop(data)) - { - LOG_ERROR(Log::SPU, "sys_spu_thread_throw_event(v=0x%x, spup=%d): Out_MBox is empty", v, spup); - return; - } - - //if (Ini.HLELogging.GetValue()) - { - LOG_WARNING(Log::SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x)", spup, v & 0x00ffffff, data); - } - - EventPort& port = SPUPs[spup]; - - std::lock_guard lock(port.m_mutex); - - if (!port.eq) - { - LOG_WARNING(Log::SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x): event queue not connected", spup, (v & 0x00ffffff), data); - return; - } - - // TODO: check passing spup value - if (!port.eq->events.push(SYS_SPU_THREAD_EVENT_USER_KEY, GetCurrentCPUThread()->GetId(), ((u64)spup << 32) | (v & 0x00ffffff), data)) - { - LOG_WARNING(Log::SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x) failed (queue is full)", spup, (v & 0x00ffffff), data); - return; - } - - return; - } - else if (code == 128) - { - /* ===== sys_event_flag_set_bit ===== */ - u32 flag = v & 0xffffff; - - u32 data; - if (!SPU.Out_MBox.Pop(data)) - { - LOG_ERROR(Log::SPU, "sys_event_flag_set_bit(v=0x%x (flag=%d)): Out_MBox is empty", v, flag); - return; - } - - if (flag > 63) - { - LOG_ERROR(Log::SPU, "sys_event_flag_set_bit(id=%d, v=0x%x): flag > 63", data, v, flag); - return; - } - - //if (Ini.HLELogging.GetValue()) - { - LOG_WARNING(Log::SPU, "sys_event_flag_set_bit(id=%d, v=0x%x (flag=%d))", data, v, flag); - } - - EventFlag* ef; - if (!Emu.GetIdManager().GetIDData(data, ef)) - { - LOG_ERROR(Log::SPU, "sys_event_flag_set_bit(id=%d, v=0x%x (flag=%d)): EventFlag not found", data, v, flag); - SPU.In_MBox.PushUncond(CELL_ESRCH); - return; - } - - u32 tid = GetCurrentCPUThread()->GetId(); - - ef->m_mutex.lock(tid); - ef->flags |= (u64)1 << flag; - if (u32 target = ef->check()) - { - // if signal, leave both mutexes locked... - ef->signal.lock(target); - ef->m_mutex.unlock(tid, target); - } - else - { - ef->m_mutex.unlock(tid); - } - - SPU.In_MBox.PushUncond(CELL_OK); - return; - } - else if (code == 192) - { - /* ===== sys_event_flag_set_bit_impatient ===== */ - u32 flag = v & 0xffffff; - - u32 data; - if (!SPU.Out_MBox.Pop(data)) - { - LOG_ERROR(Log::SPU, "sys_event_flag_set_bit_impatient(v=0x%x (flag=%d)): Out_MBox is empty", v, flag); - return; - } - - if (flag > 63) - { - LOG_ERROR(Log::SPU, "sys_event_flag_set_bit_impatient(id=%d, v=0x%x): flag > 63", data, v, flag); - return; - } - - //if (Ini.HLELogging.GetValue()) - { - LOG_WARNING(Log::SPU, "sys_event_flag_set_bit_impatient(id=%d, v=0x%x (flag=%d))", data, v, flag); - } - - EventFlag* ef; - if (!Emu.GetIdManager().GetIDData(data, ef)) - { - LOG_WARNING(Log::SPU, "sys_event_flag_set_bit_impatient(id=%d, v=0x%x (flag=%d)): EventFlag not found", data, v, flag); - return; - } - - u32 tid = GetCurrentCPUThread()->GetId(); - - ef->m_mutex.lock(tid); - ef->flags |= (u64)1 << flag; - if (u32 target = ef->check()) - { - // if signal, leave both mutexes locked... - ef->signal.lock(target); - ef->m_mutex.unlock(tid, target); - } - else - { - ef->m_mutex.unlock(tid); - } - - return; - } - else - { - u32 data; - if (SPU.Out_MBox.Pop(data)) - { - LOG_ERROR(Log::SPU, "SPU_WrOutIntrMbox: unknown data (v=0x%x); Out_MBox = 0x%x", v, data); - } - else - { - LOG_ERROR(Log::SPU, "SPU_WrOutIntrMbox: unknown data (v=0x%x)", v); - } - SPU.In_MBox.PushUncond(CELL_EINVAL); // ??? - return; - } - } - break; - } - - case SPU_WrOutMbox: - { - while (!SPU.Out_MBox.Push(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); - break; - } - - case MFC_WrTagMask: - { - MFC1.QueryMask.SetValue(v); - break; - } - - case MFC_WrTagUpdate: - { - MFC1.TagStatus.PushUncond(MFC1.QueryMask.GetValue()); - break; - } - - case MFC_LSA: - { - MFC1.LSA.SetValue(v); - break; - } - - case MFC_EAH: - { - MFC1.EAH.SetValue(v); - break; - } - - case MFC_EAL: - { - MFC1.EAL.SetValue(v); - break; - } - - case MFC_Size: - { - MFC1.Size_Tag.SetValue((MFC1.Size_Tag.GetValue() & 0xffff) | (v << 16)); - break; - } - - case MFC_TagID: - { - MFC1.Size_Tag.SetValue((MFC1.Size_Tag.GetValue() & ~0xffff) | (v & 0xffff)); - break; - } - - - case MFC_Cmd: - { - MFC1.CMDStatus.SetValue(v); - EnqMfcCmd(MFC1); - break; - } - - case MFC_WrListStallAck: - { - if (v >= 32) - { - LOG_ERROR(Log::SPU, "MFC_WrListStallAck error: invalid tag(%d)", v); - return; - } - StalledList temp = StallList[v]; - if (!temp.MFCArgs) - { - LOG_ERROR(Log::SPU, "MFC_WrListStallAck error: empty tag(%d)", v); - return; - } - StallList[v].MFCArgs = nullptr; - ListCmd(temp.lsa, temp.ea, temp.tag, temp.size, temp.cmd, *temp.MFCArgs); - break; - } - - case SPU_WrDec: - { - m_dec_start = get_time(); - m_dec_value = v; - break; - } - - case SPU_WrEventMask: - { - m_event_mask = v; - if (v & ~(SPU_EVENT_IMPLEMENTED)) LOG_ERROR(Log::SPU, "SPU_WrEventMask: unsupported event masked (0x%x)"); - break; - } - - case SPU_WrEventAck: - { - m_events &= ~v; - break; - } - - default: - { - LOG_ERROR(Log::SPU, "%s error (v=0x%x): unknown/illegal channel (%d [%s]).", __FUNCTION__, v, ch, spu_ch_name[ch]); - break; - } - } - - if (Emu.IsStopped()) LOG_WARNING(Log::SPU, "%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]); - } - - void ReadChannel(SPU_GPR_hdr& r, u32 ch) - { - r.Reset(); - u32& v = r._u32[3]; - - switch(ch) - { - case SPU_RdInMbox: - { - while (!SPU.In_MBox.Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); - break; - } - - case MFC_RdTagStat: - { - while (!MFC1.TagStatus.Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); - break; - } - - case MFC_RdTagMask: - { - v = MFC1.QueryMask.GetValue(); - break; - } - - case SPU_RdSigNotify1: - { - while (!SPU.SNR[0].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); - break; - } - - case SPU_RdSigNotify2: - { - while (!SPU.SNR[1].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); - break; - } - - case MFC_RdAtomicStat: - { - while (!MFC1.AtomicStat.Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); - break; - } - - case MFC_RdListStallStat: - { - while (!StallStat.Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); - break; - } - - case SPU_RdDec: - { - v = m_dec_value - (u32)(get_time() - m_dec_start); - break; - } - - case SPU_RdEventMask: - { - v = m_event_mask; - break; - } - - case SPU_RdEventStat: - { - while (!CheckEvents() && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); - v = m_events & m_event_mask; - break; - } - - case SPU_RdMachStat: - { - v = 1; // hack (not isolated, interrupts enabled) - // TODO: check value - break; - } - - default: - { - LOG_ERROR(Log::SPU, "%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); - break; - } - } - - if (Emu.IsStopped()) LOG_WARNING(Log::SPU, "%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]); - } - - void StopAndSignal(u32 code) - { - SetExitStatus(code); // exit code (not status) - - switch (code) - { - case 0x110: /* ===== sys_spu_thread_receive_event ===== */ - { - u32 spuq = 0; - if (!SPU.Out_MBox.Pop(spuq)) - { - LOG_ERROR(Log::SPU, "sys_spu_thread_receive_event: cannot read Out_MBox"); - SPU.In_MBox.PushUncond(CELL_EINVAL); // ??? - return; - } - - if (SPU.In_MBox.GetCount()) - { - LOG_ERROR(Log::SPU, "sys_spu_thread_receive_event(spuq=0x%x): In_MBox is not empty", spuq); - SPU.In_MBox.PushUncond(CELL_EBUSY); // ??? - return; - } - - if (Ini.HLELogging.GetValue()) - { - LOG_NOTICE(Log::SPU, "sys_spu_thread_receive_event(spuq=0x%x)", spuq); - } - - EventQueue* eq; - if (!SPUQs.GetEventQueue(FIX_SPUQ(spuq), eq)) - { - SPU.In_MBox.PushUncond(CELL_EINVAL); // TODO: check error value - return; - } - - u32 tid = GetId(); - - eq->sq.push(tid); // add thread to sleep queue - - while (true) - { - switch (eq->owner.trylock(tid)) - { - case SMR_OK: - if (!eq->events.count()) - { - eq->owner.unlock(tid); - break; - } - else - { - u32 next = (eq->protocol == SYS_SYNC_FIFO) ? eq->sq.pop() : eq->sq.pop_prio(); - if (next != tid) - { - eq->owner.unlock(tid, next); - break; - } - } - case SMR_SIGNAL: - { - sys_event_data event; - eq->events.pop(event); - eq->owner.unlock(tid); - SPU.In_MBox.PushUncond(CELL_OK); - SPU.In_MBox.PushUncond(event.data1); - SPU.In_MBox.PushUncond(event.data2); - SPU.In_MBox.PushUncond(event.data3); - return; - } - case SMR_FAILED: break; - default: eq->sq.invalidate(tid); SPU.In_MBox.PushUncond(CELL_ECANCELED); return; - } - - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - if (Emu.IsStopped()) - { - LOG_WARNING(Log::SPU, "sys_spu_thread_receive_event(spuq=0x%x) aborted", spuq); - eq->sq.invalidate(tid); - return; - } - } - } - break; - case 0x102: - if (!SPU.Out_MBox.GetCount()) - { - LOG_ERROR(Log::SPU, "sys_spu_thread_exit (no status, code 0x102)"); - } - else if (Ini.HLELogging.GetValue()) - { - // the real exit status - LOG_NOTICE(Log::SPU, "sys_spu_thread_exit (status=0x%x)", SPU.Out_MBox.GetValue()); - } - SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_STOP); - Stop(); - break; - default: - if (!SPU.Out_MBox.GetCount()) - { - LOG_ERROR(Log::SPU, "Unknown STOP code: 0x%x (no message)", code); - } - else - { - LOG_ERROR(Log::SPU, "Unknown STOP code: 0x%x (message=0x%x)", code, SPU.Out_MBox.GetValue()); - } - SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_STOP); - Stop(); - break; - } - } + void StopAndSignal(u32 code); virtual u8 ReadLS8 (const u32 lsa) const { return Memory.Read8 (lsa + m_offset); } virtual u16 ReadLS16 (const u32 lsa) const { return Memory.Read16 (lsa + m_offset); } diff --git a/rpcs3/Emu/FS/VFS.cpp b/rpcs3/Emu/FS/VFS.cpp index 1776343ce8..8263fa1acb 100644 --- a/rpcs3/Emu/FS/VFS.cpp +++ b/rpcs3/Emu/FS/VFS.cpp @@ -1,5 +1,5 @@ #include "stdafx.h" -#include "Utilities/Log.h" +#include #include "VFS.h" #include "Emu/HDD/HDD.h" diff --git a/rpcs3/Emu/FS/vfsDir.cpp b/rpcs3/Emu/FS/vfsDir.cpp index e648745fe8..aaec50c1ff 100644 --- a/rpcs3/Emu/FS/vfsDir.cpp +++ b/rpcs3/Emu/FS/vfsDir.cpp @@ -1,5 +1,4 @@ #include "stdafx.h" -#include "Utilities/Log.h" #include "Emu/System.h" #include "vfsDir.h" diff --git a/rpcs3/Emu/FS/vfsFile.cpp b/rpcs3/Emu/FS/vfsFile.cpp index f30a2de9a5..a44d0f63f2 100644 --- a/rpcs3/Emu/FS/vfsFile.cpp +++ b/rpcs3/Emu/FS/vfsFile.cpp @@ -1,5 +1,4 @@ #include "stdafx.h" -#include "Utilities/Log.h" #include "Emu/System.h" #include "vfsFile.h" diff --git a/rpcs3/Emu/FS/vfsStreamMemory.cpp b/rpcs3/Emu/FS/vfsStreamMemory.cpp index 03a71b5d38..102f4b3f8c 100644 --- a/rpcs3/Emu/FS/vfsStreamMemory.cpp +++ b/rpcs3/Emu/FS/vfsStreamMemory.cpp @@ -1,5 +1,4 @@ #include "stdafx.h" -#include "Utilities/Log.h" #include "Emu/Memory/Memory.h" #include "vfsStreamMemory.h" diff --git a/rpcs3/Emu/HDD/HDD.cpp b/rpcs3/Emu/HDD/HDD.cpp index 27927c3218..80eda63429 100644 --- a/rpcs3/Emu/HDD/HDD.cpp +++ b/rpcs3/Emu/HDD/HDD.cpp @@ -2,6 +2,337 @@ #include "Utilities/Log.h" #include "HDD.h" +void vfsHDDManager::CreateBlock(vfsHDD_Block& block) +{ + block.is_used = true; + block.next_block = 0; +} + +void vfsHDDManager::CreateEntry(vfsHDD_Entry& entry) +{ + memset(&entry, 0, sizeof(vfsHDD_Entry)); + u64 ctime = time(nullptr); + entry.atime = ctime; + entry.ctime = ctime; + entry.mtime = ctime; + entry.access = vfsReadWrite; + CreateBlock(entry); +} + +void vfsHDDManager::CreateHDD(const std::string& path, u64 size, u64 block_size) +{ + rFile f(path, rFile::write); + + static const u64 cur_dir_block = 1; + + vfsHDD_Hdr hdr; + CreateBlock(hdr); + hdr.next_block = cur_dir_block; + hdr.magic = g_hdd_magic; + hdr.version = g_hdd_version; + hdr.block_count = (size + block_size) / block_size; + hdr.block_size = block_size; + f.Write(&hdr, sizeof(vfsHDD_Hdr)); + + { + vfsHDD_Entry entry; + CreateEntry(entry); + entry.type = vfsHDD_Entry_Dir; + entry.data_block = hdr.next_block; + entry.next_block = 0; + + f.Seek(cur_dir_block * hdr.block_size); + f.Write(&entry, sizeof(vfsHDD_Entry)); + f.Write("."); + } + + u8 null = 0; + f.Seek(hdr.block_count * hdr.block_size - sizeof(null)); + f.Write(&null, sizeof(null)); +} + +void vfsHDDManager::Format() +{ +} + +void vfsHDDManager::AppendEntry(vfsHDD_Entry entry) +{ +} + +bool vfsHDDFile::goto_block(u64 n) +{ + vfsHDD_Block block_info; + + if (m_info.data_block >= m_hdd_info.block_count) + { + return false; + } + + m_hdd.Seek(m_info.data_block * m_hdd_info.block_size); + block_info.next_block = m_info.data_block; + + for (u64 i = 0; i= m_hdd_info.block_count) + { + return false; + } + + m_hdd.Seek(block_info.next_block * m_hdd_info.block_size); + m_hdd.Read(&block_info, sizeof(vfsHDD_Block)); + } + + return true; +} + +void vfsHDDFile::RemoveBlocks(u64 start_block) +{ + vfsHDD_Block block_info; + block_info.next_block = start_block; + + while (block_info.next_block && block_info.is_used) + { + u64 offset = block_info.next_block * m_hdd_info.block_size; + + ReadBlock(offset, block_info); + WriteBlock(offset, g_null_block); + } +} + +void vfsHDDFile::WriteBlock(u64 block, const vfsHDD_Block& data) +{ + m_hdd.Seek(block * m_hdd_info.block_size); + m_hdd.Write(&data, sizeof(vfsHDD_Block)); +} + +void vfsHDDFile::ReadBlock(u64 block, vfsHDD_Block& data) +{ + m_hdd.Seek(block * m_hdd_info.block_size); + m_hdd.Read(&data, sizeof(vfsHDD_Block)); +} + +void vfsHDDFile::WriteEntry(u64 block, const vfsHDD_Entry& data) +{ + m_hdd.Seek(block * m_hdd_info.block_size); + m_hdd.Write(&data, sizeof(vfsHDD_Entry)); +} + +void vfsHDDFile::ReadEntry(u64 block, vfsHDD_Entry& data) +{ + m_hdd.Seek(block * m_hdd_info.block_size); + m_hdd.Read(&data, sizeof(vfsHDD_Entry)); +} + +void vfsHDDFile::ReadEntry(u64 block, vfsHDD_Entry& data, std::string& name) +{ + m_hdd.Seek(block * m_hdd_info.block_size); + m_hdd.Read(&data, sizeof(vfsHDD_Entry)); + name.resize(GetMaxNameLen()); + m_hdd.Read(&name.front(), GetMaxNameLen()); +} + +void vfsHDDFile::ReadEntry(u64 block, std::string& name) +{ + m_hdd.Seek(block * m_hdd_info.block_size + sizeof(vfsHDD_Entry)); + name.resize(GetMaxNameLen()); + m_hdd.Read(&name.front(), GetMaxNameLen()); +} + +void vfsHDDFile::WriteEntry(u64 block, const vfsHDD_Entry& data, const std::string& name) +{ + m_hdd.Seek(block * m_hdd_info.block_size); + m_hdd.Write(&data, sizeof(vfsHDD_Entry)); + m_hdd.Write(name.c_str(), std::min(GetMaxNameLen() - 1, name.length() + 1)); +} + +void vfsHDDFile::Open(u64 info_block) +{ + m_info_block = info_block; + ReadEntry(m_info_block, m_info); + m_position = 0; + m_cur_block = m_info.data_block; +} + +u64 vfsHDDFile::FindFreeBlock() +{ + vfsHDD_Block block_info; + + for (u64 i = 0; i(block_size - m_position, size); + + vfsHDD_Block cur_block_info; + m_hdd.Seek(m_cur_block * m_hdd_info.block_size); + m_hdd.Read(&cur_block_info, sizeof(vfsHDD_Block)); + m_hdd.Seek(m_cur_block * m_hdd_info.block_size + sizeof(vfsHDD_Block)+m_position); + m_hdd.Read(dst, rsize); + size -= rsize; + m_position += rsize; + if (!size) + { + return rsize; + } + + u64 offset = rsize; + + for (; size; size -= rsize, offset += rsize) + { + if (!cur_block_info.is_used || !cur_block_info.next_block || cur_block_info.next_block >= m_hdd_info.block_count) + { + return offset; + } + + m_cur_block = cur_block_info.next_block; + rsize = std::min(block_size, size); + + m_hdd.Seek(cur_block_info.next_block * m_hdd_info.block_size); + m_hdd.Read(&cur_block_info, sizeof(vfsHDD_Block)); + + if (m_hdd.Read((u8*)dst + offset, rsize) != rsize) + { + return offset; + } + } + + m_position = rsize; + + return offset; +} + +u64 vfsHDDFile::Write(const void* src, u64 size) +{ + if (!size) + return 0; + + //vfsDeviceLocker lock(m_hdd); + + const u32 block_size = m_hdd_info.block_size - sizeof(vfsHDD_Block); + + if (!m_cur_block) + { + if (!m_info.data_block) + { + u64 new_block = FindFreeBlock(); + + if (!new_block) + { + return 0; + } + + WriteBlock(new_block, g_used_block); + m_info.data_block = new_block; + m_info.size = 0; + SaveInfo(); + } + + m_cur_block = m_info.data_block; + m_position = 0; + } + + u64 wsize = std::min(block_size - m_position, size); + + vfsHDD_Block block_info; + ReadBlock(m_cur_block, block_info); + + if (wsize) + { + m_hdd.Seek(m_cur_block * m_hdd_info.block_size + sizeof(vfsHDD_Block)+m_position); + m_hdd.Write(src, wsize); + size -= wsize; + m_info.size += wsize; + m_position += wsize; + SaveInfo(); + + if (!size) + return wsize; + } + + u64 last_block = m_cur_block; + block_info.is_used = true; + u64 offset = wsize; + + for (; size; size -= wsize, offset += wsize, m_info.size += wsize) + { + u64 new_block = FindFreeBlock(); + + if (!new_block) + { + m_position = 0; + SaveInfo(); + return offset; + } + + m_cur_block = new_block; + wsize = std::min(block_size, size); + + block_info.next_block = m_cur_block; + m_hdd.Seek(last_block * m_hdd_info.block_size); + if (m_hdd.Write(&block_info, sizeof(vfsHDD_Block)) != sizeof(vfsHDD_Block)) + { + m_position = 0; + SaveInfo(); + return offset; + } + + block_info.next_block = 0; + m_hdd.Seek(m_cur_block * m_hdd_info.block_size); + if (m_hdd.Write(&block_info, sizeof(vfsHDD_Block)) != sizeof(vfsHDD_Block)) + { + m_position = 0; + SaveInfo(); + return offset; + } + if ((m_position = m_hdd.Write((u8*)src + offset, wsize)) != wsize) + { + m_info.size += wsize; + SaveInfo(); + return offset; + } + + last_block = m_cur_block; + } + + SaveInfo(); + m_position = wsize; + return offset; +} + vfsDeviceHDD::vfsDeviceHDD(const std::string& hdd_path) : m_hdd_path(hdd_path) { } @@ -15,3 +346,438 @@ vfsDirBase* vfsDeviceHDD::GetNewDirStream() { return nullptr; } + +vfsHDD::vfsHDD(vfsDevice* device, const std::string& hdd_path) + : m_hdd_file(device) + , m_file(m_hdd_file, m_hdd_info) + , m_hdd_path(hdd_path) + , vfsFileBase(device) +{ + m_hdd_file.Open(hdd_path, vfsReadWrite); + m_hdd_file.Read(&m_hdd_info, sizeof(vfsHDD_Hdr)); + m_cur_dir_block = m_hdd_info.next_block; + if (!m_hdd_info.block_size) + { + LOG_ERROR(HLE, "Bad block size!"); + m_hdd_info.block_size = 2048; + } + m_hdd_file.Seek(m_cur_dir_block * m_hdd_info.block_size); + m_hdd_file.Read(&m_cur_dir, sizeof(vfsHDD_Entry)); +} + +bool vfsHDD::SearchEntry(const std::string& name, u64& entry_block, u64* parent_block) +{ + u64 last_block = 0; + u64 block = m_cur_dir_block; + vfsHDD_Entry entry; + std::string buf; + + while (block) + { + ReadEntry(block, entry, buf); + + if (fmt::CmpNoCase(name, buf) == 0) + { + entry_block = block; + if (parent_block) + *parent_block = last_block; + + return true; + } + + last_block = block; + block = entry.is_used ? entry.next_block : 0ULL; + } + + return false; +} + +int vfsHDD::OpenDir(const std::string& name) +{ + LOG_WARNING(HLE, "OpenDir(%s)", name.c_str()); + u64 entry_block; + if (!SearchEntry(name, entry_block)) + return -1; + + m_hdd_file.Seek(entry_block * m_hdd_info.block_size); + vfsHDD_Entry entry; + m_hdd_file.Read(&entry, sizeof(vfsHDD_Entry)); + if (entry.type == vfsHDD_Entry_File) + return 1; + + m_cur_dir_block = entry.data_block; + ReadEntry(m_cur_dir_block, m_cur_dir); + + return 0; +} + +bool vfsHDD::Rename(const std::string& from, const std::string& to) +{ + u64 entry_block; + if (!SearchEntry(from, entry_block)) + { + return false; + } + + vfsHDD_Entry entry; + ReadEntry(entry_block, entry); + WriteEntry(entry_block, entry, to); + + return true; +} + +u64 vfsHDD::FindFreeBlock() +{ + vfsHDD_Block block_info; + + for (u64 i = 0; i(GetMaxNameLen() - 1, name.length() + 1)); +} + +bool vfsHDD::Create(vfsHDD_EntryType type, const std::string& name) +{ + if (HasEntry(name)) + { + return false; + } + + u64 new_block = FindFreeBlock(); + if (!new_block) + { + return false; + } + + LOG_NOTICE(HLE, "CREATING ENTRY AT 0x%llx", new_block); + WriteBlock(new_block, g_used_block); + + { + vfsHDD_Entry new_entry; + vfsHDDManager::CreateEntry(new_entry); + new_entry.next_block = 0; + new_entry.type = type; + + if (type == vfsHDD_Entry_Dir) + { + u64 block_cur = FindFreeBlock(); + + if (!block_cur) + { + return false; + } + + WriteBlock(block_cur, g_used_block); + + u64 block_last = FindFreeBlock(); + + if (!block_last) + { + return false; + } + + WriteBlock(block_last, g_used_block); + + vfsHDD_Entry entry_cur, entry_last; + vfsHDDManager::CreateEntry(entry_cur); + vfsHDDManager::CreateEntry(entry_last); + + entry_cur.type = vfsHDD_Entry_Dir; + entry_cur.data_block = block_cur; + entry_cur.next_block = block_last; + + entry_last.type = vfsHDD_Entry_Dir; + entry_last.data_block = m_cur_dir_block; + entry_last.next_block = 0; + + new_entry.data_block = block_cur; + + WriteEntry(block_cur, entry_cur, "."); + WriteEntry(block_last, entry_last, ".."); + } + + WriteEntry(new_block, new_entry, name); + } + + { + u64 block = m_cur_dir_block; + + vfsHDD_Block tmp; + while (block) + { + ReadBlock(block, tmp); + + if (!tmp.next_block) + break; + + block = tmp.next_block; + } + + tmp.next_block = new_block; + WriteBlock(block, tmp); + } + + return true; +} + +bool vfsHDD::GetFirstEntry(u64& block, vfsHDD_Entry& entry, std::string& name) +{ + if (!m_cur_dir_block) + { + return false; + } + + ReadEntry(m_cur_dir_block, entry, name); + block = entry.is_used ? entry.next_block : 0; + + return true; +} + +bool vfsHDD::GetNextEntry(u64& block, vfsHDD_Entry& entry, std::string& name) +{ + if (!block) + { + return false; + } + + ReadEntry(block, entry, name); + + block = entry.is_used ? entry.next_block : 0; + return true; +} + +bool vfsHDD::Open(const std::string& path, vfsOpenMode mode) +{ + const char* s = path.c_str(); + u64 from = 0; + u64 pos = 0; + u64 file_pos = -1; + + do + { + if (s[pos] == '\\' || s[pos] == '/' || s[pos] == '\0') // ??? + { + if (file_pos != -1) + { + return false; + } + + if (from != -1) + { + if (pos - from > 1) + { + int res = OpenDir(std::string(s + from, pos)); + if (res == -1) + { + return false; + } + + if (res == 1) + { + file_pos = from; + } + } + + from = pos; + } + else + { + from = pos; + } + } + } while (s[pos++] != '\0'); + + if (file_pos == -1) + { + return false; + } + + u64 file_block; + if (!SearchEntry(std::string(s + file_pos), file_block)) + { + return false; + } + + LOG_NOTICE(HLE, "ENTRY FOUND AT 0x%llx", file_block); + m_file.Open(file_block); + + return vfsFileBase::Open(path, mode); +} + +bool vfsHDD::HasEntry(const std::string& name) +{ + u64 file_block; + if (!SearchEntry(name, file_block)) + { + return false; + } + + return true; +} + +void vfsHDD::RemoveBlocksDir(u64 start_block) +{ + std::string name; + u64 block = start_block; + vfsHDD_Entry entry; + + while (block) + { + ReadEntry(block, entry, name); + WriteBlock(block, g_null_block); + + if (entry.type == vfsHDD_Entry_Dir && name != "." && name != "..") + { + LOG_WARNING(HLE, "Removing sub folder '%s'", name.c_str()); + RemoveBlocksDir(entry.data_block); + } + else if (entry.type == vfsHDD_Entry_File) + { + RemoveBlocksFile(entry.data_block); + } + + block = entry.next_block; + } +} + +void vfsHDD::RemoveBlocksFile(u64 start_block) +{ + u64 block = start_block; + vfsHDD_Block block_data; + + while (block) + { + ReadBlock(block, block_data); + WriteBlock(block, g_null_block); + + block = block_data.next_block; + } +} + +bool vfsHDD::RemoveEntry(const std::string& name) +{ + u64 entry_block, parent_entry; + if (!SearchEntry(name, entry_block, &parent_entry)) + { + return false; + } + + vfsHDD_Entry entry; + ReadEntry(entry_block, entry); + if (entry.type == vfsHDD_Entry_Dir) + { + RemoveBlocksDir(entry.data_block); + } + else if (entry.type == vfsHDD_Entry_File) + { + RemoveBlocksFile(entry.data_block); + } + + if (parent_entry) + { + u64 next = entry.next_block; + ReadEntry(parent_entry, entry); + entry.next_block = next; + WriteEntry(parent_entry, entry); + } + WriteBlock(entry_block, g_null_block); + return true; +} + +bool vfsHDD::Create(const std::string& path) +{ + return false; +} + +u32 vfsHDD::Write(const void* src, u32 size) +{ + return vfsFileBase::Write(src, m_file.Write(src, size)); +} + +u32 vfsHDD::Read(void* dst, u32 size) +{ + return vfsFileBase::Read(dst, m_file.Read(dst, size)); +} + +u64 vfsHDD::Seek(s64 offset, vfsSeekMode mode) +{ + switch (mode) + { + case vfsSeekCur: + m_file.Seek(Tell() + offset); + break; + + case vfsSeekSet: + m_file.Seek(offset); + break; + + case vfsSeekEnd: + m_file.Seek(m_file.GetSize() + offset); + break; + } + + return vfsFileBase::Seek(offset, mode); +} + +bool vfsHDD::Eof() +{ + return m_file.Eof(); +} + +u64 vfsHDD::GetSize() +{ + return m_file.GetSize(); +} \ No newline at end of file diff --git a/rpcs3/Emu/HDD/HDD.h b/rpcs3/Emu/HDD/HDD.h index d68f8dbbfc..1c7cba7c5f 100644 --- a/rpcs3/Emu/HDD/HDD.h +++ b/rpcs3/Emu/HDD/HDD.h @@ -44,62 +44,15 @@ struct vfsHDD_Entry : public vfsHDD_Block class vfsHDDManager { public: - static void CreateBlock(vfsHDD_Block& block) - { - block.is_used = true; - block.next_block = 0; - } + static void CreateBlock(vfsHDD_Block& block); - static void CreateEntry(vfsHDD_Entry& entry) - { - memset(&entry, 0, sizeof(vfsHDD_Entry)); - u64 ctime = time(nullptr); - entry.atime = ctime; - entry.ctime = ctime; - entry.mtime = ctime; - entry.access = vfsReadWrite; - CreateBlock(entry); - } + static void CreateEntry(vfsHDD_Entry& entry); - static void CreateHDD(const std::string& path, u64 size, u64 block_size) - { - rFile f(path, rFile::write); + static void CreateHDD(const std::string& path, u64 size, u64 block_size); - static const u64 cur_dir_block = 1; + void Format(); - vfsHDD_Hdr hdr; - CreateBlock(hdr); - hdr.next_block = cur_dir_block; - hdr.magic = g_hdd_magic; - hdr.version = g_hdd_version; - hdr.block_count = (size + block_size) / block_size; - hdr.block_size = block_size; - f.Write(&hdr, sizeof(vfsHDD_Hdr)); - - { - vfsHDD_Entry entry; - CreateEntry(entry); - entry.type = vfsHDD_Entry_Dir; - entry.data_block = hdr.next_block; - entry.next_block = 0; - - f.Seek(cur_dir_block * hdr.block_size); - f.Write(&entry, sizeof(vfsHDD_Entry)); - f.Write("."); - } - - u8 null = 0; - f.Seek(hdr.block_count * hdr.block_size - sizeof(null)); - f.Write(&null, sizeof(null)); - } - - void Format() - { - } - - void AppendEntry(vfsHDD_Entry entry) - { - } + void AppendEntry(vfsHDD_Entry entry); }; @@ -112,91 +65,23 @@ class vfsHDDFile u32 m_position; u64 m_cur_block; - bool goto_block(u64 n) - { - vfsHDD_Block block_info; + bool goto_block(u64 n); - if(m_info.data_block >= m_hdd_info.block_count) - { - return false; - } + void RemoveBlocks(u64 start_block); - m_hdd.Seek(m_info.data_block * m_hdd_info.block_size); - block_info.next_block = m_info.data_block; + void WriteBlock(u64 block, const vfsHDD_Block& data); - for(u64 i=0; i= m_hdd_info.block_count) - { - return false; - } + void ReadBlock(u64 block, vfsHDD_Block& data); - m_hdd.Seek(block_info.next_block * m_hdd_info.block_size); - m_hdd.Read(&block_info, sizeof(vfsHDD_Block)); - } + void WriteEntry(u64 block, const vfsHDD_Entry& data); - return true; - } + void ReadEntry(u64 block, vfsHDD_Entry& data); - void RemoveBlocks(u64 start_block) - { - vfsHDD_Block block_info; - block_info.next_block = start_block; + void ReadEntry(u64 block, vfsHDD_Entry& data, std::string& name); - while(block_info.next_block && block_info.is_used) - { - u64 offset = block_info.next_block * m_hdd_info.block_size; + void ReadEntry(u64 block, std::string& name); - ReadBlock(offset, block_info); - WriteBlock(offset, g_null_block); - } - } - - void WriteBlock(u64 block, const vfsHDD_Block& data) - { - m_hdd.Seek(block * m_hdd_info.block_size); - m_hdd.Write(&data, sizeof(vfsHDD_Block)); - } - - void ReadBlock(u64 block, vfsHDD_Block& data) - { - m_hdd.Seek(block * m_hdd_info.block_size); - m_hdd.Read(&data, sizeof(vfsHDD_Block)); - } - - void WriteEntry(u64 block, const vfsHDD_Entry& data) - { - m_hdd.Seek(block * m_hdd_info.block_size); - m_hdd.Write(&data, sizeof(vfsHDD_Entry)); - } - - void ReadEntry(u64 block, vfsHDD_Entry& data) - { - m_hdd.Seek(block * m_hdd_info.block_size); - m_hdd.Read(&data, sizeof(vfsHDD_Entry)); - } - - void ReadEntry(u64 block, vfsHDD_Entry& data, std::string& name) - { - m_hdd.Seek(block * m_hdd_info.block_size); - m_hdd.Read(&data, sizeof(vfsHDD_Entry)); - name.resize(GetMaxNameLen()); - m_hdd.Read(&name.front(), GetMaxNameLen()); - } - - void ReadEntry(u64 block, std::string& name) - { - m_hdd.Seek(block * m_hdd_info.block_size + sizeof(vfsHDD_Entry)); - name.resize(GetMaxNameLen()); - m_hdd.Read(&name.front(), GetMaxNameLen()); - } - - void WriteEntry(u64 block, const vfsHDD_Entry& data, const std::string& name) - { - m_hdd.Seek(block * m_hdd_info.block_size); - m_hdd.Write(&data, sizeof(vfsHDD_Entry)); - m_hdd.Write(name.c_str(), std::min(GetMaxNameLen() - 1, name.length() + 1)); - } + void WriteEntry(u64 block, const vfsHDD_Entry& data, const std::string& name); __forceinline u32 GetMaxNameLen() const { @@ -214,198 +99,22 @@ public: { } - void Open(u64 info_block) - { - m_info_block = info_block; - ReadEntry(m_info_block, m_info); - m_position = 0; - m_cur_block = m_info.data_block; - } + void Open(u64 info_block); - u64 FindFreeBlock() - { - vfsHDD_Block block_info; - - for(u64 i = 0; i(block_size - m_position, size); - - vfsHDD_Block cur_block_info; - m_hdd.Seek(m_cur_block * m_hdd_info.block_size); - m_hdd.Read(&cur_block_info, sizeof(vfsHDD_Block)); - m_hdd.Seek(m_cur_block * m_hdd_info.block_size + sizeof(vfsHDD_Block) + m_position); - m_hdd.Read(dst, rsize); - size -= rsize; - m_position += rsize; - if(!size) - { - return rsize; - } - - u64 offset = rsize; - - for(; size; size -= rsize, offset += rsize) - { - if(!cur_block_info.is_used || !cur_block_info.next_block || cur_block_info.next_block >= m_hdd_info.block_count) - { - return offset; - } - - m_cur_block = cur_block_info.next_block; - rsize = std::min(block_size, size); - - m_hdd.Seek(cur_block_info.next_block * m_hdd_info.block_size); - m_hdd.Read(&cur_block_info, sizeof(vfsHDD_Block)); - - if(m_hdd.Read((u8*)dst + offset, rsize) != rsize) - { - return offset; - } - } - - m_position = rsize; - - return offset; - } - - u64 Write(const void* src, u64 size) - { - if(!size) - return 0; - - //vfsDeviceLocker lock(m_hdd); - - const u32 block_size = m_hdd_info.block_size - sizeof(vfsHDD_Block); - - if(!m_cur_block) - { - if(!m_info.data_block) - { - u64 new_block = FindFreeBlock(); - - if(!new_block) - { - return 0; - } - - WriteBlock(new_block, g_used_block); - m_info.data_block = new_block; - m_info.size = 0; - SaveInfo(); - } - - m_cur_block = m_info.data_block; - m_position = 0; - } - - u64 wsize = std::min(block_size - m_position, size); - - vfsHDD_Block block_info; - ReadBlock(m_cur_block, block_info); - - if(wsize) - { - m_hdd.Seek(m_cur_block * m_hdd_info.block_size + sizeof(vfsHDD_Block) + m_position); - m_hdd.Write(src, wsize); - size -= wsize; - m_info.size += wsize; - m_position += wsize; - SaveInfo(); - - if(!size) - return wsize; - } - - u64 last_block = m_cur_block; - block_info.is_used = true; - u64 offset = wsize; - - for(; size; size -= wsize, offset += wsize, m_info.size += wsize) - { - u64 new_block = FindFreeBlock(); - - if(!new_block) - { - m_position = 0; - SaveInfo(); - return offset; - } - - m_cur_block = new_block; - wsize = std::min(block_size, size); - - block_info.next_block = m_cur_block; - m_hdd.Seek(last_block * m_hdd_info.block_size); - if(m_hdd.Write(&block_info, sizeof(vfsHDD_Block)) != sizeof(vfsHDD_Block)) - { - m_position = 0; - SaveInfo(); - return offset; - } - - block_info.next_block = 0; - m_hdd.Seek(m_cur_block * m_hdd_info.block_size); - if(m_hdd.Write(&block_info, sizeof(vfsHDD_Block)) != sizeof(vfsHDD_Block)) - { - m_position = 0; - SaveInfo(); - return offset; - } - if((m_position = m_hdd.Write((u8*)src + offset, wsize)) != wsize) - { - m_info.size += wsize; - SaveInfo(); - return offset; - } - - last_block = m_cur_block; - } - - SaveInfo(); - m_position = wsize; - return offset; - } + u64 Write(const void* src, u64 size); bool Eof() const { @@ -434,444 +143,60 @@ class vfsHDD : public vfsFileBase vfsHDDFile m_file; public: - vfsHDD(vfsDevice* device, const std::string& hdd_path) - : m_hdd_file(device) - , m_file(m_hdd_file, m_hdd_info) - , m_hdd_path(hdd_path) - , vfsFileBase(device) - { - m_hdd_file.Open(hdd_path, vfsReadWrite); - m_hdd_file.Read(&m_hdd_info, sizeof(vfsHDD_Hdr)); - m_cur_dir_block = m_hdd_info.next_block; - if(!m_hdd_info.block_size) - { - LOG_ERROR(HLE, "Bad block size!"); - m_hdd_info.block_size = 2048; - } - m_hdd_file.Seek(m_cur_dir_block * m_hdd_info.block_size); - m_hdd_file.Read(&m_cur_dir, sizeof(vfsHDD_Entry)); - } + vfsHDD(vfsDevice* device, const std::string& hdd_path); __forceinline u32 GetMaxNameLen() const { return m_hdd_info.block_size - sizeof(vfsHDD_Entry); } - bool SearchEntry(const std::string& name, u64& entry_block, u64* parent_block = nullptr) - { - u64 last_block = 0; - u64 block = m_cur_dir_block; - vfsHDD_Entry entry; - std::string buf; + bool SearchEntry(const std::string& name, u64& entry_block, u64* parent_block = nullptr); - while(block) - { - ReadEntry(block, entry, buf); + int OpenDir(const std::string& name); - if (fmt::CmpNoCase(name,buf) == 0) - { - entry_block = block; - if(parent_block) - *parent_block = last_block; + bool Rename(const std::string& from, const std::string& to); - return true; - } + u64 FindFreeBlock(); - last_block = block; - block = entry.is_used ? entry.next_block : 0ULL; - } + void WriteBlock(u64 block, const vfsHDD_Block& data); - return false; - } + void ReadBlock(u64 block, vfsHDD_Block& data); - int OpenDir(const std::string& name) - { - LOG_WARNING(HLE, "OpenDir(%s)", name.c_str()); - u64 entry_block; - if(!SearchEntry(name, entry_block)) - return -1; + void WriteEntry(u64 block, const vfsHDD_Entry& data); - m_hdd_file.Seek(entry_block * m_hdd_info.block_size); - vfsHDD_Entry entry; - m_hdd_file.Read(&entry, sizeof(vfsHDD_Entry)); - if(entry.type == vfsHDD_Entry_File) - return 1; + void ReadEntry(u64 block, vfsHDD_Entry& data); - m_cur_dir_block = entry.data_block; - ReadEntry(m_cur_dir_block, m_cur_dir); + void ReadEntry(u64 block, vfsHDD_Entry& data, std::string& name); - return 0; - } + void ReadEntry(u64 block, std::string& name); - bool Rename(const std::string& from, const std::string& to) - { - u64 entry_block; - if(!SearchEntry(from, entry_block)) - { - return false; - } + void WriteEntry(u64 block, const vfsHDD_Entry& data, const std::string& name); - vfsHDD_Entry entry; - ReadEntry(entry_block, entry); - WriteEntry(entry_block, entry, to); + bool Create(vfsHDD_EntryType type, const std::string& name); - return true; - } + bool GetFirstEntry(u64& block, vfsHDD_Entry& entry, std::string& name); - u64 FindFreeBlock() - { - vfsHDD_Block block_info; + bool GetNextEntry(u64& block, vfsHDD_Entry& entry, std::string& name); - for(u64 i = 0; i(GetMaxNameLen() - 1, name.length() + 1)); - } + virtual bool Eof(); - bool Create(vfsHDD_EntryType type, const std::string& name) - { - if(HasEntry(name)) - { - return false; - } - - u64 new_block = FindFreeBlock(); - if(!new_block) - { - return false; - } - - LOG_NOTICE(HLE, "CREATING ENTRY AT 0x%llx", new_block); - WriteBlock(new_block, g_used_block); - - { - vfsHDD_Entry new_entry; - vfsHDDManager::CreateEntry(new_entry); - new_entry.next_block = 0; - new_entry.type = type; - - if(type == vfsHDD_Entry_Dir) - { - u64 block_cur = FindFreeBlock(); - - if(!block_cur) - { - return false; - } - - WriteBlock(block_cur, g_used_block); - - u64 block_last = FindFreeBlock(); - - if(!block_last) - { - return false; - } - - WriteBlock(block_last, g_used_block); - - vfsHDD_Entry entry_cur, entry_last; - vfsHDDManager::CreateEntry(entry_cur); - vfsHDDManager::CreateEntry(entry_last); - - entry_cur.type = vfsHDD_Entry_Dir; - entry_cur.data_block = block_cur; - entry_cur.next_block = block_last; - - entry_last.type = vfsHDD_Entry_Dir; - entry_last.data_block = m_cur_dir_block; - entry_last.next_block = 0; - - new_entry.data_block = block_cur; - - WriteEntry(block_cur, entry_cur, "."); - WriteEntry(block_last, entry_last, ".."); - } - - WriteEntry(new_block, new_entry, name); - } - - { - u64 block = m_cur_dir_block; - - vfsHDD_Block tmp; - while(block) - { - ReadBlock(block, tmp); - - if(!tmp.next_block) - break; - - block = tmp.next_block; - } - - tmp.next_block = new_block; - WriteBlock(block, tmp); - } - - return true; - } - - bool GetFirstEntry(u64& block, vfsHDD_Entry& entry, std::string& name) - { - if(!m_cur_dir_block) - { - return false; - } - - ReadEntry(m_cur_dir_block, entry, name); - block = entry.is_used ? entry.next_block : 0; - - return true; - } - - bool GetNextEntry(u64& block, vfsHDD_Entry& entry, std::string& name) - { - if(!block) - { - return false; - } - - ReadEntry(block, entry, name); - - block = entry.is_used ? entry.next_block : 0; - return true; - } - - virtual bool Open(const std::string& path, vfsOpenMode mode = vfsRead) - { - const char* s = path.c_str(); - u64 from = 0; - u64 pos = 0; - u64 file_pos = -1; - - do - { - if(s[pos] == '\\' || s[pos] == '/' || s[pos] == '\0') // ??? - { - if(file_pos != -1) - { - return false; - } - - if(from != -1) - { - if(pos - from > 1) - { - int res = OpenDir(std::string(s + from, pos)); - if(res == -1) - { - return false; - } - - if(res == 1) - { - file_pos = from; - } - } - - from = pos; - } - else - { - from = pos; - } - } - } - while(s[pos++] != '\0'); - - if(file_pos == -1) - { - return false; - } - - u64 file_block; - if(!SearchEntry(std::string(s + file_pos), file_block)) - { - return false; - } - - LOG_NOTICE(HLE, "ENTRY FOUND AT 0x%llx", file_block); - m_file.Open(file_block); - - return vfsFileBase::Open(path, mode); - } - - bool HasEntry(const std::string& name) - { - u64 file_block; - if(!SearchEntry(name, file_block)) - { - return false; - } - - return true; - } - - void RemoveBlocksDir(u64 start_block) - { - std::string name; - u64 block = start_block; - vfsHDD_Entry entry; - - while(block) - { - ReadEntry(block, entry, name); - WriteBlock(block, g_null_block); - - if(entry.type == vfsHDD_Entry_Dir && name != "." && name != "..") - { - LOG_WARNING(HLE, "Removing sub folder '%s'", name.c_str()); - RemoveBlocksDir(entry.data_block); - } - else if(entry.type == vfsHDD_Entry_File) - { - RemoveBlocksFile(entry.data_block); - } - - block = entry.next_block; - } - } - - void RemoveBlocksFile(u64 start_block) - { - u64 block = start_block; - vfsHDD_Block block_data; - - while(block) - { - ReadBlock(block, block_data); - WriteBlock(block, g_null_block); - - block = block_data.next_block; - } - } - - bool RemoveEntry(const std::string& name) - { - u64 entry_block, parent_entry; - if(!SearchEntry(name, entry_block, &parent_entry)) - { - return false; - } - - vfsHDD_Entry entry; - ReadEntry(entry_block, entry); - if(entry.type == vfsHDD_Entry_Dir) - { - RemoveBlocksDir(entry.data_block); - } - else if(entry.type == vfsHDD_Entry_File) - { - RemoveBlocksFile(entry.data_block); - } - - if(parent_entry) - { - u64 next = entry.next_block; - ReadEntry(parent_entry, entry); - entry.next_block = next; - WriteEntry(parent_entry, entry); - } - WriteBlock(entry_block, g_null_block); - return true; - } - - virtual bool Create(const std::string& path) - { - return false; - } - - virtual u32 Write(const void* src, u32 size) - { - return vfsFileBase::Write(src, m_file.Write(src, size)); - } - - virtual u32 Read(void* dst, u32 size) - { - return vfsFileBase::Read(dst, m_file.Read(dst, size)); - } - - virtual u64 Seek(s64 offset, vfsSeekMode mode = vfsSeekSet) - { - switch(mode) - { - case vfsSeekCur: - m_file.Seek(Tell() + offset); - break; - - case vfsSeekSet: - m_file.Seek(offset); - break; - - case vfsSeekEnd: - m_file.Seek(m_file.GetSize() + offset); - break; - } - - return vfsFileBase::Seek(offset, mode); - } - - virtual bool Eof() - { - return m_file.Eof(); - } - - virtual u64 GetSize() - { - return m_file.GetSize(); - } + virtual u64 GetSize(); }; diff --git a/rpcs3/Emu/Io/Keyboard.cpp b/rpcs3/Emu/Io/Keyboard.cpp index 03b0a72a50..f63c5530ca 100644 --- a/rpcs3/Emu/Io/Keyboard.cpp +++ b/rpcs3/Emu/Io/Keyboard.cpp @@ -1,5 +1,4 @@ #include "stdafx.h" -#include "Utilities/Log.h" #include "rpcs3/Ini.h" #include "Keyboard.h" #include "Null/NullKeyboardHandler.h" diff --git a/rpcs3/Emu/Io/Mouse.cpp b/rpcs3/Emu/Io/Mouse.cpp index 3c9d569125..fc0112e5e0 100644 --- a/rpcs3/Emu/Io/Mouse.cpp +++ b/rpcs3/Emu/Io/Mouse.cpp @@ -1,5 +1,4 @@ #include "stdafx.h" -#include "Utilities/Log.h" #include "rpcs3/Ini.h" #include "Mouse.h" #include "Null/NullMouseHandler.h" diff --git a/rpcs3/Emu/Io/Pad.cpp b/rpcs3/Emu/Io/Pad.cpp index 0e29f5a85b..55cdbf0e91 100644 --- a/rpcs3/Emu/Io/Pad.cpp +++ b/rpcs3/Emu/Io/Pad.cpp @@ -1,5 +1,4 @@ #include "stdafx.h" -#include "Utilities/Log.h" #include "rpcs3/Ini.h" #include "Pad.h" #include "Null/NullPadHandler.h" diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index c60abe9f7c..79c6f293cb 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -4,7 +4,15 @@ #include "Utilities/Log.h" #include "Memory.h" #include "Emu/System.h" -#include "Ini.h" + +#ifndef _WIN32 +#include +#endif + +/* OS X uses MAP_ANON instead of MAP_ANONYMOUS */ +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif MemoryBase Memory; @@ -535,12 +543,6 @@ bool MemoryBlockLE::Write128(const u64 addr, const u128 value) return true; } -// MemoryBase -template<> __forceinline u64 MemoryBase::ReverseData<1>(u64 val) { return val; } -template<> __forceinline u64 MemoryBase::ReverseData<2>(u64 val) { return Reverse16(val); } -template<> __forceinline u64 MemoryBase::ReverseData<4>(u64 val) { return Reverse32(val); } -template<> __forceinline u64 MemoryBase::ReverseData<8>(u64 val) { return Reverse64(val); } - VirtualMemoryBlock::VirtualMemoryBlock() : MemoryBlock(), m_reserve_size(0) { } diff --git a/rpcs3/Emu/Memory/Memory.h b/rpcs3/Emu/Memory/Memory.h index 8f09a50869..61f2e7ed73 100644 --- a/rpcs3/Emu/Memory/Memory.h +++ b/rpcs3/Emu/Memory/Memory.h @@ -1,17 +1,8 @@ #pragma once -#ifndef _WIN32 -#include -#endif - #include "MemoryBlock.h" #include "Emu/SysCalls/Callback.h" -/* OS X uses MAP_ANON instead of MAP_ANONYMOUS */ -#ifndef MAP_ANONYMOUS - #define MAP_ANONYMOUS MAP_ANON -#endif - using std::nullptr_t; #define safe_delete(x) do {delete (x);(x)=nullptr;} while(0) @@ -112,36 +103,6 @@ public: void UnregisterPages(u64 addr, u32 size); - static __forceinline u16 Reverse16(const u16 val) - { - return _byteswap_ushort(val); - } - - static __forceinline u32 Reverse32(const u32 val) - { - return _byteswap_ulong(val); - } - - static __forceinline u64 Reverse64(const u64 val) - { - return _byteswap_uint64(val); - } - - static __forceinline u128 Reverse128(const u128 val) - { - u128 ret; - ret.lo = _byteswap_uint64(val.hi); - ret.hi = _byteswap_uint64(val.lo); - return ret; - } - - template static __forceinline u64 ReverseData(u64 val); - - template static __forceinline T Reverse(T val) - { - return (T)ReverseData(val); - }; - template u8* GetMemFromAddr(const T addr) { if ((u32)addr == addr) @@ -435,11 +396,6 @@ public: strcpy((char*)GetMemFromAddr(addr), str.c_str()); } - static u64 AlignAddr(const u64 addr, const u64 align) - { - return (addr + (align-1)) & ~(align-1); - } - u32 GetUserMemTotalSize() { return UserMemory->GetSize(); diff --git a/rpcs3/Emu/SysCalls/LogBase.cpp b/rpcs3/Emu/SysCalls/LogBase.cpp index d74364e589..fa79f90ceb 100644 --- a/rpcs3/Emu/SysCalls/LogBase.cpp +++ b/rpcs3/Emu/SysCalls/LogBase.cpp @@ -1,7 +1,13 @@ #include "stdafx.h" #include "Utilities/Log.h" +#include "Emu/System.h" #include "LogBase.h" +bool LogBase::CheckLogging() const +{ + return Ini.HLELogging.GetValue(); +} + void LogBase::LogNotice(const std::string& text) { LOG_NOTICE(HLE, "%s", text.c_str()); diff --git a/rpcs3/Emu/SysCalls/LogBase.h b/rpcs3/Emu/SysCalls/LogBase.h index 317e999273..dac704e974 100644 --- a/rpcs3/Emu/SysCalls/LogBase.h +++ b/rpcs3/Emu/SysCalls/LogBase.h @@ -4,6 +4,7 @@ class LogBase { bool m_logging; + bool CheckLogging() const; void LogNotice(const std::string& text); void LogWarning(const std::string& text); void LogError(const std::string& text); @@ -33,7 +34,7 @@ public: template __forceinline void Log(const char* fmt, Targs... args) { - if (m_logging) + if (CheckLogging()) { Notice(fmt, args...); } @@ -41,7 +42,7 @@ public: template __forceinline void Log(const u32 id, const char* fmt, Targs... args) { - if (m_logging) + if (CheckLogging()) { Notice(id, fmt, args...); } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event.cpp b/rpcs3/Emu/SysCalls/lv2/sys_event.cpp index bf4b722388..9d4f423182 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_event.cpp @@ -1,11 +1,7 @@ #include "stdafx.h" -#include "Utilities/Log.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/Cell/PPUThread.h" - #include "Emu/SysCalls/SysCalls.h" -#include "Emu/Cell/SPUThread.h" #include "sys_event.h" @@ -90,7 +86,7 @@ s32 sys_event_queue_destroy(u32 equeue_id, int mode) std::this_thread::sleep_for(std::chrono::milliseconds(1)); if (Emu.IsStopped()) { - LOG_WARNING(HLE, "sys_event_queue_destroy(equeue=%d) aborted", equeue_id); + sys_event.Warning("sys_event_queue_destroy(equeue=%d) aborted", equeue_id); break; } } @@ -203,7 +199,7 @@ s32 sys_event_queue_receive(u32 equeue_id, mem_ptr_t event, u64 std::this_thread::sleep_for(std::chrono::milliseconds(1)); if (counter++ > timeout || Emu.IsStopped()) { - if (Emu.IsStopped()) LOG_WARNING(HLE, "sys_event_queue_receive(equeue=%d) aborted", equeue_id); + if (Emu.IsStopped()) sys_event.Warning("sys_event_queue_receive(equeue=%d) aborted", equeue_id); eq->sq.invalidate(tid); return CELL_ETIMEDOUT; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event_flag.h b/rpcs3/Emu/SysCalls/lv2/sys_event_flag.h index 48901ba572..3e5c502150 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event_flag.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_event_flag.h @@ -1,5 +1,7 @@ #pragma once +#include "Utilities/SMutex.h" + enum { SYS_SYNC_WAITER_SINGLE = 0x10000, diff --git a/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp b/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp index 7555a5da0e..170c063fdc 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp @@ -25,13 +25,13 @@ s32 sys_mmapper_allocate_address(u32 size, u64 flags, u32 alignment, u32 alloc_a { default: case SYS_MEMORY_PAGE_SIZE_1M: - if(Memory.AlignAddr(size, alignment) & 0xfffff) + if(AlignAddr(size, alignment) & 0xfffff) return CELL_EALIGN; addr = Memory.Alloc(size, 0x100000); break; case SYS_MEMORY_PAGE_SIZE_64K: - if(Memory.AlignAddr(size, alignment) & 0xffff) + if(AlignAddr(size, alignment) & 0xffff) return CELL_EALIGN; addr = Memory.Alloc(size, 0x10000); break; diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp index 7fe220130b..bd73e0a18e 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp @@ -1,12 +1,8 @@ #include "stdafx.h" -#include "Utilities/Log.h" -#include "Emu/Memory/Memory.h" #include "Emu/System.h" -#include "Emu/Cell/PPUThread.h" #include "Emu/FS/vfsFile.h" #include "sys_spu.h" #include "Emu/SysCalls/SysCalls.h" -#include "Emu/SysCalls/SC_FUNC.h" #include "Loader/ELF.h" #include "Emu/Cell/RawSPUThread.h" #include @@ -450,7 +446,7 @@ s32 sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status) } if (Emu.IsStopped()) { - LOG_WARNING(Log::SPU, "sys_spu_thread_group_join(id=%d) aborted", id); + sc_spu.Warning("sys_spu_thread_group_join(id=%d) aborted", id); return CELL_OK; } std::this_thread::sleep_for(std::chrono::milliseconds(1)); @@ -842,7 +838,7 @@ s32 sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq_id, u64 req, m eq->ports.add(&(t->SPUPs[i])); t->SPUPs[i].eq = eq; } - LOG_NOTICE(HLE, "*** spup -> %d", i); + sc_spu.Warning("*** spup -> %d", i); spup = (u8)i; } diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 66a087589e..30fcd619db 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -8,6 +8,7 @@ #include "Emu/RSX/GSManager.h" #include "Emu/Audio/AudioManager.h" #include "Emu/FS/VFS.h" +#include "Emu/Event.h" #include "Loader/Loader.h" enum Status diff --git a/rpcs3/stdafx.h b/rpcs3/stdafx.h index 374e4b14a4..74bfb2141f 100644 --- a/rpcs3/stdafx.h +++ b/rpcs3/stdafx.h @@ -147,6 +147,14 @@ union u128 { return From128(~hi, ~lo); } + + static __forceinline u128 byteswap(const u128 val) + { + u128 ret; + ret.lo = _byteswap_uint64(val.hi); + ret.hi = _byteswap_uint64(val.lo); + return ret; + } }; union s128 @@ -238,6 +246,8 @@ struct u128 }; */ +#define AlignAddr(addr, align) (((addr) + ((align) - 1)) & ~((align) - 1)) + #include "Utilities/StrFmt.h" #include "Utilities/GNU.h" #include "Utilities/BEType.h"