mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-27 12:35:41 +00:00
commit
d1ffea0847
@ -79,12 +79,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
volatile u32 GetCount()
|
||||
volatile u32 GetCount() // may be not safe
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
|
||||
volatile bool IsEmpty()
|
||||
volatile bool IsEmpty() // may be not safe
|
||||
{
|
||||
return !m_count;
|
||||
}
|
||||
@ -97,7 +97,28 @@ public:
|
||||
|
||||
T& Peek(u32 pos = 0)
|
||||
{
|
||||
SMutexLocker lock(m_mutex);
|
||||
while (true)
|
||||
{
|
||||
if (m_mutex.GetOwner() == m_mutex.GetDeadValue())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!m_count)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
break;
|
||||
}
|
||||
Sleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
SMutexLocker lock(m_mutex);
|
||||
if (m_count) break;
|
||||
}
|
||||
}
|
||||
return m_data[(m_pos + pos) % SQSize];
|
||||
}
|
||||
};
|
||||
|
@ -23,16 +23,22 @@ void AudioDumper::WriteHeader()
|
||||
|
||||
size_t AudioDumper::WriteData(const void* buffer, size_t size)
|
||||
{
|
||||
for (u32 i = 0; i < size / 8; i++)
|
||||
{
|
||||
if (((u64*)buffer)[i]) goto process;
|
||||
}
|
||||
for (u32 i = 0; i < size % 8; i++)
|
||||
{
|
||||
if (((u8*)buffer)[i + (size & ~7)]) goto process;
|
||||
}
|
||||
return size; // ignore empty data
|
||||
process:
|
||||
size_t ret = m_output.Write(buffer, size);
|
||||
m_header.Size += ret;
|
||||
m_header.RIFF.Size += ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void AudioDumper::UpdateHeader(size_t size)
|
||||
{
|
||||
m_header.Size += size;
|
||||
m_header.RIFF.Size += size;
|
||||
}
|
||||
|
||||
void AudioDumper::Finalize()
|
||||
{
|
||||
m_output.Seek(0);
|
||||
|
@ -64,6 +64,5 @@ public:
|
||||
bool Init();
|
||||
void WriteHeader();
|
||||
size_t WriteData(const void* buffer, size_t size);
|
||||
void UpdateHeader(size_t size);
|
||||
void Finalize();
|
||||
};
|
||||
|
@ -58,7 +58,7 @@ void CPUThread::CloseStack()
|
||||
{
|
||||
if(m_stack_addr)
|
||||
{
|
||||
Memory.Free(m_stack_addr);
|
||||
Memory.StackMem.Free(m_stack_addr);
|
||||
m_stack_addr = 0;
|
||||
}
|
||||
|
||||
|
@ -4,13 +4,16 @@
|
||||
enum
|
||||
{
|
||||
MFC_PUT_CMD = 0x20, MFC_PUTB_CMD = 0x21, MFC_PUTF_CMD = 0x22,
|
||||
MFC_PUTR_CMD = 0x30, MFC_PUTRB_CMD = 0x31, MFC_PUTRF_CMD = 0x32,
|
||||
MFC_GET_CMD = 0x40, MFC_GETB_CMD = 0x41, MFC_GETF_CMD = 0x42,
|
||||
MFC_PUTL_CMD = 0x24, MFC_PUTLB_CMD = 0x25, MFC_PUTLF_CMD = 0x26,
|
||||
MFC_PUTRL_CMD = 0x34, MFC_PUTRLB_CMD = 0x35, MFC_PUTRLF_CMD = 0x36,
|
||||
MFC_GETL_CMD = 0x44, MFC_GETLB_CMD = 0x45, MFC_GETLF_CMD = 0x46,
|
||||
MFC_GETLLAR_CMD = 0xD0,
|
||||
MFC_PUTLLC_CMD = 0xB4,
|
||||
MFC_PUTLLUC_CMD = 0xB0,
|
||||
MFC_PUTQLLUC_CMD = 0xB8,
|
||||
|
||||
MFC_SNDSIG_CMD = 0xA0, MFC_SNDSIGB_CMD = 0xA1, MFC_SNDSIGF_CMD = 0xA2,
|
||||
MFC_BARRIER_CMD = 0xC0,
|
||||
MFC_EIEIO_CMD = 0xC8,
|
||||
@ -19,6 +22,8 @@ enum
|
||||
MFC_BARRIER_MASK = 0x01,
|
||||
MFC_FENCE_MASK = 0x02,
|
||||
MFC_LIST_MASK = 0x04,
|
||||
MFC_START_MASK = 0x08, // ???
|
||||
MFC_RESULT_MASK = 0x10, // ???
|
||||
MFC_MASK_CMD = 0xffff,
|
||||
};
|
||||
|
||||
@ -55,7 +60,7 @@ enum
|
||||
MFC_SPU_MAX_QUEUE_SPACE = 0x10,
|
||||
};
|
||||
|
||||
struct DMAC_Queue
|
||||
/*struct DMAC_Queue
|
||||
{
|
||||
bool is_valid;
|
||||
u64 ea;
|
||||
@ -149,13 +154,14 @@ public:
|
||||
{
|
||||
return Memory.Read32(m_addr);
|
||||
}
|
||||
};
|
||||
};*/
|
||||
|
||||
struct DMAC
|
||||
{
|
||||
//DMAC_Queue queue[MFC_SPU_MAX_QUEUE_SPACE]; //not used yet
|
||||
DMAC_Proxy proxy[MFC_PPU_MAX_QUEUE_SPACE+MFC_SPU_MAX_QUEUE_SPACE]; //temporarily 24
|
||||
u64 ls_offset;
|
||||
|
||||
/*//DMAC_Queue queue[MFC_SPU_MAX_QUEUE_SPACE]; //not used yet
|
||||
DMAC_Proxy proxy[MFC_PPU_MAX_QUEUE_SPACE+MFC_SPU_MAX_QUEUE_SPACE]; //temporarily 24
|
||||
u32 queue_pos;
|
||||
u32 proxy_pos;
|
||||
long queue_lock;
|
||||
@ -194,18 +200,6 @@ struct DMAC
|
||||
return MFC_PPU_DMA_QUEUE_FULL;
|
||||
}
|
||||
|
||||
/* while (std::atomic_exchange(&proxy_lock, 1));
|
||||
_mm_lfence();
|
||||
DMAC_Proxy& p = proxy[proxy_pos];
|
||||
p.cmd = cmd;
|
||||
p.tag = tag;
|
||||
p.lsa = lsa;
|
||||
p.ea = ea;
|
||||
p.size = size;
|
||||
_mm_sfence(); //for DoCmd()
|
||||
proxy_pos++;
|
||||
_mm_sfence();
|
||||
proxy_lock = 0; */
|
||||
ProcessCmd(cmd, tag, lsa, ea, size);
|
||||
|
||||
return MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL;
|
||||
@ -230,10 +224,10 @@ struct DMAC
|
||||
ClearCmd();
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
};
|
||||
|
||||
struct MFC
|
||||
/*struct MFC
|
||||
{
|
||||
SPUReg<1> MFC_LSA;
|
||||
SPUReg<1> MFC_EAH;
|
||||
@ -299,4 +293,4 @@ struct MFC
|
||||
MFC_QStatus.SetValue(mask);
|
||||
}
|
||||
}
|
||||
};
|
||||
};*/
|
||||
|
@ -283,7 +283,7 @@ void RawSPUThread::Task()
|
||||
continue;
|
||||
}
|
||||
|
||||
dmac.DoCmd();
|
||||
//dmac.DoCmd();
|
||||
|
||||
if(SPU.RunCntl.GetValue() != SPU_RUNCNTL_RUNNABLE)
|
||||
{
|
||||
|
@ -113,14 +113,26 @@ private:
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x102: default:
|
||||
if (!CPU.SPU.Out_MBox.GetCount()) // the real exit status
|
||||
case 0x102:
|
||||
if (!CPU.SPU.Out_MBox.GetCount())
|
||||
{
|
||||
ConLog.Warning("STOP: 0x%x (no message)", code);
|
||||
ConLog.Error("sys_spu_thread_exit (no status, code 0x102)");
|
||||
}
|
||||
else if (Ini.HLELogging.GetValue() || code != 0x102)
|
||||
else if (Ini.HLELogging.GetValue())
|
||||
{
|
||||
ConLog.Warning("STOP: 0x%x (message=0x%x)", code, CPU.SPU.Out_MBox.GetValue());
|
||||
// the real exit status
|
||||
ConLog.Write("sys_spu_thread_exit (status=0x%x)", CPU.SPU.Out_MBox.GetValue());
|
||||
}
|
||||
CPU.Stop();
|
||||
break;
|
||||
default:
|
||||
if (!CPU.SPU.Out_MBox.GetCount())
|
||||
{
|
||||
ConLog.Error("Unknown STOP code: 0x%x (no message)", code);
|
||||
}
|
||||
else
|
||||
{
|
||||
ConLog.Error("Unknown STOP code: 0x%x (message=0x%x)", code, CPU.SPU.Out_MBox.GetValue());
|
||||
}
|
||||
CPU.Stop();
|
||||
break;
|
||||
|
@ -20,6 +20,8 @@ SPUThread::SPUThread(CPUThreadType type) : PPCThread(type)
|
||||
{
|
||||
assert(type == CPU_THREAD_SPU || type == CPU_THREAD_RAW_SPU);
|
||||
|
||||
group = nullptr;
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
@ -46,10 +48,10 @@ void SPUThread::InitRegs()
|
||||
cfg.Reset();
|
||||
|
||||
dmac.ls_offset = m_offset;
|
||||
dmac.proxy_pos = 0;
|
||||
/*dmac.proxy_pos = 0;
|
||||
dmac.queue_pos = 0;
|
||||
dmac.proxy_lock = 0;
|
||||
dmac.queue_lock = 0;
|
||||
dmac.queue_lock = 0;*/
|
||||
|
||||
SPU.RunCntl.SetValue(SPU_RUNCNTL_STOP);
|
||||
SPU.Status.SetValue(SPU_STATUS_RUNNING);
|
||||
|
@ -119,6 +119,15 @@ enum
|
||||
SPU_STATUS_SINGLE_STEP = 0x10,
|
||||
};
|
||||
|
||||
enum : u32
|
||||
{
|
||||
SYS_SPU_THREAD_BASE_LOW = 0xf0000000,
|
||||
SYS_SPU_THREAD_BASE_MASK = 0xfffffff,
|
||||
SYS_SPU_THREAD_OFFSET = 0x00100000,
|
||||
SYS_SPU_THREAD_SNR1 = 0x05400c,
|
||||
SYS_SPU_THREAD_SNR2 = 0x05C00c,
|
||||
};
|
||||
|
||||
//Floating point status and control register. Unsure if this is one of the GPRs or SPRs
|
||||
//Is 128 bits, but bits 0-19, 24-28, 32-49, 56-60, 64-81, 88-92, 96-115, 120-124 are unused
|
||||
class FPSCR
|
||||
@ -278,6 +287,7 @@ public:
|
||||
|
||||
EventPort SPUPs[64]; // SPU Thread Event Ports
|
||||
EventManager SPUQs; // SPU Queue Mapping
|
||||
SpuGroupInfo* group; // associated SPU Thread Group (null for raw spu)
|
||||
|
||||
template<size_t _max_count>
|
||||
class Channel
|
||||
@ -512,6 +522,18 @@ 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
|
||||
}
|
||||
}
|
||||
|
||||
u32 LSA;
|
||||
|
||||
union
|
||||
@ -522,6 +544,81 @@ public:
|
||||
|
||||
DMAC dmac;
|
||||
|
||||
bool ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
|
||||
{
|
||||
if (cmd & (MFC_BARRIER_MASK | MFC_FENCE_MASK)) _mm_mfence();
|
||||
|
||||
if ((ea & 0xf0000000) == SYS_SPU_THREAD_BASE_LOW)
|
||||
{
|
||||
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.GetCount() || !group->list[num])
|
||||
{
|
||||
ConLog.Error("DMAC::ProcessCmd(): SPU Thread Group MMIO Access (ea=0x%llx): invalid thread", ea);
|
||||
return false;
|
||||
}
|
||||
|
||||
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 true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ConLog.Error("DMAC::ProcessCmd(): SPU Thread Group MMIO Access (ea=0x%llx, size=%d, cmd=0x%x): invalid command", ea, size, cmd);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ConLog.Error("DMAC::ProcessCmd(): SPU Thread Group MMIO Access (ea=0x%llx): group not set", ea);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
switch(cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK | MFC_RESULT_MASK))
|
||||
{
|
||||
case MFC_PUT_CMD:
|
||||
{
|
||||
return Memory.Copy(ea, dmac.ls_offset + lsa, size);
|
||||
}
|
||||
|
||||
case MFC_GET_CMD:
|
||||
{
|
||||
return Memory.Copy(dmac.ls_offset + lsa, ea, size);
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
ConLog.Error("DMAC::ProcessCmd(): Unknown DMA cmd.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 dmacCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
|
||||
{
|
||||
/*if(proxy_pos >= MFC_PPU_MAX_QUEUE_SPACE)
|
||||
{
|
||||
return MFC_PPU_DMA_QUEUE_FULL;
|
||||
}*/
|
||||
|
||||
if (ProcessCmd(cmd, tag, lsa, ea, size))
|
||||
return MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL;
|
||||
else
|
||||
return MFC_PPU_DMA_CMD_SEQUENCE_ERROR;
|
||||
}
|
||||
|
||||
void ListCmd(u32 lsa, u64 ea, u16 tag, u16 size, u32 cmd, MFCReg& MFCArgs)
|
||||
{
|
||||
u32 list_addr = ea & 0x3ffff;
|
||||
@ -549,7 +646,7 @@ public:
|
||||
}
|
||||
|
||||
u32 addr = rec->ea;
|
||||
result = dmac.Cmd(cmd, tag, lsa | (addr & 0xf), addr, size);
|
||||
result = dmacCmd(cmd, tag, lsa | (addr & 0xf), addr, size);
|
||||
if (result == MFC_PPU_DMA_CMD_SEQUENCE_ERROR)
|
||||
{
|
||||
break;
|
||||
@ -596,17 +693,19 @@ public:
|
||||
switch(op & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK))
|
||||
{
|
||||
case MFC_PUT_CMD:
|
||||
case MFC_PUTR_CMD: // ???
|
||||
case MFC_GET_CMD:
|
||||
{
|
||||
if (Ini.HLELogging.GetValue()) ConLog.Write("DMA %s%s%s: lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x",
|
||||
wxString(op & MFC_PUT_CMD ? "PUT" : "GET").wx_str(),
|
||||
if (Ini.HLELogging.GetValue()) ConLog.Write("DMA %s%s%s%s: lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x",
|
||||
wxString(op & MFC_PUT_CMD ? "PUT" : "GET").wx_str(),
|
||||
wxString(op & MFC_RESULT_MASK ? "R" : "").wx_str(),
|
||||
wxString(op & MFC_BARRIER_MASK ? "B" : "").wx_str(),
|
||||
wxString(op & MFC_FENCE_MASK ? "F" : "").wx_str(),
|
||||
lsa, ea, tag, size, cmd);
|
||||
if (op & MFC_PUT_CMD)
|
||||
{
|
||||
SMutexLocker lock(reservation.mutex); // should be removed
|
||||
MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size));
|
||||
MFCArgs.CMDStatus.SetValue(dmacCmd(cmd, tag, lsa, ea, size));
|
||||
if ((reservation.addr + reservation.size > ea && reservation.addr <= ea + size) ||
|
||||
(ea + size > reservation.addr && ea <= reservation.addr + reservation.size))
|
||||
{
|
||||
@ -615,16 +714,18 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size));
|
||||
MFCArgs.CMDStatus.SetValue(dmacCmd(cmd, tag, lsa, ea, size));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MFC_PUTL_CMD:
|
||||
case MFC_PUTRL_CMD: // ???
|
||||
case MFC_GETL_CMD:
|
||||
{
|
||||
if (Ini.HLELogging.GetValue()) ConLog.Write("DMA %s%s%s: lsa = 0x%x, list = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x",
|
||||
wxString(op & MFC_PUT_CMD ? "PUTL" : "GETL").wx_str(),
|
||||
if (Ini.HLELogging.GetValue()) ConLog.Write("DMA %s%s%s%s: lsa = 0x%x, list = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x",
|
||||
wxString(op & MFC_PUT_CMD ? "PUT" : "GET").wx_str(),
|
||||
wxString(op & MFC_RESULT_MASK ? "RL" : "L").wx_str(),
|
||||
wxString(op & MFC_BARRIER_MASK ? "B" : "").wx_str(),
|
||||
wxString(op & MFC_FENCE_MASK ? "F" : "").wx_str(),
|
||||
lsa, ea, tag, size, cmd);
|
||||
@ -650,7 +751,7 @@ public:
|
||||
reservation.owner = lock.tid;
|
||||
reservation.addr = ea;
|
||||
reservation.size = 128;
|
||||
dmac.ProcessCmd(MFC_GET_CMD, tag, lsa, ea, 128);
|
||||
ProcessCmd(MFC_GET_CMD, tag, lsa, ea, 128);
|
||||
Prxy.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS);
|
||||
}
|
||||
else if (op == MFC_PUTLLC_CMD) // store conditional
|
||||
@ -660,7 +761,7 @@ public:
|
||||
{
|
||||
if (reservation.addr == ea && reservation.size == 128)
|
||||
{
|
||||
dmac.ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128);
|
||||
ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128);
|
||||
Prxy.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS);
|
||||
}
|
||||
else
|
||||
@ -677,7 +778,7 @@ public:
|
||||
else // store unconditional
|
||||
{
|
||||
SMutexLocker lock(reservation.mutex);
|
||||
dmac.ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128);
|
||||
ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128);
|
||||
if (op == MFC_PUTLLUC_CMD)
|
||||
{
|
||||
Prxy.AtomicStat.PushUncond(MFC_PUTLLUC_SUCCESS);
|
||||
@ -795,9 +896,66 @@ public:
|
||||
SPU.In_MBox.PushUncond(CELL_OK);
|
||||
return;
|
||||
}
|
||||
else if (code = 128)
|
||||
{
|
||||
/* ===== sys_event_flag_set_bit ===== */
|
||||
u32 flag = v & 0xffffff;
|
||||
|
||||
u32 data;
|
||||
if (!SPU.Out_MBox.Pop(data))
|
||||
{
|
||||
ConLog.Error("sys_event_flag_set_bit(v=0x%x (flag=%d)): Out_MBox is empty", v, flag);
|
||||
return;
|
||||
}
|
||||
|
||||
if (flag > 63)
|
||||
{
|
||||
ConLog.Error("sys_event_flag_set_bit(id=%d, v=0x%x): flag > 63", data, v, flag);
|
||||
return;
|
||||
}
|
||||
|
||||
//if (Ini.HLELogging.GetValue())
|
||||
{
|
||||
ConLog.Warning("sys_event_flag_set_bit(id=%d, v=0x%x (flag=%d))", data, v, flag);
|
||||
}
|
||||
|
||||
EventFlag* ef;
|
||||
if (!Emu.GetIdManager().GetIDData(data, ef))
|
||||
{
|
||||
ConLog.Error("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
|
||||
{
|
||||
ConLog.Error("SPU_WrOutIntrMbox: unknown data (v=0x%x)", v);
|
||||
u32 data;
|
||||
if (SPU.Out_MBox.Pop(data))
|
||||
{
|
||||
ConLog.Error("SPU_WrOutIntrMbox: unknown data (v=0x%x); Out_MBox = 0x%x", v, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
ConLog.Error("SPU_WrOutIntrMbox: unknown data (v=0x%x)", v);
|
||||
}
|
||||
SPU.In_MBox.PushUncond(CELL_EINVAL); // ???
|
||||
return;
|
||||
}
|
||||
|
@ -48,8 +48,14 @@ u32 vfsDevice::CmpLocalPath(const wxString& local_path)
|
||||
wxFileName path0(m_local_path);
|
||||
path0.Normalize();
|
||||
|
||||
wxArrayString arr0 = wxSplit(path0.GetFullPath(), '/');
|
||||
wxArrayString arr1 = wxSplit(local_path, '/');
|
||||
#ifdef _WIN32
|
||||
#define DL '\\'
|
||||
#else
|
||||
#define DL '/'
|
||||
#endif
|
||||
|
||||
wxArrayString arr0 = wxSplit(path0.GetFullPath(), DL);
|
||||
wxArrayString arr1 = wxSplit(local_path, DL);
|
||||
|
||||
const u32 lim = min(arr0.GetCount(), arr1.GetCount());
|
||||
u32 ret = 0;
|
||||
@ -179,7 +185,7 @@ wxString vfsDevice::GetWinPath(const wxString& p, bool is_dir)
|
||||
ret += p[i];
|
||||
}
|
||||
|
||||
if(is_dir && ret[ret.Len() - 1] != '/') ret += '/';
|
||||
if(is_dir && ret[ret.Len() - 1] != '/' && ret[ret.Len() - 1] != '\\') ret += '/'; // ???
|
||||
|
||||
wxFileName res(ret);
|
||||
res.Normalize();
|
||||
|
@ -56,7 +56,7 @@ bool vfsLocalFile::Create(const wxString& path)
|
||||
for(uint p=1; p < path.Len() && path[p] != '\0' ; p++)
|
||||
{
|
||||
for(; p < path.Len() && path[p] != '\0'; p++)
|
||||
if(path[p] == '/') break;
|
||||
if(path[p] == '/' || path[p] == '\\') break; // ???
|
||||
|
||||
if(p == path.Len() || path[p] == '\0')
|
||||
break;
|
||||
@ -70,7 +70,8 @@ bool vfsLocalFile::Create(const wxString& path)
|
||||
}
|
||||
|
||||
//create file
|
||||
if(path(path.Len() - 1, 1) != '/' && !wxFileExists(path))
|
||||
wxString m = path(path.Len() - 1, 1);
|
||||
if(m != '/' && m != '\\' && !wxFileExists(path)) // ???
|
||||
{
|
||||
wxFile f;
|
||||
return f.Create(path);
|
||||
|
@ -1144,6 +1144,14 @@ void GLGSRender::Flip()
|
||||
|
||||
if(src_buffer)
|
||||
{
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_CLIP_PLANE0);
|
||||
glDisable(GL_CLIP_PLANE1);
|
||||
glDisable(GL_CLIP_PLANE2);
|
||||
glDisable(GL_CLIP_PLANE3);
|
||||
glDisable(GL_CLIP_PLANE4);
|
||||
glDisable(GL_CLIP_PLANE5);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, g_flip_tex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, format, GL_UNSIGNED_INT_8_8_8_8, src_buffer);
|
||||
@ -1163,6 +1171,7 @@ void GLGSRender::Flip()
|
||||
m_program.Use();
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_ACCUM_BUFFER_BIT);
|
||||
|
||||
glColor3f(1, 1, 1);
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2i(0, 1);
|
||||
glVertex2i(0, 0);
|
||||
|
@ -695,7 +695,7 @@ public:
|
||||
|
||||
do
|
||||
{
|
||||
if(s[pos] == '/' || s[pos] == '\0')
|
||||
if(s[pos] == '\\' || s[pos] == '/' || s[pos] == '\0') // ???
|
||||
{
|
||||
if(file_pos != -1)
|
||||
{
|
||||
|
@ -210,6 +210,11 @@ bool DynamicMemoryBlockBase<PT>::Free(u64 addr)
|
||||
}
|
||||
}
|
||||
|
||||
ConLog.Error("DynamicMemoryBlock::Free(addr=0x%llx): failed", addr);
|
||||
for (u32 i = 0; i < m_allocated.GetCount(); i++)
|
||||
{
|
||||
ConLog.Write("*** Memory Block: addr = 0x%llx, size = 0x%x", m_allocated[i].addr, m_allocated[i].size);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ extern "C"
|
||||
{
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "libavformat/avformat.h"
|
||||
#include "libswresample/swresample.h"
|
||||
}
|
||||
|
||||
#include "cellAdec.h"
|
||||
@ -16,7 +17,7 @@ extern "C"
|
||||
void cellAdec_init();
|
||||
Module cellAdec(0x0006, cellAdec_init);
|
||||
|
||||
int adecRead(void* opaque, u8* buf, int buf_size)
|
||||
int adecRawRead(void* opaque, u8* buf, int buf_size)
|
||||
{
|
||||
AudioDecoder& adec = *(AudioDecoder*)opaque;
|
||||
|
||||
@ -61,13 +62,14 @@ next:
|
||||
|
||||
adec.reader.addr = adec.task.au.addr;
|
||||
adec.reader.size = adec.task.au.size;
|
||||
//ConLog.Write("Audio AU: size = 0x%x, pts = 0x%llx", adec.task.au.size, adec.task.au.pts);
|
||||
|
||||
adec.last_pts = adec.task.au.pts;
|
||||
//if (adec.last_pts > adec.task.au.pts) adec.last_pts = adec.task.au.pts;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ConLog.Error("adecRead(): sequence error (task %d)", adec.job.Peek().type);
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
goto next;
|
||||
@ -95,6 +97,89 @@ next:
|
||||
}
|
||||
}
|
||||
|
||||
int adecRead(void* opaque, u8* buf, int buf_size)
|
||||
{
|
||||
AudioDecoder& adec = *(AudioDecoder*)opaque;
|
||||
|
||||
int res = 0;
|
||||
|
||||
if (adec.reader.rem_size && adec.reader.rem)
|
||||
{
|
||||
if (buf_size < (int)adec.reader.rem_size)
|
||||
{
|
||||
ConLog.Error("adecRead: too small buf_size (rem_size = %d, buf_size = %d)", adec.reader.rem_size, buf_size);
|
||||
Emu.Pause();
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(buf, adec.reader.rem, adec.reader.rem_size);
|
||||
free(adec.reader.rem);
|
||||
adec.reader.rem = nullptr;
|
||||
buf += adec.reader.rem_size;
|
||||
buf_size -= adec.reader.rem_size;
|
||||
res += adec.reader.rem_size;
|
||||
adec.reader.rem_size = 0;
|
||||
}
|
||||
|
||||
while (buf_size)
|
||||
{
|
||||
u8 header[8];
|
||||
if (adecRawRead(opaque, header, 8) < 8) break;
|
||||
if (header[0] != 0x0f || header[1] != 0xd0)
|
||||
{
|
||||
ConLog.Error("adecRead: 0x0FD0 header not found");
|
||||
Emu.Pause();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!adec.reader.init)
|
||||
{
|
||||
OMAHeader oma(1 /* atrac3p id */, header[2], header[3]);
|
||||
if (buf_size < sizeof(oma) + 8)
|
||||
{
|
||||
ConLog.Error("adecRead: OMAHeader writing failed");
|
||||
Emu.Pause();
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(buf, &oma, sizeof(oma));
|
||||
buf += sizeof(oma);
|
||||
buf_size -= sizeof(oma);
|
||||
res += sizeof(oma);
|
||||
|
||||
adec.reader.init = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
|
||||
u32 size = (((header[2] & 0x3) << 8) | header[3]) * 8 + 8; // data to be read before next header
|
||||
|
||||
//ConLog.Write("*** audio block read: size = 0x%x", size);
|
||||
|
||||
if (buf_size < (int)size)
|
||||
{
|
||||
if (adecRawRead(opaque, buf, buf_size) < buf_size) break; // ???
|
||||
res += buf_size;
|
||||
size -= buf_size;
|
||||
buf_size = 0;
|
||||
|
||||
adec.reader.rem = (u8*)malloc(size);
|
||||
adec.reader.rem_size = size;
|
||||
if (adecRawRead(opaque, adec.reader.rem, size) < (int)size) break; // ???
|
||||
}
|
||||
else
|
||||
{
|
||||
if (adecRawRead(opaque, buf, size) < (int)size) break; // ???
|
||||
buf += size;
|
||||
buf_size -= size;
|
||||
res += size;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
u32 adecOpen(AudioDecoder* data)
|
||||
{
|
||||
AudioDecoder& adec = *data;
|
||||
@ -146,6 +231,10 @@ u32 adecOpen(AudioDecoder* data)
|
||||
|
||||
adec.reader.addr = 0;
|
||||
adec.reader.size = 0;
|
||||
adec.reader.init = false;
|
||||
if (adec.reader.rem) free(adec.reader.rem);
|
||||
adec.reader.rem = nullptr;
|
||||
adec.reader.rem_size = 0;
|
||||
adec.is_running = true;
|
||||
adec.just_started = true;
|
||||
}
|
||||
@ -175,8 +264,10 @@ u32 adecOpen(AudioDecoder* data)
|
||||
|
||||
adec.reader.addr = task.au.addr;
|
||||
adec.reader.size = task.au.size;
|
||||
//ConLog.Write("Audio AU: size = 0x%x, pts = 0x%llx", task.au.size, task.au.pts);
|
||||
|
||||
adec.last_pts = task.au.pts;
|
||||
//if (adec.last_pts > task.au.pts || adec.just_started) adec.last_pts = task.au.pts;
|
||||
if (adec.just_started) adec.last_pts = task.au.pts;
|
||||
|
||||
struct AVPacketHolder : AVPacket
|
||||
{
|
||||
@ -212,11 +303,11 @@ u32 adecOpen(AudioDecoder* data)
|
||||
if (Memory.CopyToReal(buf, task.au.addr, task.au.size)) dump.Write(buf, task.au.size);
|
||||
free(buf);
|
||||
dump.Close();
|
||||
}
|
||||
}*/
|
||||
|
||||
if (adec.just_started) // deferred initialization
|
||||
{
|
||||
err = avformat_open_input(&adec.fmt, NULL, NULL, NULL);
|
||||
err = avformat_open_input(&adec.fmt, NULL, av_find_input_format("oma"), NULL);
|
||||
if (err)
|
||||
{
|
||||
ConLog.Error("adecDecodeAu: avformat_open_input() failed");
|
||||
@ -230,7 +321,7 @@ u32 adecOpen(AudioDecoder* data)
|
||||
Emu.Pause();
|
||||
break;
|
||||
}
|
||||
err = avformat_find_stream_info(adec.fmt, NULL);
|
||||
/*err = avformat_find_stream_info(adec.fmt, NULL);
|
||||
if (err)
|
||||
{
|
||||
ConLog.Error("adecDecodeAu: avformat_find_stream_info() failed");
|
||||
@ -242,6 +333,12 @@ u32 adecOpen(AudioDecoder* data)
|
||||
ConLog.Error("adecDecodeAu: no stream found");
|
||||
Emu.Pause();
|
||||
break;
|
||||
}*/
|
||||
if (!avformat_new_stream(adec.fmt, codec))
|
||||
{
|
||||
ConLog.Error("adecDecodeAu: avformat_new_stream() failed");
|
||||
Emu.Pause();
|
||||
break;
|
||||
}
|
||||
adec.ctx = adec.fmt->streams[0]->codec; // TODO: check data
|
||||
|
||||
@ -259,7 +356,7 @@ u32 adecOpen(AudioDecoder* data)
|
||||
break;
|
||||
}
|
||||
adec.just_started = false;
|
||||
}*/
|
||||
}
|
||||
|
||||
bool last_frame = false;
|
||||
|
||||
@ -271,7 +368,7 @@ u32 adecOpen(AudioDecoder* data)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!adec.ctx) // fake
|
||||
/*if (!adec.ctx) // fake
|
||||
{
|
||||
AdecFrame frame;
|
||||
frame.pts = task.au.pts;
|
||||
@ -285,7 +382,7 @@ u32 adecOpen(AudioDecoder* data)
|
||||
adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg);
|
||||
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
|
||||
last_frame = av_read_frame(adec.fmt, &au) < 0;
|
||||
if (last_frame)
|
||||
@ -336,13 +433,30 @@ u32 adecOpen(AudioDecoder* data)
|
||||
|
||||
if (got_frame)
|
||||
{
|
||||
ConLog.Write("got_frame (%d, pts=0x%llx, dts=0x%llx)", got_frame, au.pts, au.dts);
|
||||
|
||||
frame.pts = task.au.pts; // ???
|
||||
frame.pts = adec.last_pts;
|
||||
adec.last_pts += ((u64)frame.data->nb_samples) * 90000 / 48000; // ???
|
||||
frame.auAddr = task.au.addr;
|
||||
frame.auSize = task.au.size;
|
||||
frame.userdata = task.au.userdata;
|
||||
frame.size = 32768; // ????
|
||||
frame.size = frame.data->nb_samples * frame.data->channels * sizeof(float);
|
||||
|
||||
if (frame.data->format != AV_SAMPLE_FMT_FLTP)
|
||||
{
|
||||
ConLog.Error("adecDecodeaAu: unsupported frame format(%d)", frame.data->format);
|
||||
Emu.Pause();
|
||||
break;
|
||||
}
|
||||
if (frame.data->channels != 2)
|
||||
{
|
||||
ConLog.Error("adecDecodeAu: unsupported channel count (%d)", frame.data->channels);
|
||||
Emu.Pause();
|
||||
break;
|
||||
}
|
||||
|
||||
//ConLog.Write("got audio frame (pts=0x%llx, nb_samples=%d, ch=%d, sample_rate=%d, nbps=%d)",
|
||||
//frame.pts, frame.data->nb_samples, frame.data->channels, frame.data->sample_rate,
|
||||
//av_get_bytes_per_sample((AVSampleFormat)frame.data->format));
|
||||
|
||||
adec.frames.Push(frame);
|
||||
frame.data = nullptr; // to prevent destruction
|
||||
|
||||
@ -569,26 +683,62 @@ int cellAdecGetPcm(u32 handle, u32 outBuffer_addr)
|
||||
|
||||
AdecFrame af;
|
||||
adec->frames.Pop(af);
|
||||
//AVFrame& frame = *af.data;
|
||||
AVFrame* frame = af.data;
|
||||
|
||||
int result = CELL_OK;
|
||||
|
||||
if (!Memory.IsGoodAddr(outBuffer_addr, af.size))
|
||||
{
|
||||
result = CELL_ADEC_ERROR_FATAL;
|
||||
goto end;
|
||||
}
|
||||
else
|
||||
|
||||
if (!af.data) // fake: empty data
|
||||
{
|
||||
// copy data
|
||||
if (!af.data) // fake: empty data
|
||||
{
|
||||
u8* buf = (u8*)malloc(4096);
|
||||
memset(buf, 0, 4096);
|
||||
Memory.CopyFromReal(outBuffer_addr, buf, 4096);
|
||||
free(buf);
|
||||
return CELL_OK;
|
||||
}
|
||||
/*u8* buf = (u8*)malloc(4096);
|
||||
memset(buf, 0, 4096);
|
||||
Memory.CopyFromReal(outBuffer_addr, buf, 4096);
|
||||
free(buf);*/
|
||||
goto end;
|
||||
}
|
||||
// copy data
|
||||
SwrContext* swr = nullptr;
|
||||
u8* out = nullptr;
|
||||
|
||||
out = (u8*)malloc(af.size);
|
||||
|
||||
/*swr = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_FLT, 48000,
|
||||
frame->channel_layout, (AVSampleFormat)frame->format, frame->sample_rate, 0, NULL);
|
||||
|
||||
if (!swr)
|
||||
{
|
||||
ConLog.Error("cellAdecGetPcm(%d): swr_alloc_set_opts() failed", handle);
|
||||
Emu.Pause();
|
||||
goto end;
|
||||
}
|
||||
// something is wrong
|
||||
swr_convert(swr, &out, frame->nb_samples, (const u8**)frame->extended_data, frame->nb_samples); */
|
||||
|
||||
// reverse byte order, extract data:
|
||||
float* in_f[2];
|
||||
in_f[0] = (float*)frame->extended_data[0];
|
||||
in_f[1] = (float*)frame->extended_data[1];
|
||||
be_t<float>* out_f = (be_t<float>*)out;
|
||||
for (u32 i = 0; i < af.size / 8; i++)
|
||||
{
|
||||
out_f[i*2] = in_f[0][i];
|
||||
out_f[i*2+1] = in_f[1][i];
|
||||
}
|
||||
|
||||
if (!Memory.CopyFromReal(outBuffer_addr, out, af.size))
|
||||
{
|
||||
ConLog.Error("cellAdecGetPcm(%d): data copying failed (addr=0x%x)", handle, outBuffer_addr);
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
end:
|
||||
if (out) free(out);
|
||||
if (swr) swr_free(&swr);
|
||||
|
||||
if (af.data)
|
||||
{
|
||||
@ -620,7 +770,7 @@ int cellAdecGetPcmItem(u32 handle, mem32_t pcmItem_ptr)
|
||||
return CELL_ADEC_ERROR_EMPTY;
|
||||
}
|
||||
|
||||
//AVFrame& frame = *af.data;
|
||||
AVFrame* frame = af.data;
|
||||
|
||||
mem_ptr_t<CellAdecPcmItem> pcm(adec->memAddr + adec->memBias);
|
||||
|
||||
@ -635,15 +785,15 @@ int cellAdecGetPcmItem(u32 handle, mem32_t pcmItem_ptr)
|
||||
pcm->startAddr = 0x00000312; // invalid address (no output)
|
||||
pcm->size = af.size;
|
||||
pcm->status = CELL_OK;
|
||||
pcm->auInfo.pts.lower = af.pts; // ???
|
||||
pcm->auInfo.pts.lower = af.pts;
|
||||
pcm->auInfo.pts.upper = af.pts >> 32;
|
||||
pcm->auInfo.size = af.auSize;
|
||||
pcm->auInfo.startAddr = af.auAddr;
|
||||
pcm->auInfo.userData = af.userdata;
|
||||
|
||||
mem_ptr_t<CellAdecAtracXInfo> atx(pcm.GetAddr() + sizeof(CellAdecPcmItem));
|
||||
atx->samplingFreq = 48000; // ???
|
||||
atx->nbytes = 2048; // ???
|
||||
atx->samplingFreq = frame->sample_rate; // ???
|
||||
atx->nbytes = frame->nb_samples * frame->channels * sizeof(float); // ???
|
||||
atx->channelConfigIndex = CELL_ADEC_CH_STEREO; // ???
|
||||
|
||||
pcmItem_ptr = pcm.GetAddr();
|
||||
|
@ -1036,6 +1036,40 @@ struct AdecFrame
|
||||
|
||||
int adecRead(void* opaque, u8* buf, int buf_size);
|
||||
|
||||
struct OMAHeader // OMA Header
|
||||
{
|
||||
u32 magic; // 0x01334145
|
||||
u16 size; // 96 << 8
|
||||
u16 unk0; // 0xffff
|
||||
u64 unk1; // 0x00500f0100000000ULL
|
||||
u64 unk2; // 0xcef5000000000400ULL
|
||||
u64 unk3; // 0x1c458024329192d2ULL
|
||||
u8 codecId; // 1 for ATRAC3P
|
||||
u8 reserved0; // 0
|
||||
u8 code1;
|
||||
u8 code2;
|
||||
u32 reserved1; // 0
|
||||
u64 reserved[7]; // 0
|
||||
|
||||
OMAHeader(u8 id, u8 code1, u8 code2)
|
||||
: magic(0x01334145)
|
||||
, size(96 << 8)
|
||||
, unk0(0xffff)
|
||||
, unk1(0x00500f0100000000ULL)
|
||||
, unk2(0xcef5000000000400ULL)
|
||||
, unk3(0x1c458024329192d2ULL)
|
||||
, codecId(id)
|
||||
, reserved0(0)
|
||||
, code1(code1)
|
||||
, code2(code2)
|
||||
, reserved1(0)
|
||||
{
|
||||
memset(reserved, 0, sizeof(reserved));
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(OMAHeader) == 96, "Wrong OMAHeader size");
|
||||
|
||||
class AudioDecoder
|
||||
{
|
||||
public:
|
||||
@ -1053,6 +1087,21 @@ public:
|
||||
{
|
||||
u32 addr;
|
||||
u32 size;
|
||||
bool init;
|
||||
u8* rem;
|
||||
u32 rem_size;
|
||||
|
||||
AudioReader()
|
||||
: rem(nullptr)
|
||||
, rem_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
~AudioReader()
|
||||
{
|
||||
if (rem) free(rem);
|
||||
rem = nullptr;
|
||||
}
|
||||
} reader;
|
||||
|
||||
SQueue<AdecFrame> frames;
|
||||
|
@ -5,32 +5,7 @@
|
||||
void cellAtrac_init();
|
||||
Module cellAtrac(0x0013, cellAtrac_init);
|
||||
|
||||
// Return Codes
|
||||
enum
|
||||
{
|
||||
CELL_ATRAC_OK = 0x00000000,
|
||||
CELL_ATRAC_ERROR_API_FAIL = 0x80610301,
|
||||
CELL_ATRAC_ERROR_READSIZE_OVER_BUFFER = 0x80610311,
|
||||
CELL_ATRAC_ERROR_UNKNOWN_FORMAT = 0x80610312,
|
||||
CELL_ATRAC_ERROR_READSIZE_IS_TOO_SMALL = 0x80610313,
|
||||
CELL_ATRAC_ERROR_ILLEGAL_SAMPLING_RATE = 0x80610314,
|
||||
CELL_ATRAC_ERROR_ILLEGAL_DATA = 0x80610315,
|
||||
CELL_ATRAC_ERROR_NO_DECODER = 0x80610321,
|
||||
CELL_ATRAC_ERROR_UNSET_DATA = 0x80610322,
|
||||
CELL_ATRAC_ERROR_DECODER_WAS_CREATED = 0x80610323,
|
||||
CELL_ATRAC_ERROR_ALLDATA_WAS_DECODED = 0x80610331,
|
||||
CELL_ATRAC_ERROR_NODATA_IN_BUFFER = 0x80610332,
|
||||
CELL_ATRAC_ERROR_NOT_ALIGNED_OUT_BUFFER = 0x80610333,
|
||||
CELL_ATRAC_ERROR_NEED_SECOND_BUFFER = 0x80610334,
|
||||
CELL_ATRAC_ERROR_ALLDATA_IS_ONMEMORY = 0x80610341,
|
||||
CELL_ATRAC_ERROR_ADD_DATA_IS_TOO_BIG = 0x80610342,
|
||||
CELL_ATRAC_ERROR_NONEED_SECOND_BUFFER = 0x80610351,
|
||||
CELL_ATRAC_ERROR_UNSET_LOOP_NUM = 0x80610361,
|
||||
CELL_ATRAC_ERROR_ILLEGAL_SAMPLE = 0x80610371,
|
||||
CELL_ATRAC_ERROR_ILLEGAL_RESET_BYTE = 0x80610372,
|
||||
CELL_ATRAC_ERROR_ILLEGAL_PPU_THREAD_PRIORITY = 0x80610381,
|
||||
CELL_ATRAC_ERROR_ILLEGAL_SPU_THREAD_PRIORITY = 0x80610382,
|
||||
};
|
||||
#include "cellAtrac.h"
|
||||
|
||||
int cellAtracSetDataAndGetMemSize()
|
||||
{
|
||||
@ -58,13 +33,13 @@ int cellAtracDeleteDecoder()
|
||||
|
||||
int cellAtracDecode()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
||||
//UNIMPLEMENTED_FUNC(cellAtrac);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellAtracGetStreamDataInfo()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
||||
//UNIMPLEMENTED_FUNC(cellAtrac);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
28
rpcs3/Emu/SysCalls/Modules/cellAtrac.h
Normal file
28
rpcs3/Emu/SysCalls/Modules/cellAtrac.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
// Return Codes
|
||||
enum
|
||||
{
|
||||
CELL_ATRAC_OK = 0x00000000,
|
||||
CELL_ATRAC_ERROR_API_FAIL = 0x80610301,
|
||||
CELL_ATRAC_ERROR_READSIZE_OVER_BUFFER = 0x80610311,
|
||||
CELL_ATRAC_ERROR_UNKNOWN_FORMAT = 0x80610312,
|
||||
CELL_ATRAC_ERROR_READSIZE_IS_TOO_SMALL = 0x80610313,
|
||||
CELL_ATRAC_ERROR_ILLEGAL_SAMPLING_RATE = 0x80610314,
|
||||
CELL_ATRAC_ERROR_ILLEGAL_DATA = 0x80610315,
|
||||
CELL_ATRAC_ERROR_NO_DECODER = 0x80610321,
|
||||
CELL_ATRAC_ERROR_UNSET_DATA = 0x80610322,
|
||||
CELL_ATRAC_ERROR_DECODER_WAS_CREATED = 0x80610323,
|
||||
CELL_ATRAC_ERROR_ALLDATA_WAS_DECODED = 0x80610331,
|
||||
CELL_ATRAC_ERROR_NODATA_IN_BUFFER = 0x80610332,
|
||||
CELL_ATRAC_ERROR_NOT_ALIGNED_OUT_BUFFER = 0x80610333,
|
||||
CELL_ATRAC_ERROR_NEED_SECOND_BUFFER = 0x80610334,
|
||||
CELL_ATRAC_ERROR_ALLDATA_IS_ONMEMORY = 0x80610341,
|
||||
CELL_ATRAC_ERROR_ADD_DATA_IS_TOO_BIG = 0x80610342,
|
||||
CELL_ATRAC_ERROR_NONEED_SECOND_BUFFER = 0x80610351,
|
||||
CELL_ATRAC_ERROR_UNSET_LOOP_NUM = 0x80610361,
|
||||
CELL_ATRAC_ERROR_ILLEGAL_SAMPLE = 0x80610371,
|
||||
CELL_ATRAC_ERROR_ILLEGAL_RESET_BYTE = 0x80610372,
|
||||
CELL_ATRAC_ERROR_ILLEGAL_PPU_THREAD_PRIORITY = 0x80610381,
|
||||
CELL_ATRAC_ERROR_ILLEGAL_SPU_THREAD_PRIORITY = 0x80610382,
|
||||
};
|
@ -118,29 +118,37 @@ int cellAudioInit()
|
||||
index = (position + 1) % port.block; // write new value
|
||||
}
|
||||
|
||||
u32 k = port.channel / 2;
|
||||
|
||||
if (first_mix)
|
||||
{
|
||||
for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i++)
|
||||
for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i += 2)
|
||||
{
|
||||
// reverse byte order (TODO: use port.m_param.level)
|
||||
buffer[i] = buffer2[i];
|
||||
buffer[i] = buffer2[i*k];
|
||||
buffer[i+1] = buffer2[i*k+1];
|
||||
|
||||
// convert the data from float to u16
|
||||
assert(buffer[i] >= -4.0f && buffer[i] <= 4.0f);
|
||||
assert(buffer[i+1] >= -4.0f && buffer[i+1] <= 4.0f);
|
||||
oal_buffer[oal_buffer_offset + i] = (u16)(buffer[i] * ((1 << 13) - 1));
|
||||
oal_buffer[oal_buffer_offset + i + 1] = (u16)(buffer[i+1] * ((1 << 13) - 1));
|
||||
}
|
||||
|
||||
first_mix = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i++)
|
||||
for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i += 2)
|
||||
{
|
||||
buffer[i] = (buffer[i] + buffer2[i]) * 0.5; // TODO: valid mixing
|
||||
buffer[i] = (buffer[i] + buffer2[i*k]) * 0.5; // TODO: valid mixing
|
||||
buffer[i+1] = (buffer[i+1] + buffer2[i*k+1]) * 0.5;
|
||||
|
||||
// convert the data from float to u16
|
||||
assert(buffer[i] >= -4.0f && buffer[i] <= 4.0f);
|
||||
assert(buffer[i+1] >= -4.0f && buffer[i+1] <= 4.0f);
|
||||
oal_buffer[oal_buffer_offset + i] = (u16)(buffer[i] * ((1 << 13) - 1));
|
||||
oal_buffer[oal_buffer_offset + i + 1] = (u16)(buffer[i+1] * ((1 << 13) - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -176,8 +184,6 @@ int cellAudioInit()
|
||||
ConLog.Error("Port aborted: cannot write file!");
|
||||
goto abort;
|
||||
}
|
||||
|
||||
m_dump.UpdateHeader(sizeof(buffer));
|
||||
}
|
||||
}
|
||||
ConLog.Write("Audio finished");
|
||||
|
@ -18,9 +18,9 @@ void dmuxQueryEsAttr(u32 info_addr /* may be 0 */, const mem_ptr_t<CellCodecEsFi
|
||||
const u32 esSpecificInfo_addr, mem_ptr_t<CellDmuxEsAttr> attr)
|
||||
{
|
||||
if (esFilterId->filterIdMajor >= 0xe0)
|
||||
attr->memSize = 0x3000000; // 0x45fa49 from ps3
|
||||
attr->memSize = 0x500000; // 0x45fa49 from ps3
|
||||
else
|
||||
attr->memSize = 0x200000; // 0x73d9 from ps3
|
||||
attr->memSize = 0x8000; // 0x73d9 from ps3
|
||||
|
||||
cellDmux.Warning("*** filter(0x%x, 0x%x, 0x%x, 0x%x)", (u32)esFilterId->filterIdMajor, (u32)esFilterId->filterIdMinor,
|
||||
(u32)esFilterId->supplementalInfo1, (u32)esFilterId->supplementalInfo2);
|
||||
@ -131,7 +131,7 @@ u32 dmuxOpen(Demuxer* data)
|
||||
}
|
||||
|
||||
// read additional header:
|
||||
stream.peek(ch);
|
||||
stream.peek(ch); // ???
|
||||
//stream.skip(4);
|
||||
//pes.size += 4;
|
||||
|
||||
@ -148,26 +148,18 @@ u32 dmuxOpen(Demuxer* data)
|
||||
Sleep(1);
|
||||
}
|
||||
|
||||
/*if (es.hasunseen()) // hack, probably useless
|
||||
if (es.hasunseen()) // hack, probably useless
|
||||
{
|
||||
stream = backup;
|
||||
continue;
|
||||
}*/
|
||||
|
||||
//ConLog.Write("*** AT3+ AU sent (pts=0x%llx, dts=0x%llx)", pes.pts, pes.dts);
|
||||
}
|
||||
|
||||
stream.skip(4);
|
||||
len -= 4;
|
||||
u32 abc;
|
||||
stream.peek(abc);
|
||||
if (abc == 0x5548D00F)
|
||||
{
|
||||
stream.skip(8);
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
es.push(stream, len - pes.size - 3, pes);
|
||||
es.finish(stream);
|
||||
//ConLog.Write("*** AT3+ AU sent (len=0x%x, pts=0x%llx)", len - pes.size - 3, pes.pts);
|
||||
|
||||
mem_ptr_t<CellDmuxEsMsg> esMsg(a128(dmux.memAddr) + (cb_add ^= 16));
|
||||
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND;
|
||||
@ -211,13 +203,18 @@ u32 dmuxOpen(Demuxer* data)
|
||||
stream.get(len);
|
||||
PesHeader pes(stream);
|
||||
|
||||
if (es.freespace() < (u32)(len + 6))
|
||||
{
|
||||
pes.new_au = true;
|
||||
}
|
||||
|
||||
if (pes.new_au && es.hasdata()) // new AU detected
|
||||
{
|
||||
/*if (es.hasunseen()) // hack, probably useless
|
||||
if (es.hasunseen()) // hack, probably useless
|
||||
{
|
||||
stream = backup;
|
||||
continue;
|
||||
}*/
|
||||
}
|
||||
es.finish(stream);
|
||||
// callback
|
||||
mem_ptr_t<CellDmuxEsMsg> esMsg(a128(dmux.memAddr) + (cb_add ^= 16));
|
||||
@ -298,8 +295,9 @@ u32 dmuxOpen(Demuxer* data)
|
||||
{
|
||||
case dmuxSetStream:
|
||||
{
|
||||
if (stream.discontinuity)
|
||||
if (task.stream.discontinuity)
|
||||
{
|
||||
ConLog.Warning("dmuxSetStream (beginning)");
|
||||
for (u32 i = 0; i < 192; i++)
|
||||
{
|
||||
if (esALL[i])
|
||||
@ -319,8 +317,8 @@ u32 dmuxOpen(Demuxer* data)
|
||||
|
||||
updates_count++;
|
||||
stream = task.stream;
|
||||
ConLog.Write("*** stream updated(addr=0x%x, size=0x%x, discont=%d, userdata=0x%llx)",
|
||||
stream.addr, stream.size, stream.discontinuity, stream.userdata);
|
||||
//ConLog.Write("*** stream updated(addr=0x%x, size=0x%x, discont=%d, userdata=0x%llx)",
|
||||
//stream.addr, stream.size, stream.discontinuity, stream.userdata);
|
||||
|
||||
dmux.is_running = true;
|
||||
dmux.fbSetStream.Push(task.stream.addr); // feedback
|
||||
@ -652,7 +650,7 @@ int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize
|
||||
|
||||
int cellDmuxResetStream(u32 demuxerHandle)
|
||||
{
|
||||
cellDmux.Log("cellDmuxResetStream(demuxerHandle=%d)", demuxerHandle);
|
||||
cellDmux.Warning("cellDmuxResetStream(demuxerHandle=%d)", demuxerHandle);
|
||||
|
||||
Demuxer* dmux;
|
||||
if (!Emu.GetIdManager().GetIDData(demuxerHandle, dmux))
|
||||
@ -667,7 +665,7 @@ int cellDmuxResetStream(u32 demuxerHandle)
|
||||
|
||||
int cellDmuxResetStreamAndWaitDone(u32 demuxerHandle)
|
||||
{
|
||||
cellDmux.Log("cellDmuxResetStreamAndWaitDone(demuxerHandle=%d)", demuxerHandle);
|
||||
cellDmux.Warning("cellDmuxResetStreamAndWaitDone(demuxerHandle=%d)", demuxerHandle);
|
||||
|
||||
Demuxer* dmux;
|
||||
if (!Emu.GetIdManager().GetIDData(demuxerHandle, dmux))
|
||||
@ -947,9 +945,7 @@ int cellDmuxPeekAuEx(u32 esHandle, mem32_t auInfoEx_ptr, mem32_t auSpecificInfo_
|
||||
|
||||
int cellDmuxReleaseAu(u32 esHandle)
|
||||
{
|
||||
cellDmux.Log("(disabled) cellDmuxReleaseAu(esHandle=0x%x)", esHandle);
|
||||
|
||||
return CELL_OK;
|
||||
cellDmux.Log("cellDmuxReleaseAu(esHandle=0x%x)", esHandle);
|
||||
|
||||
ElementaryStream* es;
|
||||
if (!Emu.GetIdManager().GetIDData(esHandle, es))
|
||||
|
@ -483,23 +483,29 @@ class ElementaryStream
|
||||
{
|
||||
SMutex mutex;
|
||||
|
||||
u32 first_addr; // AU that will be released
|
||||
u32 last_addr; // AU that is being written now
|
||||
u32 last_size; // number of bytes written (after 128b header)
|
||||
u32 peek_addr; // AU that will be obtained by GetAu(Ex)/PeekAu(Ex)
|
||||
SQueue<u32> entries; // AU starting addresses
|
||||
u32 put_count; // number of AU written
|
||||
u32 released; // number of AU released
|
||||
u32 peek_count; // number of AU obtained by GetAu(Ex)
|
||||
|
||||
u32 put; // AU that is being written now
|
||||
u32 size; // number of bytes written (after 128b header)
|
||||
//u32 first; // AU that will be released
|
||||
//u32 peek; // AU that will be obtained by GetAu(Ex)/PeekAu(Ex)
|
||||
|
||||
bool is_full()
|
||||
{
|
||||
if (first_addr)
|
||||
if (released < put_count)
|
||||
{
|
||||
if (first_addr >= last_addr)
|
||||
u32 first = entries.Peek();
|
||||
if (first >= put)
|
||||
{
|
||||
return (first_addr - last_addr) <= GetMaxAU();
|
||||
return (first - put) < GetMaxAU();
|
||||
}
|
||||
else
|
||||
{
|
||||
// probably, always false
|
||||
return (last_addr + GetMaxAU()) > (memAddr + memSize);
|
||||
return (put + GetMaxAU()) > (memAddr + memSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -532,26 +538,42 @@ public:
|
||||
, cbFunc(cbFunc)
|
||||
, cbArg(cbArg)
|
||||
, spec(spec)
|
||||
, first_addr(0)
|
||||
, peek_addr(0)
|
||||
, last_addr(memAddr)
|
||||
, last_size(0)
|
||||
//, first(0)
|
||||
//, peek(0)
|
||||
, put(memAddr)
|
||||
, size(0)
|
||||
, put_count(0)
|
||||
, released(0)
|
||||
, peek_count(0)
|
||||
{
|
||||
}
|
||||
|
||||
const u32 GetMaxAU() const
|
||||
{
|
||||
return 640 * 1024 + 128;
|
||||
return (fidMajor == 0xbd) ? 4096 : 640 * 1024 + 128; // TODO
|
||||
}
|
||||
|
||||
volatile bool hasunseen()
|
||||
u32 freespace()
|
||||
{
|
||||
return peek_addr;
|
||||
if (size > GetMaxAU())
|
||||
{
|
||||
ConLog.Error("es::freespace(): last_size too big (size=0x%x, max_au=0x%x)", size, GetMaxAU());
|
||||
Emu.Pause();
|
||||
return 0;
|
||||
}
|
||||
return GetMaxAU() - size;
|
||||
}
|
||||
|
||||
volatile bool hasdata()
|
||||
bool hasunseen()
|
||||
{
|
||||
return last_size;
|
||||
SMutexLocker lock(mutex);
|
||||
return peek_count < put_count;
|
||||
}
|
||||
|
||||
bool hasdata()
|
||||
{
|
||||
SMutexLocker lock(mutex);
|
||||
return size;
|
||||
}
|
||||
|
||||
bool isfull()
|
||||
@ -562,54 +584,70 @@ public:
|
||||
|
||||
void finish(DemuxerStream& stream) // not multithread-safe
|
||||
{
|
||||
SMutexLocker lock(mutex);
|
||||
//ConLog.Write("es::finish(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size);
|
||||
if (!first_addr)
|
||||
u32 addr;
|
||||
{
|
||||
first_addr = last_addr;
|
||||
}
|
||||
if (!peek_addr)
|
||||
{
|
||||
peek_addr = last_addr;
|
||||
}
|
||||
SMutexLocker lock(mutex);
|
||||
//if (fidMajor != 0xbd) ConLog.Write(">>> es::finish(): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", peek, first, put, size);
|
||||
|
||||
u32 new_addr = a128(last_addr + 128 + last_size);
|
||||
if ((new_addr + GetMaxAU()) > (memAddr + memSize))
|
||||
{
|
||||
last_addr = memAddr;
|
||||
addr = put;
|
||||
/*if (!first)
|
||||
{
|
||||
first = put;
|
||||
}
|
||||
if (!peek)
|
||||
{
|
||||
peek = put;
|
||||
}*/
|
||||
|
||||
mem_ptr_t<CellDmuxAuInfo> info(put);
|
||||
//if (fidMajor != 0xbd) ConLog.Warning("es::finish(): (%s) size = 0x%x, info_addr=0x%x, pts = 0x%x",
|
||||
//wxString(fidMajor == 0xbd ? "ATRAC3P Audio" : "Video AVC").wx_str(),
|
||||
//(u32)info->auSize, put, (u32)info->ptsLower);
|
||||
|
||||
u32 new_addr = a128(put + 128 + size);
|
||||
if ((new_addr + GetMaxAU()) > (memAddr + memSize))
|
||||
{
|
||||
put = memAddr;
|
||||
}
|
||||
else
|
||||
{
|
||||
put = new_addr;
|
||||
}
|
||||
size = 0;
|
||||
|
||||
put_count++;
|
||||
//if (fidMajor != 0xbd) ConLog.Write("<<< es::finish(): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", peek, first, put, size);
|
||||
}
|
||||
else
|
||||
if (!entries.Push(addr))
|
||||
{
|
||||
last_addr = new_addr;
|
||||
ConLog.Error("es::finish() aborted (no space)");
|
||||
}
|
||||
last_size = 0;
|
||||
}
|
||||
|
||||
void push(DemuxerStream& stream, u32 size, PesHeader& pes)
|
||||
void push(DemuxerStream& stream, u32 sz, PesHeader& pes)
|
||||
{
|
||||
SMutexLocker lock(mutex);
|
||||
//ConLog.Write("es::push(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size);
|
||||
|
||||
if (is_full())
|
||||
{
|
||||
ConLog.Error("ElementaryStream::push(): buffer is full");
|
||||
ConLog.Error("es::push(): buffer is full");
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
|
||||
u32 data_addr = last_addr + 128 + last_size;
|
||||
last_size += size;
|
||||
if (!Memory.Copy(data_addr, stream.addr, size))
|
||||
u32 data_addr = put + 128 + size;
|
||||
size += sz;
|
||||
if (!Memory.Copy(data_addr, stream.addr, sz))
|
||||
{
|
||||
ConLog.Error("ElementaryStream::push(): data copying failed");
|
||||
ConLog.Error("es::push(): data copying failed");
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
stream.skip(size);
|
||||
stream.skip(sz);
|
||||
|
||||
mem_ptr_t<CellDmuxAuInfoEx> info(last_addr);
|
||||
info->auAddr = last_addr + 128;
|
||||
info->auSize = last_size;
|
||||
mem_ptr_t<CellDmuxAuInfoEx> info(put);
|
||||
info->auAddr = put + 128;
|
||||
info->auSize = size;
|
||||
if (pes.new_au)
|
||||
{
|
||||
info->dts.lower = (u32)pes.dts;
|
||||
@ -621,12 +659,12 @@ public:
|
||||
info->userData = stream.userdata;
|
||||
}
|
||||
|
||||
mem_ptr_t<CellDmuxPamfAuSpecificInfoAvc> tail(last_addr + sizeof(CellDmuxAuInfoEx));
|
||||
mem_ptr_t<CellDmuxPamfAuSpecificInfoAvc> tail(put + sizeof(CellDmuxAuInfoEx));
|
||||
tail->reserved1 = 0;
|
||||
|
||||
mem_ptr_t<CellDmuxAuInfo> inf(last_addr + 64);
|
||||
inf->auAddr = last_addr + 128;
|
||||
inf->auSize = last_size;
|
||||
mem_ptr_t<CellDmuxAuInfo> inf(put + 64);
|
||||
inf->auAddr = put + 128;
|
||||
inf->auSize = size;
|
||||
if (pes.new_au)
|
||||
{
|
||||
inf->dtsLower = (u32)pes.dts;
|
||||
@ -641,76 +679,107 @@ public:
|
||||
bool release()
|
||||
{
|
||||
SMutexLocker lock(mutex);
|
||||
//ConLog.Write("es::release(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size);
|
||||
if (!first_addr)
|
||||
//if (fidMajor != 0xbd) ConLog.Write(">>> es::release(): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", peek, first, put, size);
|
||||
if (released >= put_count)
|
||||
{
|
||||
ConLog.Error("ElementaryStream::release(): buffer is empty");
|
||||
ConLog.Error("es::release(): buffer is empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 size = a128(Memory.Read32(first_addr + 4) + 128);
|
||||
u32 new_addr = first_addr + size;
|
||||
u32 addr = entries.Peek();
|
||||
|
||||
if (peek_addr == first_addr)
|
||||
mem_ptr_t<CellDmuxAuInfo> info(addr);
|
||||
//if (fidMajor != 0xbd) ConLog.Warning("es::release(): (%s) size = 0x%x, info = 0x%x, pts = 0x%x",
|
||||
//wxString(fidMajor == 0xbd ? "ATRAC3P Audio" : "Video AVC").wx_str(), (u32)info->auSize, first, (u32)info->ptsLower);
|
||||
|
||||
if (released >= peek_count)
|
||||
{
|
||||
ConLog.Error("ElementaryStream::release(): buffer has not been seen yet");
|
||||
ConLog.Error("es::release(): buffer has not been seen yet");
|
||||
return false;
|
||||
}
|
||||
|
||||
//if (peek_addr <= first_addr) peek_addr = new_addr;
|
||||
if (new_addr == last_addr)
|
||||
/*u32 new_addr = a128(info.GetAddr() + 128 + info->auSize);
|
||||
|
||||
if (new_addr == put)
|
||||
{
|
||||
first_addr = 0;
|
||||
first = 0;
|
||||
}
|
||||
else if ((new_addr + GetMaxAU()) > (memAddr + memSize))
|
||||
{
|
||||
first_addr = memAddr;
|
||||
first = memAddr;
|
||||
}
|
||||
else
|
||||
{
|
||||
first_addr = new_addr;
|
||||
}
|
||||
first = new_addr;
|
||||
}*/
|
||||
|
||||
released++;
|
||||
if (!entries.Pop(addr))
|
||||
{
|
||||
ConLog.Error("es::release(): entries.Pop() aborted (no entries found)");
|
||||
return false;
|
||||
}
|
||||
//if (fidMajor != 0xbd) ConLog.Write("<<< es::release(): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", peek, first, put, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool peek(u32& out_data, bool no_ex, u32& out_spec, bool update_index)
|
||||
{
|
||||
SMutexLocker lock(mutex);
|
||||
/*ConLog.Write("es::peek(%sAu%s): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", wxString(update_index ? "Get" : "Peek").wx_str(),
|
||||
wxString(no_ex ? "" : "Ex").wx_str(), peek_addr, first_addr, last_addr, last_size);*/
|
||||
if (!peek_addr) return false;
|
||||
//if (fidMajor != 0xbd) ConLog.Write(">>> es::peek(%sAu%s): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", wxString(update_index ? "Get" : "Peek").wx_str(),
|
||||
//wxString(no_ex ? "" : "Ex").wx_str(), peek, first, put, size);
|
||||
if (peek_count >= put_count) return false;
|
||||
|
||||
out_data = peek_addr;
|
||||
if (peek_count < released)
|
||||
{
|
||||
ConLog.Error("es::peek(): sequence error: peek_count < released (peek_count=%d, released=%d)", peek_count, released);
|
||||
Emu.Pause();
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 addr = entries.Peek(peek_count - released);
|
||||
mem_ptr_t<CellDmuxAuInfo> info(addr);
|
||||
//if (fidMajor != 0xbd) ConLog.Warning("es::peek(%sAu(Ex)): (%s) size = 0x%x, info = 0x%x, pts = 0x%x",
|
||||
//wxString(update_index ? "Get" : "Peek").wx_str(),
|
||||
//wxString(fidMajor == 0xbd ? "ATRAC3P Audio" : "Video AVC").wx_str(), (u32)info->auSize, peek, (u32)info->ptsLower);
|
||||
|
||||
out_data = addr;
|
||||
out_spec = out_data + sizeof(CellDmuxAuInfoEx);
|
||||
if (no_ex) out_data += 64;
|
||||
|
||||
if (update_index)
|
||||
{
|
||||
u32 size = a128(Memory.Read32(peek_addr + 4) + 128);
|
||||
u32 new_addr = peek_addr + size;
|
||||
if (new_addr = last_addr)
|
||||
/*u32 new_addr = a128(peek + 128 + info->auSize);
|
||||
if (new_addr = put)
|
||||
{
|
||||
peek_addr = 0;
|
||||
peek = 0;
|
||||
}
|
||||
else if ((new_addr + GetMaxAU()) > (memAddr + memSize))
|
||||
{
|
||||
peek_addr = memAddr;
|
||||
peek = memAddr;
|
||||
}
|
||||
else
|
||||
{
|
||||
peek_addr = new_addr;
|
||||
}
|
||||
peek = new_addr;
|
||||
}*/
|
||||
peek_count++;
|
||||
}
|
||||
|
||||
//if (fidMajor != 0xbd) ConLog.Write("<<< es::peek(%sAu%s): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", wxString(update_index ? "Get" : "Peek").wx_str(),
|
||||
//wxString(no_ex ? "" : "Ex").wx_str(), peek, first, put, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
SMutexLocker lock(mutex);
|
||||
first_addr = 0;
|
||||
peek_addr = 0;
|
||||
last_addr = memAddr;
|
||||
last_size = 0;
|
||||
//first = 0;
|
||||
//peek = 0;
|
||||
put = memAddr;
|
||||
size = 0;
|
||||
entries.Clear();
|
||||
put_count = 0;
|
||||
released = 0;
|
||||
peek_count = 0;
|
||||
}
|
||||
};
|
||||
|
@ -37,6 +37,7 @@ uint32_t cellGcmGetMaxIoMapSize();
|
||||
void cellGcmGetOffsetTable(mem_ptr_t<gcm_offset> table);
|
||||
int32_t cellGcmIoOffsetToAddress(u32 ioOffset, u64 address);
|
||||
int32_t cellGcmMapEaIoAddress(const u32 ea, const u32 io, const u32 size);
|
||||
int32_t cellGcmMapEaIoAddressWithFlags(const u32 ea, const u32 io, const u32 size, const u32 flags);
|
||||
int32_t cellGcmMapMainMemory(u64 ea, u32 size, mem32_t offset);
|
||||
int32_t cellGcmReserveIoMapSize(const u32 size);
|
||||
int32_t cellGcmUnmapEaIoAddress(u64 ea);
|
||||
@ -68,6 +69,14 @@ int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress)
|
||||
|
||||
cellGcmSys.Warning("*** local memory(addr=0x%x, size=0x%x)", local_addr, local_size);
|
||||
|
||||
InitOffsetTable();
|
||||
Memory.MemoryBlocks.push_back(Memory.RSXIOMem.SetRange(0x50000000, 0x10000000/*256MB*/));//TODO: implement allocateAdressSpace in memoryBase
|
||||
if(cellGcmMapEaIoAddress(ioAddress, 0, ioSize) != CELL_OK)
|
||||
{
|
||||
Memory.MemoryBlocks.pop_back();
|
||||
return CELL_GCM_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
map_offset_addr = 0;
|
||||
map_offset_pos = 0;
|
||||
current_config.ioSize = ioSize;
|
||||
@ -77,10 +86,7 @@ int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress)
|
||||
current_config.memoryFrequency = 650000000;
|
||||
current_config.coreFrequency = 500000000;
|
||||
|
||||
InitOffsetTable();
|
||||
Memory.RSXCMDMem.AllocAlign(cmdSize);
|
||||
Memory.MemoryBlocks.push_back(Memory.RSXIOMem.SetRange(0x50000000, 0x10000000/*256MB*/));//TODO: implement allocateAdressSpace in memoryBase
|
||||
cellGcmMapEaIoAddress(ioAddress, 0, ioSize);
|
||||
|
||||
u32 ctx_begin = ioAddress/* + 0x1000*/;
|
||||
u32 ctx_size = 0x6ffc;
|
||||
@ -677,6 +683,12 @@ int32_t cellGcmMapEaIoAddress(const u32 ea, const u32 io, const u32 size)
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int32_t cellGcmMapEaIoAddressWithFlags(const u32 ea, const u32 io, const u32 size, const u32 flags)
|
||||
{
|
||||
cellGcmSys.Warning("cellGcmMapEaIoAddressWithFlags(ea=0x%x, io=0x%x, size=0x%x, flags=0x%x)", ea, io, size, flags);
|
||||
return cellGcmMapEaIoAddress(ea, io, size); // TODO: strict ordering
|
||||
}
|
||||
|
||||
int32_t cellGcmMapLocalMemory(u64 address, u64 size)
|
||||
{
|
||||
if(!local_size && !local_addr)
|
||||
@ -855,6 +867,7 @@ void cellGcmSys_init()
|
||||
cellGcmSys.AddFunc(0x2922aed0, cellGcmGetOffsetTable);
|
||||
cellGcmSys.AddFunc(0x2a6fba9c, cellGcmIoOffsetToAddress);
|
||||
cellGcmSys.AddFunc(0x63441cb4, cellGcmMapEaIoAddress);
|
||||
cellGcmSys.AddFunc(0x626e8518, cellGcmMapEaIoAddressWithFlags);
|
||||
cellGcmSys.AddFunc(0xdb769b32, cellGcmMapLocalMemory);
|
||||
cellGcmSys.AddFunc(0xa114ec67, cellGcmMapMainMemory);
|
||||
cellGcmSys.AddFunc(0xa7ede268, cellGcmReserveIoMapSize);
|
||||
|
@ -19,6 +19,19 @@ enum
|
||||
ConverterUnknown,
|
||||
};
|
||||
|
||||
// detection result
|
||||
enum
|
||||
{
|
||||
L10N_STR_UNKNOWN = (1 << 0),
|
||||
L10N_STR_ASCII = (1 << 1),
|
||||
L10N_STR_JIS = (1 << 2),
|
||||
L10N_STR_EUCJP = (1 << 3),
|
||||
L10N_STR_SJIS = (1 << 4),
|
||||
L10N_STR_UTF8 = (1 << 5),
|
||||
L10N_STR_ILLEGAL = (1 << 16),
|
||||
L10N_STR_ERROR = (1 << 17),
|
||||
};
|
||||
|
||||
int UTF16stoUTF8s(mem16_ptr_t utf16, mem64_t utf16_len, mem8_ptr_t utf8, mem64_t utf8_len)
|
||||
{
|
||||
cellL10n.Warning("UTF16stoUTF8s(utf16_addr=0x%x, utf16_len_addr=0x%x, utf8_addr=0x%x, utf8_len_addr=0x%x)",
|
||||
@ -43,6 +56,13 @@ int UTF16stoUTF8s(mem16_ptr_t utf16, mem64_t utf16_len, mem8_ptr_t utf8, mem64_t
|
||||
return ConversionOK;
|
||||
}
|
||||
|
||||
int jstrchk(mem8_ptr_t jstr)
|
||||
{
|
||||
cellL10n.Log("jstrchk(jstr_addr=0x%x [%s])", jstr.GetAddr(), "omitted" /*Memory.ReadString(jstr.GetAddr()).wx_str()*/);
|
||||
|
||||
return L10N_STR_UTF8;
|
||||
}
|
||||
|
||||
void cellL10n_init()
|
||||
{
|
||||
// NOTE: I think this module should be LLE'd instead of implementing all its functions
|
||||
@ -132,7 +152,7 @@ void cellL10n_init()
|
||||
// cellL10n.AddFunc(0x73f2cd21, SJISstoJISs);
|
||||
// cellL10n.AddFunc(0x74496718, SBCStoUTF8);
|
||||
// cellL10n.AddFunc(0x74871fe0, UTF8toUTF32);
|
||||
// cellL10n.AddFunc(0x750c363d, jstrchk);
|
||||
cellL10n.AddFunc(0x750c363d, jstrchk);
|
||||
// cellL10n.AddFunc(0x7c5bde1c, UHCtoEUCKR);
|
||||
// cellL10n.AddFunc(0x7c912bda, kuten2jis);
|
||||
// cellL10n.AddFunc(0x7d07a1c2, UTF8toEUCCN);
|
||||
|
@ -66,9 +66,10 @@ next:
|
||||
|
||||
vdec.reader.addr = vdec.task.addr;
|
||||
vdec.reader.size = vdec.task.size;
|
||||
//ConLog.Write("Video AU: size = 0x%x, pts = 0x%llx, dts = 0x%llx", vdec.task.size, vdec.task.pts, vdec.task.dts);
|
||||
|
||||
vdec.last_pts = vdec.task.pts;
|
||||
vdec.last_dts = vdec.task.dts;
|
||||
//if (vdec.last_pts > vdec.task.pts) vdec.last_pts = vdec.task.pts;
|
||||
//if (vdec.last_dts > vdec.task.dts) vdec.last_dts = vdec.task.dts;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -205,9 +206,15 @@ u32 vdecOpen(VideoDecoder* data)
|
||||
|
||||
vdec.reader.addr = task.addr;
|
||||
vdec.reader.size = task.size;
|
||||
//ConLog.Write("Video AU: size = 0x%x, pts = 0x%llx, dts = 0x%llx", task.size, task.pts, task.dts);
|
||||
|
||||
vdec.last_pts = task.pts;
|
||||
vdec.last_dts = task.dts;
|
||||
//if (vdec.last_pts > task.pts || vdec.just_started) vdec.last_pts = task.pts;
|
||||
//if (vdec.last_dts > task.dts || vdec.just_started) vdec.last_dts = task.dts;
|
||||
if (vdec.just_started)
|
||||
{
|
||||
vdec.last_pts = task.pts;
|
||||
vdec.last_dts = task.dts;
|
||||
}
|
||||
|
||||
struct AVPacketHolder : AVPacket
|
||||
{
|
||||
@ -350,11 +357,12 @@ u32 vdecOpen(VideoDecoder* data)
|
||||
|
||||
if (got_picture)
|
||||
{
|
||||
//ConLog.Write("got_picture (%d, vdec: pts=0x%llx, dts=0x%llx)", got_picture, au.pts, au.dts);
|
||||
|
||||
frame.dts = vdec.last_dts; vdec.last_dts += 3003; // + duration???
|
||||
frame.pts = vdec.last_pts; vdec.last_pts += 3003;
|
||||
frame.userdata = task.userData;
|
||||
|
||||
//ConLog.Write("got picture (pts=0x%llx, dts=0x%llx)", frame.pts, frame.dts);
|
||||
|
||||
vdec.frames.Push(frame); // !!!!!!!!
|
||||
frame.data = nullptr; // to prevent destruction
|
||||
|
||||
|
@ -1,6 +1,12 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Emu/SysCalls/SC_FUNC.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "libswscale/swscale.h"
|
||||
}
|
||||
|
||||
#include "cellVpost.h"
|
||||
|
||||
void cellVpost_init();
|
||||
@ -93,13 +99,15 @@ int cellVpostExec(u32 handle, const u32 inPicBuff_addr, const mem_ptr_t<CellVpos
|
||||
|
||||
u32 w = ctrlParam->inWidth;
|
||||
u32 h = ctrlParam->inHeight;
|
||||
u32 ow = ctrlParam->outWidth;
|
||||
u32 oh = ctrlParam->outHeight;
|
||||
|
||||
if (!Memory.IsGoodAddr(inPicBuff_addr, w*h*3/2))
|
||||
{
|
||||
return CELL_VPOST_ERROR_E_ARG_INPICBUF_INVALID;
|
||||
}
|
||||
|
||||
if (!Memory.IsGoodAddr(outPicBuff_addr, w*h*4))
|
||||
if (!Memory.IsGoodAddr(outPicBuff_addr, ow*oh*4))
|
||||
{
|
||||
return CELL_VPOST_ERROR_E_ARG_OUTPICBUF_INVALID;
|
||||
}
|
||||
@ -110,13 +118,21 @@ int cellVpostExec(u32 handle, const u32 inPicBuff_addr, const mem_ptr_t<CellVpos
|
||||
}
|
||||
|
||||
ctrlParam->inWindow; // ignored
|
||||
if (ctrlParam->inWindow.x) ConLog.Warning("*** inWindow.x = %d", (u32)ctrlParam->inWindow.x);
|
||||
if (ctrlParam->inWindow.y) ConLog.Warning("*** inWindow.y = %d", (u32)ctrlParam->inWindow.y);
|
||||
if (ctrlParam->inWindow.width != w) ConLog.Warning("*** inWindow.width = %d", (u32)ctrlParam->inWindow.width);
|
||||
if (ctrlParam->inWindow.height != h) ConLog.Warning("*** inWindow.height = %d", (u32)ctrlParam->inWindow.height);
|
||||
ctrlParam->outWindow; // ignored
|
||||
if (ctrlParam->outWindow.x) ConLog.Warning("*** outWindow.x = %d", (u32)ctrlParam->outWindow.x);
|
||||
if (ctrlParam->outWindow.y) ConLog.Warning("*** outWindow.y = %d", (u32)ctrlParam->outWindow.y);
|
||||
if (ctrlParam->outWindow.width != ow) ConLog.Warning("*** outWindow.width = %d", (u32)ctrlParam->outWindow.width);
|
||||
if (ctrlParam->outWindow.height != oh) ConLog.Warning("*** outWindow.height = %d", (u32)ctrlParam->outWindow.height);
|
||||
ctrlParam->execType; // ignored
|
||||
ctrlParam->scalerType; // ignored
|
||||
ctrlParam->ipcType; // ignored
|
||||
|
||||
picInfo->inWidth = ctrlParam->inWidth; // copy
|
||||
picInfo->inHeight = ctrlParam->inHeight; // copy
|
||||
picInfo->inWidth = w; // copy
|
||||
picInfo->inHeight = h; // copy
|
||||
picInfo->inDepth = CELL_VPOST_PIC_DEPTH_8; // fixed
|
||||
picInfo->inScanType = CELL_VPOST_SCAN_TYPE_P; // TODO
|
||||
picInfo->inPicFmt = CELL_VPOST_PIC_FMT_IN_YUV420_PLANAR; // fixed
|
||||
@ -125,24 +141,25 @@ int cellVpostExec(u32 handle, const u32 inPicBuff_addr, const mem_ptr_t<CellVpos
|
||||
picInfo->inQuantRange = ctrlParam->inQuantRange; // copy
|
||||
picInfo->inColorMatrix = ctrlParam->inColorMatrix; // copy
|
||||
|
||||
picInfo->outWidth = picInfo->inWidth; // TODO (resampling)
|
||||
picInfo->outHeight = picInfo->inHeight; // TODO
|
||||
picInfo->outWidth = ow; // copy
|
||||
picInfo->outHeight = oh; // copy
|
||||
picInfo->outDepth = CELL_VPOST_PIC_DEPTH_8; // fixed
|
||||
picInfo->outScanType = CELL_VPOST_SCAN_TYPE_P; // TODO
|
||||
picInfo->outPicFmt = CELL_VPOST_PIC_FMT_OUT_RGBA_ILV; // TODO
|
||||
picInfo->outChromaPosType = ctrlParam->inChromaPosType; // ???
|
||||
picInfo->outPicStruct = picInfo->inPicStruct; // ???
|
||||
picInfo->outQuantRange = ctrlParam->inQuantRange; // ???
|
||||
picInfo->outColorMatrix = ctrlParam->inColorMatrix; // ???
|
||||
picInfo->outChromaPosType = ctrlParam->inChromaPosType; // ignored
|
||||
picInfo->outPicStruct = picInfo->inPicStruct; // ignored
|
||||
picInfo->outQuantRange = ctrlParam->inQuantRange; // ignored
|
||||
picInfo->outColorMatrix = ctrlParam->inColorMatrix; // ignored
|
||||
|
||||
picInfo->userData = ctrlParam->userData; // copy
|
||||
picInfo->reserved1 = 0;
|
||||
picInfo->reserved2 = 0;
|
||||
|
||||
|
||||
u8* pY = (u8*)malloc(w*h); // color planes
|
||||
u8* pU = (u8*)malloc(w*h/4);
|
||||
u8* pV = (u8*)malloc(w*h/4);
|
||||
u32* res = (u32*)malloc(w*h*4); // RGBA interleaved output
|
||||
u8* pA = (u8*)malloc(w*h);
|
||||
u32* res = (u32*)malloc(ow*oh*4); // RGBA interleaved output
|
||||
const u8 alpha = ctrlParam->outAlpha;
|
||||
|
||||
if (!Memory.CopyToReal(pY, inPicBuff_addr, w*h))
|
||||
@ -163,6 +180,20 @@ int cellVpostExec(u32 handle, const u32 inPicBuff_addr, const mem_ptr_t<CellVpos
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
memset(pA, alpha, w*h);
|
||||
|
||||
SwsContext* sws = sws_getContext(w, h, AV_PIX_FMT_YUVA420P, ow, oh, AV_PIX_FMT_RGBA, SWS_BILINEAR, NULL, NULL, NULL);
|
||||
|
||||
u8* in_data[4] = { pY, pU, pV, pA };
|
||||
int in_line[4] = { w, w/2, w/2, w };
|
||||
u8* out_data[4] = { (u8*)res, NULL, NULL, NULL };
|
||||
int out_line[4] = { ow*4, 0, 0, 0 };
|
||||
|
||||
sws_scale(sws, in_data, in_line, 0, h, out_data, out_line);
|
||||
|
||||
sws_freeContext(sws);
|
||||
|
||||
/*
|
||||
for (u32 i = 0; i < h; i++) for (u32 j = 0; j < w; j++)
|
||||
{
|
||||
float Cr = pV[(i/2)*(w/2)+j/2] - 128;
|
||||
@ -179,9 +210,9 @@ int cellVpostExec(u32 handle, const u32 inPicBuff_addr, const mem_ptr_t<CellVpos
|
||||
if (B < 0) B = 0;
|
||||
if (B > 255) B = 255;
|
||||
res[i*w+j] = ((u32)alpha << 24) | (B << 16) | (G << 8) | (R);
|
||||
}
|
||||
}*/
|
||||
|
||||
if (!Memory.CopyFromReal(outPicBuff_addr, res, w*h*4))
|
||||
if (!Memory.CopyFromReal(outPicBuff_addr, res, ow*oh*4))
|
||||
{
|
||||
cellVpost.Error("cellVpostExec: data copying failed(result)");
|
||||
Emu.Pause();
|
||||
@ -190,6 +221,7 @@ int cellVpostExec(u32 handle, const u32 inPicBuff_addr, const mem_ptr_t<CellVpos
|
||||
free(pY);
|
||||
free(pU);
|
||||
free(pV);
|
||||
free(pA);
|
||||
free(res);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ static func_caller* sc_table[1024] =
|
||||
bind_func(sys_spu_thread_get_exit_status), bind_func(sys_spu_thread_set_argument), null_func, null_func, bind_func(sys_spu_initialize), //169
|
||||
bind_func(sys_spu_thread_group_create), bind_func(sys_spu_thread_group_destroy), bind_func(sys_spu_thread_initialize), //172
|
||||
bind_func(sys_spu_thread_group_start), bind_func(sys_spu_thread_group_suspend), //174
|
||||
null_func, null_func, null_func, bind_func(sys_spu_thread_group_join), null_func, //179
|
||||
bind_func(sys_spu_thread_group_resume), null_func, null_func, bind_func(sys_spu_thread_group_join), null_func, //179
|
||||
null_func, bind_func(sys_spu_thread_write_ls), bind_func(sys_spu_thread_read_ls), null_func, bind_func(sys_spu_thread_write_snr), //184
|
||||
bind_func(sys_spu_thread_group_connect_event), bind_func(sys_spu_thread_group_disconnect_event), //186
|
||||
bind_func(sys_spu_thread_set_spu_cfg), bind_func(sys_spu_thread_get_spu_cfg), null_func, //189
|
||||
|
@ -356,6 +356,7 @@ extern int sys_spu_thread_set_argument(u32 id, mem_ptr_t<sys_spu_thread_argument
|
||||
extern int sys_spu_thread_group_destroy(u32 id);
|
||||
extern int sys_spu_thread_group_start(u32 id);
|
||||
extern int sys_spu_thread_group_suspend(u32 id);
|
||||
extern int sys_spu_thread_group_resume(u32 id);
|
||||
extern int sys_spu_thread_group_create(mem32_t id, u32 num, int prio, mem_ptr_t<sys_spu_thread_group_attribute> attr);
|
||||
extern int sys_spu_thread_create(mem32_t thread_id, mem32_t entry, u64 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr);
|
||||
extern int sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status);
|
||||
|
@ -74,7 +74,7 @@ int sys_cond_signal(u32 cond_id)
|
||||
|
||||
if (u32 target = (mutex->protocol == SYS_SYNC_PRIORITY ? cond->m_queue.pop_prio() : cond->m_queue.pop()))
|
||||
{
|
||||
cond->cond.lock(target);
|
||||
cond->signal.lock(target);
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
@ -99,7 +99,7 @@ int sys_cond_signal_all(u32 cond_id)
|
||||
|
||||
while (u32 target = (mutex->protocol == SYS_SYNC_PRIORITY ? cond->m_queue.pop_prio() : cond->m_queue.pop()))
|
||||
{
|
||||
cond->cond.lock(target);
|
||||
cond->signal.lock(target);
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
@ -134,7 +134,7 @@ int sys_cond_signal_to(u32 cond_id, u32 thread_id)
|
||||
|
||||
u32 target = thread_id;
|
||||
{
|
||||
cond->cond.lock(target);
|
||||
cond->signal.lock(target);
|
||||
}
|
||||
|
||||
if (Emu.IsStopped())
|
||||
@ -160,24 +160,46 @@ int sys_cond_wait(u32 cond_id, u64 timeout)
|
||||
|
||||
if (mutex->m_mutex.GetOwner() != tid)
|
||||
{
|
||||
sys_cond.Warning("sys_cond_wait(cond_id=%d) failed (EPERM)", cond_id);
|
||||
return CELL_EPERM;
|
||||
}
|
||||
|
||||
cond->m_queue.push(tid);
|
||||
|
||||
if (mutex->recursive != 1)
|
||||
{
|
||||
sys_cond.Warning("sys_cond_wait(cond_id=%d): associated mutex had wrong recursive value (%d)", cond_id, mutex->recursive);
|
||||
}
|
||||
mutex->recursive = 0;
|
||||
mutex->m_mutex.unlock(tid);
|
||||
mutex->m_mutex.unlock(tid, mutex->protocol == SYS_SYNC_PRIORITY ? mutex->m_queue.pop_prio() : mutex->m_queue.pop());
|
||||
|
||||
u32 counter = 0;
|
||||
const u32 max_counter = timeout ? (timeout / 1000) : ~0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (cond->cond.GetOwner() == tid)
|
||||
if (cond->signal.unlock(tid, tid) == SMR_OK)
|
||||
{
|
||||
mutex->m_mutex.lock(tid);
|
||||
if (SMutexResult res = mutex->m_mutex.trylock(tid))
|
||||
{
|
||||
if (res != SMR_FAILED)
|
||||
{
|
||||
goto abort;
|
||||
}
|
||||
mutex->m_queue.push(tid);
|
||||
|
||||
switch (mutex->m_mutex.lock(tid))
|
||||
{
|
||||
case SMR_OK:
|
||||
mutex->m_queue.invalidate(tid);
|
||||
case SMR_SIGNAL:
|
||||
break;
|
||||
default:
|
||||
goto abort;
|
||||
}
|
||||
}
|
||||
mutex->recursive = 1;
|
||||
cond->cond.unlock(tid);
|
||||
cond->signal.unlock(tid);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -186,13 +208,16 @@ int sys_cond_wait(u32 cond_id, u64 timeout)
|
||||
if (counter++ > max_counter)
|
||||
{
|
||||
cond->m_queue.invalidate(tid);
|
||||
GetCurrentPPUThread().owned_mutexes--;
|
||||
GetCurrentPPUThread().owned_mutexes--; // ???
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_cond_wait(id=%d) aborted", cond_id);
|
||||
return CELL_OK;
|
||||
goto abort;
|
||||
}
|
||||
}
|
||||
|
||||
abort:
|
||||
ConLog.Warning("sys_cond_wait(id=%d) aborted", cond_id);
|
||||
return CELL_OK;
|
||||
}
|
@ -16,7 +16,7 @@ struct sys_cond_attribute
|
||||
struct Cond
|
||||
{
|
||||
Mutex* mutex; // associated with mutex
|
||||
SMutex cond;
|
||||
SMutex signal;
|
||||
SleepQueue m_queue;
|
||||
|
||||
Cond(Mutex* mutex, u64 name)
|
||||
|
@ -16,10 +16,10 @@ int sys_event_flag_create(mem32_t eflag_id, mem_ptr_t<sys_event_flag_attr> attr,
|
||||
|
||||
switch (attr->protocol.ToBE())
|
||||
{
|
||||
case se32(SYS_SYNC_PRIORITY): sys_event_flag.Warning("TODO: SYS_SYNC_PRIORITY attr"); break;
|
||||
case se32(SYS_SYNC_PRIORITY): break;
|
||||
case se32(SYS_SYNC_RETRY): sys_event_flag.Warning("TODO: SYS_SYNC_RETRY attr"); break;
|
||||
case se32(SYS_SYNC_PRIORITY_INHERIT): sys_event_flag.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break;
|
||||
case se32(SYS_SYNC_FIFO): sys_event_flag.Warning("TODO: SYS_SYNC_FIFO attr"); break;
|
||||
case se32(SYS_SYNC_FIFO): break;
|
||||
default: return CELL_EINVAL;
|
||||
}
|
||||
|
||||
@ -30,12 +30,12 @@ int sys_event_flag_create(mem32_t eflag_id, mem_ptr_t<sys_event_flag_attr> attr,
|
||||
|
||||
switch (attr->type.ToBE())
|
||||
{
|
||||
case se32(SYS_SYNC_WAITER_SINGLE): sys_event_flag.Warning("TODO: SYS_SYNC_WAITER_SINGLE type"); break;
|
||||
case se32(SYS_SYNC_WAITER_MULTIPLE): sys_event_flag.Warning("TODO: SYS_SYNC_WAITER_MULTIPLE type"); break;
|
||||
case se32(SYS_SYNC_WAITER_SINGLE): break;
|
||||
case se32(SYS_SYNC_WAITER_MULTIPLE): break;
|
||||
default: return CELL_EINVAL;
|
||||
}
|
||||
|
||||
eflag_id = sys_event_flag.GetNewId(new event_flag(init, (u32)attr->protocol, (int)attr->type));
|
||||
eflag_id = sys_event_flag.GetNewId(new EventFlag(init, (u32)attr->protocol, (int)attr->type));
|
||||
|
||||
sys_event_flag.Warning("*** event_flag created [%s] (protocol=0x%x, type=0x%x): id = %d",
|
||||
wxString(attr->name, 8).wx_str(), (u32)attr->protocol, (int)attr->type, eflag_id.GetValue());
|
||||
@ -47,9 +47,14 @@ int sys_event_flag_destroy(u32 eflag_id)
|
||||
{
|
||||
sys_event_flag.Warning("sys_event_flag_destroy(eflag_id=%d)", eflag_id);
|
||||
|
||||
event_flag* ef;
|
||||
EventFlag* ef;
|
||||
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
|
||||
|
||||
if (ef->waiters.GetCount()) // ???
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
Emu.GetIdManager().RemoveID(eflag_id);
|
||||
|
||||
return CELL_OK;
|
||||
@ -57,26 +62,220 @@ int sys_event_flag_destroy(u32 eflag_id)
|
||||
|
||||
int sys_event_flag_wait(u32 eflag_id, u64 bitptn, u32 mode, mem64_t result, u64 timeout)
|
||||
{
|
||||
sys_event_flag.Error("sys_event_flag_wait(eflag_id=%d, bitptn=0x%llx, mode=0x%x, result_addr=0x%x, timeout=%lld)",
|
||||
sys_event_flag.Warning("sys_event_flag_wait(eflag_id=%d, bitptn=0x%llx, mode=0x%x, result_addr=0x%x, timeout=%lld)",
|
||||
eflag_id, bitptn, mode, result.GetAddr(), timeout);
|
||||
return CELL_OK;
|
||||
|
||||
if (result.IsGood()) result = 0;
|
||||
|
||||
switch (mode & 0xf)
|
||||
{
|
||||
case SYS_EVENT_FLAG_WAIT_AND: break;
|
||||
case SYS_EVENT_FLAG_WAIT_OR: break;
|
||||
default: return CELL_EINVAL;
|
||||
}
|
||||
|
||||
switch (mode & ~0xf)
|
||||
{
|
||||
case 0: break; // ???
|
||||
case SYS_EVENT_FLAG_WAIT_CLEAR: break;
|
||||
case SYS_EVENT_FLAG_WAIT_CLEAR_ALL: break;
|
||||
default: return CELL_EINVAL;
|
||||
}
|
||||
|
||||
EventFlag* ef;
|
||||
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
|
||||
|
||||
u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
{
|
||||
SMutexLocker lock(ef->m_mutex);
|
||||
if (ef->m_type == SYS_SYNC_WAITER_SINGLE && ef->waiters.GetCount() > 0)
|
||||
{
|
||||
return CELL_EPERM;
|
||||
}
|
||||
EventFlagWaiter rec;
|
||||
rec.bitptn = bitptn;
|
||||
rec.mode = mode;
|
||||
rec.tid = tid;
|
||||
ef->waiters.AddCpy(rec);
|
||||
|
||||
if (ef->check() == tid)
|
||||
{
|
||||
u64 flags = ef->flags;
|
||||
|
||||
ef->waiters.RemoveAt(ef->waiters.GetCount() - 1);
|
||||
|
||||
if (mode & SYS_EVENT_FLAG_WAIT_CLEAR)
|
||||
{
|
||||
ef->flags &= ~bitptn;
|
||||
}
|
||||
else if (mode & SYS_EVENT_FLAG_WAIT_CLEAR_ALL)
|
||||
{
|
||||
ef->flags = 0;
|
||||
}
|
||||
|
||||
if (result.IsGood())
|
||||
{
|
||||
result = flags;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
if (!result.GetAddr())
|
||||
{
|
||||
return CELL_OK;
|
||||
}
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
u32 counter = 0;
|
||||
const u32 max_counter = timeout ? (timeout / 1000) : ~0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (ef->signal.GetOwner() == tid)
|
||||
{
|
||||
SMutexLocker lock(ef->m_mutex);
|
||||
|
||||
ef->signal.unlock(tid);
|
||||
|
||||
u64 flags = ef->flags;
|
||||
|
||||
for (u32 i = 0; i < ef->waiters.GetCount(); i++)
|
||||
{
|
||||
if (ef->waiters[i].tid == tid)
|
||||
{
|
||||
ef->waiters.RemoveAt(i);
|
||||
|
||||
if (mode & SYS_EVENT_FLAG_WAIT_CLEAR)
|
||||
{
|
||||
ef->flags &= ~bitptn;
|
||||
}
|
||||
else if (mode & SYS_EVENT_FLAG_WAIT_CLEAR_ALL)
|
||||
{
|
||||
ef->flags = 0;
|
||||
}
|
||||
|
||||
if (result.IsGood())
|
||||
{
|
||||
result = flags;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
if (!result.GetAddr())
|
||||
{
|
||||
return CELL_OK;
|
||||
}
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
return CELL_ECANCELED;
|
||||
}
|
||||
|
||||
Sleep(1);
|
||||
|
||||
if (counter++ > max_counter)
|
||||
{
|
||||
SMutexLocker lock(ef->m_mutex);
|
||||
|
||||
for (u32 i = 0; i < ef->waiters.GetCount(); i++)
|
||||
{
|
||||
if (ef->waiters[i].tid == tid)
|
||||
{
|
||||
ef->waiters.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_event_flag_wait(id=%d) aborted", eflag_id);
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int sys_event_flag_trywait(u32 eflag_id, u64 bitptn, u32 mode, mem64_t result)
|
||||
{
|
||||
sys_event_flag.Error("sys_event_flag_trywait(eflag_id=%d, bitptn=0x%llx, mode=0x%x, result_addr=0x%x)",
|
||||
sys_event_flag.Warning("sys_event_flag_trywait(eflag_id=%d, bitptn=0x%llx, mode=0x%x, result_addr=0x%x)",
|
||||
eflag_id, bitptn, mode, result.GetAddr());
|
||||
return CELL_OK;
|
||||
|
||||
if (result.IsGood()) result = 0;
|
||||
|
||||
switch (mode & 0xf)
|
||||
{
|
||||
case SYS_EVENT_FLAG_WAIT_AND: break;
|
||||
case SYS_EVENT_FLAG_WAIT_OR: break;
|
||||
default: return CELL_EINVAL;
|
||||
}
|
||||
|
||||
switch (mode & ~0xf)
|
||||
{
|
||||
case 0: break; // ???
|
||||
case SYS_EVENT_FLAG_WAIT_CLEAR: break;
|
||||
case SYS_EVENT_FLAG_WAIT_CLEAR_ALL: break;
|
||||
default: return CELL_EINVAL;
|
||||
}
|
||||
|
||||
EventFlag* ef;
|
||||
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
|
||||
|
||||
SMutexLocker lock(ef->m_mutex);
|
||||
|
||||
u64 flags = ef->flags;
|
||||
|
||||
if (((mode & SYS_EVENT_FLAG_WAIT_AND) && (flags & bitptn) == bitptn) ||
|
||||
((mode & SYS_EVENT_FLAG_WAIT_OR) && (flags & bitptn)))
|
||||
{
|
||||
if (mode & SYS_EVENT_FLAG_WAIT_CLEAR)
|
||||
{
|
||||
ef->flags &= ~bitptn;
|
||||
}
|
||||
else if (mode & SYS_EVENT_FLAG_WAIT_CLEAR_ALL)
|
||||
{
|
||||
ef->flags = 0;
|
||||
}
|
||||
|
||||
if (result.IsGood())
|
||||
{
|
||||
result = flags;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
if (!result.GetAddr())
|
||||
{
|
||||
return CELL_OK;
|
||||
}
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
int sys_event_flag_set(u32 eflag_id, u64 bitptn)
|
||||
{
|
||||
sys_event_flag.Warning("sys_event_flag_set(eflag_id=%d, bitptn=0x%llx)", eflag_id, bitptn);
|
||||
|
||||
event_flag* ef;
|
||||
EventFlag* ef;
|
||||
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
|
||||
|
||||
u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
ef->m_mutex.lock(tid);
|
||||
ef->flags |= bitptn;
|
||||
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 CELL_OK;
|
||||
}
|
||||
@ -85,9 +284,10 @@ int sys_event_flag_clear(u32 eflag_id, u64 bitptn)
|
||||
{
|
||||
sys_event_flag.Warning("sys_event_flag_clear(eflag_id=%d, bitptn=0x%llx)", eflag_id, bitptn);
|
||||
|
||||
event_flag* ef;
|
||||
EventFlag* ef;
|
||||
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
|
||||
|
||||
SMutexLocker lock(ef->m_mutex);
|
||||
ef->flags &= bitptn;
|
||||
|
||||
return CELL_OK;
|
||||
@ -95,23 +295,61 @@ int sys_event_flag_clear(u32 eflag_id, u64 bitptn)
|
||||
|
||||
int sys_event_flag_cancel(u32 eflag_id, mem32_t num)
|
||||
{
|
||||
sys_event_flag.Error("sys_event_flag_cancel(eflag_id=%d, num_addr=0x%x)", eflag_id, num.GetAddr());
|
||||
return CELL_OK;
|
||||
sys_event_flag.Warning("sys_event_flag_cancel(eflag_id=%d, num_addr=0x%x)", eflag_id, num.GetAddr());
|
||||
|
||||
EventFlag* ef;
|
||||
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
|
||||
|
||||
Array<u32> tids;
|
||||
|
||||
{
|
||||
SMutexLocker lock(ef->m_mutex);
|
||||
tids.SetCount(ef->waiters.GetCount());
|
||||
for (u32 i = 0; i < ef->waiters.GetCount(); i++)
|
||||
{
|
||||
tids[i] = ef->waiters[i].tid;
|
||||
}
|
||||
ef->waiters.Clear();
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < tids.GetCount(); i++)
|
||||
{
|
||||
if (Emu.IsStopped()) break;
|
||||
ef->signal.lock(tids[i]);
|
||||
}
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_event_flag_cancel(id=%d) aborted", eflag_id);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
if (num.IsGood())
|
||||
{
|
||||
num = tids.GetCount();
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
if (!num.GetAddr())
|
||||
{
|
||||
return CELL_OK;
|
||||
}
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
int sys_event_flag_get(u32 eflag_id, mem64_t flags)
|
||||
{
|
||||
sys_event_flag.Warning("sys_event_flag_get(eflag_id=%d, flags_addr=0x%x)", eflag_id, flags.GetAddr());
|
||||
|
||||
EventFlag* ef;
|
||||
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
|
||||
|
||||
if (!flags.IsGood())
|
||||
{
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
event_flag* ef;
|
||||
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
|
||||
|
||||
flags = ef->flags;
|
||||
flags = ef->flags; // ???
|
||||
|
||||
return CELL_OK;
|
||||
}
|
@ -4,6 +4,12 @@ enum
|
||||
{
|
||||
SYS_SYNC_WAITER_SINGLE = 0x10000,
|
||||
SYS_SYNC_WAITER_MULTIPLE = 0x20000,
|
||||
|
||||
SYS_EVENT_FLAG_WAIT_AND = 0x01,
|
||||
SYS_EVENT_FLAG_WAIT_OR = 0x02,
|
||||
|
||||
SYS_EVENT_FLAG_WAIT_CLEAR = 0x10,
|
||||
SYS_EVENT_FLAG_WAIT_CLEAR_ALL = 0x20,
|
||||
};
|
||||
|
||||
struct sys_event_flag_attr
|
||||
@ -16,16 +22,54 @@ struct sys_event_flag_attr
|
||||
char name[8];
|
||||
};
|
||||
|
||||
struct event_flag
|
||||
struct EventFlagWaiter
|
||||
{
|
||||
std::atomic<u64> flags;
|
||||
u32 tid;
|
||||
u32 mode;
|
||||
u64 bitptn;
|
||||
};
|
||||
|
||||
struct EventFlag
|
||||
{
|
||||
SMutex m_mutex;
|
||||
u64 flags;
|
||||
Array<EventFlagWaiter> waiters;
|
||||
SMutex signal;
|
||||
const u32 m_protocol;
|
||||
const int m_type;
|
||||
|
||||
event_flag(u64 pattern, u32 protocol, int type)
|
||||
EventFlag(u64 pattern, u32 protocol, int type)
|
||||
: flags(pattern)
|
||||
, m_protocol(protocol)
|
||||
, m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
u32 check()
|
||||
{
|
||||
SleepQueue sq; // TODO: implement without SleepQueue
|
||||
|
||||
u32 target = 0;
|
||||
|
||||
for (u32 i = 0; i < waiters.GetCount(); i++)
|
||||
{
|
||||
if (((waiters[i].mode & SYS_EVENT_FLAG_WAIT_AND) && (flags & waiters[i].bitptn) == waiters[i].bitptn) ||
|
||||
((waiters[i].mode & SYS_EVENT_FLAG_WAIT_OR) && (flags & waiters[i].bitptn)))
|
||||
{
|
||||
if (m_protocol == SYS_SYNC_FIFO)
|
||||
{
|
||||
target = waiters[i].tid;
|
||||
break;
|
||||
}
|
||||
sq.list.AddCpy(waiters[i].tid);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_protocol == SYS_SYNC_PRIORITY)
|
||||
{
|
||||
target = sq.pop_prio();
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
};
|
@ -16,7 +16,7 @@ int sys_lwcond_create(mem_ptr_t<sys_lwcond_t> lwcond, mem_ptr_t<sys_lwmutex_t> l
|
||||
}
|
||||
|
||||
lwcond->lwmutex = lwmutex.GetAddr();
|
||||
lwcond->lwcond_queue = sys_lwcond.GetNewId(new SleepQueue(attr->name_u64));
|
||||
lwcond->lwcond_queue = sys_lwcond.GetNewId(new Lwcond(attr->name_u64));
|
||||
|
||||
if (lwmutex.IsGood())
|
||||
{
|
||||
@ -49,20 +49,20 @@ int sys_lwcond_destroy(mem_ptr_t<sys_lwcond_t> lwcond)
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
u32 lwc = lwcond->lwcond_queue;
|
||||
u32 id = lwcond->lwcond_queue;
|
||||
|
||||
SleepQueue* sq;
|
||||
if (!Emu.GetIdManager().GetIDData(lwc, sq))
|
||||
Lwcond* lw;
|
||||
if (!Emu.GetIdManager().GetIDData(id, lw))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (!sq->finalize())
|
||||
if (!lw->m_queue.finalize())
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
Emu.GetIdManager().RemoveID(lwc);
|
||||
Emu.GetIdManager().RemoveID(id);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -75,37 +75,23 @@ int sys_lwcond_signal(mem_ptr_t<sys_lwcond_t> lwcond)
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
SleepQueue* sq;
|
||||
if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, sq))
|
||||
Lwcond* lw;
|
||||
if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, lw))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
mem_ptr_t<sys_lwmutex_t> mutex(lwcond->lwmutex);
|
||||
be_t<u32> tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
bool was_locked = (mutex->mutex.GetOwner() == tid);
|
||||
|
||||
if (be_t<u32> target = (mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? sq->pop_prio() : sq->pop()))
|
||||
if (u32 target = (mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? lw->m_queue.pop_prio() : lw->m_queue.pop()))
|
||||
{
|
||||
if (!was_locked)
|
||||
{
|
||||
mutex->mutex.lock(tid);
|
||||
mutex->recursive_count = 1;
|
||||
mutex->mutex.unlock(tid, target);
|
||||
}
|
||||
else
|
||||
{
|
||||
mutex->recursive_count = 1;
|
||||
mutex->mutex.unlock(tid, target);
|
||||
mutex->mutex.lock(tid);
|
||||
mutex->recursive_count = 1;
|
||||
}
|
||||
}
|
||||
lw->signal.lock(target);
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_lwcond_signal(sq=%d) aborted", (u32)lwcond->lwcond_queue);
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_lwcond_signal(id=%d) aborted", (u32)lwcond->lwcond_queue);
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
@ -120,37 +106,23 @@ int sys_lwcond_signal_all(mem_ptr_t<sys_lwcond_t> lwcond)
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
SleepQueue* sq;
|
||||
if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, sq))
|
||||
Lwcond* lw;
|
||||
if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, lw))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
mem_ptr_t<sys_lwmutex_t> mutex(lwcond->lwmutex);
|
||||
be_t<u32> tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
bool was_locked = (mutex->mutex.GetOwner() == tid);
|
||||
|
||||
while (be_t<u32> target = (mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? sq->pop_prio() : sq->pop()))
|
||||
while (u32 target = (mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? lw->m_queue.pop_prio() : lw->m_queue.pop()))
|
||||
{
|
||||
if (!was_locked)
|
||||
{
|
||||
mutex->mutex.lock(tid);
|
||||
mutex->recursive_count = 1;
|
||||
mutex->mutex.unlock(tid, target);
|
||||
}
|
||||
else
|
||||
{
|
||||
mutex->recursive_count = 1;
|
||||
mutex->mutex.unlock(tid, target);
|
||||
mutex->mutex.lock(tid);
|
||||
mutex->recursive_count = 1;
|
||||
}
|
||||
}
|
||||
lw->signal.lock(target);
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_lwcond_signal_all(sq=%d) aborted", (u32)lwcond->lwcond_queue);
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_lwcond_signal_all(id=%d) aborted", (u32)lwcond->lwcond_queue);
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
@ -165,8 +137,8 @@ int sys_lwcond_signal_to(mem_ptr_t<sys_lwcond_t> lwcond, u32 ppu_thread_id)
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
SleepQueue* sq;
|
||||
if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, sq))
|
||||
Lwcond* lw;
|
||||
if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, lw))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
@ -176,36 +148,20 @@ int sys_lwcond_signal_to(mem_ptr_t<sys_lwcond_t> lwcond, u32 ppu_thread_id)
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (!sq->invalidate(ppu_thread_id))
|
||||
if (!lw->m_queue.invalidate(ppu_thread_id))
|
||||
{
|
||||
return CELL_EPERM;
|
||||
}
|
||||
|
||||
mem_ptr_t<sys_lwmutex_t> mutex(lwcond->lwmutex);
|
||||
be_t<u32> tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
bool was_locked = (mutex->mutex.GetOwner() == tid);
|
||||
|
||||
be_t<u32> target = ppu_thread_id;
|
||||
u32 target = ppu_thread_id;
|
||||
{
|
||||
if (!was_locked)
|
||||
{
|
||||
mutex->mutex.lock(tid);
|
||||
mutex->recursive_count = 1;
|
||||
mutex->mutex.unlock(tid, target);
|
||||
}
|
||||
else
|
||||
{
|
||||
mutex->recursive_count = 1;
|
||||
mutex->mutex.unlock(tid, target);
|
||||
mutex->mutex.lock(tid);
|
||||
mutex->recursive_count = 1;
|
||||
}
|
||||
}
|
||||
lw->signal.lock(target);
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_lwcond_signal_to(sq=%d, to=%d) aborted", (u32)lwcond->lwcond_queue, ppu_thread_id);
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_lwcond_signal_to(id=%d, to=%d) aborted", (u32)lwcond->lwcond_queue, ppu_thread_id);
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
@ -220,8 +176,8 @@ int sys_lwcond_wait(mem_ptr_t<sys_lwcond_t> lwcond, u64 timeout)
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
SleepQueue* sq;
|
||||
if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, sq))
|
||||
Lwcond* lw;
|
||||
if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, lw))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
@ -230,29 +186,57 @@ int sys_lwcond_wait(mem_ptr_t<sys_lwcond_t> lwcond, u64 timeout)
|
||||
u32 tid_le = GetCurrentPPUThread().GetId();
|
||||
be_t<u32> tid = tid_le;
|
||||
|
||||
SleepQueue* sq = nullptr;
|
||||
Emu.GetIdManager().GetIDData((u32)mutex->sleep_queue, sq);
|
||||
|
||||
if (mutex->mutex.GetOwner() != tid)
|
||||
{
|
||||
sys_lwcond.Warning("sys_lwcond_wait(id=%d) failed (EPERM)", (u32)lwcond->lwcond_queue);
|
||||
return CELL_EPERM; // caller must own this lwmutex
|
||||
}
|
||||
|
||||
sq->push(tid_le);
|
||||
lw->m_queue.push(tid_le);
|
||||
|
||||
if (mutex->recursive_count.ToBE() != se32(1))
|
||||
{
|
||||
sys_lwcond.Warning("sys_lwcond_wait(id=%d): associated mutex had wrong recursive value (%d)",
|
||||
(u32)lwcond->lwcond_queue, (u32)mutex->recursive_count);
|
||||
}
|
||||
mutex->recursive_count = 0;
|
||||
mutex->mutex.unlock(tid);
|
||||
|
||||
if (sq)
|
||||
{
|
||||
mutex->mutex.unlock(tid, mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? sq->pop_prio() : sq->pop());
|
||||
}
|
||||
else if (mutex->attribute.ToBE() == se32(SYS_SYNC_RETRY))
|
||||
{
|
||||
mutex->mutex.unlock(tid); // SYS_SYNC_RETRY
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_lwcond.Warning("sys_lwcond_wait(id=%d): associated mutex had invalid sleep queue (%d)",
|
||||
(u32)lwcond->lwcond_queue, (u32)mutex->sleep_queue);
|
||||
}
|
||||
|
||||
u32 counter = 0;
|
||||
const u32 max_counter = timeout ? (timeout / 1000) : ~0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
/* switch (mutex->trylock(tid))
|
||||
if (lw->signal.unlock(tid, tid) == SMR_OK)
|
||||
{
|
||||
case SMR_OK: mutex->unlock(tid); break;
|
||||
case SMR_SIGNAL: return CELL_OK;
|
||||
} */
|
||||
if (mutex->mutex.GetOwner() == tid)
|
||||
{
|
||||
_mm_mfence();
|
||||
switch (mutex->lock(tid, 0))
|
||||
{
|
||||
case CELL_OK: break;
|
||||
case CELL_EDEADLK: sys_lwcond.Warning("sys_lwcond_wait(id=%d): associated mutex was locked",
|
||||
(u32)lwcond->lwcond_queue); return CELL_OK;
|
||||
case CELL_ESRCH: sys_lwcond.Warning("sys_lwcond_wait(id=%d): associated mutex not found (%d)",
|
||||
(u32)lwcond->lwcond_queue, (u32)mutex->sleep_queue); return CELL_ESRCH;
|
||||
case CELL_EINVAL: goto abort;
|
||||
}
|
||||
|
||||
mutex->recursive_count = 1;
|
||||
lw->signal.unlock(tid);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -260,13 +244,16 @@ int sys_lwcond_wait(mem_ptr_t<sys_lwcond_t> lwcond, u64 timeout)
|
||||
|
||||
if (counter++ > max_counter)
|
||||
{
|
||||
sq->invalidate(tid_le);
|
||||
lw->m_queue.invalidate(tid_le);
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_lwcond_wait(sq=%d) aborted", (u32)lwcond->lwcond_queue);
|
||||
return CELL_OK;
|
||||
goto abort;
|
||||
}
|
||||
}
|
||||
|
||||
abort:
|
||||
ConLog.Warning("sys_lwcond_wait(id=%d) aborted", (u32)lwcond->lwcond_queue);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -13,4 +13,15 @@ struct sys_lwcond_t
|
||||
{
|
||||
be_t<u32> lwmutex;
|
||||
be_t<u32> lwcond_queue;
|
||||
};
|
||||
|
||||
struct Lwcond
|
||||
{
|
||||
SMutex signal;
|
||||
SleepQueue m_queue;
|
||||
|
||||
Lwcond(u64 name)
|
||||
: m_queue(name)
|
||||
{
|
||||
}
|
||||
};
|
@ -177,7 +177,7 @@ bool SleepQueue::invalidate(u32 tid)
|
||||
{
|
||||
if (list[i] = tid)
|
||||
{
|
||||
list[i] = 0;
|
||||
list.RemoveAt(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -206,10 +206,11 @@ int sys_lwmutex_t::trylock(be_t<u32> tid)
|
||||
{
|
||||
if (attribute.ToBE() == se32(0xDEADBEEF)) return CELL_EINVAL;
|
||||
|
||||
be_t<u32> owner_tid = mutex.GetOwner();
|
||||
be_t<u32> owner_tid = mutex.GetFreeValue();
|
||||
|
||||
if (owner_tid != mutex.GetFreeValue())
|
||||
if (mutex.unlock(owner_tid, owner_tid) != SMR_OK) // check free value
|
||||
{
|
||||
owner_tid = mutex.GetOwner();
|
||||
if (CPUThread* tt = Emu.GetCPU().GetThread(owner_tid))
|
||||
{
|
||||
if (!tt->IsAlive())
|
||||
@ -263,7 +264,7 @@ int sys_lwmutex_t::trylock(be_t<u32> tid)
|
||||
|
||||
int sys_lwmutex_t::unlock(be_t<u32> tid)
|
||||
{
|
||||
if (tid != mutex.GetOwner())
|
||||
if (mutex.unlock(tid, tid) != SMR_OK)
|
||||
{
|
||||
return CELL_EPERM;
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ int sys_mutex_destroy(u32 mutex_id)
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if ((u32&)mutex->cond_count) // check if associated condition variable exists
|
||||
if (mutex->cond_count) // check if associated condition variable exists
|
||||
{
|
||||
return CELL_EPERM;
|
||||
}
|
||||
@ -99,9 +99,7 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout)
|
||||
PPUThread& t = GetCurrentPPUThread();
|
||||
u32 tid = t.GetId();
|
||||
|
||||
_mm_mfence();
|
||||
u32 owner = mutex->m_mutex.GetOwner();
|
||||
if (owner == tid)
|
||||
if (mutex->m_mutex.unlock(tid, tid) == SMR_OK)
|
||||
{
|
||||
if (mutex->is_recursive)
|
||||
{
|
||||
@ -116,7 +114,7 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout)
|
||||
return CELL_EDEADLK;
|
||||
}
|
||||
}
|
||||
else if (owner)
|
||||
else if (u32 owner = mutex->m_mutex.GetOwner())
|
||||
{
|
||||
if (CPUThread* tt = Emu.GetCPU().GetThread(owner))
|
||||
{
|
||||
@ -170,9 +168,7 @@ int sys_mutex_trylock(u32 mutex_id)
|
||||
PPUThread& t = GetCurrentPPUThread();
|
||||
u32 tid = t.GetId();
|
||||
|
||||
_mm_mfence();
|
||||
u32 owner = mutex->m_mutex.GetOwner();
|
||||
if (owner == tid)
|
||||
if (mutex->m_mutex.unlock(tid, tid) == SMR_OK)
|
||||
{
|
||||
if (mutex->is_recursive)
|
||||
{
|
||||
@ -187,7 +183,7 @@ int sys_mutex_trylock(u32 mutex_id)
|
||||
return CELL_EDEADLK;
|
||||
}
|
||||
}
|
||||
else if (owner)
|
||||
else if (u32 owner = mutex->m_mutex.GetOwner())
|
||||
{
|
||||
if (CPUThread* tt = Emu.GetCPU().GetThread(owner))
|
||||
{
|
||||
@ -219,8 +215,7 @@ int sys_mutex_unlock(u32 mutex_id)
|
||||
PPUThread& t = GetCurrentPPUThread();
|
||||
u32 tid = t.GetId();
|
||||
|
||||
_mm_mfence();
|
||||
if (mutex->m_mutex.GetOwner() == tid)
|
||||
if (mutex->m_mutex.unlock(tid, tid) == SMR_OK)
|
||||
{
|
||||
if (!mutex->recursive || (mutex->recursive != 1 && !mutex->is_recursive))
|
||||
{
|
||||
|
@ -158,6 +158,9 @@ int sys_ppu_thread_create(u32 thread_id_addr, u32 entry, u64 arg, int prio, u32
|
||||
new_thread.SetStackSize(stacksize);
|
||||
//new_thread.flags = flags;
|
||||
new_thread.SetName(Memory.ReadString(threadname_addr).ToStdString());
|
||||
|
||||
ConLog.Write("*** New PPU Thread [%s] (): id = %d", wxString(new_thread.GetName()).wx_str(), new_thread.GetId());
|
||||
|
||||
new_thread.Run();
|
||||
new_thread.Exec();
|
||||
|
||||
@ -177,7 +180,7 @@ void sys_ppu_thread_once(u32 once_ctrl_addr, u32 entry)
|
||||
new_thread.Run();
|
||||
new_thread.Exec();
|
||||
|
||||
GetCurrentPPUThread().Wait(new_thread);
|
||||
//GetCurrentPPUThread().Wait(new_thread);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,9 +83,12 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t<
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
if(!Memory.IsGoodAddr(attr->name_addr, attr->name_len))
|
||||
if (attr->name_addr)
|
||||
{
|
||||
return CELL_EFAULT;
|
||||
if(!Memory.IsGoodAddr(attr->name_addr, attr->name_len))
|
||||
{
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
if(spu_num >= group_info->list.GetCount())
|
||||
@ -99,7 +102,13 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t<
|
||||
}
|
||||
|
||||
u32 spu_ep = (u32)img->entry_point;
|
||||
std::string name = Memory.ReadString(attr->name_addr, attr->name_len).ToStdString();
|
||||
|
||||
std::string name = "SPUThread";
|
||||
if (attr->name_addr)
|
||||
{
|
||||
name = Memory.ReadString(attr->name_addr, attr->name_len).ToStdString();
|
||||
}
|
||||
|
||||
u64 a1 = arg->arg1;
|
||||
u64 a2 = arg->arg2;
|
||||
u64 a3 = arg->arg3;
|
||||
@ -120,9 +129,10 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t<
|
||||
new_thread.Run();
|
||||
|
||||
thread = group_info->list[spu_num] = new_thread.GetId();
|
||||
(*(SPUThread*)&new_thread).group = group_info;
|
||||
|
||||
sc_spu.Warning("*** New SPU Thread [%s] (img_offset=0x%x, ls_offset=0x%x, ep=0x%x, a1=0x%llx, a2=0x%llx, a3=0x%llx, a4=0x%llx): id=%d",
|
||||
wxString(name).wx_str(), (u32)img->segs_addr, ((SPUThread&)new_thread).dmac.ls_offset, spu_ep, a1, a2, a3, a4, thread.GetValue());
|
||||
wxString(attr->name_addr ? name : "").wx_str(), (u32)img->segs_addr, ((SPUThread&)new_thread).dmac.ls_offset, spu_ep, a1, a2, a3, a4, thread.GetValue());
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -216,6 +226,8 @@ int sys_spu_thread_group_start(u32 id)
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
// TODO: check group state
|
||||
|
||||
for (u32 i = 0; i < group_info->list.GetCount(); i++)
|
||||
{
|
||||
CPUThread* t;
|
||||
@ -239,7 +251,8 @@ int sys_spu_thread_group_suspend(u32 id)
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
//Emu.Pause();
|
||||
// TODO: check group state
|
||||
|
||||
for (u32 i = 0; i < group_info->list.GetCount(); i++)
|
||||
{
|
||||
if (CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]))
|
||||
@ -251,6 +264,30 @@ int sys_spu_thread_group_suspend(u32 id)
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
//175
|
||||
int sys_spu_thread_group_resume(u32 id)
|
||||
{
|
||||
sc_spu.Log("sys_spu_thread_group_resume(id=%d)", id);
|
||||
|
||||
SpuGroupInfo* group_info;
|
||||
if(!Emu.GetIdManager().GetIDData(id, group_info))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
// TODO: check group state
|
||||
|
||||
for (u32 i = 0; i < group_info->list.GetCount(); i++)
|
||||
{
|
||||
if (CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]))
|
||||
{
|
||||
t->Resume();
|
||||
}
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
//170
|
||||
int sys_spu_thread_group_create(mem32_t id, u32 num, int prio, mem_ptr_t<sys_spu_thread_group_attribute> attr)
|
||||
{
|
||||
@ -500,14 +537,7 @@ int sys_spu_thread_write_snr(u32 id, u32 number, u32 value)
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
if ((*(SPUThread*)thr).cfg.value & ((u64)1<<number))
|
||||
{ //logical OR
|
||||
(*(SPUThread*)thr).SPU.SNR[number].PushUncond_OR(value);
|
||||
}
|
||||
else
|
||||
{ //overwrite
|
||||
(*(SPUThread*)thr).SPU.SNR[number].PushUncond(value);
|
||||
}
|
||||
(*(SPUThread*)thr).WriteSNR(number, value);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -44,8 +44,10 @@ void sys_spinlock_unlock(mem_ptr_t<spinlock> lock)
|
||||
{
|
||||
sys_spinlock.Log("sys_spinlock_unlock(lock_addr=0x%x)", lock.GetAddr());
|
||||
|
||||
again:
|
||||
switch (lock->mutex.unlock(lock->mutex.GetOwner()))
|
||||
{
|
||||
case SMR_PERMITTED: goto again;
|
||||
default: break;
|
||||
}
|
||||
}
|
@ -141,7 +141,7 @@ void Emulator::Load()
|
||||
m_path = elf_path;
|
||||
}
|
||||
|
||||
ConLog.Write("Loading '%s'...", m_path.ToStdString().c_str());
|
||||
ConLog.Write("Loading '%s'...", m_path.wx_str());
|
||||
GetInfo().Reset();
|
||||
m_vfs.Init(m_path);
|
||||
|
||||
@ -149,7 +149,7 @@ void Emulator::Load()
|
||||
ConLog.Write("Mount info:");
|
||||
for(uint i=0; i<m_vfs.m_devices.GetCount(); ++i)
|
||||
{
|
||||
ConLog.Write("%s -> %s", m_vfs.m_devices[i].GetPs3Path().ToStdString().c_str(), m_vfs.m_devices[i].GetLocalPath().ToStdString().c_str());
|
||||
ConLog.Write("%s -> %s", m_vfs.m_devices[i].GetPs3Path().wx_str(), m_vfs.m_devices[i].GetLocalPath().wx_str());
|
||||
}
|
||||
ConLog.SkipLn();
|
||||
|
||||
@ -162,7 +162,7 @@ void Emulator::Load()
|
||||
|
||||
if(!f.IsOpened())
|
||||
{
|
||||
ConLog.Error("Elf not found! (%s - %s)", m_path.ToStdString().c_str(), m_elf_path.ToStdString().c_str());
|
||||
ConLog.Error("Elf not found! (%s - %s)", m_path.wx_str(), m_elf_path.wx_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -441,7 +441,7 @@ void Emulator::LoadPoints(const std::string& path)
|
||||
if(version != bpdb_version ||
|
||||
(sizeof(u16) + break_count * sizeof(u64) + sizeof(u32) + marked_count * sizeof(u64) + sizeof(u32)) != length)
|
||||
{
|
||||
ConLog.Error("'%s' is broken", path.c_str());
|
||||
ConLog.Error("'%s' is broken", wxString(path).wx_str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -14,18 +14,18 @@ std::mutex g_cs_conlog;
|
||||
static const uint max_item_count = 500;
|
||||
static const uint buffer_size = 1024 * 64;
|
||||
|
||||
static const std::string g_log_colors[] =
|
||||
static const wxString g_log_colors[] =
|
||||
{
|
||||
"Black", "Green", "White", "Yellow", "Red",
|
||||
};
|
||||
|
||||
struct LogPacket
|
||||
{
|
||||
std::string m_prefix;
|
||||
std::string m_text;
|
||||
std::string m_colour;
|
||||
wxString m_prefix;
|
||||
wxString m_text;
|
||||
wxString m_colour;
|
||||
|
||||
LogPacket(const std::string& prefix, const std::string& text, const std::string& colour)
|
||||
LogPacket(const wxString& prefix, const wxString& text, const wxString& colour)
|
||||
: m_prefix(prefix)
|
||||
, m_text(text)
|
||||
, m_colour(colour)
|
||||
@ -46,9 +46,9 @@ struct _LogBuffer : public MTPacketBuffer<LogPacket>
|
||||
|
||||
void _push(const LogPacket& data)
|
||||
{
|
||||
const u32 sprefix = data.m_prefix.length();
|
||||
const u32 stext = data.m_text.length();
|
||||
const u32 scolour = data.m_colour.length();
|
||||
const u32 sprefix = data.m_prefix.length() * sizeof(wxChar);
|
||||
const u32 stext = data.m_text.length() * sizeof(wxChar);
|
||||
const u32 scolour = data.m_colour.length() * sizeof(wxChar);
|
||||
|
||||
m_buffer.Reserve(
|
||||
sizeof(u32) + sprefix +
|
||||
@ -59,17 +59,17 @@ struct _LogBuffer : public MTPacketBuffer<LogPacket>
|
||||
|
||||
memcpy(&m_buffer[c_put], &sprefix, sizeof(u32));
|
||||
c_put += sizeof(u32);
|
||||
memcpy(&m_buffer[c_put], data.m_prefix.c_str(), sprefix);
|
||||
memcpy(&m_buffer[c_put], data.m_prefix.wx_str(), sprefix);
|
||||
c_put += sprefix;
|
||||
|
||||
memcpy(&m_buffer[c_put], &stext, sizeof(u32));
|
||||
c_put += sizeof(u32);
|
||||
memcpy(&m_buffer[c_put], data.m_text.c_str(), stext);
|
||||
memcpy(&m_buffer[c_put], data.m_text.wx_str(), stext);
|
||||
c_put += stext;
|
||||
|
||||
memcpy(&m_buffer[c_put], &scolour, sizeof(u32));
|
||||
c_put += sizeof(u32);
|
||||
memcpy(&m_buffer[c_put], data.m_colour.c_str(), scolour);
|
||||
memcpy(&m_buffer[c_put], data.m_colour.wx_str(), scolour);
|
||||
c_put += scolour;
|
||||
|
||||
m_put = c_put;
|
||||
@ -84,20 +84,17 @@ struct _LogBuffer : public MTPacketBuffer<LogPacket>
|
||||
|
||||
const u32& sprefix = *(u32*)&m_buffer[c_get];
|
||||
c_get += sizeof(u32);
|
||||
ret.m_prefix.resize(sprefix);
|
||||
if(sprefix) memcpy((void*)ret.m_prefix.c_str(), &m_buffer[c_get], sprefix);
|
||||
ret.m_prefix = wxString((wxChar*)&m_buffer[c_get], sprefix / sizeof(wxChar));
|
||||
c_get += sprefix;
|
||||
|
||||
const u32& stext = *(u32*)&m_buffer[c_get];
|
||||
c_get += sizeof(u32);
|
||||
ret.m_text.resize(stext);
|
||||
if(stext) memcpy((void*)ret.m_text.c_str(), &m_buffer[c_get], stext);
|
||||
ret.m_text = wxString((wxChar*)&m_buffer[c_get], stext / sizeof(wxChar));
|
||||
c_get += stext;
|
||||
|
||||
const u32& scolour = *(u32*)&m_buffer[c_get];
|
||||
c_get += sizeof(u32);
|
||||
ret.m_colour.resize(scolour);
|
||||
if(scolour) memcpy((void*)ret.m_colour.c_str(), &m_buffer[c_get], scolour);
|
||||
ret.m_colour = wxString((wxChar*)&m_buffer[c_get], scolour / sizeof(wxChar));
|
||||
c_get += scolour;
|
||||
|
||||
m_get = c_get;
|
||||
@ -117,7 +114,7 @@ LogWriter::LogWriter()
|
||||
}
|
||||
}
|
||||
|
||||
void LogWriter::WriteToLog(std::string prefix, std::string value, u8 lvl/*, wxColour bgcolour*/)
|
||||
void LogWriter::WriteToLog(wxString prefix, wxString value, u8 lvl/*, wxColour bgcolour*/)
|
||||
{
|
||||
if(!prefix.empty())
|
||||
{
|
||||
@ -127,8 +124,8 @@ void LogWriter::WriteToLog(std::string prefix, std::string value, u8 lvl/*, wxCo
|
||||
}
|
||||
}
|
||||
|
||||
if(m_logfile.IsOpened())
|
||||
m_logfile.Write(wxString(prefix.empty() ? "" : std::string("[" + prefix + "]: ") + value + "\n").wx_str());
|
||||
if(m_logfile.IsOpened() && !prefix.empty())
|
||||
m_logfile.Write(wxString("[") + prefix + "]: " + value + "\n");
|
||||
|
||||
if(!ConLogFrame || Ini.HLELogLvl.GetValue() == 4 || (lvl != 0 && lvl <= Ini.HLELogLvl.GetValue()))
|
||||
return;
|
||||
@ -175,7 +172,7 @@ void LogWriter::Write(const wxString fmt, ...)
|
||||
|
||||
va_end(list);
|
||||
|
||||
WriteToLog("!", (const char *)frmt.ToAscii(), 2);
|
||||
WriteToLog("!", frmt, 2);
|
||||
}
|
||||
|
||||
void LogWriter::Error(const wxString fmt, ...)
|
||||
@ -188,7 +185,7 @@ void LogWriter::Error(const wxString fmt, ...)
|
||||
|
||||
va_end(list);
|
||||
|
||||
WriteToLog("E", static_cast<const char *>(frmt), 4);
|
||||
WriteToLog("E", frmt, 4);
|
||||
}
|
||||
|
||||
void LogWriter::Warning(const wxString fmt, ...)
|
||||
@ -201,7 +198,7 @@ void LogWriter::Warning(const wxString fmt, ...)
|
||||
|
||||
va_end(list);
|
||||
|
||||
WriteToLog("W", static_cast<const char *>(frmt), 3);
|
||||
WriteToLog("W", frmt, 3);
|
||||
}
|
||||
|
||||
void LogWriter::Success(const wxString fmt, ...)
|
||||
@ -214,7 +211,7 @@ void LogWriter::Success(const wxString fmt, ...)
|
||||
|
||||
va_end(list);
|
||||
|
||||
WriteToLog("S", static_cast<const char *>(frmt), 1);
|
||||
WriteToLog("S", frmt, 1);
|
||||
}
|
||||
|
||||
void LogWriter::SkipLn()
|
||||
@ -279,9 +276,9 @@ void LogFrame::Task()
|
||||
|
||||
const int cur_item = m_log.GetItemCount();
|
||||
|
||||
m_log.InsertItem(cur_item, wxString(item.m_prefix).wx_str());
|
||||
m_log.SetItem(cur_item, 1, wxString(item.m_text).wx_str());
|
||||
m_log.SetItemTextColour(cur_item, wxString(item.m_colour).wx_str());
|
||||
m_log.InsertItem(cur_item, item.m_prefix);
|
||||
m_log.SetItem(cur_item, 1, item.m_text);
|
||||
m_log.SetItemTextColour(cur_item, item.m_colour);
|
||||
m_log.SetColumnWidth(0, -1); // crashes on exit
|
||||
m_log.SetColumnWidth(1, -1);
|
||||
|
||||
|
@ -8,10 +8,10 @@ class LogWriter
|
||||
wxFile m_logfile;
|
||||
wxColour m_txtcolour;
|
||||
|
||||
std::string m_prefix;
|
||||
std::string m_value;
|
||||
//wxString m_prefix;
|
||||
//wxString m_value;
|
||||
|
||||
virtual void WriteToLog(std::string prefix, std::string value, u8 lvl);
|
||||
virtual void WriteToLog(wxString prefix, wxString value, u8 lvl);
|
||||
|
||||
public:
|
||||
LogWriter();
|
||||
|
@ -202,7 +202,7 @@ void MainFrame::BootGame(wxCommandEvent& WXUNUSED(event))
|
||||
}
|
||||
else
|
||||
{
|
||||
ConLog.Error("Ps3 executable not found in selected folder (%s)", ctrl.GetPath().ToStdString().c_str());
|
||||
ConLog.Error("Ps3 executable not found in selected folder (%s)", ctrl.GetPath().wx_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -286,6 +286,7 @@
|
||||
<ClCompile Include="Emu\SysCalls\lv2\SC_VM.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellAdec.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellAtrac.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellAudio.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellDmux.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellFont.cpp" />
|
||||
|
@ -475,6 +475,9 @@
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellSaveData.cpp">
|
||||
<Filter>Emu\SysCalls\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellAtrac.cpp">
|
||||
<Filter>Emu\SysCalls\Modules</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="rpcs3.rc" />
|
||||
|
@ -34,6 +34,11 @@
|
||||
#include <wx/wxprec.h>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
//hack, disabled
|
||||
//#define wx_str() ToStdString().c_str()
|
||||
#endif
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
typedef unsigned int uint;
|
||||
@ -68,6 +73,12 @@ union u128
|
||||
|
||||
operator bool() const { return _u64[0] != 0 || _u64[1] != 0; }
|
||||
|
||||
static u128 From128( u64 hi, u64 lo )
|
||||
{
|
||||
u128 ret = {hi, lo};
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u128 From64( u64 src )
|
||||
{
|
||||
u128 ret = {0, src};
|
||||
@ -84,6 +95,27 @@ union u128
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u128 FromBit ( u32 bit )
|
||||
{
|
||||
u128 ret;
|
||||
if (bit < 64)
|
||||
{
|
||||
ret.hi = 0;
|
||||
ret.lo = (u64)1 << bit;
|
||||
}
|
||||
else if (bit < 128)
|
||||
{
|
||||
ret.hi = (u64)1 << (bit - 64);
|
||||
ret.lo = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.hi = 0;
|
||||
ret.lo = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool operator == ( const u128& right ) const
|
||||
{
|
||||
return (lo == right.lo) && (hi == right.hi);
|
||||
@ -93,6 +125,26 @@ union u128
|
||||
{
|
||||
return (lo != right.lo) || (hi != right.hi);
|
||||
}
|
||||
|
||||
u128 operator | ( const u128& right ) const
|
||||
{
|
||||
return From128(hi | right.hi, lo | right.lo);
|
||||
}
|
||||
|
||||
u128 operator & ( const u128& right ) const
|
||||
{
|
||||
return From128(hi & right.hi, lo & right.lo);
|
||||
}
|
||||
|
||||
u128 operator ^ ( const u128& right ) const
|
||||
{
|
||||
return From128(hi ^ right.hi, lo ^ right.lo);
|
||||
}
|
||||
|
||||
u128 operator ~ () const
|
||||
{
|
||||
return From128(~hi, ~lo);
|
||||
}
|
||||
};
|
||||
|
||||
union s128
|
||||
|
Loading…
x
Reference in New Issue
Block a user