mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-25 12:12:50 +01:00
parent
8011cc8ec4
commit
01dbb8eb9a
3
.gitignore
vendored
3
.gitignore
vendored
@ -55,3 +55,6 @@ rpcs3/git-version.h
|
|||||||
!/bin/dev_hdd0/game/
|
!/bin/dev_hdd0/game/
|
||||||
/bin/dev_hdd0/game/*
|
/bin/dev_hdd0/game/*
|
||||||
!/bin/dev_hdd0/game/TEST12345/
|
!/bin/dev_hdd0/game/TEST12345/
|
||||||
|
|
||||||
|
# Ignore other system generated files
|
||||||
|
bin/dev_hdd0/log.txt
|
||||||
|
@ -1,15 +1,21 @@
|
|||||||
#include <stdafx.h>
|
#include <stdafx.h>
|
||||||
#include <Utilities/SMutex.h>
|
#include <Utilities/SMutex.h>
|
||||||
|
|
||||||
|
|
||||||
__forceinline void SM_Sleep()
|
__forceinline void SM_Sleep()
|
||||||
{
|
{
|
||||||
Sleep(1);
|
Sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
__declspec(thread)
|
||||||
|
#else
|
||||||
|
thread_local
|
||||||
|
#endif
|
||||||
|
size_t g_this_thread_id = 0;
|
||||||
|
|
||||||
__forceinline size_t SM_GetCurrentThreadId()
|
__forceinline size_t SM_GetCurrentThreadId()
|
||||||
{
|
{
|
||||||
return std::hash<std::thread::id>()(std::this_thread::get_id());
|
return g_this_thread_id ? g_this_thread_id : g_this_thread_id = std::hash<std::thread::id>()(std::this_thread::get_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
__forceinline u32 SM_GetCurrentCPUThreadId()
|
__forceinline u32 SM_GetCurrentCPUThreadId()
|
||||||
|
@ -21,7 +21,7 @@ template
|
|||||||
<
|
<
|
||||||
typename T,
|
typename T,
|
||||||
u64 free_value = 0,
|
u64 free_value = 0,
|
||||||
u64 dead_value = ~0,
|
u64 dead_value = 0xffffffff,
|
||||||
void (*wait)() = SM_Sleep
|
void (*wait)() = SM_Sleep
|
||||||
>
|
>
|
||||||
class SMutexBase
|
class SMutexBase
|
||||||
@ -139,7 +139,7 @@ class SMutexLockerBase
|
|||||||
public:
|
public:
|
||||||
const T tid;
|
const T tid;
|
||||||
|
|
||||||
SMutexLockerBase(SMutexBase<T>& _sm)
|
__forceinline SMutexLockerBase(SMutexBase<T>& _sm)
|
||||||
: sm(_sm)
|
: sm(_sm)
|
||||||
, tid(get_tid())
|
, tid(get_tid())
|
||||||
{
|
{
|
||||||
@ -155,7 +155,7 @@ public:
|
|||||||
sm.lock(tid);
|
sm.lock(tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
~SMutexLockerBase()
|
__forceinline ~SMutexLockerBase()
|
||||||
{
|
{
|
||||||
if (tid) sm.unlock(tid);
|
if (tid) sm.unlock(tid);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
template<typename T, u32 SQSize = 666>
|
template<typename T, u32 SQSize = 666>
|
||||||
class SQueue
|
class SQueue
|
||||||
{
|
{
|
||||||
SMutex m_mutex;
|
SMutexGeneral m_mutex;
|
||||||
u32 m_pos;
|
u32 m_pos;
|
||||||
u32 m_count;
|
u32 m_count;
|
||||||
T m_data[SQSize];
|
T m_data[SQSize];
|
||||||
@ -15,6 +15,11 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const u32 GetSize() const
|
||||||
|
{
|
||||||
|
return SQSize;
|
||||||
|
}
|
||||||
|
|
||||||
bool Push(const T& data)
|
bool Push(const T& data)
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
@ -35,7 +40,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
SMutexLocker lock(m_mutex);
|
SMutexGeneralLocker lock(m_mutex);
|
||||||
|
|
||||||
if (m_count >= SQSize) continue;
|
if (m_count >= SQSize) continue;
|
||||||
|
|
||||||
@ -66,7 +71,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
SMutexLocker lock(m_mutex);
|
SMutexGeneralLocker lock(m_mutex);
|
||||||
|
|
||||||
if (!m_count) continue;
|
if (!m_count) continue;
|
||||||
|
|
||||||
@ -91,7 +96,7 @@ public:
|
|||||||
|
|
||||||
void Clear()
|
void Clear()
|
||||||
{
|
{
|
||||||
SMutexLocker lock(m_mutex);
|
SMutexGeneralLocker lock(m_mutex);
|
||||||
m_count = 0;
|
m_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +120,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
SMutexLocker lock(m_mutex);
|
SMutexGeneralLocker lock(m_mutex);
|
||||||
if (m_count) break;
|
if (m_count) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ void AudioDumper::WriteHeader()
|
|||||||
|
|
||||||
size_t AudioDumper::WriteData(const void* buffer, size_t size)
|
size_t AudioDumper::WriteData(const void* buffer, size_t size)
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < size / 8; i++)
|
/*for (u32 i = 0; i < size / 8; i++)
|
||||||
{
|
{
|
||||||
if (((u64*)buffer)[i]) goto process;
|
if (((u64*)buffer)[i]) goto process;
|
||||||
}
|
}
|
||||||
@ -32,7 +32,7 @@ size_t AudioDumper::WriteData(const void* buffer, size_t size)
|
|||||||
if (((u8*)buffer)[i + (size & ~7)]) goto process;
|
if (((u8*)buffer)[i + (size & ~7)]) goto process;
|
||||||
}
|
}
|
||||||
return size; // ignore empty data
|
return size; // ignore empty data
|
||||||
process:
|
process:*/
|
||||||
size_t ret = m_output.Write(buffer, size);
|
size_t ret = m_output.Write(buffer, size);
|
||||||
m_header.Size += ret;
|
m_header.Size += ret;
|
||||||
m_header.RIFF.Size += ret;
|
m_header.RIFF.Size += ret;
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
extern u64 get_system_time();
|
||||||
|
|
||||||
// Error codes
|
// Error codes
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@ -20,16 +22,6 @@ enum
|
|||||||
CELL_AUDIO_ERROR_AUDIOSYSTEM_NOT_FOUND = 0x8031070e,
|
CELL_AUDIO_ERROR_AUDIOSYSTEM_NOT_FOUND = 0x8031070e,
|
||||||
CELL_AUDIO_ERROR_TAG_NOT_FOUND = 0x8031070f,
|
CELL_AUDIO_ERROR_TAG_NOT_FOUND = 0x8031070f,
|
||||||
|
|
||||||
//libmixer Error Codes
|
|
||||||
CELL_LIBMIXER_ERROR_NOT_INITIALIZED = 0x80310002,
|
|
||||||
CELL_LIBMIXER_ERROR_INVALID_PARAMATER = 0x80310003,
|
|
||||||
CELL_LIBMIXER_ERROR_NO_MEMORY = 0x80310005,
|
|
||||||
CELL_LIBMIXER_ERROR_ALREADY_EXIST = 0x80310006,
|
|
||||||
CELL_LIBMIXER_ERROR_FULL = 0x80310007,
|
|
||||||
CELL_LIBMIXER_ERROR_NOT_EXIST = 0x80310008,
|
|
||||||
CELL_LIBMIXER_ERROR_TYPE_MISMATCH = 0x80310009,
|
|
||||||
CELL_LIBMIXER_ERROR_NOT_FOUND = 0x8031000a,
|
|
||||||
|
|
||||||
//libsnd3 Error Codes
|
//libsnd3 Error Codes
|
||||||
CELL_SND3_ERROR_PARAM = 0x80310301,
|
CELL_SND3_ERROR_PARAM = 0x80310301,
|
||||||
CELL_SND3_ERROR_CREATE_MUTEX = 0x80310302,
|
CELL_SND3_ERROR_CREATE_MUTEX = 0x80310302,
|
||||||
@ -108,7 +100,6 @@ struct CellAudioPortConfig
|
|||||||
|
|
||||||
struct AudioPortConfig
|
struct AudioPortConfig
|
||||||
{
|
{
|
||||||
SMutexGeneral m_mutex;
|
|
||||||
bool m_is_audio_port_opened;
|
bool m_is_audio_port_opened;
|
||||||
bool m_is_audio_port_started;
|
bool m_is_audio_port_started;
|
||||||
u8 channel;
|
u8 channel;
|
||||||
@ -121,7 +112,6 @@ struct AudioPortConfig
|
|||||||
|
|
||||||
struct AudioConfig //custom structure
|
struct AudioConfig //custom structure
|
||||||
{
|
{
|
||||||
std::mutex m_mutex;
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
AUDIO_PORT_COUNT = 8,
|
AUDIO_PORT_COUNT = 8,
|
||||||
@ -150,7 +140,9 @@ struct AudioConfig //custom structure
|
|||||||
memset(&m_ports, 0, sizeof(AudioPortConfig) * AUDIO_PORT_COUNT);
|
memset(&m_ports, 0, sizeof(AudioPortConfig) * AUDIO_PORT_COUNT);
|
||||||
m_port_in_use = 0;
|
m_port_in_use = 0;
|
||||||
}
|
}
|
||||||
} m_config;
|
};
|
||||||
|
|
||||||
|
extern AudioConfig m_config;
|
||||||
|
|
||||||
//libsnd3 datatypes
|
//libsnd3 datatypes
|
||||||
struct CellSnd3DataCtx
|
struct CellSnd3DataCtx
|
||||||
|
@ -6,12 +6,12 @@
|
|||||||
struct reservation_struct
|
struct reservation_struct
|
||||||
{
|
{
|
||||||
SMutex mutex; // mutex for updating reservation_owner and data
|
SMutex mutex; // mutex for updating reservation_owner and data
|
||||||
volatile u32 owner; // id of thread that got reservation
|
u32 owner; // id of thread that got reservation
|
||||||
volatile u32 addr;
|
u32 addr;
|
||||||
volatile u32 size;
|
u32 size;
|
||||||
volatile u32 data32;
|
u32 data32;
|
||||||
volatile u64 data64;
|
u64 data64;
|
||||||
// atm, PPU can't break SPU MFC reservation correctly
|
u128 data[8];
|
||||||
|
|
||||||
__forceinline void clear()
|
__forceinline void clear()
|
||||||
{
|
{
|
||||||
|
@ -586,6 +586,8 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Sleep(1); // hack
|
||||||
|
|
||||||
switch(cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK | MFC_RESULT_MASK))
|
switch(cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK | MFC_RESULT_MASK))
|
||||||
{
|
{
|
||||||
case MFC_PUT_CMD:
|
case MFC_PUT_CMD:
|
||||||
@ -702,20 +704,8 @@ public:
|
|||||||
wxString(op & MFC_BARRIER_MASK ? "B" : "").wx_str(),
|
wxString(op & MFC_BARRIER_MASK ? "B" : "").wx_str(),
|
||||||
wxString(op & MFC_FENCE_MASK ? "F" : "").wx_str(),
|
wxString(op & MFC_FENCE_MASK ? "F" : "").wx_str(),
|
||||||
lsa, ea, tag, size, cmd);
|
lsa, ea, tag, size, cmd);
|
||||||
if (op & MFC_PUT_CMD)
|
|
||||||
{
|
MFCArgs.CMDStatus.SetValue(dmacCmd(cmd, tag, lsa, ea, size));
|
||||||
SMutexLocker lock(reservation.mutex); // should be removed
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
reservation.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MFCArgs.CMDStatus.SetValue(dmacCmd(cmd, tag, lsa, ea, size));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -739,7 +729,7 @@ public:
|
|||||||
case MFC_PUTLLUC_CMD:
|
case MFC_PUTLLUC_CMD:
|
||||||
case MFC_PUTQLLUC_CMD:
|
case MFC_PUTQLLUC_CMD:
|
||||||
{
|
{
|
||||||
if (Ini.HLELogging.GetValue()) ConLog.Write("DMA %s: lsa=0x%x, ea = 0x%llx, (tag) = 0x%x, (size) = 0x%x, cmd = 0x%x",
|
if (Ini.HLELogging.GetValue() || size != 128) ConLog.Write("DMA %s: lsa=0x%x, ea = 0x%llx, (tag) = 0x%x, (size) = 0x%x, cmd = 0x%x",
|
||||||
wxString(op == MFC_GETLLAR_CMD ? "GETLLAR" :
|
wxString(op == MFC_GETLLAR_CMD ? "GETLLAR" :
|
||||||
op == MFC_PUTLLC_CMD ? "PUTLLC" :
|
op == MFC_PUTLLC_CMD ? "PUTLLC" :
|
||||||
op == MFC_PUTLLUC_CMD ? "PUTLLUC" : "PUTQLLUC").wx_str(),
|
op == MFC_PUTLLUC_CMD ? "PUTLLUC" : "PUTQLLUC").wx_str(),
|
||||||
@ -751,7 +741,11 @@ public:
|
|||||||
reservation.owner = lock.tid;
|
reservation.owner = lock.tid;
|
||||||
reservation.addr = ea;
|
reservation.addr = ea;
|
||||||
reservation.size = 128;
|
reservation.size = 128;
|
||||||
ProcessCmd(MFC_GET_CMD, tag, lsa, ea, 128);
|
for (u32 i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
reservation.data[i] = *(u128*)&Memory[(u32)ea + i * 16];
|
||||||
|
*(u128*)&Memory[dmac.ls_offset + lsa + i * 16] = reservation.data[i];
|
||||||
|
}
|
||||||
Prxy.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS);
|
Prxy.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS);
|
||||||
}
|
}
|
||||||
else if (op == MFC_PUTLLC_CMD) // store conditional
|
else if (op == MFC_PUTLLC_CMD) // store conditional
|
||||||
@ -761,8 +755,68 @@ public:
|
|||||||
{
|
{
|
||||||
if (reservation.addr == ea && reservation.size == 128)
|
if (reservation.addr == ea && reservation.size == 128)
|
||||||
{
|
{
|
||||||
ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128);
|
u128 buf[8]; // data being written newly
|
||||||
Prxy.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS);
|
u32 changed = 0, mask = 0, last = 0;
|
||||||
|
for (u32 i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
buf[i] = *(u128*)&Memory[dmac.ls_offset + lsa + i * 16];
|
||||||
|
if (buf[i] != reservation.data[i])
|
||||||
|
{
|
||||||
|
changed++;
|
||||||
|
last = i;
|
||||||
|
mask |= (0xf << (i * 4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (changed == 0) // nothing changed?
|
||||||
|
{
|
||||||
|
Prxy.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS);
|
||||||
|
}
|
||||||
|
else if (changed == 1)
|
||||||
|
{
|
||||||
|
if (buf[last].hi != reservation.data[last].hi && buf[last].lo != reservation.data[last].lo)
|
||||||
|
{
|
||||||
|
ConLog.Error("MFC_PUTLLC_CMD: TODO: 128bit compare and swap");
|
||||||
|
Emu.Pause();
|
||||||
|
Prxy.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const u32 last_q = (buf[last].hi == reservation.data[last].hi);
|
||||||
|
|
||||||
|
if (InterlockedCompareExchange64((volatile long long*)(Memory + (u32)ea + last * 16 + last_q * 8),
|
||||||
|
buf[last]._u64[last_q], reservation.data[last]._u64[last_q]) == reservation.data[last]._u64[last_q])
|
||||||
|
{
|
||||||
|
Prxy.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Prxy.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE);
|
||||||
|
}
|
||||||
|
/*u32 last_d = last_q * 2;
|
||||||
|
if (buf[last]._u32[last_d] == reservation.data[last]._u32[last_d] && buf[last]._u32[last_d+1] != reservation.data[last]._u32[last_d+1])
|
||||||
|
{
|
||||||
|
last_d++;
|
||||||
|
}
|
||||||
|
else if (buf[last]._u32[last_d+1] == reservation.data[last]._u32[last_d+1])
|
||||||
|
{
|
||||||
|
last_d;
|
||||||
|
}
|
||||||
|
else // full 64 bit
|
||||||
|
{
|
||||||
|
ConLog.Error("MFC_PUTLLC_CMD: TODO: 64bit compare and swap");
|
||||||
|
Emu.Pause();
|
||||||
|
Prxy.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128);
|
||||||
|
ConLog.Error("MFC_PUTLLC_CMD: Reservation Error: impossibru (~ 16x%d (mask=0x%x)) (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)",
|
||||||
|
changed, mask, op, cmd, lsa, ea, tag, size);
|
||||||
|
Emu.Pause();
|
||||||
|
Prxy.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -170,7 +170,8 @@ public:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: ConLog.Error("Init tex error: Bad tex format (0x%x | %s | 0x%x)", format, is_swizzled ? "swizzled" : "linear", tex.GetFormat() & 0x40); break;
|
default: ConLog.Error("Init tex error: Bad tex format (0x%x | %s | 0x%x)", format,
|
||||||
|
wxString(is_swizzled ? "swizzled" : "linear").wx_str(), tex.GetFormat() & 0x40); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, tex.GetMipmap() - 1);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, tex.GetMipmap() - 1);
|
||||||
|
@ -651,7 +651,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u3
|
|||||||
|
|
||||||
case NV4097_SET_SHADER_PROGRAM:
|
case NV4097_SET_SHADER_PROGRAM:
|
||||||
{
|
{
|
||||||
m_cur_shader_prog = &m_shader_progs[/*m_cur_shader_prog_num++*/0];
|
m_cur_shader_prog = &m_shader_progs[m_cur_shader_prog_num];
|
||||||
|
//m_cur_shader_prog_num = (m_cur_shader_prog_num + 1) % 16;
|
||||||
u32 a0 = ARGS(0);
|
u32 a0 = ARGS(0);
|
||||||
m_cur_shader_prog->offset = a0 & ~0x3;
|
m_cur_shader_prog->offset = a0 & ~0x3;
|
||||||
m_cur_shader_prog->addr = GetAddress(m_cur_shader_prog->offset, (a0 & 0x3) - 1);
|
m_cur_shader_prog->addr = GetAddress(m_cur_shader_prog->offset, (a0 & 0x3) - 1);
|
||||||
@ -948,7 +949,17 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u3
|
|||||||
|
|
||||||
case NV4097_SET_VIEWPORT_OFFSET:
|
case NV4097_SET_VIEWPORT_OFFSET:
|
||||||
{
|
{
|
||||||
|
/*const u32 offset0 = ARGS(0);
|
||||||
|
const u32 offset1 = ARGS(1);
|
||||||
|
const u32 offset2 = ARGS(2);
|
||||||
|
const u32 offset3 = ARGS(3);
|
||||||
|
const u32 scale0 = ARGS(4);
|
||||||
|
const u32 scale1 = ARGS(5);
|
||||||
|
const u32 scale2 = ARGS(6);
|
||||||
|
const u32 scale3 = ARGS(7);*/
|
||||||
//TODO
|
//TODO
|
||||||
|
//ConLog.Warning("NV4097_SET_VIEWPORT_OFFSET: offset (%d, %d, %d, %d), scale (%d, %d, %d, %d)",
|
||||||
|
//offset0, offset1, offset2, offset3, scale0, scale1, scale2, scale3);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1369,10 +1380,58 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u3
|
|||||||
case 0x000002f8:
|
case 0x000002f8:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NV0039_SET_CONTEXT_DMA_BUFFER_IN:
|
case NV0039_SET_CONTEXT_DMA_BUFFER_IN: // [E : RSXThread]: TODO: unknown/illegal method [0x00002184](0xfeed0000, 0xfeed0000)
|
||||||
case NV0039_OFFSET_IN:
|
{
|
||||||
case NV0039_OFFSET_OUT:
|
const u32 srcContext = ARGS(0);
|
||||||
//TODO
|
const u32 dstContext = ARGS(1);
|
||||||
|
|
||||||
|
if (srcContext == 0xfeed0000 && dstContext == 0xfeed0000)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ConLog.Warning("NV0039_SET_CONTEXT_DMA_BUFFER_IN: TODO: srcContext=0x%x, dstContext=0x%x", srcContext, dstContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NV0039_OFFSET_IN: // [E : RSXThread]: TODO: unknown/illegal method [0x0000230c](0x0, 0xb00400, 0x0, 0x0, 0x384000, 0x1, 0x101, 0x0)
|
||||||
|
{
|
||||||
|
const u32 inOffset = ARGS(0);
|
||||||
|
const u32 outOffset = ARGS(1);
|
||||||
|
const u32 inPitch = ARGS(2);
|
||||||
|
const u32 outPitch = ARGS(3);
|
||||||
|
const u32 lineLength = ARGS(4);
|
||||||
|
const u32 lineCount = ARGS(5);
|
||||||
|
const u32 format = ARGS(6);
|
||||||
|
const u8 outFormat = (format >> 8);
|
||||||
|
const u8 inFormat = (format >> 0);
|
||||||
|
const u32 notify = ARGS(7);
|
||||||
|
|
||||||
|
if (lineCount == 1 && !inPitch && !outPitch && !notify && format == 0x101)
|
||||||
|
{
|
||||||
|
memcpy(&Memory[GetAddress(outOffset, 0)], &Memory[GetAddress(inOffset, 0)], lineLength);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ConLog.Warning("NV0039_OFFSET_IN: TODO: offset(in=0x%x, out=0x%x), pitch(in=0x%x, out=0x%x), line(len=0x%x, cnt=0x%x), fmt(in=0x%x, out=0x%x), notify=0x%x",
|
||||||
|
inOffset, outOffset, inPitch, outPitch, lineLength, lineCount, inFormat, outFormat, notify);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NV0039_OFFSET_OUT: // [E : RSXThread]: TODO: unknown/illegal method [0x00002310](0x0)
|
||||||
|
{
|
||||||
|
const u32 offset = ARGS(0);
|
||||||
|
|
||||||
|
if (!offset)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ConLog.Warning("NV0039_OFFSET_OUT: TODO: offset=0x%x", offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NV4097_SET_SURFACE_COLOR_AOFFSET:
|
case NV4097_SET_SURFACE_COLOR_AOFFSET:
|
||||||
@ -1531,7 +1590,7 @@ void RSXThread::Task()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i=0; i<count; i++)
|
for(u32 i=0; i<count; i++)
|
||||||
{
|
{
|
||||||
methodRegisters[(cmd & 0xffff) + (i*4*inc)] = ARGS(i);
|
methodRegisters[(cmd & 0xffff) + (i*4*inc)] = ARGS(i);
|
||||||
}
|
}
|
||||||
|
2
rpcs3/Emu/SysCalls/Dialogs/Dialog.cpp
Normal file
2
rpcs3/Emu/SysCalls/Dialogs/Dialog.cpp
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "Dialog.h"
|
8
rpcs3/Emu/SysCalls/Dialogs/Dialog.h
Normal file
8
rpcs3/Emu/SysCalls/Dialogs/Dialog.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class Dialog
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Show();
|
||||||
|
void Close();
|
||||||
|
};
|
7
rpcs3/Emu/SysCalls/Dialogs/MessageDialog.cpp
Normal file
7
rpcs3/Emu/SysCalls/Dialogs/MessageDialog.cpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "MessageDialog.h"
|
||||||
|
|
||||||
|
MessageDialog::MessageDialog(std::string message, std::string title, int flags, char* icon)
|
||||||
|
{
|
||||||
|
// TODO: Use RSX post-drawing instead of wxWidgets
|
||||||
|
}
|
15
rpcs3/Emu/SysCalls/Dialogs/MessageDialog.h
Normal file
15
rpcs3/Emu/SysCalls/Dialogs/MessageDialog.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Dialog.h"
|
||||||
|
|
||||||
|
enum MessageDialogFlags
|
||||||
|
{
|
||||||
|
MessageDialog_Button_Enter = 0x1,
|
||||||
|
MessageDialog_Button_Back = 0x2,
|
||||||
|
|
||||||
|
MessageDialog_Controls_YesNo = 0x4,
|
||||||
|
};
|
||||||
|
|
||||||
|
class MessageDialog : public Dialog
|
||||||
|
{
|
||||||
|
MessageDialog(std::string message, std::string title, int flags, char* icon);
|
||||||
|
};
|
37
rpcs3/Emu/SysCalls/Dialogs/SaveDataList.cpp
Normal file
37
rpcs3/Emu/SysCalls/Dialogs/SaveDataList.cpp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "SaveDataList.h"
|
||||||
|
|
||||||
|
void SaveDataList::Load(const std::vector<SaveDataListEntry>& entries)
|
||||||
|
{
|
||||||
|
wxDialog dialog(NULL, wxID_ANY, "test", wxDefaultPosition, wxSize(450, 680));
|
||||||
|
|
||||||
|
wxPanel *panel = new wxPanel(&dialog, -1);
|
||||||
|
wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
|
||||||
|
wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
wxListCtrl* list = new wxListCtrl(&dialog, wxID_ANY, wxPoint(10,10), wxSize(400,600));
|
||||||
|
|
||||||
|
list->InsertColumn(0, "Icon");
|
||||||
|
list->InsertColumn(1, "Information");
|
||||||
|
wxImageList* pImageList = new wxImageList(320,176);
|
||||||
|
|
||||||
|
for (int i=0; i<entries.size(); i++)
|
||||||
|
{
|
||||||
|
list->InsertItem (i, i);
|
||||||
|
list->SetItemColumnImage (i, 0, i);
|
||||||
|
list->SetItem (i, 1, wxString::Format("%d",i+1));
|
||||||
|
|
||||||
|
wxImage img(320, 176, entries[i].iconBuffer);
|
||||||
|
pImageList->Add(img);
|
||||||
|
}
|
||||||
|
list->SetImageList(pImageList, wxIMAGE_LIST_SMALL);
|
||||||
|
|
||||||
|
panel->AddChild(list);
|
||||||
|
|
||||||
|
vbox->Add(panel, 1);
|
||||||
|
vbox->Add(hbox, 0, wxALIGN_CENTER | wxTOP | wxBOTTOM, 10);
|
||||||
|
|
||||||
|
dialog.SetSizer(vbox);
|
||||||
|
dialog.Centre();
|
||||||
|
dialog.ShowModal();
|
||||||
|
dialog.Destroy();
|
||||||
|
}
|
9
rpcs3/Emu/SysCalls/Dialogs/SaveDataList.h
Normal file
9
rpcs3/Emu/SysCalls/Dialogs/SaveDataList.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Dialog.h"
|
||||||
|
#include "Emu/SysCalls/Modules/cellSysutil_SaveData.h"
|
||||||
|
|
||||||
|
class SaveDataList : public Dialog
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Load(const std::vector<SaveDataListEntry>& entries);
|
||||||
|
};
|
2
rpcs3/Emu/SysCalls/Dialogs/UserList.cpp
Normal file
2
rpcs3/Emu/SysCalls/Dialogs/UserList.cpp
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "UserList.h"
|
0
rpcs3/Emu/SysCalls/Dialogs/UserList.h
Normal file
0
rpcs3/Emu/SysCalls/Dialogs/UserList.h
Normal file
@ -34,8 +34,11 @@ struct SFuncOp
|
|||||||
struct SFunc
|
struct SFunc
|
||||||
{
|
{
|
||||||
func_caller* func;
|
func_caller* func;
|
||||||
|
void* ptr;
|
||||||
char* name;
|
char* name;
|
||||||
Array<SFuncOp> ops;
|
Array<SFuncOp> ops;
|
||||||
|
u64 group;
|
||||||
|
u32 found;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ArrayF<SFunc> g_static_funcs_list;
|
extern ArrayF<SFunc> g_static_funcs_list;
|
||||||
@ -110,7 +113,7 @@ public:
|
|||||||
|
|
||||||
template<typename T> __forceinline void AddFunc(u32 id, T func);
|
template<typename T> __forceinline void AddFunc(u32 id, T func);
|
||||||
|
|
||||||
template<typename T> __forceinline void AddFuncSub(const u64 ops[], char* name, T func);
|
template<typename T> __forceinline void AddFuncSub(const char group[8], const u64 ops[], char* name, T func);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -120,13 +123,16 @@ __forceinline void Module::AddFunc(u32 id, T func)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
__forceinline void Module::AddFuncSub(const u64 ops[], char* name, T func)
|
__forceinline void Module::AddFuncSub(const char group[8], const u64 ops[], char* name, T func)
|
||||||
{
|
{
|
||||||
if (!ops[0]) return;
|
if (!ops[0]) return;
|
||||||
|
|
||||||
SFunc* sf = new SFunc;
|
SFunc* sf = new SFunc;
|
||||||
|
sf->ptr = func;
|
||||||
sf->func = bind_func(func);
|
sf->func = bind_func(func);
|
||||||
sf->name = name;
|
sf->name = name;
|
||||||
|
sf->group = *(u64*)group;
|
||||||
|
sf->found = 0;
|
||||||
|
|
||||||
// TODO: check for self-inclusions, use CRC
|
// TODO: check for self-inclusions, use CRC
|
||||||
|
|
||||||
@ -134,7 +140,8 @@ __forceinline void Module::AddFuncSub(const u64 ops[], char* name, T func)
|
|||||||
{
|
{
|
||||||
SFuncOp op;
|
SFuncOp op;
|
||||||
op.mask = ops[i] >> 32;
|
op.mask = ops[i] >> 32;
|
||||||
op.crc = ops[i] & op.mask;
|
op.crc = ops[i];
|
||||||
|
if (op.mask) op.crc &= op.mask;
|
||||||
op.mask = re(op.mask);
|
op.mask = re(op.mask);
|
||||||
op.crc = re(op.crc);
|
op.crc = re(op.crc);
|
||||||
sf->ops.AddCpy(op);
|
sf->ops.AddCpy(op);
|
||||||
|
@ -63,8 +63,6 @@ next:
|
|||||||
adec.reader.addr = adec.task.au.addr;
|
adec.reader.addr = adec.task.au.addr;
|
||||||
adec.reader.size = adec.task.au.size;
|
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);
|
//ConLog.Write("Audio AU: size = 0x%x, pts = 0x%llx", adec.task.au.size, adec.task.au.pts);
|
||||||
|
|
||||||
//if (adec.last_pts > adec.task.au.pts) adec.last_pts = adec.task.au.pts;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -266,8 +264,11 @@ u32 adecOpen(AudioDecoder* data)
|
|||||||
adec.reader.size = task.au.size;
|
adec.reader.size = task.au.size;
|
||||||
//ConLog.Write("Audio AU: size = 0x%x, pts = 0x%llx", task.au.size, task.au.pts);
|
//ConLog.Write("Audio AU: size = 0x%x, pts = 0x%llx", task.au.size, task.au.pts);
|
||||||
|
|
||||||
//if (adec.last_pts > task.au.pts || adec.just_started) adec.last_pts = task.au.pts;
|
if (adec.just_started)
|
||||||
if (adec.just_started) adec.last_pts = task.au.pts;
|
{
|
||||||
|
adec.first_pts = task.au.pts;
|
||||||
|
adec.last_pts = task.au.pts /*- 3816*8*/; // hack
|
||||||
|
}
|
||||||
|
|
||||||
struct AVPacketHolder : AVPacket
|
struct AVPacketHolder : AVPacket
|
||||||
{
|
{
|
||||||
@ -433,8 +434,19 @@ u32 adecOpen(AudioDecoder* data)
|
|||||||
|
|
||||||
if (got_frame)
|
if (got_frame)
|
||||||
{
|
{
|
||||||
frame.pts = adec.last_pts;
|
u64 ts = av_frame_get_best_effort_timestamp(frame.data);
|
||||||
adec.last_pts += ((u64)frame.data->nb_samples) * 90000 / 48000; // ???
|
if (ts != AV_NOPTS_VALUE)
|
||||||
|
{
|
||||||
|
frame.pts = ts/* - adec.first_pts*/;
|
||||||
|
adec.last_pts = frame.pts;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
adec.last_pts += ((u64)frame.data->nb_samples) * 90000 / 48000;
|
||||||
|
frame.pts = adec.last_pts;
|
||||||
|
}
|
||||||
|
//frame.pts = adec.last_pts;
|
||||||
|
//adec.last_pts += ((u64)frame.data->nb_samples) * 90000 / 48000; // ???
|
||||||
frame.auAddr = task.au.addr;
|
frame.auAddr = task.au.addr;
|
||||||
frame.auSize = task.au.size;
|
frame.auSize = task.au.size;
|
||||||
frame.userdata = task.au.userdata;
|
frame.userdata = task.au.userdata;
|
||||||
|
@ -1114,7 +1114,7 @@ public:
|
|||||||
u32 memBias;
|
u32 memBias;
|
||||||
|
|
||||||
AdecTask task;
|
AdecTask task;
|
||||||
u64 last_pts;
|
u64 last_pts, first_pts;
|
||||||
|
|
||||||
CPUThread* adecCb;
|
CPUThread* adecCb;
|
||||||
|
|
||||||
|
@ -7,141 +7,200 @@ Module cellAtrac(0x0013, cellAtrac_init);
|
|||||||
|
|
||||||
#include "cellAtrac.h"
|
#include "cellAtrac.h"
|
||||||
|
|
||||||
int cellAtracSetDataAndGetMemSize()
|
int cellAtracSetDataAndGetMemSize(mem_ptr_t<CellAtracHandle> pHandle, u32 pucBufferAddr, u32 uiReadByte, u32 uiBufferByte, mem32_t puiWorkMemByte)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
cellAtrac.Error("cellAtracSetDataAndGetMemSize(pHandle=0x%x, pucBufferAddr=0x%x, uiReadByte=0x%x, uiBufferByte=0x%x, puiWorkMemByte_addr=0x%x)",
|
||||||
|
pHandle.GetAddr(), pucBufferAddr, uiReadByte, uiBufferByte, puiWorkMemByte.GetAddr());
|
||||||
|
|
||||||
|
puiWorkMemByte = 0x1000; // unproved
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellAtracCreateDecoder()
|
int cellAtracCreateDecoder(mem_ptr_t<CellAtracHandle> pHandle, u32 pucWorkMem_addr, u32 uiPpuThreadPriority, u32 uiSpuThreadPriority)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
cellAtrac.Error("cellAtracCreateDecoder(pHandle=0x%x, pucWorkMem_addr=0x%x, uiPpuThreadPriority=%d, uiSpuThreadPriority=%d)",
|
||||||
|
pHandle.GetAddr(), pucWorkMem_addr, uiPpuThreadPriority, uiSpuThreadPriority);
|
||||||
|
|
||||||
|
pHandle->data.pucWorkMem_addr = pucWorkMem_addr;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellAtracCreateDecoderExt()
|
int cellAtracCreateDecoderExt(mem_ptr_t<CellAtracHandle> pHandle, u32 pucWorkMem_addr, u32 uiPpuThreadPriority, mem_ptr_t<CellAtracExtRes> pExtRes)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
cellAtrac.Error("cellAtracCreateDecoderExt(pHandle=0x%x, pucWorkMem_addr=0x%x, uiPpuThreadPriority=%d, pExtRes_addr=0x%x)",
|
||||||
|
pHandle.GetAddr(), pucWorkMem_addr, uiPpuThreadPriority, pExtRes.GetAddr());
|
||||||
|
|
||||||
|
pHandle->data.pucWorkMem_addr = pucWorkMem_addr;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellAtracDeleteDecoder()
|
int cellAtracDeleteDecoder(mem_ptr_t<CellAtracHandle> pHandle)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
cellAtrac.Error("cellAtracDeleteDecoder(pHandle=0x%x)", pHandle.GetAddr());
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellAtracDecode()
|
int cellAtracDecode(mem_ptr_t<CellAtracHandle> pHandle, u32 pfOutAddr, mem32_t puiSamples, mem32_t puiFinishflag, mem32_t piRemainFrame)
|
||||||
{
|
{
|
||||||
//UNIMPLEMENTED_FUNC(cellAtrac);
|
cellAtrac.Error("cellAtracDecode(pHandle=0x%x, pfOutAddr=0x%x, puiSamples_addr=0x%x, puiFinishFlag_addr=0x%x, piRemainFrame_addr=0x%x)",
|
||||||
|
pHandle.GetAddr(), pfOutAddr, puiSamples.GetAddr(), puiFinishflag.GetAddr(), piRemainFrame.GetAddr());
|
||||||
|
|
||||||
|
puiSamples = 0;
|
||||||
|
puiFinishflag = 1;
|
||||||
|
piRemainFrame = CELL_ATRAC_ALLDATA_IS_ON_MEMORY;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellAtracGetStreamDataInfo()
|
int cellAtracGetStreamDataInfo(mem_ptr_t<CellAtracHandle> pHandle, mem32_t ppucWritePointer, mem32_t puiWritableByte, mem32_t puiReadPosition)
|
||||||
{
|
{
|
||||||
//UNIMPLEMENTED_FUNC(cellAtrac);
|
cellAtrac.Error("cellAtracGetStreamDataInfo(pHandle=0x%x, ppucWritePointer_addr=0x%x, puiWritableByte_addr=0x%x, puiReadPosition_addr=0x%x)",
|
||||||
|
pHandle.GetAddr(), ppucWritePointer.GetAddr(), puiWritableByte.GetAddr(), puiReadPosition.GetAddr());
|
||||||
|
|
||||||
|
ppucWritePointer = pHandle->data.pucWorkMem_addr;
|
||||||
|
puiWritableByte = 0x1000;
|
||||||
|
puiReadPosition = 0;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellAtracAddStreamData()
|
int cellAtracAddStreamData(mem_ptr_t<CellAtracHandle> pHandle, u32 uiAddByte)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
cellAtrac.Error("cellAtracAddStreamData(pHandle=0x%x, uiAddByte=0x%x)", pHandle.GetAddr(), uiAddByte);
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellAtracGetRemainFrame()
|
int cellAtracGetRemainFrame(mem_ptr_t<CellAtracHandle> pHandle, mem32_t piRemainFrame)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
cellAtrac.Error("cellAtracGetRemainFrame(pHandle=0x%x, piRemainFrame_addr=0x%x)", pHandle.GetAddr(), piRemainFrame.GetAddr());
|
||||||
|
|
||||||
|
piRemainFrame = CELL_ATRAC_ALLDATA_IS_ON_MEMORY;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellAtracGetVacantSize()
|
int cellAtracGetVacantSize(mem_ptr_t<CellAtracHandle> pHandle, mem32_t puiVacantSize)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
cellAtrac.Error("cellAtracGetVacantSize(pHandle=0x%x, puiVacantSize_addr=0x%x)", pHandle.GetAddr(), puiVacantSize.GetAddr());
|
||||||
|
|
||||||
|
puiVacantSize = 0x1000;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellAtracIsSecondBufferNeeded()
|
int cellAtracIsSecondBufferNeeded(mem_ptr_t<CellAtracHandle> pHandle)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
cellAtrac.Error("cellAtracIsSecondBufferNeeded(pHandle=0x%x)", pHandle.GetAddr());
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellAtracGetSecondBufferInfo()
|
int cellAtracGetSecondBufferInfo(mem_ptr_t<CellAtracHandle> pHandle, mem32_t puiReadPosition, mem32_t puiDataByte)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
cellAtrac.Error("cellAtracGetSecondBufferInfo(pHandle=0x%x, puiReadPosition_addr=0x%x, puiDataByte_addr=0x%x)",
|
||||||
|
pHandle.GetAddr(), puiReadPosition.GetAddr(), puiDataByte.GetAddr());
|
||||||
|
|
||||||
|
puiReadPosition = 0;
|
||||||
|
puiDataByte = 0; // write to null block will occur
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellAtracSetSecondBuffer()
|
int cellAtracSetSecondBuffer(mem_ptr_t<CellAtracHandle> pHandle, u32 pucSecondBufferAddr, u32 uiSecondBufferByte)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
cellAtrac.Error("cellAtracSetSecondBuffer(pHandle=0x%x, pucSecondBufferAddr=0x%x, uiSecondBufferByte=0x%x)",
|
||||||
|
pHandle.GetAddr(), pucSecondBufferAddr, uiSecondBufferByte);
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellAtracGetChannel()
|
int cellAtracGetChannel(mem_ptr_t<CellAtracHandle> pHandle, mem32_t puiChannel)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
cellAtrac.Error("cellAtracGetChannel(pHandle=0x%x, puiChannel_addr=0x%x)", pHandle.GetAddr(), puiChannel.GetAddr());
|
||||||
|
|
||||||
|
puiChannel = 2;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellAtracGetMaxSample()
|
int cellAtracGetMaxSample(mem_ptr_t<CellAtracHandle> pHandle, mem32_t puiMaxSample)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
cellAtrac.Error("cellAtracGetMaxSample(pHandle=0x%x, puiMaxSample_addr=0x%x)", pHandle.GetAddr(), puiMaxSample.GetAddr());
|
||||||
|
|
||||||
|
puiMaxSample = 512;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellAtracGetNextSample()
|
int cellAtracGetNextSample(mem_ptr_t<CellAtracHandle> pHandle, mem32_t puiNextSample)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
cellAtrac.Error("cellAtracGetNextSample(pHandle=0x%x, puiNextSample_addr=0x%x)", pHandle.GetAddr(), puiNextSample.GetAddr());
|
||||||
|
|
||||||
|
puiNextSample = 0;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellAtracGetSoundInfo()
|
int cellAtracGetSoundInfo(mem_ptr_t<CellAtracHandle> pHandle, mem32_t piEndSample, mem32_t piLoopStartSample, mem32_t piLoopEndSample)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
cellAtrac.Error("cellAtracGetSoundInfo(pHandle=0x%x, piEndSample_addr=0x%x, piLoopStartSample_addr=0x%x, piLoopEndSample_addr=0x%x)",
|
||||||
|
pHandle.GetAddr(), piEndSample.GetAddr(), piLoopStartSample.GetAddr(), piLoopEndSample.GetAddr());
|
||||||
|
|
||||||
|
piEndSample = 0;
|
||||||
|
piLoopStartSample = 0;
|
||||||
|
piLoopEndSample = 0;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellAtracGetNextDecodePosition()
|
int cellAtracGetNextDecodePosition(mem_ptr_t<CellAtracHandle> pHandle, mem32_t puiSamplePosition)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
cellAtrac.Error("cellAtracGetNextDecodePosition(pHandle=0x%x, puiSamplePosition_addr=0x%x)",
|
||||||
|
pHandle.GetAddr(), puiSamplePosition.GetAddr());
|
||||||
|
|
||||||
|
puiSamplePosition = 0;
|
||||||
|
return CELL_ATRAC_ERROR_ALLDATA_WAS_DECODED;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cellAtracGetBitrate(mem_ptr_t<CellAtracHandle> pHandle, mem32_t puiBitrate)
|
||||||
|
{
|
||||||
|
cellAtrac.Error("cellAtracGetBitrate(pHandle=0x%x, puiBitrate_addr=0x%x)",
|
||||||
|
pHandle.GetAddr(), puiBitrate.GetAddr());
|
||||||
|
|
||||||
|
puiBitrate = 128;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellAtracGetBitrate()
|
int cellAtracGetLoopInfo(mem_ptr_t<CellAtracHandle> pHandle, mem32_t piLoopNum, mem32_t puiLoopStatus)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
cellAtrac.Error("cellAtracGetLoopInfo(pHandle=0x%x, piLoopNum_addr=0x%x, puiLoopStatus_addr=0x%x)",
|
||||||
|
pHandle.GetAddr(), piLoopNum.GetAddr(), puiLoopStatus.GetAddr());
|
||||||
|
|
||||||
|
piLoopNum = 0;
|
||||||
|
puiLoopStatus = 0;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellAtracGetLoopInfo()
|
int cellAtracSetLoopNum(mem_ptr_t<CellAtracHandle> pHandle, int iLoopNum)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
cellAtrac.Error("cellAtracSetLoopNum(pHandle=0x%x, iLoopNum=0x%x)", pHandle.GetAddr(), iLoopNum);
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellAtracSetLoopNum()
|
int cellAtracGetBufferInfoForResetting(mem_ptr_t<CellAtracHandle> pHandle, u32 uiSample, mem_ptr_t<CellAtracBufferInfo> pBufferInfo)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
cellAtrac.Error("cellAtracGetBufferInfoForResetting(pHandle=0x%x, uiSample=0x%x, pBufferInfo_addr=0x%x)",
|
||||||
|
pHandle.GetAddr(), uiSample, pBufferInfo.GetAddr());
|
||||||
|
|
||||||
|
pBufferInfo->pucWriteAddr = pHandle->data.pucWorkMem_addr;
|
||||||
|
pBufferInfo->uiWritableByte = 0x1000;
|
||||||
|
pBufferInfo->uiMinWriteByte = 0;
|
||||||
|
pBufferInfo->uiReadPosition = 0;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellAtracGetBufferInfoForResetting()
|
int cellAtracResetPlayPosition(mem_ptr_t<CellAtracHandle> pHandle, u32 uiSample, u32 uiWriteByte)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
cellAtrac.Error("cellAtracResetPlayPosition(pHandle=0x%x, uiSample=0x%x, uiWriteByte=0x%x)",
|
||||||
|
pHandle.GetAddr(), uiSample, uiWriteByte);
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellAtracResetPlayPosition()
|
int cellAtracGetInternalErrorInfo(mem_ptr_t<CellAtracHandle> pHandle, mem32_t piResult)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
cellAtrac.Error("cellAtracGetInternalErrorInfo(pHandle=0x%x, piResult_addr=0x%x)",
|
||||||
return CELL_OK;
|
pHandle.GetAddr(), piResult.GetAddr());
|
||||||
}
|
|
||||||
|
|
||||||
int cellAtracGetInternalErrorInfo()
|
piResult = 0;
|
||||||
{
|
|
||||||
UNIMPLEMENTED_FUNC(cellAtrac);
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,4 +25,35 @@ enum
|
|||||||
CELL_ATRAC_ERROR_ILLEGAL_RESET_BYTE = 0x80610372,
|
CELL_ATRAC_ERROR_ILLEGAL_RESET_BYTE = 0x80610372,
|
||||||
CELL_ATRAC_ERROR_ILLEGAL_PPU_THREAD_PRIORITY = 0x80610381,
|
CELL_ATRAC_ERROR_ILLEGAL_PPU_THREAD_PRIORITY = 0x80610381,
|
||||||
CELL_ATRAC_ERROR_ILLEGAL_SPU_THREAD_PRIORITY = 0x80610382,
|
CELL_ATRAC_ERROR_ILLEGAL_SPU_THREAD_PRIORITY = 0x80610382,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Remain Frame
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CELL_ATRAC_ALLDATA_IS_ON_MEMORY = -1,
|
||||||
|
CELL_ATRAC_NONLOOP_STREAM_DATA_IS_ON_MEMORY = -2,
|
||||||
|
CELL_ATRAC_LOOP_STREAM_DATA_IS_ON_MEMORY = -3,
|
||||||
|
};
|
||||||
|
|
||||||
|
union CellAtracHandle
|
||||||
|
{
|
||||||
|
u8 uiWorkMem[512];
|
||||||
|
struct AtracHandle
|
||||||
|
{
|
||||||
|
u32 pucWorkMem_addr;
|
||||||
|
} data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CellAtracBufferInfo
|
||||||
|
{
|
||||||
|
be_t<u32> pucWriteAddr;
|
||||||
|
be_t<u32> uiWritableByte;
|
||||||
|
be_t<u32> uiMinWriteByte;
|
||||||
|
be_t<u32> uiReadPosition;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CellAtracExtRes
|
||||||
|
{
|
||||||
|
be_t<u32> pSpurs_addr;
|
||||||
|
u8 priority[8];
|
||||||
};
|
};
|
@ -1,6 +1,7 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "Emu/SysCalls/SysCalls.h"
|
#include "Emu/SysCalls/SysCalls.h"
|
||||||
#include "Emu/SysCalls/SC_FUNC.h"
|
#include "Emu/SysCalls/SC_FUNC.h"
|
||||||
|
#include "Utilities/SQueue.h"
|
||||||
#include "Emu/Audio/cellAudio.h"
|
#include "Emu/Audio/cellAudio.h"
|
||||||
#include "Emu/Audio/AudioManager.h"
|
#include "Emu/Audio/AudioManager.h"
|
||||||
#include "Emu/Audio/AudioDumper.h"
|
#include "Emu/Audio/AudioDumper.h"
|
||||||
@ -9,7 +10,9 @@ void cellAudio_init();
|
|||||||
void cellAudio_unload();
|
void cellAudio_unload();
|
||||||
Module cellAudio(0x0011, cellAudio_init, nullptr, cellAudio_unload);
|
Module cellAudio(0x0011, cellAudio_init, nullptr, cellAudio_unload);
|
||||||
|
|
||||||
extern u64 get_system_time();
|
static SMutexGeneral audioMutex;
|
||||||
|
|
||||||
|
AudioConfig m_config;
|
||||||
|
|
||||||
// libaudio Functions
|
// libaudio Functions
|
||||||
|
|
||||||
@ -23,6 +26,7 @@ int cellAudioInit()
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_config.m_is_audio_initialized = true;
|
m_config.m_is_audio_initialized = true;
|
||||||
|
m_config.start_time = 0;
|
||||||
m_config.counter = 0;
|
m_config.counter = 0;
|
||||||
|
|
||||||
// alloc memory
|
// alloc memory
|
||||||
@ -34,8 +38,10 @@ int cellAudioInit()
|
|||||||
thread t("Audio Thread", []()
|
thread t("Audio Thread", []()
|
||||||
{
|
{
|
||||||
AudioDumper m_dump(2); // WAV file header (stereo)
|
AudioDumper m_dump(2); // WAV file header (stereo)
|
||||||
|
|
||||||
|
bool do_dump = Ini.AudioDumpToFile.GetValue();
|
||||||
|
|
||||||
if (Ini.AudioDumpToFile.GetValue() && !m_dump.Init())
|
if (do_dump && !m_dump.Init())
|
||||||
{
|
{
|
||||||
ConLog.Error("Audio aborted: cannot create file!");
|
ConLog.Error("Audio aborted: cannot create file!");
|
||||||
return;
|
return;
|
||||||
@ -43,31 +49,54 @@ int cellAudioInit()
|
|||||||
|
|
||||||
ConLog.Write("Audio started");
|
ConLog.Write("Audio started");
|
||||||
|
|
||||||
m_config.start_time = get_system_time();
|
|
||||||
|
|
||||||
if (Ini.AudioDumpToFile.GetValue())
|
if (Ini.AudioDumpToFile.GetValue())
|
||||||
m_dump.WriteHeader();
|
m_dump.WriteHeader();
|
||||||
|
|
||||||
float buffer[2*256]; // buffer for 2 channels
|
float buffer[2*256]; // intermediate buffer for 2 channels
|
||||||
be_t<float> buffer2[8*256]; // buffer for 8 channels (max count)
|
|
||||||
//u16 oal_buffer[2*256]; // buffer for OpenAL
|
|
||||||
|
|
||||||
uint oal_buffer_offset = 0;
|
uint oal_buffer_offset = 0;
|
||||||
uint oal_buffer_size = 2 * 256;
|
uint oal_buffer_size = sizeof(buffer) / sizeof(float);
|
||||||
std::unique_ptr<u16[]> oal_buffer(new u16[oal_buffer_size]);
|
std::unique_ptr<u16[]> oal_buffer[32];
|
||||||
|
SQueue<u16*, sizeof(oal_buffer) / sizeof(oal_buffer[0])> queue;
|
||||||
memset(buffer, 0, sizeof(buffer));
|
for (u32 i = 0; i < queue.GetSize(); i++)
|
||||||
memset(buffer2, 0, sizeof(buffer2));
|
{
|
||||||
memset(oal_buffer.get(), 0, oal_buffer_size * sizeof(u16));
|
oal_buffer[i] = std::unique_ptr<u16[]>(new u16[oal_buffer_size]);
|
||||||
|
memset(oal_buffer[i].get(), 0, oal_buffer_size * sizeof(u16));
|
||||||
|
}
|
||||||
|
queue.Clear();
|
||||||
|
|
||||||
Array<u64> keys;
|
Array<u64> keys;
|
||||||
|
|
||||||
if(m_audio_out)
|
if(m_audio_out)
|
||||||
{
|
{
|
||||||
m_audio_out->Init();
|
m_audio_out->Init();
|
||||||
m_audio_out->Open(oal_buffer.get(), oal_buffer_size*sizeof(u16));
|
m_audio_out->Open(oal_buffer[0].get(), oal_buffer_size * sizeof(u16));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_config.start_time = get_system_time();
|
||||||
|
|
||||||
|
volatile bool internal_finished = false;
|
||||||
|
|
||||||
|
thread iat("Internal Audio Thread", [oal_buffer_size, &queue, &internal_finished]()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
u16* oal_buffer = nullptr;
|
||||||
|
queue.Pop(oal_buffer);
|
||||||
|
|
||||||
|
if (oal_buffer)
|
||||||
|
{
|
||||||
|
m_audio_out->AddData(oal_buffer, oal_buffer_size * sizeof(u16));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
internal_finished = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
iat.detach();
|
||||||
|
|
||||||
while (m_config.m_is_audio_initialized)
|
while (m_config.m_is_audio_initialized)
|
||||||
{
|
{
|
||||||
if (Emu.IsStopped())
|
if (Emu.IsStopped())
|
||||||
@ -76,10 +105,12 @@ int cellAudioInit()
|
|||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const u64 stamp0 = get_system_time();
|
||||||
|
|
||||||
// TODO: send beforemix event (in ~2,6 ms before mixing)
|
// TODO: send beforemix event (in ~2,6 ms before mixing)
|
||||||
|
|
||||||
// Sleep(5); // precise time of sleeping: 5,(3) ms (or 256/48000 sec)
|
// precise time of sleeping: 5,(3) ms (or 256/48000 sec)
|
||||||
if (m_config.counter * 256000000 / 48000 >= get_system_time() - m_config.start_time)
|
if (m_config.counter * 256000000 / 48000 >= stamp0 - m_config.start_time)
|
||||||
{
|
{
|
||||||
Sleep(1);
|
Sleep(1);
|
||||||
continue;
|
continue;
|
||||||
@ -87,6 +118,8 @@ int cellAudioInit()
|
|||||||
|
|
||||||
m_config.counter++;
|
m_config.counter++;
|
||||||
|
|
||||||
|
const u32 oal_pos = m_config.counter % queue.GetSize();
|
||||||
|
|
||||||
if (Emu.IsPaused())
|
if (Emu.IsPaused())
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@ -94,68 +127,134 @@ int cellAudioInit()
|
|||||||
|
|
||||||
bool first_mix = true;
|
bool first_mix = true;
|
||||||
|
|
||||||
// MIX:
|
// mixing:
|
||||||
for (u32 i = 0; i < m_config.AUDIO_PORT_COUNT; i++)
|
for (u32 i = 0; i < m_config.AUDIO_PORT_COUNT; i++)
|
||||||
{
|
{
|
||||||
if (!m_config.m_ports[i].m_is_audio_port_started) continue;
|
if (!m_config.m_ports[i].m_is_audio_port_started) continue;
|
||||||
|
|
||||||
AudioPortConfig& port = m_config.m_ports[i];
|
AudioPortConfig& port = m_config.m_ports[i];
|
||||||
mem64_t index(m_config.m_indexes + i * sizeof(u64));
|
|
||||||
|
|
||||||
const u32 block_size = port.channel * 256;
|
const u32 block_size = port.channel * 256;
|
||||||
|
const u32 position = port.tag % port.block; // old value
|
||||||
|
const u32 buf_addr = m_config.m_buffer + (i * 128 * 1024) + (position * block_size * sizeof(float));
|
||||||
|
|
||||||
u32 position = port.tag % port.block; // old value
|
auto buf = (be_t<float>*)&Memory[buf_addr];
|
||||||
|
|
||||||
u32 buf_addr = m_config.m_buffer + (i * 128 * 1024) + (position * block_size * sizeof(float));
|
static const float k = 1.0f;
|
||||||
|
const float m = (port.level == 0.0f) ? 1.0f : port.level;
|
||||||
memcpy(buffer2, Memory + buf_addr, block_size * sizeof(float));
|
|
||||||
memset(Memory + buf_addr, 0, block_size * sizeof(float));
|
|
||||||
|
|
||||||
|
if (port.channel == 2)
|
||||||
{
|
{
|
||||||
SMutexGeneralLocker lock(port.m_mutex);
|
if (first_mix)
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i++)
|
||||||
|
{
|
||||||
|
// reverse byte order
|
||||||
|
buffer[i] = buf[i] * m;
|
||||||
|
}
|
||||||
|
first_mix = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i++)
|
||||||
|
{
|
||||||
|
buffer[i] += buf[i] * m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (port.channel == 6)
|
||||||
|
{
|
||||||
|
if (first_mix)
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i += 2)
|
||||||
|
{
|
||||||
|
const float center = (buf[i*3+2] + buf[i*3+3]) * 0.708f;
|
||||||
|
buffer[i] = (buf[i*3] + buf[i*3+4] + center) * k * m;
|
||||||
|
buffer[i+1] = (buf[i*3+1] + buf[i*3+5] + center) * k * m;
|
||||||
|
}
|
||||||
|
first_mix = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i += 2)
|
||||||
|
{
|
||||||
|
const float center = (buf[i*3+2] + buf[i*3+3]) * 0.708f;
|
||||||
|
buffer[i] += (buf[i*3] + buf[i*3+4] + center) * k * m;
|
||||||
|
buffer[i+1] += (buf[i*3+1] + buf[i*3+5] + center) * k * m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (port.channel == 8)
|
||||||
|
{
|
||||||
|
if (first_mix)
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i += 2)
|
||||||
|
{
|
||||||
|
const float center = (buf[i*4+2] + buf[i*4+3]) * 0.708f;
|
||||||
|
buffer[i] = (buf[i*4] + buf[i*4+4] + buf[i*4+6] + center) * k * m;
|
||||||
|
buffer[i+1] = (buf[i*4+1] + buf[i*4+5] + buf[i*4+7] + center) * k * m;
|
||||||
|
}
|
||||||
|
first_mix = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i += 2)
|
||||||
|
{
|
||||||
|
const float center = (buf[i*4+2] + buf[i*4+3]) * 0.708f;
|
||||||
|
buffer[i] += (buf[i*4] + buf[i*4+4] + buf[i*4+6] + center) * k * m;
|
||||||
|
buffer[i+1] += (buf[i*4+1] + buf[i*4+5] + buf[i*4+7] + center) * k * m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(buf, 0, block_size * sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert the data from float to u16 and clip:
|
||||||
|
if (!first_mix)
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i++)
|
||||||
|
{
|
||||||
|
oal_buffer[oal_pos][oal_buffer_offset + i] = (s16)(min<float>(max<float>(buffer[i] * 0x8000, -0x8000), 0x7fff));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const u64 stamp1 = get_system_time();
|
||||||
|
|
||||||
|
if (!first_mix)
|
||||||
|
{
|
||||||
|
oal_buffer_offset += sizeof(buffer) / sizeof(float);
|
||||||
|
|
||||||
|
if(oal_buffer_offset >= oal_buffer_size)
|
||||||
|
{
|
||||||
|
if(m_audio_out)
|
||||||
|
{
|
||||||
|
queue.Push(&oal_buffer[oal_pos][0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
oal_buffer_offset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const u64 stamp2 = get_system_time();
|
||||||
|
|
||||||
|
// send aftermix event (normal audio event)
|
||||||
|
{
|
||||||
|
SMutexGeneralLocker lock(audioMutex);
|
||||||
|
// update indexes:
|
||||||
|
for (u32 i = 0; i < m_config.AUDIO_PORT_COUNT; i++)
|
||||||
|
{
|
||||||
|
if (!m_config.m_ports[i].m_is_audio_port_started) continue;
|
||||||
|
|
||||||
|
AudioPortConfig& port = m_config.m_ports[i];
|
||||||
|
mem64_t index(m_config.m_indexes + i * sizeof(u64));
|
||||||
|
|
||||||
|
u32 position = port.tag % port.block; // old value
|
||||||
port.counter = m_config.counter;
|
port.counter = m_config.counter;
|
||||||
port.tag++; // absolute index of block that will be read
|
port.tag++; // absolute index of block that will be read
|
||||||
index = (position + 1) % port.block; // write new value
|
index = (position + 1) % port.block; // write new value
|
||||||
}
|
}
|
||||||
|
// load keys:
|
||||||
u32 k = port.channel / 2;
|
|
||||||
|
|
||||||
if (first_mix)
|
|
||||||
{
|
|
||||||
for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i += 2)
|
|
||||||
{
|
|
||||||
// reverse byte order (TODO: use port.m_param.level)
|
|
||||||
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 += 2)
|
|
||||||
{
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// send aftermix event (normal audio event)
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(m_config.m_mutex);
|
|
||||||
keys.SetCount(m_config.m_keys.GetCount());
|
keys.SetCount(m_config.m_keys.GetCount());
|
||||||
memcpy(keys.GetPtr(), m_config.m_keys.GetPtr(), sizeof(u64) * keys.GetCount());
|
memcpy(keys.GetPtr(), m_config.m_keys.GetPtr(), sizeof(u64) * keys.GetCount());
|
||||||
}
|
}
|
||||||
@ -165,19 +264,9 @@ int cellAudioInit()
|
|||||||
Emu.GetEventManager().SendEvent(keys[i], 0x10103000e010e07, 0, 0, 0);
|
Emu.GetEventManager().SendEvent(keys[i], 0x10103000e010e07, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
oal_buffer_offset += sizeof(buffer) / sizeof(float);
|
const u64 stamp3 = get_system_time();
|
||||||
|
|
||||||
if(oal_buffer_offset >= oal_buffer_size)
|
if (do_dump && !first_mix)
|
||||||
{
|
|
||||||
if(m_audio_out)
|
|
||||||
{
|
|
||||||
m_audio_out->AddData(oal_buffer.get(), oal_buffer_offset * sizeof(u16));
|
|
||||||
}
|
|
||||||
|
|
||||||
oal_buffer_offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Ini.AudioDumpToFile.GetValue())
|
|
||||||
{
|
{
|
||||||
if (m_dump.WriteData(&buffer, sizeof(buffer)) != sizeof(buffer)) // write file data
|
if (m_dump.WriteData(&buffer, sizeof(buffer)) != sizeof(buffer)) // write file data
|
||||||
{
|
{
|
||||||
@ -185,16 +274,49 @@ int cellAudioInit()
|
|||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const u64 stamp4 = get_system_time();
|
||||||
|
|
||||||
|
//ConLog.Write("Audio perf: start=%d (access=%d, AddData=%d, events=%d, dump=%d)",
|
||||||
|
//stamp0 - m_config.start_time, stamp1-stamp0, stamp2-stamp1, stamp3-stamp2, stamp4-stamp3);
|
||||||
}
|
}
|
||||||
ConLog.Write("Audio finished");
|
ConLog.Write("Audio finished");
|
||||||
abort:
|
abort:
|
||||||
if(Ini.AudioDumpToFile.GetValue())
|
queue.Push(nullptr);
|
||||||
|
|
||||||
|
if(do_dump)
|
||||||
m_dump.Finalize();
|
m_dump.Finalize();
|
||||||
|
|
||||||
|
m_config.m_is_audio_initialized = false;
|
||||||
|
|
||||||
|
m_config.m_keys.Clear();
|
||||||
|
for (u32 i = 0; i < m_config.AUDIO_PORT_COUNT; i++)
|
||||||
|
{
|
||||||
|
AudioPortConfig& port = m_config.m_ports[i];
|
||||||
|
port.m_is_audio_port_opened = false;
|
||||||
|
port.m_is_audio_port_started = false;
|
||||||
|
}
|
||||||
|
m_config.m_port_in_use = 0;
|
||||||
|
|
||||||
|
while (!internal_finished)
|
||||||
|
{
|
||||||
|
Sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
m_config.m_is_audio_finalized = true;
|
m_config.m_is_audio_finalized = true;
|
||||||
});
|
});
|
||||||
t.detach();
|
t.detach();
|
||||||
|
|
||||||
|
while (!m_config.start_time) // waiting for initialization
|
||||||
|
{
|
||||||
|
if (Emu.IsStopped())
|
||||||
|
{
|
||||||
|
ConLog.Warning("cellAudioInit() aborted");
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
Sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,6 +469,7 @@ int cellAudioPortClose(u32 portNum)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_config.m_ports[portNum].m_is_audio_port_started = false;
|
m_config.m_ports[portNum].m_is_audio_port_started = false;
|
||||||
|
m_config.m_ports[portNum].m_is_audio_port_opened = false;
|
||||||
m_config.m_port_in_use--;
|
m_config.m_port_in_use--;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
@ -395,7 +518,7 @@ int cellAudioGetPortTimestamp(u32 portNum, u64 tag, mem64_t stamp)
|
|||||||
|
|
||||||
AudioPortConfig& port = m_config.m_ports[portNum];
|
AudioPortConfig& port = m_config.m_ports[portNum];
|
||||||
|
|
||||||
SMutexGeneralLocker lock(port.m_mutex);
|
SMutexGeneralLocker lock(audioMutex);
|
||||||
|
|
||||||
stamp = m_config.start_time + (port.counter + (tag - port.tag)) * 256000000 / 48000;
|
stamp = m_config.start_time + (port.counter + (tag - port.tag)) * 256000000 / 48000;
|
||||||
|
|
||||||
@ -429,7 +552,7 @@ int cellAudioGetPortBlockTag(u32 portNum, u64 blockNo, mem64_t tag)
|
|||||||
return CELL_AUDIO_ERROR_PARAM;
|
return CELL_AUDIO_ERROR_PARAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
SMutexGeneralLocker lock(port.m_mutex);
|
SMutexGeneralLocker lock(audioMutex);
|
||||||
|
|
||||||
u64 tag_base = port.tag;
|
u64 tag_base = port.tag;
|
||||||
if (tag_base % port.block > blockNo)
|
if (tag_base % port.block > blockNo)
|
||||||
@ -457,7 +580,7 @@ int cellAudioCreateNotifyEventQueue(mem32_t id, mem64_t key)
|
|||||||
{
|
{
|
||||||
cellAudio.Warning("cellAudioCreateNotifyEventQueue(id_addr=0x%x, key_addr=0x%x)", id.GetAddr(), key.GetAddr());
|
cellAudio.Warning("cellAudioCreateNotifyEventQueue(id_addr=0x%x, key_addr=0x%x)", id.GetAddr(), key.GetAddr());
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(m_config.m_mutex);
|
SMutexGeneralLocker lock(audioMutex);
|
||||||
|
|
||||||
u64 event_key = 0;
|
u64 event_key = 0;
|
||||||
while (Emu.GetEventManager().CheckKey((event_key << 48) | 0x80004d494f323221))
|
while (Emu.GetEventManager().CheckKey((event_key << 48) | 0x80004d494f323221))
|
||||||
@ -475,7 +598,6 @@ int cellAudioCreateNotifyEventQueue(mem32_t id, mem64_t key)
|
|||||||
return CELL_AUDIO_ERROR_EVENT_QUEUE;
|
return CELL_AUDIO_ERROR_EVENT_QUEUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_config.m_keys.AddCpy(event_key);
|
|
||||||
id = cellAudio.GetNewId(eq);
|
id = cellAudio.GetNewId(eq);
|
||||||
key = event_key;
|
key = event_key;
|
||||||
|
|
||||||
@ -492,8 +614,15 @@ int cellAudioSetNotifyEventQueue(u64 key)
|
|||||||
{
|
{
|
||||||
cellAudio.Warning("cellAudioSetNotifyEventQueue(key=0x%llx)", key);
|
cellAudio.Warning("cellAudioSetNotifyEventQueue(key=0x%llx)", key);
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(m_config.m_mutex);
|
SMutexGeneralLocker lock(audioMutex);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < m_config.m_keys.GetCount(); i++) // check for duplicates
|
||||||
|
{
|
||||||
|
if (m_config.m_keys[i] == key)
|
||||||
|
{
|
||||||
|
return CELL_AUDIO_ERROR_PARAM;
|
||||||
|
}
|
||||||
|
}
|
||||||
m_config.m_keys.AddCpy(key);
|
m_config.m_keys.AddCpy(key);
|
||||||
|
|
||||||
/*EventQueue* eq;
|
/*EventQueue* eq;
|
||||||
@ -517,7 +646,7 @@ int cellAudioRemoveNotifyEventQueue(u64 key)
|
|||||||
{
|
{
|
||||||
cellAudio.Warning("cellAudioRemoveNotifyEventQueue(key=0x%llx)", key);
|
cellAudio.Warning("cellAudioRemoveNotifyEventQueue(key=0x%llx)", key);
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(m_config.m_mutex);
|
SMutexGeneralLocker lock(audioMutex);
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (u32 i = 0; i < m_config.m_keys.GetCount(); i++)
|
for (u32 i = 0; i < m_config.m_keys.GetCount(); i++)
|
||||||
|
@ -338,7 +338,17 @@ int cellGcmSetPrepareFlip(mem_ptr_t<CellGcmContextData> ctxt, u32 id)
|
|||||||
if(current + 8 >= end)
|
if(current + 8 >= end)
|
||||||
{
|
{
|
||||||
ConLog.Warning("bad flip!");
|
ConLog.Warning("bad flip!");
|
||||||
cellGcmCallback(ctxt.GetAddr(), current + 8 - end);
|
//cellGcmCallback(ctxt.GetAddr(), current + 8 - end);
|
||||||
|
//copied:
|
||||||
|
|
||||||
|
CellGcmControl& ctrl = (CellGcmControl&)Memory[gcm_info.control_addr];
|
||||||
|
|
||||||
|
const s32 res = ctxt->current - ctxt->begin - ctrl.put;
|
||||||
|
|
||||||
|
if(res > 0) Memory.Copy(ctxt->begin, ctxt->current - res, res);
|
||||||
|
ctxt->current = ctxt->begin + res;
|
||||||
|
ctrl.put = res;
|
||||||
|
ctrl.get = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
current = ctxt->current;
|
current = ctxt->current;
|
||||||
|
@ -60,7 +60,12 @@ int UTF16stoUTF8s(mem16_ptr_t utf16, mem64_t utf16_len, mem8_ptr_t utf8, mem64_t
|
|||||||
|
|
||||||
int jstrchk(mem8_ptr_t jstr)
|
int jstrchk(mem8_ptr_t jstr)
|
||||||
{
|
{
|
||||||
cellL10n.Log("jstrchk(jstr_addr=0x%x [%s])", jstr.GetAddr(), "omitted" /*Memory.ReadString(jstr.GetAddr()).wx_str()*/);
|
if (!jstr.IsGood())
|
||||||
|
cellL10n.Error("jstrchk(jstr_addr=0x%x): invalid address", jstr.GetAddr());
|
||||||
|
else if (jstr[0])
|
||||||
|
cellL10n.Log("jstrchk(jstr_addr=0x%x): utf-8: [%s]", jstr.GetAddr(), Memory.ReadString(jstr.GetAddr()).wx_str());
|
||||||
|
else
|
||||||
|
cellL10n.Log("jstrchk(jstr_addr=0x%x): empty string", jstr.GetAddr());
|
||||||
|
|
||||||
return L10N_STR_UTF8;
|
return L10N_STR_UTF8;
|
||||||
}
|
}
|
||||||
|
@ -1,244 +1,244 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Emu/Cell/SPURSManager.h"
|
#include "Emu/Cell/SPURSManager.h"
|
||||||
|
|
||||||
// Core return codes.
|
// Core return codes.
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
CELL_SPURS_CORE_ERROR_AGAIN = 0x80410701,
|
CELL_SPURS_CORE_ERROR_AGAIN = 0x80410701,
|
||||||
CELL_SPURS_CORE_ERROR_INVAL = 0x80410702,
|
CELL_SPURS_CORE_ERROR_INVAL = 0x80410702,
|
||||||
CELL_SPURS_CORE_ERROR_NOMEM = 0x80410704,
|
CELL_SPURS_CORE_ERROR_NOMEM = 0x80410704,
|
||||||
CELL_SPURS_CORE_ERROR_SRCH = 0x80410705,
|
CELL_SPURS_CORE_ERROR_SRCH = 0x80410705,
|
||||||
CELL_SPURS_CORE_ERROR_PERM = 0x80410709,
|
CELL_SPURS_CORE_ERROR_PERM = 0x80410709,
|
||||||
CELL_SPURS_CORE_ERROR_BUSY = 0x8041070A,
|
CELL_SPURS_CORE_ERROR_BUSY = 0x8041070A,
|
||||||
CELL_SPURS_CORE_ERROR_STAT = 0x8041070F,
|
CELL_SPURS_CORE_ERROR_STAT = 0x8041070F,
|
||||||
CELL_SPURS_CORE_ERROR_ALIGN = 0x80410710,
|
CELL_SPURS_CORE_ERROR_ALIGN = 0x80410710,
|
||||||
CELL_SPURS_CORE_ERROR_NULL_POINTER = 0x80410711,
|
CELL_SPURS_CORE_ERROR_NULL_POINTER = 0x80410711,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Task return codes.
|
// Task return codes.
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
CELL_SPURS_TASK_ERROR_AGAIN = 0x80410901,
|
CELL_SPURS_TASK_ERROR_AGAIN = 0x80410901,
|
||||||
CELL_SPURS_TASK_ERROR_INVAL = 0x80410902,
|
CELL_SPURS_TASK_ERROR_INVAL = 0x80410902,
|
||||||
CELL_SPURS_TASK_ERROR_NOMEM = 0x80410904,
|
CELL_SPURS_TASK_ERROR_NOMEM = 0x80410904,
|
||||||
CELL_SPURS_TASK_ERROR_SRCH = 0x80410905,
|
CELL_SPURS_TASK_ERROR_SRCH = 0x80410905,
|
||||||
CELL_SPURS_TASK_ERROR_NOEXEC = 0x80410907,
|
CELL_SPURS_TASK_ERROR_NOEXEC = 0x80410907,
|
||||||
CELL_SPURS_TASK_ERROR_PERM = 0x80410909,
|
CELL_SPURS_TASK_ERROR_PERM = 0x80410909,
|
||||||
CELL_SPURS_TASK_ERROR_BUSY = 0x8041090A,
|
CELL_SPURS_TASK_ERROR_BUSY = 0x8041090A,
|
||||||
CELL_SPURS_TASK_ERROR_FAULT = 0x8041090D,
|
CELL_SPURS_TASK_ERROR_FAULT = 0x8041090D,
|
||||||
CELL_SPURS_TASK_ERROR_STAT = 0x8041090F,
|
CELL_SPURS_TASK_ERROR_STAT = 0x8041090F,
|
||||||
CELL_SPURS_TASK_ERROR_ALIGN = 0x80410910,
|
CELL_SPURS_TASK_ERROR_ALIGN = 0x80410910,
|
||||||
CELL_SPURS_TASK_ERROR_NULL_POINTER = 0x80410911,
|
CELL_SPURS_TASK_ERROR_NULL_POINTER = 0x80410911,
|
||||||
CELL_SPURS_TASK_ERROR_FATAL = 0x80410914,
|
CELL_SPURS_TASK_ERROR_FATAL = 0x80410914,
|
||||||
CELL_SPURS_TASK_ERROR_SHUTDOWN = 0x80410920,
|
CELL_SPURS_TASK_ERROR_SHUTDOWN = 0x80410920,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Core CellSpurs structures.
|
// Core CellSpurs structures.
|
||||||
struct CellSpurs
|
struct CellSpurs
|
||||||
{
|
{
|
||||||
SPURSManager *spurs;
|
SPURSManager *spurs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellSpurs2
|
struct CellSpurs2
|
||||||
{
|
{
|
||||||
SPURSManager *spurs;
|
SPURSManager *spurs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellSpursAttribute
|
struct CellSpursAttribute
|
||||||
{
|
{
|
||||||
SPURSManagerAttribute *attr;
|
SPURSManagerAttribute *attr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellSpursInfo
|
struct CellSpursInfo
|
||||||
{
|
{
|
||||||
be_t<int> nSpus;
|
be_t<int> nSpus;
|
||||||
be_t<int> spuThreadGroupPriority;
|
be_t<int> spuThreadGroupPriority;
|
||||||
be_t<int> ppuThreadPriority;
|
be_t<int> ppuThreadPriority;
|
||||||
bool exitIfNoWork;
|
bool exitIfNoWork;
|
||||||
bool spurs2;
|
bool spurs2;
|
||||||
be_t<u32> traceBuffer_addr; //void *traceBuffer;
|
be_t<u32> traceBuffer_addr; //void *traceBuffer;
|
||||||
be_t<u64> traceBufferSize;
|
be_t<u64> traceBufferSize;
|
||||||
be_t<u32> traceMode;
|
be_t<u32> traceMode;
|
||||||
be_t<u32> spuThreadGroup; //typedef u32 sys_spu_thread_group_t;
|
be_t<u32> spuThreadGroup; //typedef u32 sys_spu_thread_group_t;
|
||||||
be_t<u32> spuThreads[8]; //typedef u32 sys_spu_thread_t;
|
be_t<u32> spuThreads[8]; //typedef u32 sys_spu_thread_t;
|
||||||
be_t<u32> spursHandlerThread0;
|
be_t<u32> spursHandlerThread0;
|
||||||
be_t<u32> spursHandlerThread1;
|
be_t<u32> spursHandlerThread1;
|
||||||
char namePrefix[CELL_SPURS_NAME_MAX_LENGTH+1];
|
char namePrefix[CELL_SPURS_NAME_MAX_LENGTH+1];
|
||||||
be_t<u64> namePrefixLength;
|
be_t<u64> namePrefixLength;
|
||||||
be_t<u32> deadlineMissCounter;
|
be_t<u32> deadlineMissCounter;
|
||||||
be_t<u32> deadlineMeetCounter;
|
be_t<u32> deadlineMeetCounter;
|
||||||
//u8 padding[];
|
//u8 padding[];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellSpursExceptionInfo
|
struct CellSpursExceptionInfo
|
||||||
{
|
{
|
||||||
be_t<u32> spu_thread;
|
be_t<u32> spu_thread;
|
||||||
be_t<u32> spu_npc;
|
be_t<u32> spu_npc;
|
||||||
be_t<u32> cause;
|
be_t<u32> cause;
|
||||||
be_t<u64> option;
|
be_t<u64> option;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellSpursTraceInfo
|
struct CellSpursTraceInfo
|
||||||
{
|
{
|
||||||
be_t<u32> spu_thread[8];
|
be_t<u32> spu_thread[8];
|
||||||
be_t<u32> count[8];
|
be_t<u32> count[8];
|
||||||
be_t<u32> spu_thread_grp;
|
be_t<u32> spu_thread_grp;
|
||||||
be_t<u32> nspu;
|
be_t<u32> nspu;
|
||||||
//u8 padding[];
|
//u8 padding[];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellTraceHeader
|
struct CellTraceHeader
|
||||||
{
|
{
|
||||||
u8 tag;
|
u8 tag;
|
||||||
u8 length;
|
u8 length;
|
||||||
u8 cpu;
|
u8 cpu;
|
||||||
u8 thread;
|
u8 thread;
|
||||||
be_t<u32> time;
|
be_t<u32> time;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellSpursTracePacket
|
struct CellSpursTracePacket
|
||||||
{
|
{
|
||||||
struct header_struct
|
struct header_struct
|
||||||
{
|
{
|
||||||
u8 tag;
|
u8 tag;
|
||||||
u8 length;
|
u8 length;
|
||||||
u8 spu;
|
u8 spu;
|
||||||
u8 workload;
|
u8 workload;
|
||||||
be_t<u32> time;
|
be_t<u32> time;
|
||||||
} header;
|
} header;
|
||||||
|
|
||||||
struct data_struct
|
struct data_struct
|
||||||
{
|
{
|
||||||
struct load_struct
|
struct load_struct
|
||||||
{
|
{
|
||||||
be_t<u32> ea;
|
be_t<u32> ea;
|
||||||
be_t<u16> ls;
|
be_t<u16> ls;
|
||||||
be_t<u16> size;
|
be_t<u16> size;
|
||||||
} load;
|
} load;
|
||||||
|
|
||||||
struct map_struct
|
struct map_struct
|
||||||
{
|
{
|
||||||
be_t<u32> offset;
|
be_t<u32> offset;
|
||||||
be_t<u16> ls;
|
be_t<u16> ls;
|
||||||
be_t<u16> size;
|
be_t<u16> size;
|
||||||
} map;
|
} map;
|
||||||
|
|
||||||
struct start_struct
|
struct start_struct
|
||||||
{
|
{
|
||||||
char module[4];
|
char module[4];
|
||||||
be_t<u16> level;
|
be_t<u16> level;
|
||||||
be_t<u16> ls;
|
be_t<u16> ls;
|
||||||
} start;
|
} start;
|
||||||
|
|
||||||
be_t<u64> user;
|
be_t<u64> user;
|
||||||
be_t<u64> guid;
|
be_t<u64> guid;
|
||||||
} data;
|
} data;
|
||||||
};
|
};
|
||||||
|
|
||||||
// cellSpurs taskset structures.
|
// cellSpurs taskset structures.
|
||||||
struct CellSpursTaskset
|
struct CellSpursTaskset
|
||||||
{
|
{
|
||||||
u8 skip[6400];
|
u8 skip[6400];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Exception handlers.
|
// Exception handlers.
|
||||||
typedef void (*CellSpursGlobalExceptionEventHandler)(mem_ptr_t<CellSpurs> spurs, const mem_ptr_t<CellSpursExceptionInfo> info,
|
typedef void (*CellSpursGlobalExceptionEventHandler)(mem_ptr_t<CellSpurs> spurs, const mem_ptr_t<CellSpursExceptionInfo> info,
|
||||||
uint id, mem_ptr_t<void> arg);
|
uint id, mem_ptr_t<void> arg);
|
||||||
|
|
||||||
typedef void (*CellSpursTasksetExceptionEventHandler)(mem_ptr_t<CellSpurs> spurs, mem_ptr_t<CellSpursTaskset> taskset,
|
typedef void (*CellSpursTasksetExceptionEventHandler)(mem_ptr_t<CellSpurs> spurs, mem_ptr_t<CellSpursTaskset> taskset,
|
||||||
uint idTask, const mem_ptr_t<CellSpursExceptionInfo> info, mem_ptr_t<void> arg);
|
uint idTask, const mem_ptr_t<CellSpursExceptionInfo> info, mem_ptr_t<void> arg);
|
||||||
|
|
||||||
struct CellSpursTasksetInfo
|
struct CellSpursTasksetInfo
|
||||||
{
|
{
|
||||||
//CellSpursTaskInfo taskInfo[CELL_SPURS_MAX_TASK];
|
//CellSpursTaskInfo taskInfo[CELL_SPURS_MAX_TASK];
|
||||||
be_t<u64> argument;
|
be_t<u64> argument;
|
||||||
be_t<uint> idWorkload;
|
be_t<uint> idWorkload;
|
||||||
be_t<uint> idLastScheduledTask; //typedef unsigned CellSpursTaskId
|
be_t<uint> idLastScheduledTask; //typedef unsigned CellSpursTaskId
|
||||||
be_t<u32> name_addr;
|
be_t<u32> name_addr;
|
||||||
CellSpursTasksetExceptionEventHandler exceptionEventHandler;
|
CellSpursTasksetExceptionEventHandler exceptionEventHandler;
|
||||||
be_t<u32> exceptionEventHandlerArgument_addr; //void *exceptionEventHandlerArgument
|
be_t<u32> exceptionEventHandlerArgument_addr; //void *exceptionEventHandlerArgument
|
||||||
be_t<u64> sizeTaskset;
|
be_t<u64> sizeTaskset;
|
||||||
//be_t<u8> reserved[];
|
//be_t<u8> reserved[];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellSpursTaskset2
|
struct CellSpursTaskset2
|
||||||
{
|
{
|
||||||
be_t<u8> skip[10496];
|
be_t<u8> skip[10496];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellSpursTasksetAttribute2
|
struct CellSpursTasksetAttribute2
|
||||||
{
|
{
|
||||||
be_t<u32> revision;
|
be_t<u32> revision;
|
||||||
be_t<u32> name_addr;
|
be_t<u32> name_addr;
|
||||||
be_t<u64> argTaskset;
|
be_t<u64> argTaskset;
|
||||||
u8 priority[8];
|
u8 priority[8];
|
||||||
be_t<u32> maxContention;
|
be_t<u32> maxContention;
|
||||||
be_t<s32> enableClearLs;
|
be_t<s32> enableClearLs;
|
||||||
be_t<s32> CellSpursTaskNameBuffer_addr; //??? *taskNameBuffer
|
be_t<s32> CellSpursTaskNameBuffer_addr; //??? *taskNameBuffer
|
||||||
//be_t<u32> __reserved__[];
|
//be_t<u32> __reserved__[];
|
||||||
};
|
};
|
||||||
|
|
||||||
// cellSpurs task structures.
|
// cellSpurs task structures.
|
||||||
struct CellSpursTaskNameBuffer
|
struct CellSpursTaskNameBuffer
|
||||||
{
|
{
|
||||||
char taskName[CELL_SPURS_MAX_TASK][CELL_SPURS_MAX_TASK_NAME_LENGTH];
|
char taskName[CELL_SPURS_MAX_TASK][CELL_SPURS_MAX_TASK_NAME_LENGTH];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellSpursTraceTaskData
|
struct CellSpursTraceTaskData
|
||||||
{
|
{
|
||||||
be_t<u32> incident;
|
be_t<u32> incident;
|
||||||
be_t<u32> task;
|
be_t<u32> task;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellSpursTaskArgument
|
struct CellSpursTaskArgument
|
||||||
{
|
{
|
||||||
be_t<u32> u32[4];
|
be_t<u32> u32[4];
|
||||||
be_t<u64> u64[2];
|
be_t<u64> u64[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellSpursTaskLsPattern
|
struct CellSpursTaskLsPattern
|
||||||
{
|
{
|
||||||
be_t<u32> u32[4];
|
be_t<u32> u32[4];
|
||||||
be_t<u64> u64[2];
|
be_t<u64> u64[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellSpursTaskAttribute2
|
struct CellSpursTaskAttribute2
|
||||||
{
|
{
|
||||||
be_t<u32> revision;
|
be_t<u32> revision;
|
||||||
be_t<u32> sizeContext;
|
be_t<u32> sizeContext;
|
||||||
be_t<u64> eaContext;
|
be_t<u64> eaContext;
|
||||||
CellSpursTaskLsPattern lsPattern; //???
|
CellSpursTaskLsPattern lsPattern; //???
|
||||||
be_t<u32> name_addr;
|
be_t<u32> name_addr;
|
||||||
//be_t<u32> __reserved__[];
|
//be_t<u32> __reserved__[];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellSpursTaskExitCode
|
struct CellSpursTaskExitCode
|
||||||
{
|
{
|
||||||
unsigned char skip[128];
|
unsigned char skip[128];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellSpursTaskInfo
|
struct CellSpursTaskInfo
|
||||||
{
|
{
|
||||||
CellSpursTaskLsPattern lsPattern;
|
CellSpursTaskLsPattern lsPattern;
|
||||||
CellSpursTaskArgument argument;
|
CellSpursTaskArgument argument;
|
||||||
const be_t<u32> eaElf_addr; //void *eaElf
|
const be_t<u32> eaElf_addr; //void *eaElf
|
||||||
const be_t<u32> eaContext_addr; //void *eaContext
|
const be_t<u32> eaContext_addr; //void *eaContext
|
||||||
be_t<u32> sizeContext;
|
be_t<u32> sizeContext;
|
||||||
be_t<u8> state;
|
be_t<u8> state;
|
||||||
be_t<u8> hasSignal;
|
be_t<u8> hasSignal;
|
||||||
const be_t<u32> CellSpursTaskExitCode_addr;
|
const be_t<u32> CellSpursTaskExitCode_addr;
|
||||||
u8 guid[8];
|
u8 guid[8];
|
||||||
//be_t<u8> reserved[];
|
//be_t<u8> reserved[];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellSpursTaskBinInfo
|
struct CellSpursTaskBinInfo
|
||||||
{
|
{
|
||||||
be_t<u64> eaElf;
|
be_t<u64> eaElf;
|
||||||
be_t<u32> sizeContext;
|
be_t<u32> sizeContext;
|
||||||
be_t<u32> __reserved__;
|
be_t<u32> __reserved__;
|
||||||
CellSpursTaskLsPattern lsPattern;
|
CellSpursTaskLsPattern lsPattern;
|
||||||
};
|
};
|
||||||
|
|
||||||
// cellSpurs event flag.
|
// cellSpurs event flag.
|
||||||
struct CellSpursEventFlag {
|
struct CellSpursEventFlag {
|
||||||
u8 skip[128];
|
u8 skip[128];
|
||||||
|
@ -158,6 +158,10 @@ int cellSysmoduleSetMemcontainer(u32 ct_id)
|
|||||||
|
|
||||||
int cellSysmoduleLoadModule(u16 id)
|
int cellSysmoduleLoadModule(u16 id)
|
||||||
{
|
{
|
||||||
|
if (id == 0xf054)
|
||||||
|
{
|
||||||
|
cellSysmodule.Error("cellSysmoduleLoadModule: TODO: CELL_SYSMODULE_LIBATRAC3MULTI");
|
||||||
|
}
|
||||||
cellSysmodule.Warning("cellSysmoduleLoadModule(%s)", wxString(getModuleName(id)).wx_str());
|
cellSysmodule.Warning("cellSysmoduleLoadModule(%s)", wxString(getModuleName(id)).wx_str());
|
||||||
Module* m = GetModuleById(id);
|
Module* m = GetModuleById(id);
|
||||||
|
|
||||||
|
@ -23,17 +23,18 @@ public:
|
|||||||
if (sortOrder == CELL_SAVEDATA_SORTORDER_DESCENT)
|
if (sortOrder == CELL_SAVEDATA_SORTORDER_DESCENT)
|
||||||
{
|
{
|
||||||
if (sortType == CELL_SAVEDATA_SORTTYPE_MODIFIEDTIME)
|
if (sortType == CELL_SAVEDATA_SORTTYPE_MODIFIEDTIME)
|
||||||
return entry1.timestamp >= entry2.timestamp;
|
return entry1.st_mtime_ >= entry2.st_mtime_;
|
||||||
else //if (sortType == CELL_SAVEDATA_SORTTYPE_SUBTITLE)
|
if (sortType == CELL_SAVEDATA_SORTTYPE_SUBTITLE)
|
||||||
return entry1.subtitle >= entry2.subtitle;
|
return entry1.subtitle >= entry2.subtitle;
|
||||||
}
|
}
|
||||||
else //if (sortOrder == CELL_SAVEDATA_SORTORDER_ASCENT)
|
if (sortOrder == CELL_SAVEDATA_SORTORDER_ASCENT)
|
||||||
{
|
{
|
||||||
if (sortType == CELL_SAVEDATA_SORTTYPE_MODIFIEDTIME)
|
if (sortType == CELL_SAVEDATA_SORTTYPE_MODIFIEDTIME)
|
||||||
return entry1.timestamp < entry2.timestamp;
|
return entry1.st_mtime_ < entry2.st_mtime_;
|
||||||
else //if (sortType == CELL_SAVEDATA_SORTTYPE_SUBTITLE)
|
if (sortType == CELL_SAVEDATA_SORTTYPE_SUBTITLE)
|
||||||
return entry1.subtitle < entry2.subtitle;
|
return entry1.subtitle < entry2.subtitle;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -55,7 +56,7 @@ u64 getSaveDataSize(const std::string& dirName)
|
|||||||
return totalSize;
|
return totalSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void getSaveDataEntry(std::vector<SaveDataListEntry>& saveEntries, const std::string& saveDir)
|
void addSaveDataEntry(std::vector<SaveDataListEntry>& saveEntries, const std::string& saveDir)
|
||||||
{
|
{
|
||||||
// PSF parameters
|
// PSF parameters
|
||||||
vfsFile f(saveDir + "/PARAM.SFO");
|
vfsFile f(saveDir + "/PARAM.SFO");
|
||||||
@ -75,12 +76,56 @@ void getSaveDataEntry(std::vector<SaveDataListEntry>& saveEntries, const std::st
|
|||||||
saveEntry.subtitle = psf.GetString("SUB_TITLE");
|
saveEntry.subtitle = psf.GetString("SUB_TITLE");
|
||||||
saveEntry.details = psf.GetString("DETAIL");
|
saveEntry.details = psf.GetString("DETAIL");
|
||||||
saveEntry.sizeKb = getSaveDataSize(saveDir)/1024;
|
saveEntry.sizeKb = getSaveDataSize(saveDir)/1024;
|
||||||
saveEntry.timestamp = 0; // TODO
|
saveEntry.st_atime_ = 0; // TODO
|
||||||
saveEntry.iconBuffer = stbi_load(localPath.mb_str(), &width, &height, &actual_components, 3);
|
saveEntry.st_mtime_ = 0; // TODO
|
||||||
|
saveEntry.st_ctime_ = 0; // TODO
|
||||||
|
saveEntry.iconBuf = stbi_load(localPath.mb_str(), &width, &height, &actual_components, 3);
|
||||||
|
saveEntry.iconBufSize = width * height * 3;
|
||||||
|
saveEntry.isNew = false;
|
||||||
|
|
||||||
saveEntries.push_back(saveEntry);
|
saveEntries.push_back(saveEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addNewSaveDataEntry(std::vector<SaveDataListEntry>& saveEntries, mem_ptr_t<CellSaveDataListNewData> newData)
|
||||||
|
{
|
||||||
|
SaveDataListEntry saveEntry;
|
||||||
|
saveEntry.dirName = (char*)Memory.VirtualToRealAddr(newData->dirName_addr);
|
||||||
|
saveEntry.title = (char*)Memory.VirtualToRealAddr(newData->icon->title_addr);
|
||||||
|
saveEntry.subtitle = (char*)Memory.VirtualToRealAddr(newData->icon->title_addr);
|
||||||
|
saveEntry.iconBuf = Memory.VirtualToRealAddr(newData->icon->iconBuf_addr);
|
||||||
|
saveEntry.iconBufSize = newData->icon->iconBufSize;
|
||||||
|
saveEntry.isNew = true;
|
||||||
|
// TODO: Add information stored in newData->iconPosition. (It's not very relevant)
|
||||||
|
|
||||||
|
saveEntries.push_back(saveEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 focusSaveDataEntry(const std::vector<SaveDataListEntry>& saveEntries, u32 focusPosition)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSaveDataEntries(std::vector<SaveDataListEntry>& saveEntries, mem_ptr_t<CellSaveDataDirList> fixedList, u32 fixedListNum)
|
||||||
|
{
|
||||||
|
std::vector<SaveDataListEntry>::iterator entry = saveEntries.begin();
|
||||||
|
while (entry != saveEntries.end())
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
for (u32 j=0; j<fixedListNum; j++)
|
||||||
|
{
|
||||||
|
if (entry->dirName == (char*)fixedList[j].dirName)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
entry = saveEntries.erase(entry);
|
||||||
|
else
|
||||||
|
entry++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
int cellSaveDataListSave2(u32 version, mem_ptr_t<CellSaveDataSetList> setList, mem_ptr_t<CellSaveDataSetBuf> setBuf,
|
int cellSaveDataListSave2(u32 version, mem_ptr_t<CellSaveDataSetList> setList, mem_ptr_t<CellSaveDataSetBuf> setBuf,
|
||||||
@ -95,7 +140,7 @@ int cellSaveDataListSave2(u32 version, mem_ptr_t<CellSaveDataSetList> setList, m
|
|||||||
|
|
||||||
MemoryAllocator<CellSaveDataCBResult> result;
|
MemoryAllocator<CellSaveDataCBResult> result;
|
||||||
MemoryAllocator<CellSaveDataListGet> listGet;
|
MemoryAllocator<CellSaveDataListGet> listGet;
|
||||||
MemoryAllocator<CellSaveDataListGet> listSet;
|
MemoryAllocator<CellSaveDataListSet> listSet;
|
||||||
|
|
||||||
std::string saveBaseDir = "/dev_hdd0/home/00000001/savedata/"; // TODO: Get the path of the current user
|
std::string saveBaseDir = "/dev_hdd0/home/00000001/savedata/"; // TODO: Get the path of the current user
|
||||||
vfsDir dir(saveBaseDir);
|
vfsDir dir(saveBaseDir);
|
||||||
@ -115,14 +160,14 @@ int cellSaveDataListSave2(u32 version, mem_ptr_t<CellSaveDataSetList> setList, m
|
|||||||
listGet->dirNum++;
|
listGet->dirNum++;
|
||||||
|
|
||||||
std::string saveDir = saveBaseDir + (const char*)(entry->name.mb_str());
|
std::string saveDir = saveBaseDir + (const char*)(entry->name.mb_str());
|
||||||
getSaveDataEntry(saveEntries, saveDir);
|
addSaveDataEntry(saveEntries, saveDir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort the entries and fill the listGet->dirList array
|
// Sort the entries and fill the listGet->dirList array
|
||||||
std::sort(saveEntries.begin(), saveEntries.end(), sortSaveDataEntry(setList->sortType, setList->sortOrder));
|
std::sort(saveEntries.begin(), saveEntries.end(), sortSaveDataEntry(setList->sortType, setList->sortOrder));
|
||||||
listGet->dirList_addr = setBuf->buf_addr;
|
listGet->dirList.SetAddr(setBuf->buf_addr);
|
||||||
CellSaveDataDirList* dirList = (CellSaveDataDirList*)Memory.VirtualToRealAddr(listGet->dirList_addr);
|
CellSaveDataDirList* dirList = (CellSaveDataDirList*)Memory.VirtualToRealAddr(listGet->dirList.GetAddr());
|
||||||
for (u32 i=0; i<saveEntries.size(); i++) {
|
for (u32 i=0; i<saveEntries.size(); i++) {
|
||||||
memcpy(dirList[i].dirName, saveEntries[i].dirName.c_str(), CELL_SAVEDATA_DIRNAME_SIZE);
|
memcpy(dirList[i].dirName, saveEntries[i].dirName.c_str(), CELL_SAVEDATA_DIRNAME_SIZE);
|
||||||
memcpy(dirList[i].listParam, saveEntries[i].listParam.c_str(), CELL_SAVEDATA_SYSP_LPARAM_SIZE);
|
memcpy(dirList[i].listParam, saveEntries[i].listParam.c_str(), CELL_SAVEDATA_SYSP_LPARAM_SIZE);
|
||||||
@ -139,8 +184,8 @@ int cellSaveDataListSave2(u32 version, mem_ptr_t<CellSaveDataSetList> setList, m
|
|||||||
funcFile(result.GetAddr(), fileGet.GetAddr(), fileSet.GetAddr());
|
funcFile(result.GetAddr(), fileGet.GetAddr(), fileSet.GetAddr());
|
||||||
|
|
||||||
for (auto& entry : saveEntries) {
|
for (auto& entry : saveEntries) {
|
||||||
delete[] entry.iconBuffer;
|
delete[] entry.iconBuf;
|
||||||
entry.iconBuffer = nullptr;
|
entry.iconBuf = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CELL_SAVEDATA_RET_OK;
|
return CELL_SAVEDATA_RET_OK;
|
||||||
@ -158,7 +203,7 @@ int cellSaveDataListLoad2(u32 version, mem_ptr_t<CellSaveDataSetList> setList, m
|
|||||||
|
|
||||||
MemoryAllocator<CellSaveDataCBResult> result;
|
MemoryAllocator<CellSaveDataCBResult> result;
|
||||||
MemoryAllocator<CellSaveDataListGet> listGet;
|
MemoryAllocator<CellSaveDataListGet> listGet;
|
||||||
MemoryAllocator<CellSaveDataListGet> listSet;
|
MemoryAllocator<CellSaveDataListSet> listSet;
|
||||||
|
|
||||||
std::string saveBaseDir = "/dev_hdd0/home/00000001/savedata/"; // TODO: Get the path of the current user
|
std::string saveBaseDir = "/dev_hdd0/home/00000001/savedata/"; // TODO: Get the path of the current user
|
||||||
vfsDir dir(saveBaseDir);
|
vfsDir dir(saveBaseDir);
|
||||||
@ -178,23 +223,42 @@ int cellSaveDataListLoad2(u32 version, mem_ptr_t<CellSaveDataSetList> setList, m
|
|||||||
listGet->dirNum++;
|
listGet->dirNum++;
|
||||||
|
|
||||||
std::string saveDir = saveBaseDir + (const char*)(entry->name.mb_str());
|
std::string saveDir = saveBaseDir + (const char*)(entry->name.mb_str());
|
||||||
getSaveDataEntry(saveEntries, saveDir);
|
addSaveDataEntry(saveEntries, saveDir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort the entries and fill the listGet->dirList array
|
// Sort the entries and fill the listGet->dirList array
|
||||||
std::sort(saveEntries.begin(), saveEntries.end(), sortSaveDataEntry(setList->sortType, setList->sortOrder));
|
std::sort(saveEntries.begin(), saveEntries.end(), sortSaveDataEntry(setList->sortType, setList->sortOrder));
|
||||||
listGet->dirList_addr = setBuf->buf_addr;
|
listGet->dirList.SetAddr(setBuf->buf_addr);
|
||||||
CellSaveDataDirList* dirList = (CellSaveDataDirList*)Memory.VirtualToRealAddr(listGet->dirList_addr);
|
CellSaveDataDirList* dirList = (CellSaveDataDirList*)Memory.VirtualToRealAddr(listGet->dirList.GetAddr());
|
||||||
for (u32 i=0; i<saveEntries.size(); i++) {
|
for (u32 i=0; i<saveEntries.size(); i++) {
|
||||||
memcpy(dirList[i].dirName, saveEntries[i].dirName.c_str(), CELL_SAVEDATA_DIRNAME_SIZE);
|
memcpy(dirList[i].dirName, saveEntries[i].dirName.c_str(), CELL_SAVEDATA_DIRNAME_SIZE);
|
||||||
memcpy(dirList[i].listParam, saveEntries[i].listParam.c_str(), CELL_SAVEDATA_SYSP_LPARAM_SIZE);
|
memcpy(dirList[i].listParam, saveEntries[i].listParam.c_str(), CELL_SAVEDATA_SYSP_LPARAM_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
funcList(result.GetAddr(), listGet.GetAddr(), listSet.GetAddr());
|
funcList(result.GetAddr(), listGet.GetAddr(), listSet.GetAddr());
|
||||||
|
|
||||||
|
if (result->result < 0) {
|
||||||
|
ConLog.Error("cellSaveDataListLoad2: CellSaveDataListCallback failed."); // TODO: Once we verify that the entire SysCall is working, delete this debug error message.
|
||||||
|
return CELL_SAVEDATA_ERROR_CBRESULT;
|
||||||
|
}
|
||||||
|
if (!listSet->fixedList.IsGood()) {
|
||||||
|
return CELL_SAVEDATA_ERROR_PARAM;
|
||||||
|
}
|
||||||
|
setSaveDataEntries(saveEntries, (u32)listSet->fixedList.GetAddr(), listSet->fixedListNum);
|
||||||
|
u32 focusIndex = focusSaveDataEntry(saveEntries, listSet->focusPosition);
|
||||||
|
|
||||||
MemoryAllocator<CellSaveDataStatGet> statGet;
|
MemoryAllocator<CellSaveDataStatGet> statGet;
|
||||||
MemoryAllocator<CellSaveDataStatSet> statSet;
|
MemoryAllocator<CellSaveDataStatSet> statSet;
|
||||||
|
|
||||||
|
// TODO: Display the dialog here
|
||||||
|
ConLog.Warning("cellSaveDataListLoad2:");
|
||||||
|
|
||||||
|
statGet->isNewData = CELL_SAVEDATA_ISNEWDATA_NO; // You can *never* load new data
|
||||||
|
//statGet->dir =
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
funcStat(result.GetAddr(), statGet.GetAddr(), statSet.GetAddr());
|
funcStat(result.GetAddr(), statGet.GetAddr(), statSet.GetAddr());
|
||||||
|
|
||||||
MemoryAllocator<CellSaveDataFileGet> fileGet;
|
MemoryAllocator<CellSaveDataFileGet> fileGet;
|
||||||
@ -202,8 +266,8 @@ int cellSaveDataListLoad2(u32 version, mem_ptr_t<CellSaveDataSetList> setList, m
|
|||||||
funcFile(result.GetAddr(), fileGet.GetAddr(), fileSet.GetAddr());
|
funcFile(result.GetAddr(), fileGet.GetAddr(), fileSet.GetAddr());
|
||||||
|
|
||||||
for (auto& entry : saveEntries) {
|
for (auto& entry : saveEntries) {
|
||||||
delete[] entry.iconBuffer;
|
delete[] entry.iconBuf;
|
||||||
entry.iconBuffer = nullptr;
|
entry.iconBuf = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CELL_SAVEDATA_RET_OK;
|
return CELL_SAVEDATA_RET_OK;
|
||||||
|
@ -19,6 +19,19 @@ enum
|
|||||||
CELL_SAVEDATA_ERROR_NOTSUPPORTED = 0x8002b40c,
|
CELL_SAVEDATA_ERROR_NOTSUPPORTED = 0x8002b40c,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Callback return codes
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CELL_SAVEDATA_CBRESULT_OK_LAST_NOCONFIRM = 2,
|
||||||
|
CELL_SAVEDATA_CBRESULT_OK_LAST = 1,
|
||||||
|
CELL_SAVEDATA_CBRESULT_OK_NEXT = 0,
|
||||||
|
CELL_SAVEDATA_CBRESULT_ERR_NOSPACE = -1,
|
||||||
|
CELL_SAVEDATA_CBRESULT_ERR_FAILURE = -2,
|
||||||
|
CELL_SAVEDATA_CBRESULT_ERR_BROKEN = -3,
|
||||||
|
CELL_SAVEDATA_CBRESULT_ERR_NODATA = -4,
|
||||||
|
CELL_SAVEDATA_CBRESULT_ERR_INVALID = -5,
|
||||||
|
};
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@ -46,6 +59,18 @@ enum
|
|||||||
// CellSaveDataSortOrder
|
// CellSaveDataSortOrder
|
||||||
CELL_SAVEDATA_SORTORDER_DESCENT = 0,
|
CELL_SAVEDATA_SORTORDER_DESCENT = 0,
|
||||||
CELL_SAVEDATA_SORTORDER_ASCENT = 1,
|
CELL_SAVEDATA_SORTORDER_ASCENT = 1,
|
||||||
|
|
||||||
|
// CellSaveDataIsNewData
|
||||||
|
CELL_SAVEDATA_ISNEWDATA_NO = 0,
|
||||||
|
CELL_SAVEDATA_ISNEWDATA_YES = 1,
|
||||||
|
|
||||||
|
// CellSaveDataFocusPosition
|
||||||
|
CELL_SAVEDATA_FOCUSPOS_DIRNAME = 0,
|
||||||
|
CELL_SAVEDATA_FOCUSPOS_LISTHEAD = 1,
|
||||||
|
CELL_SAVEDATA_FOCUSPOS_LISTTAIL = 2,
|
||||||
|
CELL_SAVEDATA_FOCUSPOS_LATEST = 3,
|
||||||
|
CELL_SAVEDATA_FOCUSPOS_OLDEST = 4,
|
||||||
|
CELL_SAVEDATA_FOCUSPOS_NEWDATA = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -77,7 +102,7 @@ struct CellSaveDataListNewData
|
|||||||
{
|
{
|
||||||
be_t<u32> iconPosition;
|
be_t<u32> iconPosition;
|
||||||
be_t<u32> dirName_addr; // char*
|
be_t<u32> dirName_addr; // char*
|
||||||
be_t<u32> icon_addr; // CellSaveDataNewDataIcon*
|
mem_beptr_t<CellSaveDataNewDataIcon> icon;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellSaveDataDirList
|
struct CellSaveDataDirList
|
||||||
@ -90,7 +115,7 @@ struct CellSaveDataListGet
|
|||||||
{
|
{
|
||||||
be_t<u32> dirNum;
|
be_t<u32> dirNum;
|
||||||
be_t<u32> dirListNum;
|
be_t<u32> dirListNum;
|
||||||
be_t<u32> dirList_addr; // CellSaveDataDirList*
|
mem_beptr_t<CellSaveDataDirList> dirList;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellSaveDataListSet
|
struct CellSaveDataListSet
|
||||||
@ -98,14 +123,15 @@ struct CellSaveDataListSet
|
|||||||
be_t<u32> focusPosition;
|
be_t<u32> focusPosition;
|
||||||
be_t<u32> focusDirName_addr; // char*
|
be_t<u32> focusDirName_addr; // char*
|
||||||
be_t<u32> fixedListNum;
|
be_t<u32> fixedListNum;
|
||||||
be_t<u32> fixedList_addr; // CellSaveDataDirList*
|
mem_beptr_t<CellSaveDataDirList> fixedList;
|
||||||
be_t<u32> newData_addr; // CellSaveDataListNewData*
|
mem_beptr_t<CellSaveDataListNewData> newData;
|
||||||
|
be_t<u32> reserved_addr; // void*
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellSaveDataFixedSet
|
struct CellSaveDataFixedSet
|
||||||
{
|
{
|
||||||
be_t<u32> dirName_addr; // char*
|
be_t<u32> dirName_addr; // char*
|
||||||
be_t<u32> newIcon_addr; // CellSaveDataNewDataIcon*
|
mem_beptr_t<CellSaveDataNewDataIcon> newIcon;
|
||||||
be_t<u32> option;
|
be_t<u32> option;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -151,7 +177,7 @@ struct CellSaveDataStatGet
|
|||||||
be_t<s32> sysSizeKB;
|
be_t<s32> sysSizeKB;
|
||||||
be_t<u32> fileNum;
|
be_t<u32> fileNum;
|
||||||
be_t<u32> fileListNum;
|
be_t<u32> fileListNum;
|
||||||
be_t<u32> fileList_addr; // CellSaveDataFileStat*
|
mem_beptr_t<CellSaveDataFileStat> fileList;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellSaveDataAutoIndicator
|
struct CellSaveDataAutoIndicator
|
||||||
@ -165,9 +191,9 @@ struct CellSaveDataAutoIndicator
|
|||||||
|
|
||||||
struct CellSaveDataStatSet
|
struct CellSaveDataStatSet
|
||||||
{
|
{
|
||||||
be_t<u32> setParam_addr; // CellSaveDataSystemFileParam*
|
mem_beptr_t<CellSaveDataSystemFileParam> setParam;
|
||||||
be_t<u32> reCreateMode;
|
be_t<u32> reCreateMode;
|
||||||
be_t<u32> indicator_addr; // CellSaveDataAutoIndicator*
|
mem_beptr_t<CellSaveDataAutoIndicator> indicator;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellSaveDataFileGet
|
struct CellSaveDataFileGet
|
||||||
@ -223,8 +249,12 @@ struct SaveDataListEntry
|
|||||||
std::string subtitle;
|
std::string subtitle;
|
||||||
std::string details;
|
std::string details;
|
||||||
u32 sizeKb;
|
u32 sizeKb;
|
||||||
u64 timestamp;
|
s64 st_atime_;
|
||||||
void* iconBuffer;
|
s64 st_mtime_;
|
||||||
|
s64 st_ctime_;
|
||||||
|
void* iconBuf;
|
||||||
|
u32 iconBufSize;
|
||||||
|
bool isNew;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,9 +67,6 @@ next:
|
|||||||
vdec.reader.addr = vdec.task.addr;
|
vdec.reader.addr = vdec.task.addr;
|
||||||
vdec.reader.size = vdec.task.size;
|
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);
|
//ConLog.Write("Video AU: size = 0x%x, pts = 0x%llx, dts = 0x%llx", vdec.task.size, vdec.task.pts, 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;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -208,12 +205,11 @@ u32 vdecOpen(VideoDecoder* data)
|
|||||||
vdec.reader.size = task.size;
|
vdec.reader.size = task.size;
|
||||||
//ConLog.Write("Video AU: size = 0x%x, pts = 0x%llx, dts = 0x%llx", task.size, task.pts, task.dts);
|
//ConLog.Write("Video AU: size = 0x%x, pts = 0x%llx, dts = 0x%llx", task.size, task.pts, 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)
|
if (vdec.just_started)
|
||||||
{
|
{
|
||||||
|
vdec.first_pts = task.pts;
|
||||||
vdec.last_pts = task.pts;
|
vdec.last_pts = task.pts;
|
||||||
vdec.last_dts = task.dts;
|
vdec.first_dts = task.dts;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AVPacketHolder : AVPacket
|
struct AVPacketHolder : AVPacket
|
||||||
@ -357,8 +353,20 @@ u32 vdecOpen(VideoDecoder* data)
|
|||||||
|
|
||||||
if (got_picture)
|
if (got_picture)
|
||||||
{
|
{
|
||||||
frame.dts = vdec.last_dts; vdec.last_dts += 3003; // + duration???
|
u64 ts = av_frame_get_best_effort_timestamp(frame.data);
|
||||||
frame.pts = vdec.last_pts; vdec.last_pts += 3003;
|
if (ts != AV_NOPTS_VALUE)
|
||||||
|
{
|
||||||
|
frame.pts = ts/* - vdec.first_pts*/; // ???
|
||||||
|
vdec.last_pts = frame.pts;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vdec.last_pts += vdec.ctx->time_base.num * 90000 / (vdec.ctx->time_base.den / vdec.ctx->ticks_per_frame);
|
||||||
|
frame.pts = vdec.last_pts;
|
||||||
|
}
|
||||||
|
//frame.pts = vdec.last_pts;
|
||||||
|
//vdec.last_pts += 3754;
|
||||||
|
frame.dts = (frame.pts - vdec.first_pts) + vdec.first_dts;
|
||||||
frame.userdata = task.userData;
|
frame.userdata = task.userData;
|
||||||
|
|
||||||
//ConLog.Write("got picture (pts=0x%llx, dts=0x%llx)", frame.pts, frame.dts);
|
//ConLog.Write("got picture (pts=0x%llx, dts=0x%llx)", frame.pts, frame.dts);
|
||||||
@ -726,7 +734,27 @@ int cellVdecGetPicItem(u32 handle, mem32_t picItem_ptr)
|
|||||||
avc->transfer_characteristics = CELL_VDEC_AVC_TC_ITU_R_BT_709_5;
|
avc->transfer_characteristics = CELL_VDEC_AVC_TC_ITU_R_BT_709_5;
|
||||||
avc->matrix_coefficients = CELL_VDEC_AVC_MXC_ITU_R_BT_709_5; // important
|
avc->matrix_coefficients = CELL_VDEC_AVC_MXC_ITU_R_BT_709_5; // important
|
||||||
avc->timing_info_present_flag = true;
|
avc->timing_info_present_flag = true;
|
||||||
avc->frameRateCode = CELL_VDEC_AVC_FRC_30000DIV1001; // important (!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)
|
if (vdec->ctx->time_base.num == 1001)
|
||||||
|
{
|
||||||
|
if (vdec->ctx->time_base.den == 48000 && vdec->ctx->ticks_per_frame == 2)
|
||||||
|
{
|
||||||
|
avc->frameRateCode = CELL_VDEC_AVC_FRC_24000DIV1001;
|
||||||
|
}
|
||||||
|
else if (vdec->ctx->time_base.den == 60000 && vdec->ctx->ticks_per_frame == 2)
|
||||||
|
{
|
||||||
|
avc->frameRateCode = CELL_VDEC_AVC_FRC_30000DIV1001;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ConLog.Error("cellVdecGetPicItem: unsupported time_base.den (%d)", vdec->ctx->time_base.den);
|
||||||
|
Emu.Pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ConLog.Error("cellVdecGetPicItem: unsupported time_base.num (%d)", vdec->ctx->time_base.num);
|
||||||
|
Emu.Pause();
|
||||||
|
}
|
||||||
avc->fixed_frame_rate_flag = true;
|
avc->fixed_frame_rate_flag = true;
|
||||||
avc->low_delay_hrd_flag = true; // ???
|
avc->low_delay_hrd_flag = true; // ???
|
||||||
avc->entropy_coding_mode_flag = true; // ???
|
avc->entropy_coding_mode_flag = true; // ???
|
||||||
|
@ -719,7 +719,8 @@ public:
|
|||||||
u32 memBias;
|
u32 memBias;
|
||||||
|
|
||||||
VdecTask task; // current task variable
|
VdecTask task; // current task variable
|
||||||
u64 last_pts, last_dts;
|
u64 last_pts, first_pts, first_dts;
|
||||||
|
AVRational rfr, afr;
|
||||||
|
|
||||||
CPUThread* vdecCb;
|
CPUThread* vdecCb;
|
||||||
|
|
||||||
|
@ -1,15 +1,103 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "Emu/SysCalls/SysCalls.h"
|
#include "Emu/SysCalls/SysCalls.h"
|
||||||
#include "Emu/SysCalls/SC_FUNC.h"
|
#include "Emu/SysCalls/SC_FUNC.h"
|
||||||
|
#include "Emu/Audio/cellAudio.h"
|
||||||
#include "libmixer.h"
|
#include "libmixer.h"
|
||||||
|
|
||||||
void libmixer_init();
|
void libmixer_init();
|
||||||
Module libmixer("libmixer", libmixer_init);
|
Module libmixer("libmixer", libmixer_init);
|
||||||
|
|
||||||
int cellAANAddData(u32 handle, u32 port, u32 offset, u32 addr, u32 samples)
|
CellSurMixerConfig surMixer;
|
||||||
|
|
||||||
|
#define SUR_PORT (7)
|
||||||
|
u32 surMixerCb = 0;
|
||||||
|
u32 surMixerCbArg = 0;
|
||||||
|
SMutex mixer_mutex;
|
||||||
|
float mixdata[8*256];
|
||||||
|
u64 mixcount = 0;
|
||||||
|
|
||||||
|
int cellAANAddData(u32 aan_handle, u32 aan_port, u32 offset, u32 addr, u32 samples)
|
||||||
{
|
{
|
||||||
libmixer.Error("cellAANAddData(handle=0x%x, port=0x%x, offset=0x%x, addr=0x%x, samples=0x%x)",
|
u32 ch = aan_port >> 16;
|
||||||
handle, port, offset, addr, samples);
|
u32 port = aan_port & 0xffff;
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
if (port >= surMixer.chStrips1) ch = 0; break;
|
||||||
|
case 2:
|
||||||
|
if (port >= surMixer.chStrips2) ch = 0; break;
|
||||||
|
case 6:
|
||||||
|
/*if (port >= surMixer.chStrips6)*/ ch = 0; break;
|
||||||
|
case 8:
|
||||||
|
if (port >= surMixer.chStrips8) ch = 0; break;
|
||||||
|
default:
|
||||||
|
ch = 0; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aan_handle == 0x11111111 && samples == 256 && ch && offset == 0)
|
||||||
|
{
|
||||||
|
libmixer.Log("cellAANAddData(handle=0x%x, port=0x%x, offset=0x%x, addr=0x%x, samples=0x%x)",
|
||||||
|
aan_handle, aan_port, offset, addr, samples);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
libmixer.Error("cellAANAddData(handle=0x%x, port=0x%x, offset=0x%x, addr=0x%x, samples=0x%x)",
|
||||||
|
aan_handle, aan_port, offset, addr, samples);
|
||||||
|
Emu.Pause();
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SMutexLocker lock(mixer_mutex);
|
||||||
|
|
||||||
|
if (ch == 1)
|
||||||
|
{
|
||||||
|
// mono upmixing
|
||||||
|
for (u32 i = 0; i < samples; i++)
|
||||||
|
{
|
||||||
|
const float center = *(be_t<float>*)&Memory[addr + i * sizeof(float)];
|
||||||
|
mixdata[i*8+0] += center;
|
||||||
|
mixdata[i*8+1] += center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ch == 2)
|
||||||
|
{
|
||||||
|
// stereo upmixing
|
||||||
|
for (u32 i = 0; i < samples; i++)
|
||||||
|
{
|
||||||
|
const float left = *(be_t<float>*)&Memory[addr + i * 2 * sizeof(float)];
|
||||||
|
const float right = *(be_t<float>*)&Memory[addr + (i * 2 + 1) * sizeof(float)];
|
||||||
|
mixdata[i*8+0] += left;
|
||||||
|
mixdata[i*8+1] += right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ch == 6)
|
||||||
|
{
|
||||||
|
// 5.1 upmixing
|
||||||
|
for (u32 i = 0; i < samples; i++)
|
||||||
|
{
|
||||||
|
const float left = *(be_t<float>*)&Memory[addr + i * 6 * sizeof(float)];
|
||||||
|
const float right = *(be_t<float>*)&Memory[addr + (i * 6 + 1) * sizeof(float)];
|
||||||
|
const float center = *(be_t<float>*)&Memory[addr + (i * 6 + 2) * sizeof(float)];
|
||||||
|
const float low_freq = *(be_t<float>*)&Memory[addr + (i * 6 + 3) * sizeof(float)];
|
||||||
|
const float rear_left = *(be_t<float>*)&Memory[addr + (i * 6 + 4) * sizeof(float)];
|
||||||
|
const float rear_right = *(be_t<float>*)&Memory[addr + (i * 6 + 5) * sizeof(float)];
|
||||||
|
mixdata[i*8+0] += left;
|
||||||
|
mixdata[i*8+1] += right;
|
||||||
|
mixdata[i*8+2] += center;
|
||||||
|
mixdata[i*8+3] += low_freq;
|
||||||
|
mixdata[i*8+4] += rear_left;
|
||||||
|
mixdata[i*8+5] += rear_right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ch == 8)
|
||||||
|
{
|
||||||
|
// 7.1
|
||||||
|
for (u32 i = 0; i < samples * 8; i++)
|
||||||
|
{
|
||||||
|
mixdata[i] += *(be_t<float>*)&Memory[addr + i * sizeof(float)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,37 +159,117 @@ s32 cellSSPlayerGetState() //CellAANHandle handle
|
|||||||
|
|
||||||
int cellSurMixerCreate(const mem_ptr_t<CellSurMixerConfig> config)
|
int cellSurMixerCreate(const mem_ptr_t<CellSurMixerConfig> config)
|
||||||
{
|
{
|
||||||
libmixer.Error("cellSurMixerCreate(config_addr=0x%x)", config.GetAddr());
|
libmixer.Warning("cellSurMixerCreate(config_addr=0x%x)", config.GetAddr());
|
||||||
|
surMixer = *config;
|
||||||
|
libmixer.Warning("*** surMixer created (ch1=%d, ch2=%d, ch6=%d, ch8=%d)",
|
||||||
|
(u32)surMixer.chStrips1, (u32)surMixer.chStrips2, (u32)surMixer.chStrips6, (u32)surMixer.chStrips8);
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellSurMixerGetAANHandle(mem32_t handle)
|
int cellSurMixerGetAANHandle(mem32_t handle)
|
||||||
{
|
{
|
||||||
libmixer.Error("cellSurMixerGetAANHandle(handle_addr=0x%x)", handle.GetAddr());
|
libmixer.Warning("cellSurMixerGetAANHandle(handle_addr=0x%x) -> 0x11111111", handle.GetAddr());
|
||||||
|
handle = 0x11111111;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellSurMixerChStripGetAANPortNo(mem32_t port, u32 type, u32 index)
|
int cellSurMixerChStripGetAANPortNo(mem32_t port, u32 type, u32 index)
|
||||||
{
|
{
|
||||||
libmixer.Error("cellSurMixerChStripGetAANPortNo(port_addr=0x%x, type=0x%x, index=0x%x)", port.GetAddr(), type, index);
|
libmixer.Warning("cellSurMixerChStripGetAANPortNo(port_addr=0x%x, type=0x%x, index=0x%x) -> 0x%x", port.GetAddr(), type, index, (type << 16) | index);
|
||||||
|
port = (type << 16) | index;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellSurMixerSetNotifyCallback(u32 func, u32 arg)
|
int cellSurMixerSetNotifyCallback(u32 func, u32 arg)
|
||||||
{
|
{
|
||||||
libmixer.Error("cellSurMixerSetNotifyCallback(func_addr=0x%x, arg=0x%x)", func, arg);
|
libmixer.Warning("cellSurMixerSetNotifyCallback(func_addr=0x%x, arg=0x%x) (surMixerCb=0x%x)", func, arg, surMixerCb);
|
||||||
|
surMixerCb = func;
|
||||||
|
surMixerCbArg = arg;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellSurMixerRemoveNotifyCallback(u32 func)
|
int cellSurMixerRemoveNotifyCallback(u32 func)
|
||||||
{
|
{
|
||||||
libmixer.Error("cellSurMixerSetNotifyCallback(func_addr=0x%x)", func);
|
libmixer.Warning("cellSurMixerSetNotifyCallback(func_addr=0x%x) (surMixerCb=0x%x)", func, surMixerCb);
|
||||||
|
surMixerCb = 0;
|
||||||
|
surMixerCbArg = 0;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellSurMixerStart()
|
int cellSurMixerStart()
|
||||||
{
|
{
|
||||||
libmixer.Error("cellSurMixerStart()");
|
libmixer.Warning("cellSurMixerStart()");
|
||||||
|
|
||||||
|
AudioPortConfig& port = m_config.m_ports[SUR_PORT];
|
||||||
|
|
||||||
|
if (port.m_is_audio_port_opened)
|
||||||
|
{
|
||||||
|
return CELL_LIBMIXER_ERROR_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
port.channel = 8;
|
||||||
|
port.block = 16;
|
||||||
|
port.attr = 0;
|
||||||
|
port.level = 1.0f;
|
||||||
|
|
||||||
|
libmixer.Warning("*** audio port opened(default)");
|
||||||
|
|
||||||
|
port.m_is_audio_port_opened = true;
|
||||||
|
port.tag = 0;
|
||||||
|
m_config.m_port_in_use++;
|
||||||
|
port.m_is_audio_port_started = true;
|
||||||
|
|
||||||
|
thread t("Surmixer Thread", []()
|
||||||
|
{
|
||||||
|
AudioPortConfig& port = m_config.m_ports[SUR_PORT];
|
||||||
|
|
||||||
|
CPUThread* mixerCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU);
|
||||||
|
|
||||||
|
mixerCb->SetName("Surmixer Callback");
|
||||||
|
|
||||||
|
mixcount = 0;
|
||||||
|
|
||||||
|
while (port.m_is_audio_port_started)
|
||||||
|
{
|
||||||
|
if (Emu.IsStopped())
|
||||||
|
{
|
||||||
|
ConLog.Warning("Surmixer aborted");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mixcount > (port.tag + 15)) // preemptive buffer filling (probably hack)
|
||||||
|
{
|
||||||
|
Sleep(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 stamp0 = get_system_time();
|
||||||
|
|
||||||
|
memset(mixdata, 0, sizeof(mixdata));
|
||||||
|
mixerCb->ExecAsCallback(surMixerCb, true, surMixerCbArg, mixcount, 256);
|
||||||
|
|
||||||
|
u64 stamp1 = get_system_time();
|
||||||
|
|
||||||
|
auto buf = (be_t<float>*)&Memory[m_config.m_buffer + (128 * 1024 * SUR_PORT) + (mixcount % port.block) * port.channel * 256 * sizeof(float)];
|
||||||
|
|
||||||
|
for (u32 i = 0; i < (sizeof(mixdata) / sizeof(float)); i++)
|
||||||
|
{
|
||||||
|
// reverse byte order
|
||||||
|
buf[i] = mixdata[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 stamp2 = get_system_time();
|
||||||
|
|
||||||
|
//ConLog.Write("Libmixer perf: start=%d (cb=%d, finalize=%d)",
|
||||||
|
//stamp0 - m_config.start_time, stamp1-stamp0, stamp2-stamp1);
|
||||||
|
|
||||||
|
mixcount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Emu.GetCPU().RemoveThread(mixerCb->GetId());
|
||||||
|
});
|
||||||
|
t.detach();
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,67 +281,102 @@ int cellSurMixerSetParameter(u32 param, float value)
|
|||||||
|
|
||||||
int cellSurMixerFinalize()
|
int cellSurMixerFinalize()
|
||||||
{
|
{
|
||||||
libmixer.Error("cellSurMixerFinalize()");
|
libmixer.Warning("cellSurMixerFinalize()");
|
||||||
|
|
||||||
|
AudioPortConfig& port = m_config.m_ports[SUR_PORT];
|
||||||
|
|
||||||
|
if (port.m_is_audio_port_opened)
|
||||||
|
{
|
||||||
|
port.m_is_audio_port_started = false;
|
||||||
|
port.m_is_audio_port_opened = false;
|
||||||
|
m_config.m_port_in_use--;
|
||||||
|
}
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*int cellSurMixerSurBusAddData() //u32 busNo, u32 offset, float *addr, u32 samples
|
int cellSurMixerSurBusAddData(u32 busNo, u32 offset, u32 addr, u32 samples)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(libmixer);
|
if (busNo < 8 && samples == 256 && offset == 0)
|
||||||
return 0;
|
{
|
||||||
|
libmixer.Log("cellSurMixerSurBusAddData(busNo=%d, offset=0x%x, addr=0x%x, samples=%d)", busNo, offset, addr, samples);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
libmixer.Error("cellSurMixerSurBusAddData(busNo=%d, offset=0x%x, addr=0x%x, samples=%d)", busNo, offset, addr, samples);
|
||||||
|
Emu.Pause();
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SMutexLocker lock(mixer_mutex);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < samples; i++)
|
||||||
|
{
|
||||||
|
// reverse byte order and mix
|
||||||
|
u32 v = Memory.Read32(addr + i * sizeof(float));
|
||||||
|
mixdata[i*8+busNo] += (float&)v;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellSurMixerChStripSetParameter() //u32 type, u32 index, CellSurMixerChStripParam *param
|
int cellSurMixerChStripSetParameter(u32 type, u32 index, mem_ptr_t<CellSurMixerChStripParam> param)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(libmixer);
|
libmixer.Error("cellSurMixerChStripSetParameter(type=%d, index=%d, param_addr=0x%x)", type, index, param.GetAddr());
|
||||||
return 0;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellSurMixerPause() //u32 switch
|
int cellSurMixerPause(u32 type)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(libmixer);
|
libmixer.Error("cellSurMixerPause(type=%d)", type);
|
||||||
return 0;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellSurMixerGetCurrentBlockTag() //u64 *tag
|
int cellSurMixerGetCurrentBlockTag(mem64_t tag)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(libmixer);
|
libmixer.Error("cellSurMixerGetCurrentBlockTag(tag_addr=0x%x)", tag.GetAddr());
|
||||||
return 0;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellSurMixerGetTimestamp() //u64 tag, u64 *stamp
|
int cellSurMixerGetTimestamp(u64 tag, mem64_t stamp)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(libmixer);
|
libmixer.Error("cellSurMixerGetTimestamp(tag=0x%llx, stamp_addr=0x%x)", tag, stamp.GetAddr());
|
||||||
return 0;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cellSurMixerBeep(); //void *arg
|
void cellSurMixerBeep(u32 arg)
|
||||||
|
|
||||||
float cellSurMixerUtilGetLevelFromDB() //float dB
|
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(libmixer);
|
libmixer.Error("cellSurMixerBeep(arg=%d)", arg);
|
||||||
return CELL_OK; //it's NOT real value
|
return;
|
||||||
//TODO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float cellSurMixerUtilGetLevelFromDBIndex() //int index
|
void cellSurMixerUtilGetLevelFromDB(float dB)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(libmixer);
|
// not hooked, probably unnecessary
|
||||||
return CELL_OK; //it's NOT real value
|
libmixer.Error("cellSurMixerUtilGetLevelFromDB(dB=%f)", dB);
|
||||||
//TODO;
|
declCPU();
|
||||||
|
(float&)CPU.FPR[0] = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
float cellSurMixerUtilNoteToRatio() //unsigned char refNote, unsigned char note
|
void cellSurMixerUtilGetLevelFromDBIndex(int index)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(libmixer);
|
// not hooked, probably unnecessary
|
||||||
return CELL_OK; //it's NOT real value
|
libmixer.Error("cellSurMixerUtilGetLevelFromDBIndex(index=%d)", index);
|
||||||
//TODO
|
declCPU();
|
||||||
}*/
|
(float&)CPU.FPR[0] = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cellSurMixerUtilNoteToRatio(u8 refNote, u8 note)
|
||||||
|
{
|
||||||
|
// not hooked, probably unnecessary
|
||||||
|
libmixer.Error("cellSurMixerUtilNoteToRatio(refNote=%d, note=%d)", refNote, note);
|
||||||
|
declCPU();
|
||||||
|
(float&)CPU.FPR[0] = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
void libmixer_init()
|
void libmixer_init()
|
||||||
{
|
{
|
||||||
static const u64 cellAANAddData_table[] = {
|
static const u64 cellAANAddData_table[] = {
|
||||||
// TODO
|
|
||||||
0xffffffff7c691b78,
|
0xffffffff7c691b78,
|
||||||
0xffffffff7c0802a6,
|
0xffffffff7c0802a6,
|
||||||
0xfffffffff821ff91,
|
0xfffffffff821ff91,
|
||||||
@ -183,6 +386,7 @@ void libmixer_init()
|
|||||||
0xffffffff81690000,
|
0xffffffff81690000,
|
||||||
0xffffffff7c050378,
|
0xffffffff7c050378,
|
||||||
0xffffffff7cc43378,
|
0xffffffff7cc43378,
|
||||||
|
0x78630020, // clrldi r3,r3,32
|
||||||
0xffffffff7d465378,
|
0xffffffff7d465378,
|
||||||
0xffffffff812b0030,
|
0xffffffff812b0030,
|
||||||
0xffffffff80090000,
|
0xffffffff80090000,
|
||||||
@ -198,9 +402,9 @@ void libmixer_init()
|
|||||||
0xffffffff4e800020,
|
0xffffffff4e800020,
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
libmixer.AddFuncSub(cellAANAddData_table, "cellAANAddData", cellAANAddData);
|
libmixer.AddFuncSub("surmxAAN", cellAANAddData_table, "cellAANAddData", cellAANAddData);
|
||||||
|
|
||||||
u64 cellAANConnect_table[39] = {
|
static const u64 cellAANConnect_table[] = {
|
||||||
0xfffffffff821ff71,
|
0xfffffffff821ff71,
|
||||||
0xffffffff7c0802a6,
|
0xffffffff7c0802a6,
|
||||||
0xffffffff2f830000,
|
0xffffffff2f830000,
|
||||||
@ -225,7 +429,7 @@ void libmixer_init()
|
|||||||
0xffffffff90a10070,
|
0xffffffff90a10070,
|
||||||
0xffffffff90c10078,
|
0xffffffff90c10078,
|
||||||
0xffffffff9141007c,
|
0xffffffff9141007c,
|
||||||
0xffffffff812b0018, // [24]
|
0xffffffff812b0018, // difference
|
||||||
0xffffffff90010080,
|
0xffffffff90010080,
|
||||||
0xffffffff80090000,
|
0xffffffff80090000,
|
||||||
0xfffffffff8410028,
|
0xfffffffff8410028,
|
||||||
@ -239,40 +443,52 @@ void libmixer_init()
|
|||||||
0xffffffff38210090,
|
0xffffffff38210090,
|
||||||
0xffffffff7c0803a6,
|
0xffffffff7c0803a6,
|
||||||
0xffffffff4e800020,
|
0xffffffff4e800020,
|
||||||
0, // [38]
|
0,
|
||||||
};
|
};
|
||||||
libmixer.AddFuncSub(cellAANConnect_table, "cellAANConnect", cellAANConnect);
|
libmixer.AddFuncSub("surmxAAN", cellAANConnect_table, "cellAANConnect", cellAANConnect);
|
||||||
cellAANConnect_table[24] = 0xffffffff812b001c;
|
|
||||||
libmixer.AddFuncSub(cellAANConnect_table, "cellAANDisconnect", cellAANDisconnect);
|
|
||||||
|
|
||||||
static const u64 cellAANAddData_table1[] = {
|
static const u64 cellAANDisconnect_table[] = {
|
||||||
// TODO
|
0xfffffffff821ff71,
|
||||||
0xffffffff7c691b78,
|
|
||||||
0xffffffff7c0802a6,
|
0xffffffff7c0802a6,
|
||||||
0xfffffffff821ff91,
|
0xffffffff2f830000,
|
||||||
0xfffffffff8010080,
|
0xfffffffff80100a0,
|
||||||
0xffffffff7c802378,
|
0xffffffff3c008031,
|
||||||
0xffffffff7caa2b78,
|
0xffffffff7c691b78,
|
||||||
|
0xffffffff7c8a2378,
|
||||||
|
0xffffffff60000003,
|
||||||
|
0xffffff00409e0018, // bne
|
||||||
|
0xffffffff7c0307b4,
|
||||||
|
0xffffffffe80100a0,
|
||||||
|
0xffffffff38210090,
|
||||||
|
0xffffffff7c0803a6,
|
||||||
|
0xffffffff4e800020,
|
||||||
|
0xffffffff2f850000,
|
||||||
|
0xffffffff78630020,
|
||||||
|
0xffffffff38810070,
|
||||||
|
0xffffff00419effe0, // beq
|
||||||
0xffffffff81690000,
|
0xffffffff81690000,
|
||||||
0xffffffff7c050378,
|
0xffffffff38000001,
|
||||||
0xffffffff7cc43378,
|
0xffffffff91210074,
|
||||||
0xffffffff78630020, // clrldi r3,r3,32
|
0xffffffff90a10070,
|
||||||
0xffffffff7d465378,
|
0xffffffff90c10078,
|
||||||
0xffffffff812b0030,
|
0xffffffff9141007c,
|
||||||
|
0xffffffff812b001c, // difference
|
||||||
|
0xffffffff90010080,
|
||||||
0xffffffff80090000,
|
0xffffffff80090000,
|
||||||
0xfffffffff8410028,
|
0xfffffffff8410028,
|
||||||
0xffffffff7c0903a6,
|
0xffffffff7c0903a6,
|
||||||
0xffffffff80490004,
|
0xffffffff80490004,
|
||||||
0xffffffff4e800421,
|
0xffffffff4e800421,
|
||||||
0xffffffffe8410028,
|
0xffffffffe8410028,
|
||||||
0xffffffffe8010080,
|
0xffffffff7c601b78,
|
||||||
0xffffffff7c6307b4,
|
0xffffffff7c0307b4,
|
||||||
|
0xffffffffe80100a0,
|
||||||
|
0xffffffff38210090,
|
||||||
0xffffffff7c0803a6,
|
0xffffffff7c0803a6,
|
||||||
0xffffffff38210070,
|
|
||||||
0xffffffff4e800020,
|
0xffffffff4e800020,
|
||||||
0
|
0,
|
||||||
};
|
};
|
||||||
libmixer.AddFuncSub(cellAANAddData_table1, "cellAANAddData(1)", cellAANAddData);
|
libmixer.AddFuncSub("surmxAAN", cellAANDisconnect_table, "cellAANDisconnect", cellAANDisconnect);
|
||||||
|
|
||||||
static const u64 cellSurMixerCreate_table[] = {
|
static const u64 cellSurMixerCreate_table[] = {
|
||||||
0xffffffff2f830000,
|
0xffffffff2f830000,
|
||||||
@ -303,7 +519,7 @@ void libmixer_init()
|
|||||||
0xffffffff382100b0,
|
0xffffffff382100b0,
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
libmixer.AddFuncSub(cellSurMixerCreate_table, "cellSurMixerCreate", cellSurMixerCreate);
|
libmixer.AddFuncSub("surmx___", cellSurMixerCreate_table, "cellSurMixerCreate", cellSurMixerCreate);
|
||||||
|
|
||||||
static const u64 cellSurMixerGetAANHandle_table[] = {
|
static const u64 cellSurMixerGetAANHandle_table[] = {
|
||||||
// first instruction ignored
|
// first instruction ignored
|
||||||
@ -322,7 +538,7 @@ void libmixer_init()
|
|||||||
0xffffffff4e800020,
|
0xffffffff4e800020,
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
libmixer.AddFuncSub(cellSurMixerGetAANHandle_table, "cellSurMixerGetAANHandle", cellSurMixerGetAANHandle);
|
libmixer.AddFuncSub("surmx___", cellSurMixerGetAANHandle_table, "cellSurMixerGetAANHandle", cellSurMixerGetAANHandle);
|
||||||
|
|
||||||
static const u64 cellSurMixerChStripGetAANPortNo_table[] = {
|
static const u64 cellSurMixerChStripGetAANPortNo_table[] = {
|
||||||
// first instruction ignored
|
// first instruction ignored
|
||||||
@ -339,7 +555,7 @@ void libmixer_init()
|
|||||||
0xf000000040000000, // b
|
0xf000000040000000, // b
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
libmixer.AddFuncSub(cellSurMixerChStripGetAANPortNo_table, "cellSurMixerChStripGetAANPortNo", cellSurMixerChStripGetAANPortNo);
|
libmixer.AddFuncSub("surmx___", cellSurMixerChStripGetAANPortNo_table, "cellSurMixerChStripGetAANPortNo", cellSurMixerChStripGetAANPortNo);
|
||||||
|
|
||||||
static const u64 cellSurMixerSetNotifyCallback_table[] = {
|
static const u64 cellSurMixerSetNotifyCallback_table[] = {
|
||||||
// first instruction ignored
|
// first instruction ignored
|
||||||
@ -369,7 +585,7 @@ void libmixer_init()
|
|||||||
0xffffffff7d234b78,
|
0xffffffff7d234b78,
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
libmixer.AddFuncSub(cellSurMixerSetNotifyCallback_table, "cellSurMixerSetNotifyCallback", cellSurMixerSetNotifyCallback);
|
libmixer.AddFuncSub("surmx___", cellSurMixerSetNotifyCallback_table, "cellSurMixerSetNotifyCallback", cellSurMixerSetNotifyCallback);
|
||||||
|
|
||||||
static const u64 cellSurMixerRemoveNotifyCallback_table[] = {
|
static const u64 cellSurMixerRemoveNotifyCallback_table[] = {
|
||||||
// first instruction ignored
|
// first instruction ignored
|
||||||
@ -379,9 +595,9 @@ void libmixer_init()
|
|||||||
0xffffffff7c6a1b78,
|
0xffffffff7c6a1b78,
|
||||||
0xffffffff3d208031,
|
0xffffffff3d208031,
|
||||||
0xffffffff806b0018,
|
0xffffffff806b0018,
|
||||||
0xffffffff61290002,
|
0xffffffff61290002, // ori
|
||||||
0xffffffff2f830000,
|
0xffffffff2f830000,
|
||||||
0xf0000000409e0018, // bne
|
0xffff0000409e0018, // bne
|
||||||
0xffffffffe8010090,
|
0xffffffffe8010090,
|
||||||
0xffffffff7d2307b4,
|
0xffffffff7d2307b4,
|
||||||
0xffffffff38210080,
|
0xffffffff38210080,
|
||||||
@ -389,7 +605,7 @@ void libmixer_init()
|
|||||||
0xffffffff4e800020,
|
0xffffffff4e800020,
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
libmixer.AddFuncSub(cellSurMixerRemoveNotifyCallback_table, "cellSurMixerRemoveNotifyCallback", cellSurMixerRemoveNotifyCallback);
|
libmixer.AddFuncSub("surmx___", cellSurMixerRemoveNotifyCallback_table, "cellSurMixerRemoveNotifyCallback", cellSurMixerRemoveNotifyCallback);
|
||||||
|
|
||||||
static const u64 cellSurMixerStart_table[] = {
|
static const u64 cellSurMixerStart_table[] = {
|
||||||
0xfffffffff821ff71,
|
0xfffffffff821ff71,
|
||||||
@ -414,7 +630,7 @@ void libmixer_init()
|
|||||||
0xffffffff4e800020,
|
0xffffffff4e800020,
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
libmixer.AddFuncSub(cellSurMixerStart_table, "cellSurMixerStart", cellSurMixerStart);
|
libmixer.AddFuncSub("surmx___", cellSurMixerStart_table, "cellSurMixerStart", cellSurMixerStart);
|
||||||
|
|
||||||
static const u64 cellSurMixerSetParameter_table[] = {
|
static const u64 cellSurMixerSetParameter_table[] = {
|
||||||
0xfffffffff821ff81,
|
0xfffffffff821ff81,
|
||||||
@ -446,7 +662,7 @@ void libmixer_init()
|
|||||||
0xffff0000409d0054, // ble
|
0xffff0000409d0054, // ble
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
libmixer.AddFuncSub(cellSurMixerSetParameter_table, "cellSurMixerSetParameter", cellSurMixerSetParameter);
|
libmixer.AddFuncSub("surmx___", cellSurMixerSetParameter_table, "cellSurMixerSetParameter", cellSurMixerSetParameter);
|
||||||
|
|
||||||
static const u64 cellSurMixerFinalize_table[] = {
|
static const u64 cellSurMixerFinalize_table[] = {
|
||||||
0xfffffffff821ff91,
|
0xfffffffff821ff91,
|
||||||
@ -474,5 +690,147 @@ void libmixer_init()
|
|||||||
0xffffffff4e800421,
|
0xffffffff4e800421,
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
libmixer.AddFuncSub(cellSurMixerFinalize_table, "cellSurMixerFinalize", cellSurMixerFinalize);
|
libmixer.AddFuncSub("surmx___", cellSurMixerFinalize_table, "cellSurMixerFinalize", cellSurMixerFinalize);
|
||||||
|
|
||||||
|
static const u64 cellSurMixerSurBusAddData_table[] = {
|
||||||
|
0xff00000081428250,
|
||||||
|
0xffffffff7c0802a6,
|
||||||
|
0xfffffffff821ff91,
|
||||||
|
0xfffffffff8010080,
|
||||||
|
0xffffffff7c601b78,
|
||||||
|
0xffffffff3d208031,
|
||||||
|
0xffffffff806a0018,
|
||||||
|
0xffffffff7c8b2378,
|
||||||
|
0xffffffff7cc73378,
|
||||||
|
0xffffffff2f830000,
|
||||||
|
0xffffffff61290002,
|
||||||
|
0xffff0000409e0018, // bne
|
||||||
|
0xffffffffe8010080,
|
||||||
|
0xffffffff7d2307b4,
|
||||||
|
0xffffffff38210070,
|
||||||
|
0xffffffff7c0803a6,
|
||||||
|
0xffffffff4e800020,
|
||||||
|
0xffffffff78a40020,
|
||||||
|
0xffffffff78050020,
|
||||||
|
0xffffffff800a001c,
|
||||||
|
0xffffffff78680020,
|
||||||
|
0xffffffff2f800000,
|
||||||
|
0xffffffff7d034378,
|
||||||
|
0xffffffff79660020,
|
||||||
|
0xffffffff78e70020,
|
||||||
|
0xffff0000419cffcc, // blt
|
||||||
|
0
|
||||||
|
};
|
||||||
|
libmixer.AddFuncSub("surmx___", cellSurMixerSurBusAddData_table, "cellSurMixerSurBusAddData", cellSurMixerSurBusAddData);
|
||||||
|
|
||||||
|
static const u64 cellSurMixerChStripSetParameter_table[] = {
|
||||||
|
0xff00000081028250,
|
||||||
|
0xffffffff7c6b1b78,
|
||||||
|
0xffffffff3c608031,
|
||||||
|
0xffffffff7c8a2378,
|
||||||
|
0xffffffff7ca62b78,
|
||||||
|
0xffffffff60630002,
|
||||||
|
0xffffffff81280018,
|
||||||
|
0xffffffff2f890000,
|
||||||
|
0xffff00004d9e0020, // beqlr
|
||||||
|
0xffffffff8008001c,
|
||||||
|
0xffffffff79640020,
|
||||||
|
0xffffffff79450020,
|
||||||
|
0xffffffff2f800000,
|
||||||
|
0xffffffff78c60020,
|
||||||
|
0xffffffff4d9c0020,
|
||||||
|
0xffffffff79230020,
|
||||||
|
0xf000000048000000, // b
|
||||||
|
0
|
||||||
|
};
|
||||||
|
libmixer.AddFuncSub("surmx___", cellSurMixerChStripSetParameter_table, "cellSurMixerChStripSetParameter", cellSurMixerChStripSetParameter);
|
||||||
|
|
||||||
|
static const u64 cellSurMixerPause_table[] = {
|
||||||
|
// first instruction ignored
|
||||||
|
0xffffffff7c0802a6,
|
||||||
|
0xfffffffff821ff81,
|
||||||
|
0xfffffffff8010090,
|
||||||
|
0xffffffff3d208031,
|
||||||
|
0xfffffffffbe10078,
|
||||||
|
0xffffffff800a0018,
|
||||||
|
0xffffffff7c7f1b78,
|
||||||
|
0xfffffffffbc10070,
|
||||||
|
0xffffffff2f800000,
|
||||||
|
0xffffffff61290002,
|
||||||
|
0xffff0000409e0020, // bne
|
||||||
|
0xffffffffe8010090,
|
||||||
|
0xffffffff7d2307b4,
|
||||||
|
0xffffffffebc10070,
|
||||||
|
0xffffffffebe10078,
|
||||||
|
0xffffffff7c0803a6,
|
||||||
|
0xffffffff38210080,
|
||||||
|
0xffffffff4e800020,
|
||||||
|
0xffffffff800a001c,
|
||||||
|
0xffffffff2b030002,
|
||||||
|
0xffffffff2f800000,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
libmixer.AddFuncSub("surmx___", cellSurMixerPause_table, "cellSurMixerPause", cellSurMixerPause);
|
||||||
|
|
||||||
|
static const u64 cellSurMixerGetCurrentBlockTag_table[] = {
|
||||||
|
// first instruction ignored
|
||||||
|
0xffffffff3d208031,
|
||||||
|
0xffffffff61290002,
|
||||||
|
0xffffffff880b0020,
|
||||||
|
0xffffffff2f800000,
|
||||||
|
0xffff0000419e0010, // beq
|
||||||
|
0xffffffffe80b0028,
|
||||||
|
0xffffffff39200000,
|
||||||
|
0xfffffffff8030000,
|
||||||
|
0xffffffff7d2307b4,
|
||||||
|
0xffffffff4e800020,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
libmixer.AddFuncSub("surmx___", cellSurMixerGetCurrentBlockTag_table, "cellSurMixerGetCurrentBlockTag", cellSurMixerGetCurrentBlockTag);
|
||||||
|
|
||||||
|
static const u64 cellSurMixerGetTimestamp_table[] = {
|
||||||
|
// first instruction ignored
|
||||||
|
0xffffffff7c0802a6,
|
||||||
|
0xfffffffff821ff91,
|
||||||
|
0xfffffffff8010080,
|
||||||
|
0xffffffff7c852378,
|
||||||
|
0xffffffff3d208031,
|
||||||
|
0xffffffff880b0020,
|
||||||
|
0xffffffff7c641b78,
|
||||||
|
0xffffffff78a50020,
|
||||||
|
0xffffffff2f800000,
|
||||||
|
0xffffffff61290002,
|
||||||
|
0xffff000040de0018, // bne-
|
||||||
|
0xffffffffe8010080,
|
||||||
|
0xffffffff7d2307b4,
|
||||||
|
0xffffffff38210070,
|
||||||
|
0xffffffff7c0803a6,
|
||||||
|
0xffffffff4e800020,
|
||||||
|
0xffffffff806b04d8,
|
||||||
|
0xf000000048000001, // bl
|
||||||
|
0
|
||||||
|
};
|
||||||
|
libmixer.AddFuncSub("surmx___", cellSurMixerGetTimestamp_table, "cellSurMixerGetTimestamp", cellSurMixerGetTimestamp);
|
||||||
|
|
||||||
|
static const u64 cellSurMixerBeep_table[] = {
|
||||||
|
// first instruction ignored
|
||||||
|
0xffffffff7c641b78,
|
||||||
|
0xffffffff80690018,
|
||||||
|
0xffffffff2f830000,
|
||||||
|
0xffff00004d9e0020, // beqlr
|
||||||
|
0xffffffff8009001c,
|
||||||
|
0xffffffff78630020,
|
||||||
|
0xffffffff78840020,
|
||||||
|
0xffffffff2f800000,
|
||||||
|
0xffffffff4d9c0020,
|
||||||
|
0xf000000048000000, // b
|
||||||
|
0
|
||||||
|
};
|
||||||
|
libmixer.AddFuncSub("surmx___", cellSurMixerBeep_table, "cellSurMixerBeep", cellSurMixerBeep);
|
||||||
|
|
||||||
|
// TODO: SSPlayer functions
|
||||||
|
/*static const u64 cell_table[] = {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
libmixer.AddFuncSub("surmxSSP", cell_table, "cell", nullptr);*/
|
||||||
}
|
}
|
@ -1,11 +1,19 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
//libmixer Error Codes
|
||||||
|
CELL_LIBMIXER_ERROR_NOT_INITIALIZED = 0x80310002,
|
||||||
|
CELL_LIBMIXER_ERROR_INVALID_PARAMATER = 0x80310003,
|
||||||
|
CELL_LIBMIXER_ERROR_NO_MEMORY = 0x80310005,
|
||||||
|
CELL_LIBMIXER_ERROR_ALREADY_EXIST = 0x80310006,
|
||||||
|
CELL_LIBMIXER_ERROR_FULL = 0x80310007,
|
||||||
|
CELL_LIBMIXER_ERROR_NOT_EXIST = 0x80310008,
|
||||||
|
CELL_LIBMIXER_ERROR_TYPE_MISMATCH = 0x80310009,
|
||||||
|
CELL_LIBMIXER_ERROR_NOT_FOUND = 0x8031000a,
|
||||||
|
};
|
||||||
|
|
||||||
//Callback Functions
|
typedef int (*CellSurMixerNotifyCallbackFunction)(void *arg, u32 counter, u32 samples);
|
||||||
typedef int (*CellSurMixerNotifyCallbackFunction)(void *arg, u32 counter, u32 samples); //Currently unused.
|
|
||||||
|
|
||||||
//libmixer datatypes
|
|
||||||
typedef void * CellAANHandle;
|
|
||||||
|
|
||||||
struct CellSSPlayerConfig
|
struct CellSSPlayerConfig
|
||||||
{
|
{
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
extern ArrayF<SFunc> g_static_funcs_list;
|
extern ArrayF<SFunc> g_static_funcs_list;
|
||||||
|
|
||||||
void StaticAnalyse(void* ptr, u32 size)
|
void StaticAnalyse(void* ptr, u32 size, u32 base)
|
||||||
{
|
{
|
||||||
u32* data = (u32*)ptr; size /= 4;
|
u32* data = (u32*)ptr; size /= 4;
|
||||||
|
|
||||||
@ -17,35 +17,167 @@ void StaticAnalyse(void* ptr, u32 size)
|
|||||||
{
|
{
|
||||||
for (u32 j = 0; j < g_static_funcs_list.GetCount(); j++)
|
for (u32 j = 0; j < g_static_funcs_list.GetCount(); j++)
|
||||||
{
|
{
|
||||||
if ((data[i] & g_static_funcs_list[j].ops[0].mask) == g_static_funcs_list[j].ops[0].crc && (i + g_static_funcs_list[j].ops.GetCount()) < size)
|
if ((data[i] & g_static_funcs_list[j].ops[0].mask) == g_static_funcs_list[j].ops[0].crc)
|
||||||
{
|
{
|
||||||
bool found = true;
|
bool found = true;
|
||||||
for (u32 k = i + 1, x = 1; x < g_static_funcs_list[j].ops.GetCount(); k++, x++)
|
u32 can_skip = 0;
|
||||||
|
for (u32 k = i, x = 0; x + 1 <= g_static_funcs_list[j].ops.GetCount(); k++, x++)
|
||||||
{
|
{
|
||||||
// skip NOP
|
if (k >= size)
|
||||||
if (data[k] == se32(0x60000000))
|
|
||||||
{
|
|
||||||
k++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((data[k] & g_static_funcs_list[j].ops[x].mask) != g_static_funcs_list[j].ops[x].crc)
|
|
||||||
{
|
{
|
||||||
found = false;
|
found = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// skip NOP
|
||||||
|
if (data[k] == se32(0x60000000))
|
||||||
|
{
|
||||||
|
x--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 mask = g_static_funcs_list[j].ops[x].mask;
|
||||||
|
const u32 crc = g_static_funcs_list[j].ops[x].crc;
|
||||||
|
|
||||||
|
if (!mask)
|
||||||
|
{
|
||||||
|
// TODO: define syntax
|
||||||
|
if (crc < 4) // skip various number of instructions that don't match next pattern entry
|
||||||
|
{
|
||||||
|
can_skip += crc;
|
||||||
|
k--; // process this position again
|
||||||
|
}
|
||||||
|
else if (data[k] != crc) // skippable pattern ("optional" instruction), no mask allowed
|
||||||
|
{
|
||||||
|
k--;
|
||||||
|
if (can_skip) // cannot define this behaviour properly
|
||||||
|
{
|
||||||
|
ConLog.Warning("StaticAnalyse(): can_skip = %d (unchanged)", can_skip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (can_skip) // cannot define this behaviour properly
|
||||||
|
{
|
||||||
|
ConLog.Warning("StaticAnalyse(): can_skip = %d (set to 0)", can_skip);
|
||||||
|
can_skip = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((data[k] & mask) != crc) // masked pattern
|
||||||
|
{
|
||||||
|
if (can_skip)
|
||||||
|
{
|
||||||
|
can_skip--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
found = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
can_skip = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
ConLog.Success("Function '%s' hooked", wxString(g_static_funcs_list[j].name).wx_str());
|
ConLog.Write("Function '%s' hooked (addr=0x%x)", wxString(g_static_funcs_list[j].name).wx_str(), i * 4 + base);
|
||||||
data[i] = re(0x39600000 | j); // li r11, j
|
g_static_funcs_list[j].found++;
|
||||||
|
data[i+0] = re32(0x39600000 | j); // li r11, j
|
||||||
data[i+1] = se32(0x44000003); // sc 3
|
data[i+1] = se32(0x44000003); // sc 3
|
||||||
data[i+2] = se32(0x4e800020); // blr
|
data[i+2] = se32(0x4e800020); // blr
|
||||||
i += 2; // ???
|
i += 2; // skip modified code
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check function groups
|
||||||
|
for (u32 i = 0; i < g_static_funcs_list.GetCount(); i++)
|
||||||
|
{
|
||||||
|
if (g_static_funcs_list[i].found) // start from some group
|
||||||
|
{
|
||||||
|
const u64 group = g_static_funcs_list[i].group;
|
||||||
|
|
||||||
|
enum GroupSearchResult : u32
|
||||||
|
{
|
||||||
|
GSR_SUCCESS = 0, // every function from this group has been found once
|
||||||
|
GSR_MISSING = 1, // (error) some function not found
|
||||||
|
GSR_EXCESS = 2, // (error) some function found twice or more
|
||||||
|
};
|
||||||
|
u32 res = GSR_SUCCESS;
|
||||||
|
|
||||||
|
// analyse
|
||||||
|
for (u32 j = i; j < g_static_funcs_list.GetCount(); j++) if (g_static_funcs_list[j].group == group)
|
||||||
|
{
|
||||||
|
u32 count = g_static_funcs_list[j].found;
|
||||||
|
|
||||||
|
if (count == 0) // not found
|
||||||
|
{
|
||||||
|
// check if this function has been found with different pattern
|
||||||
|
for (u32 k = i; k < g_static_funcs_list.GetCount(); k++) if (g_static_funcs_list[k].group == group)
|
||||||
|
{
|
||||||
|
if (k != j && g_static_funcs_list[k].ptr == g_static_funcs_list[j].ptr)
|
||||||
|
{
|
||||||
|
count += g_static_funcs_list[k].found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count == 0)
|
||||||
|
{
|
||||||
|
res |= GSR_MISSING;
|
||||||
|
ConLog.Error("Function '%s' not found", wxString(g_static_funcs_list[j].name).wx_str());
|
||||||
|
}
|
||||||
|
else if (count > 1)
|
||||||
|
{
|
||||||
|
res |= GSR_EXCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (count == 1) // found
|
||||||
|
{
|
||||||
|
// ensure that this function has NOT been found with different pattern
|
||||||
|
for (u32 k = i; k < g_static_funcs_list.GetCount(); k++) if (g_static_funcs_list[k].group == group)
|
||||||
|
{
|
||||||
|
if (k != j && g_static_funcs_list[k].ptr == g_static_funcs_list[j].ptr)
|
||||||
|
{
|
||||||
|
if (g_static_funcs_list[k].found)
|
||||||
|
{
|
||||||
|
res |= GSR_EXCESS;
|
||||||
|
ConLog.Error("Function '%s' hooked twice", wxString(g_static_funcs_list[j].name).wx_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res |= GSR_EXCESS;
|
||||||
|
ConLog.Error("Function '%s' hooked twice", wxString(g_static_funcs_list[j].name).wx_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear data
|
||||||
|
for (u32 j = i; j < g_static_funcs_list.GetCount(); j++)
|
||||||
|
{
|
||||||
|
if (g_static_funcs_list[j].group == group) g_static_funcs_list[j].found = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char name[9] = "????????";
|
||||||
|
|
||||||
|
*(u64*)name = group;
|
||||||
|
|
||||||
|
if (res == GSR_SUCCESS)
|
||||||
|
{
|
||||||
|
ConLog.Success("Function group [%s] successfully hooked", wxString(name, 9).wx_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ConLog.Error("Function group [%s] failed:%s%s", wxString(name, 9).wx_str(),
|
||||||
|
wxString(res & GSR_MISSING ? " missing;" : "").wx_str(),
|
||||||
|
wxString(res & GSR_EXCESS ? " excess;" : "").wx_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StaticExecute(u32 code)
|
void StaticExecute(u32 code)
|
||||||
|
@ -464,6 +464,6 @@ public:
|
|||||||
|
|
||||||
//extern SysCalls SysCallsManager;
|
//extern SysCalls SysCallsManager;
|
||||||
|
|
||||||
void StaticAnalyse(void* ptr, u32 size);
|
void StaticAnalyse(void* ptr, u32 size, u32 base);
|
||||||
void StaticExecute(u32 code);
|
void StaticExecute(u32 code);
|
||||||
void StaticFinalize();
|
void StaticFinalize();
|
||||||
|
@ -28,7 +28,7 @@ int sys_lwmutex_create(mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_a
|
|||||||
}
|
}
|
||||||
|
|
||||||
lwmutex->attribute = attr->attr_protocol | attr->attr_recursive;
|
lwmutex->attribute = attr->attr_protocol | attr->attr_recursive;
|
||||||
lwmutex->all_info() = ~0;
|
lwmutex->waiter = 0;
|
||||||
lwmutex->mutex.initialize();
|
lwmutex->mutex.initialize();
|
||||||
//lwmutex->waiter = lwmutex->owner.GetOwner();
|
//lwmutex->waiter = lwmutex->owner.GetOwner();
|
||||||
lwmutex->pad = 0;
|
lwmutex->pad = 0;
|
||||||
@ -211,7 +211,7 @@ int sys_lwmutex_t::trylock(be_t<u32> tid)
|
|||||||
if (mutex.unlock(owner_tid, owner_tid) != SMR_OK) // check free value
|
if (mutex.unlock(owner_tid, owner_tid) != SMR_OK) // check free value
|
||||||
{
|
{
|
||||||
owner_tid = mutex.GetOwner();
|
owner_tid = mutex.GetOwner();
|
||||||
if (CPUThread* tt = Emu.GetCPU().GetThread(owner_tid))
|
/*if (CPUThread* tt = Emu.GetCPU().GetThread(owner_tid))
|
||||||
{
|
{
|
||||||
if (!tt->IsAlive())
|
if (!tt->IsAlive())
|
||||||
{
|
{
|
||||||
@ -227,7 +227,7 @@ int sys_lwmutex_t::trylock(be_t<u32> tid)
|
|||||||
mutex.unlock(owner_tid, tid);
|
mutex.unlock(owner_tid, tid);
|
||||||
recursive_count = 1;
|
recursive_count = 1;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/*while ((attribute.ToBE() & se32(SYS_SYNC_ATTR_RECURSIVE_MASK)) == 0)
|
/*while ((attribute.ToBE() & se32(SYS_SYNC_ATTR_RECURSIVE_MASK)) == 0)
|
||||||
@ -272,7 +272,7 @@ int sys_lwmutex_t::unlock(be_t<u32> tid)
|
|||||||
{
|
{
|
||||||
if (!recursive_count || (recursive_count.ToBE() != se32(1) && (attribute.ToBE() & se32(SYS_SYNC_NOT_RECURSIVE))))
|
if (!recursive_count || (recursive_count.ToBE() != se32(1) && (attribute.ToBE() & se32(SYS_SYNC_NOT_RECURSIVE))))
|
||||||
{
|
{
|
||||||
sc_lwmutex.Error("sys_lwmutex_t::unlock(%d): wrong recursive value (%d)", (u32)sleep_queue, (u32)recursive_count);
|
sc_lwmutex.Error("sys_lwmutex_t::unlock(%d): wrong recursive value fixed (%d)", (u32)sleep_queue, (u32)recursive_count);
|
||||||
recursive_count = 1;
|
recursive_count = 1;
|
||||||
}
|
}
|
||||||
recursive_count -= 1;
|
recursive_count -= 1;
|
||||||
|
@ -358,7 +358,7 @@ void Emulator::Resume()
|
|||||||
m_status = Running;
|
m_status = Running;
|
||||||
|
|
||||||
CheckStatus();
|
CheckStatus();
|
||||||
if(IsRunning() && Ini.CPUDecoderMode.GetValue() != 1) GetCPU().Exec();
|
//if(IsRunning() && Ini.CPUDecoderMode.GetValue() != 1) GetCPU().Exec();
|
||||||
#ifndef QT_UI
|
#ifndef QT_UI
|
||||||
wxGetApp().SendDbgCommand(DID_RESUMED_EMU);
|
wxGetApp().SendDbgCommand(DID_RESUMED_EMU);
|
||||||
#endif
|
#endif
|
||||||
|
@ -12,7 +12,7 @@ LogFrame* ConLogFrame;
|
|||||||
std::mutex g_cs_conlog;
|
std::mutex g_cs_conlog;
|
||||||
|
|
||||||
static const uint max_item_count = 500;
|
static const uint max_item_count = 500;
|
||||||
static const uint buffer_size = 1024 * 64;
|
static const uint buffer_size = 1024 * 64 * sizeof(wxChar);
|
||||||
|
|
||||||
static const wxString g_log_colors[] =
|
static const wxString g_log_colors[] =
|
||||||
{
|
{
|
||||||
@ -32,10 +32,6 @@ struct LogPacket
|
|||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LogPacket()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _LogBuffer : public MTPacketBuffer<LogPacket>
|
struct _LogBuffer : public MTPacketBuffer<LogPacket>
|
||||||
@ -78,29 +74,27 @@ struct _LogBuffer : public MTPacketBuffer<LogPacket>
|
|||||||
|
|
||||||
LogPacket _pop()
|
LogPacket _pop()
|
||||||
{
|
{
|
||||||
LogPacket ret;
|
|
||||||
|
|
||||||
u32 c_get = m_get;
|
u32 c_get = m_get;
|
||||||
|
|
||||||
const u32& sprefix = *(u32*)&m_buffer[c_get];
|
const u32& sprefix = *(u32*)&m_buffer[c_get];
|
||||||
c_get += sizeof(u32);
|
c_get += sizeof(u32);
|
||||||
ret.m_prefix = wxString((wxChar*)&m_buffer[c_get], sprefix / sizeof(wxChar));
|
const wxString& prefix = wxString((wxChar*)&m_buffer[c_get], sprefix / sizeof(wxChar));
|
||||||
c_get += sprefix;
|
c_get += sprefix;
|
||||||
|
|
||||||
const u32& stext = *(u32*)&m_buffer[c_get];
|
const u32& stext = *(u32*)&m_buffer[c_get];
|
||||||
c_get += sizeof(u32);
|
c_get += sizeof(u32);
|
||||||
ret.m_text = wxString((wxChar*)&m_buffer[c_get], stext / sizeof(wxChar));
|
const wxString& text = wxString((wxChar*)&m_buffer[c_get], stext / sizeof(wxChar));
|
||||||
c_get += stext;
|
c_get += stext;
|
||||||
|
|
||||||
const u32& scolour = *(u32*)&m_buffer[c_get];
|
const u32& scolour = *(u32*)&m_buffer[c_get];
|
||||||
c_get += sizeof(u32);
|
c_get += sizeof(u32);
|
||||||
ret.m_colour = wxString((wxChar*)&m_buffer[c_get], scolour / sizeof(wxChar));
|
const wxString& colour = wxString((wxChar*)&m_buffer[c_get], scolour / sizeof(wxChar));
|
||||||
c_get += scolour;
|
c_get += scolour;
|
||||||
|
|
||||||
m_get = c_get;
|
m_get = c_get;
|
||||||
if(!HasNewPacket()) Flush();
|
if(!HasNewPacket()) Flush();
|
||||||
|
|
||||||
return ret;
|
return LogPacket(prefix, text, colour);
|
||||||
}
|
}
|
||||||
} LogBuffer;
|
} LogBuffer;
|
||||||
|
|
||||||
@ -114,18 +108,19 @@ LogWriter::LogWriter()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogWriter::WriteToLog(wxString prefix, wxString value, u8 lvl/*, wxColour bgcolour*/)
|
void LogWriter::WriteToLog(const wxString& prefix, const wxString& value, u8 lvl/*, wxColour bgcolour*/)
|
||||||
{
|
{
|
||||||
|
wxString new_prefix = prefix;
|
||||||
if(!prefix.empty())
|
if(!prefix.empty())
|
||||||
{
|
{
|
||||||
if(NamedThreadBase* thr = GetCurrentNamedThread())
|
if(NamedThreadBase* thr = GetCurrentNamedThread())
|
||||||
{
|
{
|
||||||
prefix += " : " + thr->GetThreadName();
|
new_prefix += " : " + thr->GetThreadName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_logfile.IsOpened() && !prefix.empty())
|
if(m_logfile.IsOpened() && !new_prefix.empty())
|
||||||
m_logfile.Write(wxString("[") + prefix + "]: " + value + "\n");
|
m_logfile.Write(wxString("[") + new_prefix + "]: " + value + "\n");
|
||||||
|
|
||||||
if(!ConLogFrame || Ini.HLELogLvl.GetValue() == 4 || (lvl != 0 && lvl <= Ini.HLELogLvl.GetValue()))
|
if(!ConLogFrame || Ini.HLELogLvl.GetValue() == 4 || (lvl != 0 && lvl <= Ini.HLELogLvl.GetValue()))
|
||||||
return;
|
return;
|
||||||
@ -159,10 +154,10 @@ void LogWriter::WriteToLog(wxString prefix, wxString value, u8 lvl/*, wxColour b
|
|||||||
|
|
||||||
//if(LogBuffer.put == LogBuffer.get) LogBuffer.Flush();
|
//if(LogBuffer.put == LogBuffer.get) LogBuffer.Flush();
|
||||||
|
|
||||||
LogBuffer.Push(LogPacket(prefix, value, g_log_colors[lvl]));
|
LogBuffer.Push(LogPacket(new_prefix, value, g_log_colors[lvl]));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogWriter::Write(const wxString fmt, ...)
|
void LogWriter::Write(const wxString& fmt, ...)
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
va_start(list, fmt);
|
va_start(list, fmt);
|
||||||
@ -175,7 +170,7 @@ void LogWriter::Write(const wxString fmt, ...)
|
|||||||
WriteToLog("!", frmt, 2);
|
WriteToLog("!", frmt, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogWriter::Error(const wxString fmt, ...)
|
void LogWriter::Error(const wxString& fmt, ...)
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
va_start(list, fmt);
|
va_start(list, fmt);
|
||||||
@ -188,7 +183,7 @@ void LogWriter::Error(const wxString fmt, ...)
|
|||||||
WriteToLog("E", frmt, 4);
|
WriteToLog("E", frmt, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogWriter::Warning(const wxString fmt, ...)
|
void LogWriter::Warning(const wxString& fmt, ...)
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
va_start(list, fmt);
|
va_start(list, fmt);
|
||||||
@ -201,7 +196,7 @@ void LogWriter::Warning(const wxString fmt, ...)
|
|||||||
WriteToLog("W", frmt, 3);
|
WriteToLog("W", frmt, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogWriter::Success(const wxString fmt, ...)
|
void LogWriter::Success(const wxString& fmt, ...)
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
va_start(list, fmt);
|
va_start(list, fmt);
|
||||||
|
@ -11,15 +11,15 @@ class LogWriter
|
|||||||
//wxString m_prefix;
|
//wxString m_prefix;
|
||||||
//wxString m_value;
|
//wxString m_value;
|
||||||
|
|
||||||
virtual void WriteToLog(wxString prefix, wxString value, u8 lvl);
|
virtual void WriteToLog(const wxString& prefix, const wxString& value, u8 lvl);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LogWriter();
|
LogWriter();
|
||||||
|
|
||||||
virtual void Write(const wxString fmt, ...);
|
virtual void Write(const wxString& fmt, ...);
|
||||||
virtual void Error(const wxString fmt, ...);
|
virtual void Error(const wxString& fmt, ...);
|
||||||
virtual void Warning(const wxString fmt, ...);
|
virtual void Warning(const wxString& fmt, ...);
|
||||||
virtual void Success(const wxString fmt, ...);
|
virtual void Success(const wxString& fmt, ...);
|
||||||
virtual void SkipLn();
|
virtual void SkipLn();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -175,15 +175,16 @@ bool ELF32Loader::LoadShdrInfo()
|
|||||||
for(u32 i=0; i<shdr_arr.GetCount(); ++i)
|
for(u32 i=0; i<shdr_arr.GetCount(); ++i)
|
||||||
{
|
{
|
||||||
elf32_f.Seek(shdr_arr[ehdr.e_shstrndx].sh_offset + shdr_arr[i].sh_name);
|
elf32_f.Seek(shdr_arr[ehdr.e_shstrndx].sh_offset + shdr_arr[i].sh_name);
|
||||||
wxString name = wxEmptyString;
|
Array<char> name;
|
||||||
while(!elf32_f.Eof())
|
while(!elf32_f.Eof())
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
elf32_f.Read(&c, 1);
|
elf32_f.Read(&c, 1);
|
||||||
if(c == 0) break;
|
if(c == 0) break;
|
||||||
name += c;
|
name.AddCpy(c);
|
||||||
}
|
}
|
||||||
shdr_name_arr.Add(name);
|
name.AddCpy('\0');
|
||||||
|
shdr_name_arr.Add(wxString(name.GetPtr(), wxConvUTF8));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -176,16 +176,16 @@ bool ELF64Loader::LoadShdrInfo(s64 offset)
|
|||||||
for(u32 i=0; i<shdr_arr.GetCount(); ++i)
|
for(u32 i=0; i<shdr_arr.GetCount(); ++i)
|
||||||
{
|
{
|
||||||
elf64_f.Seek((offset < 0 ? shdr_arr[ehdr.e_shstrndx].sh_offset : shdr_arr[ehdr.e_shstrndx].sh_offset - ehdr.e_shoff + offset) + shdr_arr[i].sh_name);
|
elf64_f.Seek((offset < 0 ? shdr_arr[ehdr.e_shstrndx].sh_offset : shdr_arr[ehdr.e_shstrndx].sh_offset - ehdr.e_shoff + offset) + shdr_arr[i].sh_name);
|
||||||
wxString name = wxEmptyString;
|
Array<char> name;
|
||||||
while(!elf64_f.Eof())
|
while(!elf64_f.Eof())
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
elf64_f.Read(&c, 1);
|
elf64_f.Read(&c, 1);
|
||||||
if(c == 0) break;
|
if(c == 0) break;
|
||||||
name += c;
|
name.AddCpy(c);
|
||||||
}
|
}
|
||||||
|
name.AddCpy('\0');
|
||||||
shdr_name_arr.Add(name);
|
shdr_name_arr.Add(wxString(name.GetPtr(), wxConvUTF8));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -246,7 +246,7 @@ bool ELF64Loader::LoadPhdrData(u64 offset)
|
|||||||
{
|
{
|
||||||
elf64_f.Seek(phdr_arr[i].p_offset);
|
elf64_f.Seek(phdr_arr[i].p_offset);
|
||||||
elf64_f.Read(&Memory[offset + phdr_arr[i].p_vaddr], phdr_arr[i].p_filesz);
|
elf64_f.Read(&Memory[offset + phdr_arr[i].p_vaddr], phdr_arr[i].p_filesz);
|
||||||
StaticAnalyse(&Memory[offset + phdr_arr[i].p_vaddr], phdr_arr[i].p_filesz);
|
StaticAnalyse(&Memory[offset + phdr_arr[i].p_vaddr], phdr_arr[i].p_filesz, phdr_arr[i].p_vaddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user