mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-30 07:20:13 +00:00
ARMv7: ARM encoding introduced; bugfixes
This commit is contained in:
parent
dab80497bb
commit
23c7028b2a
@ -14,6 +14,12 @@
|
||||
#define __noinline __attribute__((noinline))
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define __safebuffers __declspec(safebuffers)
|
||||
#else
|
||||
#define __safebuffers
|
||||
#endif
|
||||
|
||||
template<size_t size>
|
||||
void strcpy_trunc(char(&dst)[size], const std::string& src)
|
||||
{
|
||||
|
@ -132,5 +132,5 @@ void log_message(Log::LogType type, Log::LogSeverity sev, std::string text);
|
||||
template<typename... Targs>
|
||||
__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)...));
|
||||
}
|
||||
|
@ -144,8 +144,9 @@ size_t fmt::detail::get_fmt_precision(const char* fmt, size_t len)
|
||||
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);
|
||||
if (fmt_start != len)
|
||||
{
|
||||
|
@ -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>
|
||||
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_len = get_fmt_len(fmt + fmt_start, len - fmt_start);
|
||||
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.
|
||||
*/
|
||||
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
|
||||
|
@ -137,7 +137,7 @@ struct ARMv7Context
|
||||
}
|
||||
else
|
||||
{
|
||||
write_pc(value & ~1);
|
||||
write_pc(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1159,9 +1159,44 @@ 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;
|
||||
|
||||
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;
|
||||
|
||||
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 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:
|
||||
if (target >= end_addr && ((target - end_addr) % 16) == 0 && vm::psv::read16(target) == 0xf870)
|
||||
{
|
||||
const u32 instr = vm::psv::read32(target);
|
||||
const u32 instr = vm::psv::read32(target);
|
||||
|
||||
// check if not "unimplemented"
|
||||
if (instr >> 16)
|
||||
// possibly a call to imported function:
|
||||
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
|
||||
vm::psv::write32(addr, instr);
|
||||
// replace BLX with "HACK" instruction directly (in Thumb form), it can help to see where it was called from
|
||||
vm::psv::write32(addr, 0xf870 | func << 16);
|
||||
g_opct[0xf8700000 | func] = g_op4t.HACK();
|
||||
}
|
||||
else
|
||||
{
|
||||
// leave as is if unimplemented
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1257,50 +1297,60 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump)
|
||||
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());
|
||||
}
|
||||
|
||||
u32 ARMv7Decoder::DecodeMemory(const u32 address)
|
||||
{
|
||||
if (address & 0x1)
|
||||
{
|
||||
throw "ARMv7Decoder::DecodeMemory() failed (something is wrong with instruction set)";
|
||||
}
|
||||
|
||||
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);
|
||||
return 2;
|
||||
code.code0 = vm::psv::read16(address);
|
||||
|
||||
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;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
code.code1 = code.code0;
|
||||
code.code0 = vm::psv::read16(address + 2);
|
||||
|
||||
auto op = g_opct.find(code.data);
|
||||
if (op != g_opct.end())
|
||||
else if (m_ctx.ISET == ARM)
|
||||
{
|
||||
(*op->second->func)(m_ctx, code, op->second->type);
|
||||
return 4;
|
||||
code.data = vm::psv::read32(address);
|
||||
|
||||
for (auto opcode : g_op4arm.table)
|
||||
{
|
||||
if ((code.data & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(code.data)))
|
||||
{
|
||||
(*opcode->func)(m_ctx, code, opcode->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
|
||||
{
|
||||
throw "ARMv7Decoder::DecodeMemory() failed (invalid instruction set set)";
|
||||
}
|
||||
|
||||
ARMv7_instrs::UNK(m_ctx, code);
|
||||
return 4;
|
||||
|
||||
|
@ -280,7 +280,14 @@ namespace ARMv7_instrs
|
||||
|
||||
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)
|
||||
@ -976,16 +983,7 @@ void ARMv7_instrs::BLX(ARMv7Context& context, const ARMv7Code code, const ARMv7_
|
||||
if (ConditionPassed(context, cond))
|
||||
{
|
||||
context.LR = newLR;
|
||||
if (target & 1)
|
||||
{
|
||||
context.ISET = Thumb;
|
||||
context.thread.SetBranch(target & ~1);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.ISET = ARM;
|
||||
context.thread.SetBranch(target);
|
||||
}
|
||||
context.write_pc(target);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1014,16 +1012,7 @@ void ARMv7_instrs::BX(ARMv7Context& context, const ARMv7Code code, const ARMv7_e
|
||||
|
||||
if (ConditionPassed(context, cond))
|
||||
{
|
||||
if (target & 1)
|
||||
{
|
||||
context.ISET = Thumb;
|
||||
context.thread.SetBranch(target & ~1);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.ISET = ARM;
|
||||
context.thread.SetBranch(target);
|
||||
}
|
||||
context.write_pc(target);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,8 @@
|
||||
|
||||
void ARMv7Context::write_pc(u32 value)
|
||||
{
|
||||
thread.SetBranch(value);
|
||||
ISET = value & 1 ? Thumb : ARM;
|
||||
thread.SetBranch(value & ~1);
|
||||
}
|
||||
|
||||
u32 ARMv7Context::read_pc()
|
||||
@ -109,10 +110,11 @@ ARMv7Thread::~ARMv7Thread()
|
||||
|
||||
void ARMv7Thread::InitRegs()
|
||||
{
|
||||
memset(context.GPR, 0, sizeof(context.GPR[0]) * 15);
|
||||
memset(context.GPR, 0, sizeof(context.GPR));
|
||||
context.APSR.APSR = 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.SP = m_stack_addr + m_stack_size;
|
||||
context.TLS = armv7_get_tls(GetId());
|
||||
|
@ -48,12 +48,12 @@ s32 sceKernelCreateThread(
|
||||
ARMv7Thread& new_thread = static_cast<ARMv7Thread&>(Emu.GetCPU().AddThread(CPU_THREAD_ARMv7));
|
||||
|
||||
const auto id = new_thread.GetId();
|
||||
new_thread.SetEntry(entry.addr() ^ 1);
|
||||
new_thread.SetEntry(entry.addr());
|
||||
new_thread.SetPrio(initPriority);
|
||||
new_thread.SetStackSize(stackSize);
|
||||
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();
|
||||
return id;
|
||||
|
@ -59,7 +59,7 @@ s32 sceRtcCheckValid(vm::psv::ptr<const SceDateTime> pTime)
|
||||
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__;
|
||||
}
|
||||
@ -69,7 +69,7 @@ s32 sceRtcSetTime64_t(vm::psv::ptr<SceDateTime> pTime, u64 ullTime)
|
||||
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__;
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ namespace vm
|
||||
|
||||
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
|
||||
@ -249,7 +249,10 @@ namespace vm
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -17,9 +17,9 @@ class LogBase
|
||||
void LogOutput(LogType type, const std::string& text) const;
|
||||
|
||||
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:
|
||||
@ -38,7 +38,7 @@ public:
|
||||
template<typename... Targs>
|
||||
__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>
|
||||
@ -53,25 +53,25 @@ public:
|
||||
template<typename... Targs>
|
||||
__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>
|
||||
__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>
|
||||
__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>
|
||||
__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)...);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -372,7 +372,7 @@ s32 cellSaveDataListSave2(
|
||||
for (u32 i=0; i<saveEntries.size(); i++) {
|
||||
strcpy_trunc(dirList[i].dirName, saveEntries[i].dirName);
|
||||
strcpy_trunc(dirList[i].listParam, saveEntries[i].listParam);
|
||||
*dirList[i].reserved = {};
|
||||
memset(dirList[i].reserved, 0, sizeof(dirList[i].reserved));
|
||||
}
|
||||
|
||||
funcList(result, listGet, listSet);
|
||||
@ -464,7 +464,7 @@ s32 cellSaveDataListLoad2(
|
||||
for (u32 i=0; i<saveEntries.size(); i++) {
|
||||
strcpy_trunc(dirList[i].dirName, saveEntries[i].dirName);
|
||||
strcpy_trunc(dirList[i].listParam, saveEntries[i].listParam);
|
||||
*dirList[i].reserved = {};
|
||||
memset(dirList[i].reserved, 0, sizeof(dirList[i].reserved));
|
||||
}
|
||||
|
||||
funcList(result, listGet, listSet);
|
||||
@ -553,7 +553,7 @@ s32 cellSaveDataFixedSave2(
|
||||
for (u32 i = 0; i<saveEntries.size(); i++) {
|
||||
strcpy_trunc(dirList[i].dirName, saveEntries[i].dirName);
|
||||
strcpy_trunc(dirList[i].listParam, saveEntries[i].listParam);
|
||||
*dirList[i].reserved = {};
|
||||
memset(dirList[i].reserved, 0, sizeof(dirList[i].reserved));
|
||||
}
|
||||
funcFixed(result, listGet, fixedSet);
|
||||
if (result->result < 0) {
|
||||
@ -629,7 +629,7 @@ s32 cellSaveDataFixedLoad2(
|
||||
for (u32 i = 0; i<saveEntries.size(); i++) {
|
||||
strcpy_trunc(dirList[i].dirName, saveEntries[i].dirName);
|
||||
strcpy_trunc(dirList[i].listParam, saveEntries[i].listParam);
|
||||
*dirList[i].reserved = {};
|
||||
memset(dirList[i].reserved, 0, sizeof(dirList[i].reserved));
|
||||
}
|
||||
funcFixed(result, listGet, fixedSet);
|
||||
if (result->result < 0) {
|
||||
@ -826,7 +826,7 @@ s32 cellSaveDataListAutoSave(
|
||||
//for (u32 i = 0; i<saveEntries.size(); i++) {
|
||||
// strcpy_trunc(dirList[i].dirName, saveEntries[i].dirName.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);
|
||||
@ -909,7 +909,7 @@ s32 cellSaveDataListAutoLoad(
|
||||
//for (u32 i = 0; i<saveEntries.size(); i++) {
|
||||
// strcpy_trunc(dirList[i].dirName, saveEntries[i].dirName);
|
||||
// strcpy_trunc(dirList[i].listParam, saveEntries[i].listParam);
|
||||
// *dirList[i].reserved = {};
|
||||
// memset(dirList[i].reserved, 0, sizeof(dirList[i].reserved));
|
||||
//}
|
||||
|
||||
//funcFixed(result, listGet, fixedSet);
|
||||
|
@ -850,8 +850,8 @@ void syncLFQueueInit(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u8> buffer, u32 siz
|
||||
queue->m_depth = depth;
|
||||
queue->m_buffer = buffer;
|
||||
queue->m_direction = direction;
|
||||
*queue->m_hs1 = {};
|
||||
*queue->m_hs2 = {};
|
||||
memset(queue->m_hs1, 0, sizeof(queue->m_hs1));
|
||||
memset(queue->m_hs2, 0, sizeof(queue->m_hs2));
|
||||
queue->m_eaSignal = eaSignal;
|
||||
|
||||
if (direction == CELL_SYNC_QUEUE_ANY2ANY)
|
||||
|
@ -217,6 +217,7 @@ int cellVideoOutGetConfiguration(u32 videoOut, vm::ptr<CellVideoOutConfiguration
|
||||
videoOut, config.addr(), option.addr());
|
||||
|
||||
if (option) *option = {};
|
||||
*config = {};
|
||||
|
||||
switch(videoOut)
|
||||
{
|
||||
@ -224,13 +225,11 @@ int cellVideoOutGetConfiguration(u32 videoOut, vm::ptr<CellVideoOutConfiguration
|
||||
config->resolutionId = Emu.GetGSManager().GetInfo().mode.resolutionId;
|
||||
config->format = Emu.GetGSManager().GetInfo().mode.format;
|
||||
config->aspect = Emu.GetGSManager().GetInfo().mode.aspect;
|
||||
*config->reserved = {};
|
||||
config->pitch = Emu.GetGSManager().GetInfo().mode.pitch;
|
||||
|
||||
return CELL_VIDEO_OUT_SUCCEEDED;
|
||||
|
||||
case CELL_VIDEO_OUT_SECONDARY:
|
||||
*config = {}; // ???
|
||||
|
||||
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());
|
||||
|
||||
*state = {};
|
||||
|
||||
switch(audioOut)
|
||||
{
|
||||
case CELL_AUDIO_OUT_PRIMARY:
|
||||
state->state = Emu.GetAudioManager().GetState();
|
||||
state->encoder = Emu.GetAudioManager().GetInfo().mode.encoder;
|
||||
*state->reserved = {};
|
||||
state->downMixer = Emu.GetAudioManager().GetInfo().mode.downMixer;
|
||||
state->soundMode.type = Emu.GetAudioManager().GetInfo().mode.type;
|
||||
state->soundMode.channel = Emu.GetAudioManager().GetInfo().mode.channel;
|
||||
state->soundMode.fs = Emu.GetAudioManager().GetInfo().mode.fs;
|
||||
state->soundMode.reserved = 0;
|
||||
state->soundMode.layout = Emu.GetAudioManager().GetInfo().mode.layout;
|
||||
|
||||
return CELL_AUDIO_OUT_SUCCEEDED;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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());
|
||||
|
||||
if (option) *option = {};
|
||||
*config = {};
|
||||
|
||||
switch(audioOut)
|
||||
{
|
||||
case CELL_AUDIO_OUT_PRIMARY:
|
||||
config->channel = Emu.GetAudioManager().GetInfo().mode.channel;
|
||||
config->encoder = Emu.GetAudioManager().GetInfo().mode.encoder;
|
||||
*config->reserved = {};
|
||||
config->downMixer = Emu.GetAudioManager().GetInfo().mode.downMixer;
|
||||
|
||||
return CELL_AUDIO_OUT_SUCCEEDED;
|
||||
|
||||
case CELL_AUDIO_OUT_SECONDARY:
|
||||
*config = {};
|
||||
|
||||
return CELL_AUDIO_OUT_SUCCEEDED;
|
||||
}
|
||||
|
@ -104,6 +104,10 @@ namespace loader
|
||||
vm::psv::ptr<u32> sceLibcHeapDelayedAlloc;
|
||||
|
||||
u32 unk2;
|
||||
u32 unk3;
|
||||
|
||||
vm::psv::ptr<u32> __sce_libcmallocreplace;
|
||||
vm::psv::ptr<u32> __sce_libcnewreplace;
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// writing Thumb code (temporarily, because it should be ARM)
|
||||
vm::psv::write16(addr + 0, 0xf870); // HACK instruction (Thumb)
|
||||
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
|
||||
const u32 code = get_psv_func_index(func);
|
||||
vm::psv::write32(addr + 0, 0xe0700090 | (code & 0xfff0) << 4 | (code & 0xf)); // HACK instruction (ARM)
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(LOADER, "Unknown function 0x%08x (addr=0x%x)", nid, addr);
|
||||
|
||||
vm::psv::write16(addr + 0, 0xf870); // HACK instruction (Thumb)
|
||||
vm::psv::write16(addr + 2, 0); // index 0 (unimplemented stub)
|
||||
vm::psv::write32(addr + 0, 0xe0700090); // HACK instruction (ARM), unimplemented stub (code 0)
|
||||
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 priority = proc_param->sceUserMainThreadPriority ? *proc_param->sceUserMainThreadPriority : 0;
|
||||
|
||||
/* TODO: Thumb/ARM encoding selection */
|
||||
armv7_thread(entry & ~1, thread_name, stack_size, priority).args({ Emu.GetPath(), "-emu" }).run();
|
||||
armv7_thread(entry, thread_name, stack_size, priority).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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user