ARMv7: ARM encoding introduced; bugfixes

This commit is contained in:
Nekotekina 2015-02-02 12:14:49 +03:00
parent dab80497bb
commit 23c7028b2a
16 changed files with 161 additions and 109 deletions

View file

@ -14,6 +14,12 @@
#define __noinline __attribute__((noinline)) #define __noinline __attribute__((noinline))
#endif #endif
#ifdef _WIN32
#define __safebuffers __declspec(safebuffers)
#else
#define __safebuffers
#endif
template<size_t size> template<size_t size>
void strcpy_trunc(char(&dst)[size], const std::string& src) void strcpy_trunc(char(&dst)[size], const std::string& src)
{ {

View file

@ -132,5 +132,5 @@ void log_message(Log::LogType type, Log::LogSeverity sev, std::string text);
template<typename... Targs> template<typename... Targs>
__noinline void log_message(Log::LogType type, Log::LogSeverity sev, const char* fmt, Targs... args) __noinline void log_message(Log::LogType type, Log::LogSeverity sev, const char* fmt, Targs... args)
{ {
log_message(type, sev, fmt::detail::format(fmt, strlen(fmt), fmt::do_unveil(args)...)); log_message(type, sev, fmt::detail::format(fmt, fmt::do_unveil(args)...));
} }

View file

@ -144,8 +144,9 @@ size_t fmt::detail::get_fmt_precision(const char* fmt, size_t len)
return 1; return 1;
} }
std::string fmt::detail::format(const char* fmt, size_t len) std::string fmt::detail::format(const char* fmt)
{ {
const size_t len = strlen(fmt);
const size_t fmt_start = get_fmt_start(fmt, len); const size_t fmt_start = get_fmt_start(fmt, len);
if (fmt_start != len) if (fmt_start != len)
{ {

View file

@ -429,16 +429,17 @@ namespace fmt
} }
}; };
std::string format(const char* fmt, size_t len); // terminator std::string format(const char* fmt); // terminator
template<typename T, typename... Args> template<typename T, typename... Args>
std::string format(const char* fmt, size_t len, const T& arg, Args... args) std::string format(const char* fmt, const T& arg, Args... args)
{ {
const size_t len = strlen(fmt);
const size_t fmt_start = get_fmt_start(fmt, len); const size_t fmt_start = get_fmt_start(fmt, len);
const size_t fmt_len = get_fmt_len(fmt + fmt_start, len - fmt_start); const size_t fmt_len = get_fmt_len(fmt + fmt_start, len - fmt_start);
const size_t fmt_end = fmt_start + fmt_len; const size_t fmt_end = fmt_start + fmt_len;
return std::string(fmt, fmt_start) + get_fmt<T>::text(fmt + fmt_start, fmt_len, arg) + format(fmt + fmt_end, len - fmt_end, args...); return std::string(fmt, fmt_start) + get_fmt<T>::text(fmt + fmt_start, fmt_len, arg) + format(fmt + fmt_end, args...);
} }
}; };
@ -551,9 +552,9 @@ namespace fmt
Other features are not supported. Other features are not supported.
*/ */
template<typename... Args> template<typename... Args>
__forceinline std::string format(const char* fmt, Args... args) __forceinline __safebuffers std::string format(const char* fmt, Args... args)
{ {
return detail::format(fmt, strlen(fmt), do_unveil(args)...); return detail::format(fmt, do_unveil(args)...);
} }
//convert a wxString to a std::string encoded in utf8 //convert a wxString to a std::string encoded in utf8

View file

@ -137,7 +137,7 @@ struct ARMv7Context
} }
else else
{ {
write_pc(value & ~1); write_pc(value);
} }
} }

View file

@ -1160,8 +1160,43 @@ struct ARMv7_op4t_table_t
} }
} }
const ARMv7_opcode_t* HACK()
{
for (auto& opcode : table)
{
if (opcode->func == ARMv7_instrs::HACK)
{
return opcode;
}
}
throw "HACK instruction not found";
}
} g_op4t; } g_op4t;
struct ARMv7_op4arm_table_t
{
std::vector<const ARMv7_opcode_t*> table;
ARMv7_op4arm_table_t()
{
for (auto& opcode : ARMv7_opcode_table)
{
if (opcode.type >= A1)
{
if (opcode.code & ~opcode.mask)
{
LOG_ERROR(GENERAL, "%s: wrong opcode mask (mask=0x%08x, code=0x%08x)", opcode.name, opcode.mask, opcode.code);
}
table.push_back(&opcode);
}
}
}
} g_op4arm;
std::unordered_map<u32, const ARMv7_opcode_t*> g_opct; std::unordered_map<u32, const ARMv7_opcode_t*> g_opct;
void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump) void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump)
@ -1231,16 +1266,21 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump)
const u32 i2 = (code.data >> 11) & 0x1 ^ s ^ 1; const u32 i2 = (code.data >> 11) & 0x1 ^ s ^ 1;
const u32 target = (addr + 4 & ~3) + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1); const u32 target = (addr + 4 & ~3) + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1);
// possibly a call to imported function: const u32 instr = vm::psv::read32(target);
if (target >= end_addr && ((target - end_addr) % 16) == 0 && vm::psv::read16(target) == 0xf870)
{
const u32 instr = vm::psv::read32(target);
// check if not "unimplemented" // possibly a call to imported function:
if (instr >> 16) if (target >= end_addr && ((target - end_addr) % 16) == 0 && (instr & 0xfff000f0) == 0xe0700090)
{
// check if implemented
if (const u32 func = (instr & 0xfff00) >> 4 | (instr & 0xf))
{ {
// replace BLX with "hack" instruction directly, it can help to see where it was called from // replace BLX with "HACK" instruction directly (in Thumb form), it can help to see where it was called from
vm::psv::write32(addr, instr); vm::psv::write32(addr, 0xf870 | func << 16);
g_opct[0xf8700000 | func] = g_op4t.HACK();
}
else
{
// leave as is if unimplemented
} }
} }
else else
@ -1257,49 +1297,59 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump)
addr += found->length; addr += found->length;
} }
while (vm::psv::read16(addr) == 0xf870)
{
g_opct[0xf8700000 | vm::psv::read16(addr + 2)] = g_op4t.table[0];
addr += 16;
}
LOG_NOTICE(ARMv7, "armv7_decoder_initialize() finished, g_opct.size() = %lld", (u64)g_opct.size()); LOG_NOTICE(ARMv7, "armv7_decoder_initialize() finished, g_opct.size() = %lld", (u64)g_opct.size());
} }
u32 ARMv7Decoder::DecodeMemory(const u32 address) u32 ARMv7Decoder::DecodeMemory(const u32 address)
{ {
if (address & 0x1)
{
throw "ARMv7Decoder::DecodeMemory() failed (something is wrong with instruction set)";
}
ARMv7Code code = {}; ARMv7Code code = {};
code.code0 = vm::psv::read16(address);
if (auto opcode = g_op2t.data[code.code0]) if (m_ctx.ISET == Thumb)
{ {
(*opcode->func)(m_ctx, code, opcode->type); code.code0 = vm::psv::read16(address);
return 2;
if (auto opcode = g_op2t.data[code.code0])
{
(*opcode->func)(m_ctx, code, opcode->type);
return 2;
}
code.code1 = code.code0;
code.code0 = vm::psv::read16(address + 2);
auto op = g_opct.find(code.data);
if (op != g_opct.end())
{
(*op->second->func)(m_ctx, code, op->second->type);
return 4;
}
//for (auto opcode : g_op4t.table)
//{
// if ((code.data & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(code.data)))
// {
// (*opcode->func)(m_ctx, code, opcode->type);
// return 4;
// }
//}
} }
else if (m_ctx.ISET == ARM)
code.code1 = code.code0;
code.code0 = vm::psv::read16(address + 2);
auto op = g_opct.find(code.data);
if (op != g_opct.end())
{ {
(*op->second->func)(m_ctx, code, op->second->type); code.data = vm::psv::read32(address);
return 4;
}
//for (auto opcode : g_op4t.table) for (auto opcode : g_op4arm.table)
//{ {
// if ((code.data & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(code.data))) if ((code.data & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(code.data)))
// { {
// (*opcode->func)(m_ctx, code, opcode->type); (*opcode->func)(m_ctx, code, opcode->type);
// return 4; return 4;
// } }
//} }
}
else
{
throw "ARMv7Decoder::DecodeMemory() failed (invalid instruction set set)";
}
ARMv7_instrs::UNK(m_ctx, code); ARMv7_instrs::UNK(m_ctx, code);
return 4; return 4;

View file

@ -280,7 +280,14 @@ namespace ARMv7_instrs
void ARMv7_instrs::UNK(ARMv7Context& context, const ARMv7Code code) void ARMv7_instrs::UNK(ARMv7Context& context, const ARMv7Code code)
{ {
throw fmt::format("Unknown/illegal opcode: 0x%04x 0x%04x", code.code1, code.code0); if (context.ISET == Thumb)
{
throw fmt::format("Unknown/illegal opcode: 0x%04x 0x%04x", code.code1, code.code0);
}
else
{
throw fmt::format("Unknown/illegal opcode: 0x%08x", code.data);
}
} }
void ARMv7_instrs::HACK(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) void ARMv7_instrs::HACK(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
@ -976,16 +983,7 @@ void ARMv7_instrs::BLX(ARMv7Context& context, const ARMv7Code code, const ARMv7_
if (ConditionPassed(context, cond)) if (ConditionPassed(context, cond))
{ {
context.LR = newLR; context.LR = newLR;
if (target & 1) context.write_pc(target);
{
context.ISET = Thumb;
context.thread.SetBranch(target & ~1);
}
else
{
context.ISET = ARM;
context.thread.SetBranch(target);
}
} }
} }
@ -1014,16 +1012,7 @@ void ARMv7_instrs::BX(ARMv7Context& context, const ARMv7Code code, const ARMv7_e
if (ConditionPassed(context, cond)) if (ConditionPassed(context, cond))
{ {
if (target & 1) context.write_pc(target);
{
context.ISET = Thumb;
context.thread.SetBranch(target & ~1);
}
else
{
context.ISET = ARM;
context.thread.SetBranch(target);
}
} }
} }

View file

@ -12,7 +12,8 @@
void ARMv7Context::write_pc(u32 value) void ARMv7Context::write_pc(u32 value)
{ {
thread.SetBranch(value); ISET = value & 1 ? Thumb : ARM;
thread.SetBranch(value & ~1);
} }
u32 ARMv7Context::read_pc() u32 ARMv7Context::read_pc()
@ -109,10 +110,11 @@ ARMv7Thread::~ARMv7Thread()
void ARMv7Thread::InitRegs() void ARMv7Thread::InitRegs()
{ {
memset(context.GPR, 0, sizeof(context.GPR[0]) * 15); memset(context.GPR, 0, sizeof(context.GPR));
context.APSR.APSR = 0; context.APSR.APSR = 0;
context.IPSR.IPSR = 0; context.IPSR.IPSR = 0;
//context.ISET = Thumb; context.ISET = PC & 1 ? Thumb : ARM; // select instruction set
context.thread.SetPc(PC & ~1); // and fix PC
context.ITSTATE.IT = 0; context.ITSTATE.IT = 0;
context.SP = m_stack_addr + m_stack_size; context.SP = m_stack_addr + m_stack_size;
context.TLS = armv7_get_tls(GetId()); context.TLS = armv7_get_tls(GetId());

View file

@ -48,12 +48,12 @@ s32 sceKernelCreateThread(
ARMv7Thread& new_thread = static_cast<ARMv7Thread&>(Emu.GetCPU().AddThread(CPU_THREAD_ARMv7)); ARMv7Thread& new_thread = static_cast<ARMv7Thread&>(Emu.GetCPU().AddThread(CPU_THREAD_ARMv7));
const auto id = new_thread.GetId(); const auto id = new_thread.GetId();
new_thread.SetEntry(entry.addr() ^ 1); new_thread.SetEntry(entry.addr());
new_thread.SetPrio(initPriority); new_thread.SetPrio(initPriority);
new_thread.SetStackSize(stackSize); new_thread.SetStackSize(stackSize);
new_thread.SetName(pName.get_ptr()); new_thread.SetName(pName.get_ptr());
sceLibKernel.Error("*** New ARMv7 Thread [%s] (entry=0x%x)^1: id -> 0x%x", pName.get_ptr(), entry, id); sceLibKernel.Warning("*** New ARMv7 Thread [%s] (entry=0x%x): id -> 0x%x", pName.get_ptr(), entry, id);
new_thread.Run(); new_thread.Run();
return id; return id;

View file

@ -59,7 +59,7 @@ s32 sceRtcCheckValid(vm::psv::ptr<const SceDateTime> pTime)
throw __FUNCTION__; throw __FUNCTION__;
} }
s32 sceRtcSetTime_t(vm::psv::ptr<SceDateTime> pTime, time_t iTime) s32 sceRtcSetTime_t(vm::psv::ptr<SceDateTime> pTime, u32 iTime)
{ {
throw __FUNCTION__; throw __FUNCTION__;
} }
@ -69,7 +69,7 @@ s32 sceRtcSetTime64_t(vm::psv::ptr<SceDateTime> pTime, u64 ullTime)
throw __FUNCTION__; throw __FUNCTION__;
} }
s32 sceRtcGetTime_t(vm::psv::ptr<const SceDateTime> pTime, vm::psv::ptr<time_t> piTime) s32 sceRtcGetTime_t(vm::psv::ptr<const SceDateTime> pTime, vm::psv::ptr<u32> piTime)
{ {
throw __FUNCTION__; throw __FUNCTION__;
} }

View file

@ -69,7 +69,7 @@ namespace vm
void error(const u64 addr, const char* func) void error(const u64 addr, const char* func)
{ {
throw fmt::format("%s(): invalid address 0x%llx", func, addr); throw fmt::format("%s(): failed to cast 0x%llx (too big value)", func, addr);
} }
namespace ps3 namespace ps3
@ -249,7 +249,10 @@ namespace vm
case CPU_THREAD_ARMv7: case CPU_THREAD_ARMv7:
{ {
assert(!"stack_pop(): ARMv7 not supported"); ARMv7Context& context = static_cast<ARMv7Thread&>(CPU).context;
assert(context.SP == addr);
context.SP = old_pos;
return; return;
} }

View file

@ -17,9 +17,9 @@ class LogBase
void LogOutput(LogType type, const std::string& text) const; void LogOutput(LogType type, const std::string& text) const;
template<typename... Targs> template<typename... Targs>
__noinline void LogPrepare(LogType type, const char* fmt, size_t len, Targs... args) const __noinline void LogPrepare(LogType type, const char* fmt, Targs... args) const
{ {
LogOutput(type, fmt::detail::format(fmt, len, args...)); LogOutput(type, fmt::detail::format(fmt, args...));
} }
public: public:
@ -38,7 +38,7 @@ public:
template<typename... Targs> template<typename... Targs>
__forceinline void Notice(const char* fmt, Targs... args) const __forceinline void Notice(const char* fmt, Targs... args) const
{ {
LogPrepare(LogNotice, fmt, strlen(fmt), fmt::do_unveil(args)...); LogPrepare(LogNotice, fmt, fmt::do_unveil(args)...);
} }
template<typename... Targs> template<typename... Targs>
@ -53,25 +53,25 @@ public:
template<typename... Targs> template<typename... Targs>
__forceinline void Success(const char* fmt, Targs... args) const __forceinline void Success(const char* fmt, Targs... args) const
{ {
LogPrepare(LogSuccess, fmt, strlen(fmt), fmt::do_unveil(args)...); LogPrepare(LogSuccess, fmt, fmt::do_unveil(args)...);
} }
template<typename... Targs> template<typename... Targs>
__forceinline void Warning(const char* fmt, Targs... args) const __forceinline void Warning(const char* fmt, Targs... args) const
{ {
LogPrepare(LogWarning, fmt, strlen(fmt), fmt::do_unveil(args)...); LogPrepare(LogWarning, fmt, fmt::do_unveil(args)...);
} }
template<typename... Targs> template<typename... Targs>
__forceinline void Error(const char* fmt, Targs... args) const __forceinline void Error(const char* fmt, Targs... args) const
{ {
LogPrepare(LogError, fmt, strlen(fmt), fmt::do_unveil(args)...); LogPrepare(LogError, fmt, fmt::do_unveil(args)...);
} }
template<typename... Targs> template<typename... Targs>
__forceinline void Todo(const char* fmt, Targs... args) const __forceinline void Todo(const char* fmt, Targs... args) const
{ {
LogPrepare(LogTodo, fmt, strlen(fmt), fmt::do_unveil(args)...); LogPrepare(LogTodo, fmt, fmt::do_unveil(args)...);
} }
}; };

View file

@ -372,7 +372,7 @@ s32 cellSaveDataListSave2(
for (u32 i=0; i<saveEntries.size(); i++) { for (u32 i=0; i<saveEntries.size(); i++) {
strcpy_trunc(dirList[i].dirName, saveEntries[i].dirName); strcpy_trunc(dirList[i].dirName, saveEntries[i].dirName);
strcpy_trunc(dirList[i].listParam, saveEntries[i].listParam); strcpy_trunc(dirList[i].listParam, saveEntries[i].listParam);
*dirList[i].reserved = {}; memset(dirList[i].reserved, 0, sizeof(dirList[i].reserved));
} }
funcList(result, listGet, listSet); funcList(result, listGet, listSet);
@ -464,7 +464,7 @@ s32 cellSaveDataListLoad2(
for (u32 i=0; i<saveEntries.size(); i++) { for (u32 i=0; i<saveEntries.size(); i++) {
strcpy_trunc(dirList[i].dirName, saveEntries[i].dirName); strcpy_trunc(dirList[i].dirName, saveEntries[i].dirName);
strcpy_trunc(dirList[i].listParam, saveEntries[i].listParam); strcpy_trunc(dirList[i].listParam, saveEntries[i].listParam);
*dirList[i].reserved = {}; memset(dirList[i].reserved, 0, sizeof(dirList[i].reserved));
} }
funcList(result, listGet, listSet); funcList(result, listGet, listSet);
@ -553,7 +553,7 @@ s32 cellSaveDataFixedSave2(
for (u32 i = 0; i<saveEntries.size(); i++) { for (u32 i = 0; i<saveEntries.size(); i++) {
strcpy_trunc(dirList[i].dirName, saveEntries[i].dirName); strcpy_trunc(dirList[i].dirName, saveEntries[i].dirName);
strcpy_trunc(dirList[i].listParam, saveEntries[i].listParam); strcpy_trunc(dirList[i].listParam, saveEntries[i].listParam);
*dirList[i].reserved = {}; memset(dirList[i].reserved, 0, sizeof(dirList[i].reserved));
} }
funcFixed(result, listGet, fixedSet); funcFixed(result, listGet, fixedSet);
if (result->result < 0) { if (result->result < 0) {
@ -629,7 +629,7 @@ s32 cellSaveDataFixedLoad2(
for (u32 i = 0; i<saveEntries.size(); i++) { for (u32 i = 0; i<saveEntries.size(); i++) {
strcpy_trunc(dirList[i].dirName, saveEntries[i].dirName); strcpy_trunc(dirList[i].dirName, saveEntries[i].dirName);
strcpy_trunc(dirList[i].listParam, saveEntries[i].listParam); strcpy_trunc(dirList[i].listParam, saveEntries[i].listParam);
*dirList[i].reserved = {}; memset(dirList[i].reserved, 0, sizeof(dirList[i].reserved));
} }
funcFixed(result, listGet, fixedSet); funcFixed(result, listGet, fixedSet);
if (result->result < 0) { if (result->result < 0) {
@ -826,7 +826,7 @@ s32 cellSaveDataListAutoSave(
//for (u32 i = 0; i<saveEntries.size(); i++) { //for (u32 i = 0; i<saveEntries.size(); i++) {
// strcpy_trunc(dirList[i].dirName, saveEntries[i].dirName.c_str()); // strcpy_trunc(dirList[i].dirName, saveEntries[i].dirName.c_str());
// strcpy_trunc(dirList[i].listParam, saveEntries[i].listParam.c_str()); // strcpy_trunc(dirList[i].listParam, saveEntries[i].listParam.c_str());
// *dirList[i].reserved = {}; // memset(dirList[i].reserved, 0, sizeof(dirList[i].reserved));
//} //}
//funcFixed(result, listGet, fixedSet); //funcFixed(result, listGet, fixedSet);
@ -909,7 +909,7 @@ s32 cellSaveDataListAutoLoad(
//for (u32 i = 0; i<saveEntries.size(); i++) { //for (u32 i = 0; i<saveEntries.size(); i++) {
// strcpy_trunc(dirList[i].dirName, saveEntries[i].dirName); // strcpy_trunc(dirList[i].dirName, saveEntries[i].dirName);
// strcpy_trunc(dirList[i].listParam, saveEntries[i].listParam); // strcpy_trunc(dirList[i].listParam, saveEntries[i].listParam);
// *dirList[i].reserved = {}; // memset(dirList[i].reserved, 0, sizeof(dirList[i].reserved));
//} //}
//funcFixed(result, listGet, fixedSet); //funcFixed(result, listGet, fixedSet);

View file

@ -850,8 +850,8 @@ void syncLFQueueInit(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u8> buffer, u32 siz
queue->m_depth = depth; queue->m_depth = depth;
queue->m_buffer = buffer; queue->m_buffer = buffer;
queue->m_direction = direction; queue->m_direction = direction;
*queue->m_hs1 = {}; memset(queue->m_hs1, 0, sizeof(queue->m_hs1));
*queue->m_hs2 = {}; memset(queue->m_hs2, 0, sizeof(queue->m_hs2));
queue->m_eaSignal = eaSignal; queue->m_eaSignal = eaSignal;
if (direction == CELL_SYNC_QUEUE_ANY2ANY) if (direction == CELL_SYNC_QUEUE_ANY2ANY)

View file

@ -217,6 +217,7 @@ int cellVideoOutGetConfiguration(u32 videoOut, vm::ptr<CellVideoOutConfiguration
videoOut, config.addr(), option.addr()); videoOut, config.addr(), option.addr());
if (option) *option = {}; if (option) *option = {};
*config = {};
switch(videoOut) switch(videoOut)
{ {
@ -224,13 +225,11 @@ int cellVideoOutGetConfiguration(u32 videoOut, vm::ptr<CellVideoOutConfiguration
config->resolutionId = Emu.GetGSManager().GetInfo().mode.resolutionId; config->resolutionId = Emu.GetGSManager().GetInfo().mode.resolutionId;
config->format = Emu.GetGSManager().GetInfo().mode.format; config->format = Emu.GetGSManager().GetInfo().mode.format;
config->aspect = Emu.GetGSManager().GetInfo().mode.aspect; config->aspect = Emu.GetGSManager().GetInfo().mode.aspect;
*config->reserved = {};
config->pitch = Emu.GetGSManager().GetInfo().mode.pitch; config->pitch = Emu.GetGSManager().GetInfo().mode.pitch;
return CELL_VIDEO_OUT_SUCCEEDED; return CELL_VIDEO_OUT_SUCCEEDED;
case CELL_VIDEO_OUT_SECONDARY: case CELL_VIDEO_OUT_SECONDARY:
*config = {}; // ???
return CELL_VIDEO_OUT_SUCCEEDED; return CELL_VIDEO_OUT_SUCCEEDED;
} }
@ -478,22 +477,25 @@ int cellAudioOutGetState(u32 audioOut, u32 deviceIndex, vm::ptr<CellAudioOutStat
{ {
cellSysutil->Warning("cellAudioOutGetState(audioOut=0x%x, deviceIndex=0x%x, state_addr=0x%x)", audioOut, deviceIndex, state.addr()); cellSysutil->Warning("cellAudioOutGetState(audioOut=0x%x, deviceIndex=0x%x, state_addr=0x%x)", audioOut, deviceIndex, state.addr());
*state = {};
switch(audioOut) switch(audioOut)
{ {
case CELL_AUDIO_OUT_PRIMARY: case CELL_AUDIO_OUT_PRIMARY:
state->state = Emu.GetAudioManager().GetState(); state->state = Emu.GetAudioManager().GetState();
state->encoder = Emu.GetAudioManager().GetInfo().mode.encoder; state->encoder = Emu.GetAudioManager().GetInfo().mode.encoder;
*state->reserved = {};
state->downMixer = Emu.GetAudioManager().GetInfo().mode.downMixer; state->downMixer = Emu.GetAudioManager().GetInfo().mode.downMixer;
state->soundMode.type = Emu.GetAudioManager().GetInfo().mode.type; state->soundMode.type = Emu.GetAudioManager().GetInfo().mode.type;
state->soundMode.channel = Emu.GetAudioManager().GetInfo().mode.channel; state->soundMode.channel = Emu.GetAudioManager().GetInfo().mode.channel;
state->soundMode.fs = Emu.GetAudioManager().GetInfo().mode.fs; state->soundMode.fs = Emu.GetAudioManager().GetInfo().mode.fs;
state->soundMode.reserved = 0; state->soundMode.reserved = 0;
state->soundMode.layout = Emu.GetAudioManager().GetInfo().mode.layout; state->soundMode.layout = Emu.GetAudioManager().GetInfo().mode.layout;
return CELL_AUDIO_OUT_SUCCEEDED; return CELL_AUDIO_OUT_SUCCEEDED;
case CELL_AUDIO_OUT_SECONDARY: case CELL_AUDIO_OUT_SECONDARY:
*state = { CELL_AUDIO_OUT_OUTPUT_STATE_DISABLED }; state->state = CELL_AUDIO_OUT_OUTPUT_STATE_DISABLED;
return CELL_AUDIO_OUT_SUCCEEDED; return CELL_AUDIO_OUT_SUCCEEDED;
} }
@ -534,19 +536,18 @@ int cellAudioOutGetConfiguration(u32 audioOut, vm::ptr<CellAudioOutConfiguration
cellSysutil->Warning("cellAudioOutGetConfiguration(audioOut=%d, config_addr=0x%x, option_addr=0x%x)", audioOut, config.addr(), option.addr()); cellSysutil->Warning("cellAudioOutGetConfiguration(audioOut=%d, config_addr=0x%x, option_addr=0x%x)", audioOut, config.addr(), option.addr());
if (option) *option = {}; if (option) *option = {};
*config = {};
switch(audioOut) switch(audioOut)
{ {
case CELL_AUDIO_OUT_PRIMARY: case CELL_AUDIO_OUT_PRIMARY:
config->channel = Emu.GetAudioManager().GetInfo().mode.channel; config->channel = Emu.GetAudioManager().GetInfo().mode.channel;
config->encoder = Emu.GetAudioManager().GetInfo().mode.encoder; config->encoder = Emu.GetAudioManager().GetInfo().mode.encoder;
*config->reserved = {};
config->downMixer = Emu.GetAudioManager().GetInfo().mode.downMixer; config->downMixer = Emu.GetAudioManager().GetInfo().mode.downMixer;
return CELL_AUDIO_OUT_SUCCEEDED; return CELL_AUDIO_OUT_SUCCEEDED;
case CELL_AUDIO_OUT_SECONDARY: case CELL_AUDIO_OUT_SECONDARY:
*config = {};
return CELL_AUDIO_OUT_SUCCEEDED; return CELL_AUDIO_OUT_SUCCEEDED;
} }

View file

@ -104,6 +104,10 @@ namespace loader
vm::psv::ptr<u32> sceLibcHeapDelayedAlloc; vm::psv::ptr<u32> sceLibcHeapDelayedAlloc;
u32 unk2; u32 unk2;
u32 unk3;
vm::psv::ptr<u32> __sce_libcmallocreplace;
vm::psv::ptr<u32> __sce_libcnewreplace;
}; };
struct psv_process_param_t struct psv_process_param_t
@ -233,18 +237,14 @@ namespace loader
LOG_NOTICE(LOADER, "Imported function %s (nid=0x%08x, addr=0x%x)", func->name, nid, addr); LOG_NOTICE(LOADER, "Imported function %s (nid=0x%08x, addr=0x%x)", func->name, nid, addr);
} }
// writing Thumb code (temporarily, because it should be ARM) const u32 code = get_psv_func_index(func);
vm::psv::write16(addr + 0, 0xf870); // HACK instruction (Thumb) vm::psv::write32(addr + 0, 0xe0700090 | (code & 0xfff0) << 4 | (code & 0xf)); // HACK instruction (ARM)
vm::psv::write16(addr + 2, (u16)get_psv_func_index(func)); // function index
vm::psv::write16(addr + 4, 0x4770); // BX LR
vm::psv::write16(addr + 6, 0); // null
} }
else else
{ {
LOG_ERROR(LOADER, "Unknown function 0x%08x (addr=0x%x)", nid, addr); LOG_ERROR(LOADER, "Unknown function 0x%08x (addr=0x%x)", nid, addr);
vm::psv::write16(addr + 0, 0xf870); // HACK instruction (Thumb) vm::psv::write32(addr + 0, 0xe0700090); // HACK instruction (ARM), unimplemented stub (code 0)
vm::psv::write16(addr + 2, 0); // index 0 (unimplemented stub)
vm::psv::write32(addr + 4, nid); // nid vm::psv::write32(addr + 4, nid); // nid
} }
@ -404,8 +404,7 @@ namespace loader
const u32 stack_size = proc_param->sceUserMainThreadStackSize ? *proc_param->sceUserMainThreadStackSize : 0; const u32 stack_size = proc_param->sceUserMainThreadStackSize ? *proc_param->sceUserMainThreadStackSize : 0;
const u32 priority = proc_param->sceUserMainThreadPriority ? *proc_param->sceUserMainThreadPriority : 0; const u32 priority = proc_param->sceUserMainThreadPriority ? *proc_param->sceUserMainThreadPriority : 0;
/* TODO: Thumb/ARM encoding selection */ armv7_thread(entry, thread_name, stack_size, priority).args({ Emu.GetPath(), "-emu" }).run();
armv7_thread(entry & ~1, thread_name, stack_size, priority).args({ Emu.GetPath(), "-emu" }).run();
break; break;
} }
case MACHINE_SPU: spu_thread(m_ehdr.is_le() ? m_ehdr.data_le.e_entry : m_ehdr.data_be.e_entry, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); break; case MACHINE_SPU: spu_thread(m_ehdr.is_le() ? m_ehdr.data_le.e_entry : m_ehdr.data_be.e_entry, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); break;