diff --git a/CMakeLists.txt b/CMakeLists.txt index 860e4e8b72..1ab9f29001 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -177,8 +177,6 @@ elseif(X86) Common/ABI.h Common/CPUDetect.cpp Common/CPUDetect.h - Common/MathUtil.cpp - Common/MathUtil.h Common/Thunk.cpp Common/Thunk.h Common/x64Analyzer.cpp @@ -220,6 +218,8 @@ add_library(Common STATIC Common/IniFile.h Common/LogManager.cpp Common/LogManager.h + Common/MathUtil.cpp + Common/MathUtil.h Common/MemArena.cpp Common/MemArena.h Common/MemoryUtil.cpp diff --git a/Common/ArmEmitter.cpp b/Common/ArmEmitter.cpp index 72b8040b2b..ad7651d968 100644 --- a/Common/ArmEmitter.cpp +++ b/Common/ArmEmitter.cpp @@ -22,6 +22,10 @@ #include #include +#ifdef __SYMBIAN32__ +#include +#endif + namespace ArmGen { @@ -61,7 +65,11 @@ const u8 *ARMXEmitter::AlignCodePage() void ARMXEmitter::FlushIcache() { +#ifdef __SYMBIAN32__ + User::IMB_Range( startcode, code ); +#else __builtin___clear_cache (startcode, code); +#endif SLEEP(0); } void ARMXEmitter::SetCC(CCFlags cond) @@ -536,4 +544,4 @@ void ARMXEmitter::VMOV(ARMReg Dest, ARMReg Src) } } -} \ No newline at end of file +} diff --git a/Common/ChunkFile.h b/Common/ChunkFile.h index d9866e3f8d..261ac37965 100644 --- a/Common/ChunkFile.h +++ b/Common/ChunkFile.h @@ -261,7 +261,7 @@ public: case MODE_READ: x = (wchar_t*)*ptr; break; case MODE_WRITE: memcpy(*ptr, x.c_str(), stringLen); break; case MODE_MEASURE: break; - case MODE_VERIFY: _dbg_assert_msg_(COMMON, x == (wchar_t*)*ptr, "Savestate verification failure: \"%s\" != \"%s\" (at %p).\n", x.c_str(), (wchar_t*)*ptr, ptr); break; + case MODE_VERIFY: _dbg_assert_msg_(COMMON, x == (wchar_t*)*ptr, "Savestate verification failure: \"%ls\" != \"%ls\" (at %p).\n", x.c_str(), (wchar_t*)*ptr, ptr); break; } (*ptr) += stringLen; } diff --git a/Common/MemoryUtil.cpp b/Common/MemoryUtil.cpp index f4ff4da1a5..d3be724610 100644 --- a/Common/MemoryUtil.cpp +++ b/Common/MemoryUtil.cpp @@ -45,6 +45,12 @@ #define round_page(x) ((((unsigned long)(x)) + PAGE_MASK) & ~(PAGE_MASK)) #endif +#ifdef __SYMBIAN32__ +#include +#define SYMBIAN_CODECHUNCK_SIZE 1024*1024*17; +static RChunk* g_code_chunk = NULL; +static RHeap* g_code_heap = NULL; +#endif // This is purposely not a full wrapper for virtualalloc/mmap, but it // provides exactly the primitive operations that Dolphin needs. @@ -54,9 +60,16 @@ void* AllocateExecutableMemory(size_t size, bool low) #if defined(_WIN32) void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); #elif defined(__SYMBIAN32__) - // On Symbian, we will need to create an RChunk and allocate with ->CreateLocalCode(size, size); - static char *map_hint = 0; - void* ptr = mmap(map_hint, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, -1, 0); + //This function may be called more than once, and we want to create only one big + //memory chunck for all the executable code for the JIT + if( g_code_chunk == NULL && g_code_heap == NULL) + { + TInt minsize = SYMBIAN_CODECHUNCK_SIZE; + TInt maxsize = SYMBIAN_CODECHUNCK_SIZE + 3*4096; //some offsets + g_code_chunk->CreateLocalCode(minsize, maxsize); + g_code_heap = UserHeap::ChunkHeap(*g_code_chunk, minsize, 1, maxsize); + } + void* ptr = (void*) g_code_heap->Alloc( size ); #else static char *map_hint = 0; #if defined(__x86_64__) && !defined(MAP_32BIT) @@ -143,7 +156,8 @@ void* AllocateAlignedMemory(size_t size,size_t alignment) // On Symbian, we will want to create an RChunk. ptr = malloc(size); #else - posix_memalign(&ptr, alignment, size); + if(posix_memalign(&ptr, alignment, size) != 0) + ptr = NULL; #endif #endif diff --git a/Common/StringUtil.cpp b/Common/StringUtil.cpp index ae0a09b0c4..189b82e158 100644 --- a/Common/StringUtil.cpp +++ b/Common/StringUtil.cpp @@ -55,25 +55,30 @@ std::string StringFromFormat(const char* format, ...) { va_list args; char *buf = NULL; + std::string temp = ""; #ifdef _WIN32 int required = 0; va_start(args, format); required = _vscprintf(format, args); buf = new char[required + 1]; - vsnprintf(buf, required, format, args); + if(vsnprintf(buf, required, format, args) < 0) + buf[0] = '\0'; va_end(args); buf[required] = '\0'; - std::string temp = buf; + temp = buf; delete[] buf; #else va_start(args, format); - vasprintf(&buf, format, args); + if(vasprintf(&buf, format, args) < 0) + buf = NULL; va_end(args); - std::string temp = buf; - free(buf); + if(buf != NULL) { + temp = buf; + free(buf); + } #endif return temp; } diff --git a/Core/Debugger/SymbolMap.cpp b/Core/Debugger/SymbolMap.cpp index c2481ec71d..a78049620f 100644 --- a/Core/Debugger/SymbolMap.cpp +++ b/Core/Debugger/SymbolMap.cpp @@ -143,7 +143,10 @@ bool SymbolMap::LoadSymbolMap(const char *filename) while (!feof(f)) { char line[512],temp[256]; - fgets(line,511,f); + char *p = fgets(line,512,f); + if(p == NULL) + break; + if (strlen(line) < 4 || sscanf(line, "%s", temp) != 1) continue; diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index 00b539fc4b..44ba6a200b 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -123,7 +123,7 @@ void PSPOskDialog::RenderKeyboard() else temp[0] = '_'; - PPGeDrawText(temp, previewLeftSide + (i * 16.0f), 40.0f, NULL, 0.5f, color); + PPGeDrawText(temp, previewLeftSide + (i * 16.0f), 40.0f, 0, 0.5f, color); } for (int row = 0; row < NUMKEYROWS; ++row) { @@ -134,10 +134,10 @@ void PSPOskDialog::RenderKeyboard() color = 0xFF7f7f7f; temp[0] = oskKeys[row][col]; - PPGeDrawText(temp, keyboardLeftSide + (25.0f * col), 70.0f + (25.0f * row), NULL, 0.6f, color); + PPGeDrawText(temp, keyboardLeftSide + (25.0f * col), 70.0f + (25.0f * row), 0, 0.6f, color); if (selectedRow == row && col == selectedExtra) - PPGeDrawText("_", keyboardLeftSide + (25.0f * col), 70.0f + (25.0f * row), NULL, 0.6f, 0xFFFFFFFF); + PPGeDrawText("_", keyboardLeftSide + (25.0f * col), 70.0f + (25.0f * row), 0, 0.6f, 0xFFFFFFFF); } } diff --git a/Core/FileSystems/BlockDevices.cpp b/Core/FileSystems/BlockDevices.cpp index 025e3427ea..2af43646f0 100644 --- a/Core/FileSystems/BlockDevices.cpp +++ b/Core/FileSystems/BlockDevices.cpp @@ -41,7 +41,9 @@ FileBlockDevice::~FileBlockDevice() bool FileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr) { fseek(f, blockNumber * GetBlockSize(), SEEK_SET); - fread(outPtr, 2048, 1, f); + if(fread(outPtr, 1, 2048, f) != 2048) + DEBUG_LOG(LOADER, "Could not read 2048 bytes from block"); + return true; } @@ -80,10 +82,10 @@ CISOFileBlockDevice::CISOFileBlockDevice(std::string _filename) f = fopen(_filename.c_str(), "rb"); CISO_H hdr; - fread(&hdr, 1, sizeof(CISO_H), f); - if (memcmp(hdr.magic, "CISO", 4) != 0) + size_t readSize = fread(&hdr, sizeof(CISO_H), 1, f); + if (readSize != 1 || memcmp(hdr.magic, "CISO", 4) != 0) { - //ARGH! + WARN_LOG(LOADER, "Invalid CSO!"); } else { @@ -109,7 +111,8 @@ CISOFileBlockDevice::CISOFileBlockDevice(std::string _filename) int indexSize = numBlocks + 1; index = new u32[indexSize]; - fread(index, 4, indexSize, f); + if(fread(index, sizeof(u32), indexSize, f) != indexSize) + memset(index, 0, indexSize * sizeof(u32)); } CISOFileBlockDevice::~CISOFileBlockDevice() @@ -134,12 +137,12 @@ bool CISOFileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr) u32 compressedReadSize = idx2 - idx; fseek(f, compressedReadPos, SEEK_SET); - fread(inbuffer, compressedReadSize, 1, f); + size_t readSize = fread(inbuffer, 1, compressedReadSize, f); if (plain) { memset(outPtr, 0, 2048); - memcpy(outPtr, inbuffer, compressedReadSize); + memcpy(outPtr, inbuffer, readSize); } else { @@ -152,7 +155,7 @@ bool CISOFileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr) ERROR_LOG(LOADER, "deflateInit ERROR : %s\n", (z.msg) ? z.msg : "???"); return 1; } - z.avail_in = compressedReadSize; + z.avail_in = readSize; z.next_out = outPtr; z.avail_out = blockSize; z.next_in = inbuffer; diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index 70787af6fe..cc100517fc 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -201,6 +201,11 @@ template void WrapU_UIIIII() { RETURN(retval); } +template void WrapU_UIIIU() { + u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); + RETURN(retval); +} + template void WrapU_UIIIIII() { u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5), PARAM(6)); RETURN(retval); @@ -211,6 +216,11 @@ template void WrapU_UU() { RETURN(retval); } +template void WrapU_UUI() { + u32 retval = func(PARAM(0), PARAM(1), PARAM(2)); + RETURN(retval); +} + template void WrapU_CUUU() { u32 retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3)); RETURN(retval); @@ -225,6 +235,11 @@ template void WrapU_UIUII() { RETURN(retval); } +template void WrapU_UIUU() { + u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); + RETURN(retval); +} + template void WrapU_UII() { u32 retval = func(PARAM(0), PARAM(1), PARAM(2)); RETURN(retval); @@ -439,6 +454,11 @@ template void WrapU_UUUI() { RETURN(retval); } +template void WrapU_UUUIU() { + u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); + RETURN(retval); +} + template void WrapU_UUIU() { u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); RETURN(retval); diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index 2ebb7b5149..4fcb6b93c1 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -51,6 +51,7 @@ enum static std::vector moduleDB; static std::vector unresolvedSyscalls; +static std::vector exportedCalls; static int hleAfterSyscall = HLE_AFTER_NOTHING; static char hleAfterSyscallReschedReason[512]; @@ -63,6 +64,7 @@ void HLEDoState(PointerWrap &p) { Syscall sc = {0}; p.Do(unresolvedSyscalls, sc); + p.Do(exportedCalls, sc); p.DoMarker("HLE"); } @@ -71,6 +73,7 @@ void HLEShutdown() hleAfterSyscall = HLE_AFTER_NOTHING; moduleDB.clear(); unresolvedSyscalls.clear(); + exportedCalls.clear(); } void RegisterModule(const char *name, int numFunctions, const HLEFunction *funcTable) @@ -124,15 +127,26 @@ const HLEFunction *GetFunc(const char *moduleName, u32 nib) const char *GetFuncName(const char *moduleName, u32 nib) { + _dbg_assert_msg_(HLE, moduleName != NULL, "Invalid module name."); + const HLEFunction *func = GetFunc(moduleName,nib); if (func) return func->name; - else + + // Was this function exported previously? + static char temp[256]; + for (auto it = exportedCalls.begin(), end = exportedCalls.end(); it != end; ++it) { - static char temp[256]; - sprintf(temp,"[UNK: 0x%08x ]",nib); - return temp; + if (!strcmp(it->moduleName, moduleName) && it->nid == nib) + { + sprintf(temp, "[EXP: 0x%08x]", nib); + return temp; + } } + + // No good, we can't find it. + sprintf(temp,"[UNK: 0x%08x]", nib); + return temp; } u32 GetSyscallOp(const char *moduleName, u32 nib) @@ -173,17 +187,34 @@ void WriteSyscall(const char *moduleName, u32 nib, u32 address) } else { + // Did another module export this already? + for (auto it = exportedCalls.begin(), end = exportedCalls.end(); it != end; ++it) + { + if (!strcmp(it->moduleName, moduleName) && it->nid == nib) + { + Memory::Write_U32(MIPS_MAKE_J(it->symAddr), address); // j symAddr + Memory::Write_U32(MIPS_MAKE_NOP(), address + 4); // nop (delay slot) + return; + } + } + // Module inexistent.. for now; let's store the syscall for it to be resolved later INFO_LOG(HLE,"Syscall (%s,%08x) unresolved, storing for later resolving", moduleName, nib); Syscall sysc = {"", address, nib}; - strncpy(sysc.moduleName, moduleName, 32); - sysc.moduleName[31] = '\0'; + strncpy(sysc.moduleName, moduleName, KERNELOBJECT_MAX_NAME_LENGTH); + sysc.moduleName[KERNELOBJECT_MAX_NAME_LENGTH] = '\0'; unresolvedSyscalls.push_back(sysc); + + // Write a trap so we notice this func if it's called before resolving. + Memory::Write_U32(MIPS_MAKE_JR_RA(), address); // jr ra + Memory::Write_U32(GetSyscallOp("(invalid syscall)", nib), address + 4); } } void ResolveSyscall(const char *moduleName, u32 nib, u32 address) { + _dbg_assert_msg_(HLE, moduleName != NULL, "Invalid module name."); + for (size_t i = 0; i < unresolvedSyscalls.size(); i++) { Syscall *sysc = &unresolvedSyscalls[i]; @@ -196,6 +227,11 @@ void ResolveSyscall(const char *moduleName, u32 nib, u32 address) Memory::Write_U32(MIPS_MAKE_NOP(), sysc->symAddr + 4); } } + + Syscall ex = {"", address, nib}; + strncpy(ex.moduleName, moduleName, KERNELOBJECT_MAX_NAME_LENGTH); + ex.moduleName[KERNELOBJECT_MAX_NAME_LENGTH] = '\0'; + exportedCalls.push_back(ex); } const char *GetFuncName(int moduleIndex, int func) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 9a07bd8f6f..1ab805cf49 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -377,6 +377,7 @@ const HLEFunction sceAtrac3plus[] = {0x9CD7DE03,0,"sceAtracSetMOutHalfwayBufferAndGetID"}, {0x5622B7C1,WrapI_UIIU,"sceAtracSetAA3DataAndGetID"}, {0x5DD66588,0,"sceAtracSetAA3HalfwayBufferAndGetID"}, + {0x231FC6B7,0,"_sceAtracGetContextAddress"}, }; diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 698c76c0c3..26909f5574 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -549,7 +549,7 @@ const HLEFunction ThreadManForUser[] = {0x52089CA1,sceKernelGetThreadStackFreeSize,"sceKernelGetThreadStackFreeSize"}, {0xFFC36A14,WrapU_UU,"sceKernelReferThreadRunStatus"}, {0x17c1684e,WrapU_UU,"sceKernelReferThreadStatus"}, - {0x2C34E053,0,"sceKernelReleaseWaitThread"}, + {0x2C34E053,WrapI_I,"sceKernelReleaseWaitThread"}, {0x75156e8f,sceKernelResumeThread,"sceKernelResumeThread"}, {0x3ad58b8c,&WrapU_V,"sceKernelSuspendDispatchThread"}, {0x27e22ec2,&WrapU_U,"sceKernelResumeDispatchThread"}, @@ -560,7 +560,7 @@ const HLEFunction ThreadManForUser[] = {0x9944f31f,sceKernelSuspendThread,"sceKernelSuspendThread"}, {0x616403ba,WrapI_U,"sceKernelTerminateThread"}, {0x383f7bcc,WrapI_I,"sceKernelTerminateDeleteThread"}, - {0x840E8133,sceKernelWaitThreadEndCB,"sceKernelWaitThreadEndCB"}, + {0x840E8133,WrapI_IU,"sceKernelWaitThreadEndCB"}, {0xd13bde95,sceKernelCheckThreadStack,"sceKernelCheckThreadStack"}, {0x94416130,WrapU_UUUU,"sceKernelGetThreadmanIdList"}, @@ -586,7 +586,7 @@ const HLEFunction ThreadManForUser[] = {0xE1619D7C,sceKernelSysClock2USecWide,"sceKernelSysClock2USecWide"}, {0x110dec9a,sceKernelUSec2SysClock,"sceKernelUSec2SysClock"}, - {0x278C0DF5,sceKernelWaitThreadEnd,"sceKernelWaitThreadEnd"}, + {0x278C0DF5,WrapI_IU,"sceKernelWaitThreadEnd"}, {0xd59ead2f,sceKernelWakeupThread,"sceKernelWakeupThread"}, //AI Go, audio? {0x0C106E53,0,"sceKernelRegisterThreadEventHandler"}, diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 3a5907dd40..94319a8ccc 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -44,6 +44,22 @@ enum { PSP_THREAD_ATTR_USER = 0x80000000 }; +enum { + // Function exports. + NID_MODULE_START = 0xD632ACDB, + NID_MODULE_STOP = 0xCEE8593C, + NID_MODULE_REBOOT_BEFORE = 0x2F064FA6, + NID_MODULE_REBOOT_PHASE = 0xADF12745, + NID_MODULE_BOOTSTART = 0xD3744BE0, + + // Variable exports. + NID_MODULE_INFO = 0xF01D73A7, + NID_MODULE_START_THREAD_PARAMETER = 0x0F7C276C, + NID_MODULE_STOP_THREAD_PARAMETER = 0xCF0CC697, + NID_MODULE_REBOOT_BEFORE_THREAD_PARAMETER = 0xF4F4299D, + NID_MODULE_SDK_VERSION = 0x11B97506, +}; + static const char *blacklistedModules[] = { "sceATRAC3plus_Library", "sceFont_Library", @@ -229,6 +245,7 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro { Module *module = new Module; kernelObjects.Create(module); + memset(&module->nm, 0, sizeof(module->nm)); u8 *newptr = 0; if (*(u32*)ptr == 0x4543537e) { // "~SCE" @@ -464,8 +481,68 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro { u32 nid = residentPtr[j]; u32 exportAddr = residentPtr[ent->fcount + ent->vcount + j]; - ResolveSyscall(name, nid, exportAddr); + + switch (nid) + { + case NID_MODULE_START: + module->nm.module_start_func = exportAddr; + break; + case NID_MODULE_STOP: + module->nm.module_stop_func = exportAddr; + break; + case NID_MODULE_REBOOT_BEFORE: + module->nm.module_reboot_before_func = exportAddr; + break; + case NID_MODULE_REBOOT_PHASE: + module->nm.module_reboot_phase_func = exportAddr; + break; + case NID_MODULE_BOOTSTART: + module->nm.module_bootstart_func = exportAddr; + break; + default: + ResolveSyscall(name, nid, exportAddr); + } } + + for (u32 j = 0; j < ent->vcount; j++) + { + u32 nid = residentPtr[ent->fcount + j]; + u32 exportAddr = residentPtr[ent->fcount + ent->vcount + ent->fcount + j]; + + switch (nid) + { + case NID_MODULE_INFO: + break; + case NID_MODULE_START_THREAD_PARAMETER: + if (Memory::Read_U32(exportAddr) != 3) + WARN_LOG(LOADER, "Strange value at module_start_thread_parameter export: %08x", Memory::Read_U32(exportAddr)); + module->nm.module_start_thread_priority = Memory::Read_U32(exportAddr + 4); + module->nm.module_start_thread_stacksize = Memory::Read_U32(exportAddr + 8); + module->nm.module_start_thread_attr = Memory::Read_U32(exportAddr + 12); + break; + case NID_MODULE_STOP_THREAD_PARAMETER: + if (Memory::Read_U32(exportAddr) != 3) + WARN_LOG(LOADER, "Strange value at module_stop_thread_parameter export: %08x", Memory::Read_U32(exportAddr)); + module->nm.module_stop_thread_priority = Memory::Read_U32(exportAddr + 4); + module->nm.module_stop_thread_stacksize = Memory::Read_U32(exportAddr + 8); + module->nm.module_stop_thread_attr = Memory::Read_U32(exportAddr + 12); + break; + case NID_MODULE_REBOOT_BEFORE_THREAD_PARAMETER: + if (Memory::Read_U32(exportAddr) != 3) + WARN_LOG(LOADER, "Strange value at module_reboot_before_thread_parameter export: %08x", Memory::Read_U32(exportAddr)); + module->nm.module_reboot_before_thread_priority = Memory::Read_U32(exportAddr + 4); + module->nm.module_reboot_before_thread_stacksize = Memory::Read_U32(exportAddr + 8); + module->nm.module_reboot_before_thread_attr = Memory::Read_U32(exportAddr + 12); + break; + case NID_MODULE_SDK_VERSION: + DEBUG_LOG(LOADER, "Module SDK: %08x", Memory::Read_U32(exportAddr)); + break; + default: + DEBUG_LOG(LOADER, "Unexpected variable with nid: %08x", nid); + break; + } + } + if (ent->size > 4) { ent = (PspLibEntEntry*)((u8*)ent + ent->size * 4); @@ -562,6 +639,12 @@ Module *__KernelLoadModule(u8 *fileptr, SceKernelLMOption *options, std::string void __KernelStartModule(Module *m, int args, const char *argp, SceKernelSMOption *options) { + if (m->nm.module_start_func != 0 || m->nm.module_start_func != -1) + { + if (m->nm.module_start_func != m->nm.entry_addr) + WARN_LOG(LOADER, "Main module has start func (%08x) different from entry (%08x)?", m->nm.module_start_func, m->nm.entry_addr); + } + __KernelSetupRootThread(m->GetUID(), args, argp, options->priority, options->stacksize, options->attribute); mainModuleID = m->GetUID(); //TODO: if current thread, put it in wait state, waiting for the new thread @@ -621,6 +704,14 @@ bool __KernelLoadExec(const char *filename, SceKernelLoadExecParam *param, std:: option.priority = 0x20; option.stacksize = 0x40000; // crazy? but seems to be the truth + // Replace start options with module-specified values if they exist. + if (module->nm.module_start_thread_attr != 0) + option.attribute = module->nm.module_start_thread_attr; + if (module->nm.module_start_thread_priority != 0) + option.priority = module->nm.module_start_thread_priority; + if (module->nm.module_start_thread_stacksize != 0) + option.stacksize = module->nm.module_start_thread_stacksize; + __KernelStartModule(module, (u32)strlen(filename) + 1, filename, &option); __KernelStartIdleThreads(); diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index df4945d9bb..2f6788b274 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -412,7 +412,7 @@ public: // Utils bool isRunning() const { return (nt.status & THREADSTATUS_RUNNING) != 0; } bool isStopped() const { return (nt.status & THREADSTATUS_DORMANT) != 0; } - bool isReady() const { return (nt.status & THREADSTATUS_DORMANT) != 0; } + bool isReady() const { return (nt.status & THREADSTATUS_READY) != 0; } bool isWaiting() const { return (nt.status & THREADSTATUS_WAIT) != 0; } bool isSuspended() const { return (nt.status & THREADSTATUS_SUSPEND) != 0; } @@ -468,6 +468,7 @@ void __KernelExecuteMipsCallOnCurrentThread(int callId, bool reschedAfter); Thread *__KernelCreateThread(SceUID &id, SceUID moduleID, const char *name, u32 entryPoint, u32 priority, int stacksize, u32 attr); void __KernelResetThread(Thread *t); void __KernelCancelWakeup(SceUID threadID); +void __KernelCancelThreadEndTimeout(SceUID threadID); bool __KernelCheckThreadCallbacks(Thread *thread, bool force); ////////////////////////////////////////////////////////////////////////// @@ -485,6 +486,7 @@ std::vector threadEndListeners; SceUID threadIdleID[2]; int eventScheduledWakeup; +int eventThreadEndTimeout; bool dispatchEnabled = true; @@ -570,6 +572,7 @@ u32 __KernelInterruptReturnAddress() } void hleScheduledWakeup(u64 userdata, int cyclesLate); +void hleThreadEndTimeout(u64 userdata, int cyclesLate); void __KernelThreadingInit() { @@ -600,6 +603,7 @@ void __KernelThreadingInit() WriteSyscall("FakeSysCalls", NID_INTERRUPTRETURN, intReturnHackAddr); eventScheduledWakeup = CoreTiming::RegisterEvent("ScheduledWakeup", &hleScheduledWakeup); + eventThreadEndTimeout = CoreTiming::RegisterEvent("ThreadEndTimeout", &hleThreadEndTimeout); actionAfterMipsCall = __KernelRegisterActionType(ActionAfterMipsCall::Create); actionAfterCallback = __KernelRegisterActionType(ActionAfterCallback::Create); @@ -610,6 +614,7 @@ void __KernelThreadingInit() // These idle threads are later started in LoadExec, which calls __KernelStartIdleThreads below. __KernelListenThreadEnd(__KernelCancelWakeup); + __KernelListenThreadEnd(__KernelCancelThreadEndTimeout); } void __KernelThreadingDoState(PointerWrap &p) @@ -629,6 +634,8 @@ void __KernelThreadingDoState(PointerWrap &p) p.Do(eventScheduledWakeup); CoreTiming::RestoreRegisterEvent(eventScheduledWakeup, "ScheduledWakeup", &hleScheduledWakeup); + p.Do(eventThreadEndTimeout); + CoreTiming::RestoreRegisterEvent(eventThreadEndTimeout, "ThreadEndTimeout", &hleThreadEndTimeout); p.Do(actionAfterMipsCall); __KernelRestoreActionType(actionAfterMipsCall, ActionAfterMipsCall::Create); p.Do(actionAfterCallback); @@ -1066,6 +1073,34 @@ void __KernelCancelWakeup(SceUID threadID) CoreTiming::UnscheduleEvent(eventScheduledWakeup, threadID); } +void hleThreadEndTimeout(u64 userdata, int cyclesLate) +{ + SceUID threadID = (SceUID) userdata; + SceUID waitID = (SceUID) (userdata >> 32); + + u32 error; + // Just in case it was woken on its own. + if (__KernelGetWaitID(threadID, WAITTYPE_THREADEND, error) == waitID) + { + u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); + if (Memory::IsValidAddress(timeoutPtr)) + Memory::Write_U32(0, timeoutPtr); + + __KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_TIMEOUT); + } +} + +void __KernelScheduleThreadEndTimeout(SceUID threadID, SceUID waitID, s64 usFromNow) +{ + s64 cycles = usToCycles(usFromNow); + CoreTiming::ScheduleEvent(cycles, eventThreadEndTimeout, (u64) threadID | ((u64) waitID << 32)); +} + +void __KernelCancelThreadEndTimeout(SceUID threadID) +{ + CoreTiming::UnscheduleEvent(eventThreadEndTimeout, threadID); +} + void __KernelRemoveFromThreadQueue(Thread *t) { for (size_t i = 0; i < threadqueue.size(); i++) @@ -1240,7 +1275,7 @@ void __KernelResetThread(Thread *t) t->nt.waitID = 0; memset(&t->waitInfo, 0, sizeof(t->waitInfo)); - t->nt.exitStatus = 0; + t->nt.exitStatus = SCE_KERNEL_ERROR_NOT_DORMANT; t->isProcessingCallbacks = false; // TODO: Is this correct? t->pendingMipsCalls.clear(); @@ -1273,7 +1308,7 @@ Thread *__KernelCreateThread(SceUID &id, SceUID moduleId, const char *name, u32 t->nt.wakeupCount = 0; t->nt.initialStack = 0; t->nt.waitID = 0; - t->nt.exitStatus = 0; + t->nt.exitStatus = SCE_KERNEL_ERROR_DORMANT; t->nt.waitType = WAITTYPE_NONE; if (moduleId) @@ -1282,11 +1317,8 @@ Thread *__KernelCreateThread(SceUID &id, SceUID moduleId, const char *name, u32 t->nt.gpreg = 0; // sceKernelStartThread will take care of this. t->moduleId = moduleId; - if (name) { - strncpy(t->nt.name, name, 32); - } else { - ERROR_LOG(HLE, "Threads must have names!"); - } + strncpy(t->nt.name, name, KERNELOBJECT_MAX_NAME_LENGTH); + t->nt.name[KERNELOBJECT_MAX_NAME_LENGTH] = '\0'; return t; } @@ -1315,6 +1347,27 @@ void __KernelSetupRootThread(SceUID moduleID, int args, const char *argp, int pr int sceKernelCreateThread(const char *threadName, u32 entry, u32 prio, int stacksize, u32 attr, u32 optionAddr) { + if (threadName == NULL) + { + ERROR_LOG(HLE, "SCE_KERNEL_ERROR_ERROR = sceKernelCreateThread(): NULL name"); + return SCE_KERNEL_ERROR_ERROR; + } + + // TODO: PSP actually fails for many of these cases, but trying for compat. + if (stacksize < 0x200 || stacksize >= 0x20000000) + { + WARN_LOG(HLE, "sceKernelCreateThread(name=\"%s\"): bogus stack size %08x, using 0x4000", threadName, stacksize); + stacksize = 0x4000; + } + if (prio < 0x08 || prio > 0x77) + WARN_LOG(HLE, "sceKernelCreateThread(name=\"%s\"): bogus priority %08x", threadName, prio); + if (!Memory::IsValidAddress(entry)) + WARN_LOG(HLE, "sceKernelCreateThread(name=\"%s\"): invalid entry %08x", threadName, entry); + + // We're assuming all threads created are user threads. + if ((attr & PSP_THREAD_ATTR_KERNEL) == 0) + attr |= PSP_THREAD_ATTR_USER; + SceUID id; __KernelCreateThread(id, curModule, threadName, entry, prio, stacksize, attr); INFO_LOG(HLE, "%i = sceKernelCreateThread(name=\"%s\", entry=%08x, prio=%x, stacksize=%i)", id, threadName, entry, prio, stacksize); @@ -1426,16 +1479,14 @@ void __KernelReturnFromThread() thread->FreeStack(); } - thread->nt.exitStatus = thread->context.r[2]; + thread->nt.exitStatus = currentMIPS->r[2]; thread->nt.status = THREADSTATUS_DORMANT; __KernelFireThreadEnd(thread); // TODO: Need to remove the thread from any ready queues. - // Find threads that waited for me - // Wake them - if (!__KernelTriggerWait(WAITTYPE_THREADEND, __KernelGetCurThread())) - hleReSchedule("return from thread"); + __KernelTriggerWait(WAITTYPE_THREADEND, __KernelGetCurThread(), thread->nt.exitStatus, true); + hleReSchedule("thread returned"); // The stack will be deallocated when the thread is deleted. } @@ -1450,10 +1501,8 @@ void sceKernelExitThread() thread->nt.exitStatus = PARAM(0); __KernelFireThreadEnd(thread); - //Find threads that waited for me - // Wake them - if (!__KernelTriggerWait(WAITTYPE_THREADEND, __KernelGetCurThread())) - hleReSchedule("exited thread"); + __KernelTriggerWait(WAITTYPE_THREADEND, __KernelGetCurThread(), thread->nt.exitStatus, true); + hleReSchedule("thread exited"); // The stack will be deallocated when the thread is deleted. } @@ -1468,10 +1517,8 @@ void _sceKernelExitThread() thread->nt.exitStatus = PARAM(0); __KernelFireThreadEnd(thread); - //Find threads that waited for this one - // Wake them - if (!__KernelTriggerWait(WAITTYPE_THREADEND, __KernelGetCurThread())) - hleReSchedule("_exit thread"); + __KernelTriggerWait(WAITTYPE_THREADEND, __KernelGetCurThread(), thread->nt.exitStatus, true); + hleReSchedule("thread _exited"); // The stack will be deallocated when the thread is deleted. } @@ -1487,15 +1534,17 @@ void sceKernelExitDeleteThread() t->nt.status = THREADSTATUS_DORMANT; t->nt.exitStatus = PARAM(0); __KernelFireThreadEnd(t); + // TODO: Why not? //userMemory.Free(currentThread->stackBlock); t->stackBlock = 0; __KernelRemoveFromThreadQueue(t); currentThread = 0; - RETURN(kernelObjects.Destroy(threadHandle)); + __KernelTriggerWait(WAITTYPE_THREADEND, threadHandle, t->nt.exitStatus, true); + hleReSchedule("thead exited with delete"); - __KernelTriggerWait(WAITTYPE_THREADEND, threadHandle); + RETURN(kernelObjects.Destroy(threadHandle)); } else { @@ -1540,11 +1589,9 @@ int sceKernelDeleteThread(int threadHandle) __KernelRemoveFromThreadQueue(t); __KernelFireThreadEnd(t); - __KernelTriggerWait(WAITTYPE_THREADEND, threadHandle); + // TODO: Should this reschedule ever? Probably no? + __KernelTriggerWait(WAITTYPE_THREADEND, threadHandle, SCE_KERNEL_ERROR_THREAD_TERMINATED, true); - //TODO: should we really reschedule here? - //if (!__KernelTriggerWait(WAITTYPE_THREADEND, threadHandle)) - // hleReSchedule("thread deleted"); return kernelObjects.Destroy(threadHandle); } @@ -1566,8 +1613,8 @@ int sceKernelTerminateDeleteThread(int threadno) INFO_LOG(HLE, "sceKernelTerminateDeleteThread(%i)", threadno); //TODO: should we really reschedule here? - if (!__KernelTriggerWait(WAITTYPE_THREADEND, threadno)) - hleReSchedule("termdeletethread"); + __KernelTriggerWait(WAITTYPE_THREADEND, threadno, SCE_KERNEL_ERROR_THREAD_TERMINATED, false); + hleReSchedule("termdeletethread"); // TODO: Why not delete? return 0; //kernelObjects.Destroy(threadno)); @@ -1589,9 +1636,11 @@ int sceKernelTerminateThread(u32 threadID) Thread *t = kernelObjects.Get(threadID, error); if (t) { + t->nt.exitStatus = SCE_KERNEL_ERROR_THREAD_TERMINATED; t->nt.status = THREADSTATUS_DORMANT; __KernelFireThreadEnd(t); - __KernelTriggerWait(WAITTYPE_THREADEND, threadID); + // TODO: Should this really reschedule? + __KernelTriggerWait(WAITTYPE_THREADEND, threadID, t->nt.exitStatus, true); } // TODO: Return an error if it doesn't exist? return 0; @@ -1811,47 +1860,84 @@ void sceKernelSleepThreadCB() __KernelCheckCallbacks(); } -void sceKernelWaitThreadEnd() +int sceKernelWaitThreadEnd(SceUID threadID, u32 timeoutPtr) { - SceUID id = PARAM(0); - DEBUG_LOG(HLE,"sceKernelWaitThreadEnd(%i)",id); + DEBUG_LOG(HLE, "sceKernelWaitThreadEnd(%i, %08x)", threadID); + if (threadID == 0 || threadID == currentThread) + return SCE_KERNEL_ERROR_ILLEGAL_THID; + u32 error; - Thread *t = kernelObjects.Get(id, error); + Thread *t = kernelObjects.Get(threadID, error); if (t) { - if (t->nt.status != THREADSTATUS_DORMANT) { - __KernelWaitCurThread(WAITTYPE_THREADEND, id, 0, 0, false); - } else { - DEBUG_LOG(HLE,"sceKernelWaitThreadEnd - thread %i already ended. Doing nothing.", id); + if (t->nt.status != THREADSTATUS_DORMANT) + { + if (Memory::IsValidAddress(timeoutPtr)) + __KernelScheduleThreadEndTimeout(currentThread, threadID, Memory::Read_U32(timeoutPtr)); + __KernelWaitCurThread(WAITTYPE_THREADEND, threadID, 0, timeoutPtr, false); } + + return t->nt.exitStatus; } else { - ERROR_LOG(HLE,"sceKernelWaitThreadEnd - bad thread %i", id); + ERROR_LOG(HLE, "sceKernelWaitThreadEnd - bad thread %i", threadID); + return error; } - RETURN(0); } -void sceKernelWaitThreadEndCB() +int sceKernelWaitThreadEndCB(SceUID threadID, u32 timeoutPtr) { - SceUID id = PARAM(0); - DEBUG_LOG(HLE,"sceKernelWaitThreadEnd(%i)",id); + DEBUG_LOG(HLE, "sceKernelWaitThreadEnd(%i)", threadID); + if (threadID == 0 || threadID == currentThread) + return SCE_KERNEL_ERROR_ILLEGAL_THID; + u32 error; - Thread *t = kernelObjects.Get(id, error); + Thread *t = kernelObjects.Get(threadID, error); if (t) { - if (t->nt.status != THREADSTATUS_DORMANT) { - __KernelWaitCurThread(WAITTYPE_THREADEND, id, 0, 0, true); - } else { - DEBUG_LOG(HLE,"sceKernelWaitThreadEnd - thread %i already ended. Doing nothing.", id); + hleCheckCurrentCallbacks(); + if (t->nt.status != THREADSTATUS_DORMANT) + { + if (Memory::IsValidAddress(timeoutPtr)) + __KernelScheduleThreadEndTimeout(currentThread, threadID, Memory::Read_U32(timeoutPtr)); + __KernelWaitCurThread(WAITTYPE_THREADEND, threadID, 0, timeoutPtr, true); } - __KernelCheckCallbacks(); + + return t->nt.exitStatus; } else { - ERROR_LOG(HLE,"sceKernelWaitThreadEnd - bad thread %i", id); + ERROR_LOG(HLE, "sceKernelWaitThreadEnd - bad thread %i", threadID); + return error; + } +} + +int sceKernelReleaseWaitThread(SceUID threadID) +{ + DEBUG_LOG(HLE, "sceKernelReleaseWaitThread(%i)", threadID); + if (__KernelInCallback()) + WARN_LOG(HLE, "UNTESTED sceKernelReleaseWaitThread() might not do the right thing in a callback"); + + if (threadID == 0 || threadID == currentThread) + return SCE_KERNEL_ERROR_ILLEGAL_THID; + + u32 error; + Thread *t = kernelObjects.Get(threadID, error); + if (t) + { + if (!t->isWaiting()) + return SCE_KERNEL_ERROR_NOT_WAIT; + + __KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_RELEASE_WAIT); + hleReSchedule("thread released from wait"); + return 0; + } + else + { + ERROR_LOG(HLE, "sceKernelReleaseWaitThread - bad thread %i", threadID); + return error; } - RETURN(0); } void sceKernelSuspendThread() @@ -2113,7 +2199,10 @@ void __KernelSwitchContext(Thread *target, const char *reason) __KernelSaveContext(&cur->context); oldPC = currentMIPS->pc; oldUID = cur->GetUID(); - oldName = cur->GetName(); + + // Profile on Windows shows this takes time, skip it. + if (DEBUG_LEVEL <= MAX_LOGLEVEL) + oldName = cur->GetName(); } currentThread = target->GetUID(); __KernelLoadContext(&target->context); diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index e501f9d5cd..90c845c9da 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -40,9 +40,10 @@ void sceKernelGetThreadCurrentPriority(); int sceKernelStartThread(SceUID threadToStartID, u32 argSize, u32 argBlockPtr); u32 sceKernelSuspendDispatchThread(); u32 sceKernelResumeDispatchThread(u32 suspended); -void sceKernelWaitThreadEnd(); +int sceKernelWaitThreadEnd(SceUID threadID, u32 timeoutPtr); u32 sceKernelReferThreadStatus(u32 uid, u32 statusPtr); u32 sceKernelReferThreadRunStatus(u32 uid, u32 statusPtr); +int sceKernelReleaseWaitThread(SceUID threadID); void sceKernelChangeCurrentThreadAttr(); void sceKernelRotateThreadReadyQueue(); void sceKernelCheckThreadStack(); @@ -52,7 +53,7 @@ void sceKernelWakeupThread(); void sceKernelCancelWakeupThread(); int sceKernelTerminateDeleteThread(int threadno); int sceKernelTerminateThread(u32 threadID); -void sceKernelWaitThreadEndCB(); +int sceKernelWaitThreadEndCB(SceUID threadID, u32 timeoutPtr); void sceKernelGetThreadExitStatus(); u32 sceKernelGetThreadmanIdType(u32); u32 sceKernelGetThreadmanIdList(u32 type, u32 readBufPtr, u32 readBufSize, u32 idCountPtr); diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp index 54483b82df..6c1f57b92b 100644 --- a/Core/HLE/sceMpeg.cpp +++ b/Core/HLE/sceMpeg.cpp @@ -28,17 +28,25 @@ static bool useMediaEngine; // MPEG AVC elementary stream. static const int MPEG_AVC_ES_SIZE = 2048; // MPEG packet size. + // MPEG ATRAC elementary stream. static const int MPEG_ATRAC_ES_SIZE = 2112; static const int MPEG_ATRAC_ES_OUTPUT_SIZE = 8192; + // MPEG PCM elementary stream. static const int MPEG_PCM_ES_SIZE = 320; static const int MPEG_PCM_ES_OUTPUT_SIZE = 320; + +// MPEG Userdata elementary stream. +static const int MPEG_DATA_ES_SIZE = 0xA0000; +static const int MPEG_DATA_ES_OUTPUT_SIZE = 0xA0000; + // MPEG analysis results. static const int MPEG_VERSION_0012 = 0; static const int MPEG_VERSION_0013 = 1; static const int MPEG_VERSION_0014 = 2; static const int MPEG_VERSION_0015 = 3; + // MPEG streams. static const int MPEG_AVC_STREAM = 0; static const int MPEG_ATRAC_STREAM = 1; @@ -69,6 +77,9 @@ static const int NUM_ES_BUFFERS = 2; static const int PSP_ERROR_MPEG_NO_DATA = 0x80618001; +static const int TPSM_PIXEL_STORAGE_MODE_16BIT_BGR5650 = 0X00; +static const int TPSM_PIXEL_STORAGE_MODE_32BIT_ABGR8888 = 0X03; + int getMaxAheadTimestamp(const SceMpegRingBuffer &ringbuf) { return std::max(40000, ringbuf.packets * 700); // empiric value from JPCSP, thanks! } @@ -82,9 +93,10 @@ struct AvcContext { }; struct StreamInfo -{ +{ int type; int num; + int sid; }; typedef std::map StreamInfoMap; @@ -114,6 +126,10 @@ struct MpegContext { p.Do(avcRegistered); p.Do(atracRegistered); p.Do(pcmRegistered); + p.Do(dataRegistered); + p.Do(ignoreAtrac); + p.Do(ignorePcm); + p.Do(ignoreAvc); p.Do(isAnalyzed); p.Do(streamMap); mediaengine->DoState(p); @@ -143,6 +159,11 @@ struct MpegContext { bool avcRegistered; bool atracRegistered; bool pcmRegistered; + bool dataRegistered; + + bool ignoreAtrac; + bool ignorePcm; + bool ignoreAvc; bool isAnalyzed; @@ -322,23 +343,22 @@ void __MpegShutdown() { mpegMap.clear(); } -void sceMpegInit() +u32 sceMpegInit() { WARN_LOG(HLE, "sceMpegInit()"); - - RETURN(0); + return 0; } u32 sceMpegRingbufferQueryMemSize(int packets) { DEBUG_LOG(HLE, "sceMpegRingbufferQueryMemSize(%i)", packets); - return packets * (104 + 2048); + int size = packets * (104 + 2048); + return size; } u32 sceMpegRingbufferConstruct(u32 ringbufferAddr, u32 numPackets, u32 data, u32 size, u32 callbackAddr, u32 callbackArg) { - DEBUG_LOG(HLE, "sceMpegRingbufferConstruct(%08x, %i, %08x, %i, %08x, %i)", - ringbufferAddr, numPackets, data, size, callbackAddr, callbackArg); + DEBUG_LOG(HLE, "sceMpegRingbufferConstruct(%08x, %i, %08x, %i, %08x, %i)", ringbufferAddr, numPackets, data, size, callbackAddr, callbackArg); SceMpegRingBuffer ring; InitRingbuffer(&ring, numPackets, data, size, callbackAddr, callbackArg); Memory::WriteStruct(ringbufferAddr, &ring); @@ -384,6 +404,10 @@ u32 sceMpegCreate(u32 mpegAddr, u32 dataPtr, u32 size, u32 ringbufferAddr, u32 f ctx->avcRegistered = false; ctx->atracRegistered = false; ctx->pcmRegistered = false; + ctx->dataRegistered = false; + ctx->ignoreAtrac = false; + ctx->ignorePcm = false; + ctx->ignoreAvc = false; ctx->defaultFrameWidth = frameWidth; for (int i = 0; i < NUM_ES_BUFFERS; i++) { ctx->esBuffers[i] = false; @@ -428,12 +452,17 @@ int sceMpegAvcDecodeMode(u32 mpeg, u32 modeAddr) if (Memory::IsValidAddress(modeAddr)) { int mode = Memory::Read_U32(modeAddr); int pixelMode = Memory::Read_U32(modeAddr + 4); - ctx->videoPixelMode = pixelMode; - return 0; + if (pixelMode >= TPSM_PIXEL_STORAGE_MODE_16BIT_BGR5650 && pixelMode <= TPSM_PIXEL_STORAGE_MODE_32BIT_ABGR8888) { + ctx->videoPixelMode = pixelMode; + } else { + ERROR_LOG(HLE, "sceMpegAvcDecodeMode(%i, %i): unknown pixelMode ", mode, pixelMode); + } } else { - WARN_LOG(HLE, "sceMpegAvcDecodeMode(%08x, %08x): invalid modeAddr", mpeg, modeAddr); - return -1; + ERROR_LOG(HLE, "sceMpegAvcDecodeMode(%08x, %08x): invalid modeAddr", mpeg, modeAddr); + return -1; } + + return 0; } int sceMpegQueryStreamOffset(u32 mpeg, u32 bufferAddr, u32 offsetAddr) @@ -451,13 +480,13 @@ int sceMpegQueryStreamOffset(u32 mpeg, u32 bufferAddr, u32 offsetAddr) if (ctx->mpegMagic != PSMF_MAGIC) { ERROR_LOG(HLE, "sceMpegQueryStreamOffset: Bad PSMF magic"); - return -1; //ERROR_MPEG_INVALID_VALUE + return ERROR_MPEG_INVALID_VALUE; } else if (ctx->mpegVersion < 0) { ERROR_LOG(HLE, "sceMpegQueryStreamOffset: Bad version"); - return -1; //ERROR_MPEG_BAD_VERSION + return ERROR_MPEG_BAD_VERSION; } else if ((ctx->mpegOffset & 2047) != 0 || ctx->mpegOffset == 0) { ERROR_LOG(HLE, "sceMpegQueryStreamOffset: Bad offset"); - return -1; //ERROR_MPEG_INVALID_VALUE + return ERROR_MPEG_INVALID_VALUE; } Memory::Write_U32(ctx->mpegOffset, offsetAddr); return 0; @@ -510,6 +539,12 @@ int sceMpegRegistStream(u32 mpeg, u32 streamType, u32 streamNum) case MPEG_PCM_STREAM: ctx->pcmRegistered = true; break; + case MPEG_DATA_STREAM: + ctx->dataRegistered = true; + break; + default : + DEBUG_LOG(HLE, "sceMpegRegistStream(%i) : unknown stream type", streamType); + break; } // ... u32 sid = streamIdGen++; @@ -664,16 +699,50 @@ u32 sceMpegAvcDecode(u32 mpeg, u32 auAddr, u32 frameWidth, u32 bufferAddr, u32 i u32 sceMpegAvcDecodeStop(u32 mpeg, u32 frameWidth, u32 bufferAddr, u32 statusAddr) { - WARN_LOG(HLE, "HACK sceMpegAvcDecodeStop(%08x, %08x, %08x, statusAddr=%08x)", - mpeg, frameWidth, bufferAddr, statusAddr); - + ERROR_LOG(HLE, "sceMpegAvcDecodeStop(%08x, %08x, %08x, %08x)", mpeg, frameWidth, bufferAddr, statusAddr); + if (Memory::IsValidAddress(statusAddr)) { + Memory::Write_U32(0,statusAddr); + } else { + ERROR_LOG(HLE, "sceMpegAvcDecodeStop(%08x, %08x): invalid statusAddr", mpeg, statusAddr); + return -1; + } return 0; } -void sceMpegUnRegistStream() +u32 sceMpegUnRegistStream(u32 mpeg, int streamUid) { - WARN_LOG(HLE, "HACK sceMpegUnRegistStream(...)"); - RETURN(0); + MpegContext *ctx = getMpegCtx(mpeg); + if (!ctx) + { + WARN_LOG(HLE, "sceMpegUnRegistStream(%08x, %i, %i): bad mpeg handle", mpeg, streamUid); + return -1; + } + + StreamInfo info; + + switch (info.type) { + case MPEG_AVC_STREAM: + ctx->avcRegistered = false; + break; + case MPEG_AUDIO_STREAM: + case MPEG_ATRAC_STREAM: + ctx->atracRegistered = false; + break; + case MPEG_PCM_STREAM: + ctx->pcmRegistered = false; + break; + case MPEG_DATA_STREAM: + ctx->dataRegistered = false; + break; + default : + DEBUG_LOG(HLE, "sceMpegUnRegistStream(%i) : unknown streamID ", streamUid); + break; + } + ctx->streamMap[streamUid] = info; + info.type = -1; + info.sid = -1 ; + ctx->isAnalyzed = false; + return 0; } int sceMpegAvcDecodeDetail(u32 mpeg, u32 detailAddr) @@ -704,21 +773,25 @@ int sceMpegAvcDecodeDetail(u32 mpeg, u32 detailAddr) return 0; } -void sceMpegAvcDecodeStopYCbCr() +u32 sceMpegAvcDecodeStopYCbCr(u32 mpeg, u32 bufferAddr, u32 statusAddr) { - WARN_LOG(HLE, "HACK sceMpegAvcDecodeStopYCbCr(...)"); - RETURN(0); + ERROR_LOG(HLE, "UNIMPL sceMpegAvcDecodeStopYCbCr(%08x, %08x, %08x)", mpeg, bufferAddr, statusAddr); + return 0; } int sceMpegAvcDecodeYCbCr(u32 mpeg, u32 auAddr, u32 bufferAddr, u32 initAddr) { - WARN_LOG(HLE, "HACK sceMpegAvcDecodeYCbCr(%08x, %08x, %08x, %08x)", mpeg, auAddr, bufferAddr, initAddr); + ERROR_LOG(HLE, "UNIMPL sceMpegAvcDecodeYCbCr(%08x, %08x, %08x, %08x)", mpeg, auAddr, bufferAddr, initAddr); return 0; } u32 sceMpegAvcDecodeFlush(u32 mpeg) { + MpegContext *ctx = getMpegCtx(mpeg); ERROR_LOG(HLE, "UNIMPL sceMpegAvcDecodeFlush(%08x)", mpeg); + if ( ctx->videoFrameCount > 0 || ctx->audioFrameCount > 0) { + //__MpegFinish(); + } return 0; } @@ -781,9 +854,6 @@ int sceMpegRingbufferAvailableSize(u32 ringbufferAddr) return ringbuffer.packetsFree; } - - - void PostPutAction::run(MipsCall &call) { SceMpegRingBuffer ringbuffer; Memory::ReadStruct(ringAddr_, &ringbuffer); @@ -908,11 +978,11 @@ int sceMpegGetAvcAu(u32 mpeg, u32 streamId, u32 auAddr, u32 attrAddr) return result; } -void sceMpegFinish() +u32 sceMpegFinish() { - WARN_LOG(HLE, "sceMpegFinish(...)"); + ERROR_LOG(HLE, "sceMpegFinish(...)"); //__MpegFinish(); - RETURN(0); + return 0; } u32 sceMpegQueryMemSize() @@ -973,47 +1043,103 @@ int sceMpegQueryPcmEsSize(u32 mpeg, u32 esSizeAddr, u32 outSizeAddr) } -void sceMpegChangeGetAuMode() +u32 sceMpegChangeGetAuMode(u32 mpeg, int streamUid, int mode) { - WARN_LOG(HLE, "HACK sceMpegChangeGetAuMode(...)"); - RETURN(0); + MpegContext *ctx = getMpegCtx(mpeg); + if (!ctx) { + WARN_LOG(HLE, "sceMpegChangeGetAuMode(%08x, %i, %i): bad mpeg handle", mpeg, streamUid, mode); + return -1; + } + + StreamInfo info; + info.sid = streamUid; + if (info.sid) { + switch (info.type) { + case MPEG_AVC_STREAM: + if(mode == MPEG_AU_MODE_DECODE) { + ctx->ignoreAvc = false; + } else if (mode == MPEG_AU_MODE_SKIP) { + ctx->ignoreAvc = true; + } + break; + case MPEG_AUDIO_STREAM: + case MPEG_ATRAC_STREAM: + if(mode == MPEG_AU_MODE_DECODE) { + ctx->ignoreAtrac = false; + } else if (mode == MPEG_AU_MODE_SKIP) { + ctx->ignoreAtrac = true; + } + break; + case MPEG_PCM_STREAM: + if(mode == MPEG_AU_MODE_DECODE) { + ctx->ignorePcm = false; + } else if (mode == MPEG_AU_MODE_SKIP) { + ctx->ignorePcm = true; + } + break; + default: + ERROR_LOG(HLE, "UNIMPL sceMpegChangeGetAuMode(%08x, %i): unkown streamID", mpeg, streamUid); + break; + } + } else { + ERROR_LOG(HLE, "UNIMPL sceMpegChangeGetAuMode(%08x, %i): unkown streamID", mpeg, streamUid); + } + return 0; } -void sceMpegGetPcmAu() +u32 sceMpegChangeGetAvcAuMode(u32 mpeg, u32 stream_addr, int mode) { - WARN_LOG(HLE, "HACK sceMpegGetPcmAu(...)"); - RETURN(0); + ERROR_LOG(HLE, "UNIMPL sceMpegChangeGetAvcAuMode(%08x, %08x, %i)", mpeg, stream_addr, mode); + return 0; } -void sceMpegRingbufferQueryPackNum() +u32 sceMpegGetPcmAu(u32 mpeg, int streamUid, u32 auAddr, u32 attrAddr) { - WARN_LOG(HLE, "HACK sceMpegRingbufferQueryPackNum(...)"); - RETURN(0); + ERROR_LOG(HLE, "UNIMPL sceMpegGetPcmAu(%08x, %i, %08x, %08x)", mpeg, streamUid, auAddr, attrAddr); + return 0; } -void sceMpegFlushAllStream() +u32 sceMpegRingbufferQueryPackNum(int memorySize) { - WARN_LOG(HLE, "HACK sceMpegFlushAllStream(...)"); - RETURN(0); + ERROR_LOG(HLE, "sceMpegRingbufferQueryPackNum(%i)", memorySize); + int packets = memorySize / (2048 + 104); + return packets; } -void sceMpegAvcCopyYCbCr() +u32 sceMpegFlushAllStream(u32 mpeg) { - WARN_LOG(HLE, "HACK sceMpegAvcCopyYCbCr(...)"); - RETURN(0); + MpegContext *ctx = getMpegCtx(mpeg); + ERROR_LOG(HLE, "UNIMPL sceMpegFlushAllStream(%08x)", mpeg); + if ( ctx->videoFrameCount > 0 || ctx->audioFrameCount > 0) { + //__MpegFinish(); + } + return 0; } -void sceMpegAtracDecode() +u32 sceMpegFlushStream(u32 mpeg, int stream_addr) { - WARN_LOG(HLE, "HACK sceMpegAtracDecode(...)"); - RETURN(0); + ERROR_LOG(HLE, "UNIMPL sceMpegFlushStream(%08x, %i)", mpeg , stream_addr); + //__MpegFinish(); + return 0; +} + +u32 sceMpegAvcCopyYCbCr(u32 mpeg, u32 sourceAddr, u32 YCbCrAddr) +{ + ERROR_LOG(HLE, "UNIMPL sceMpegAvcCopyYCbCr(%08x, %08x, %08x)", mpeg, sourceAddr, YCbCrAddr); + return 0; +} + +u32 sceMpegAtracDecode(u32 mpeg, u32 auAddr, u32 bufferAddr, int init) +{ + ERROR_LOG(HLE, "UNIMPL sceMpegAtracDecode(%08x, %08x, %08x, %i)", mpeg, auAddr, bufferAddr, init); + return 0; } // YCbCr -> RGB color space conversion -void sceMpegAvcCsc() +u32 sceMpegAvcCsc(u32 mpeg, u32 sourceAddr, u32 rangeAddr, int frameWidth, u32 destAddr) { - WARN_LOG(HLE, "HACK sceMpegAvcCsc(...)"); - RETURN(0); + ERROR_LOG(HLE, "UNIMPL sceMpegAvcCsc(%08x, %08x, %08x, %i, %08x)", mpeg, sourceAddr, rangeAddr, frameWidth, destAddr); + return 0; } u32 sceMpegRingbufferDestruct(u32 ringbufferAddr) @@ -1023,10 +1149,10 @@ u32 sceMpegRingbufferDestruct(u32 ringbufferAddr) return 0; } -void sceMpegAvcInitYCbCr() +u32 sceMpegAvcInitYCbCr(u32 mpeg, int mode, int width, int height, u32 ycbcr_addr) { - WARN_LOG(HLE, "HACK sceMpegAvcInitYCbCr(...)"); - RETURN(0); + ERROR_LOG(HLE, "UNIMPL sceMpegAvcInitYCbCr(%08x, %i, %i, %i, %08x)", mpeg, mode, width, height, ycbcr_addr); + return 0; } int sceMpegAvcQueryYCbCrSize(u32 mpeg, u32 mode, u32 width, u32 height, u32 resultAddr) @@ -1034,7 +1160,7 @@ int sceMpegAvcQueryYCbCrSize(u32 mpeg, u32 mode, u32 width, u32 height, u32 resu if ((width & 15) != 0 || (height & 15) != 0 || height > 272 || width > 480) { ERROR_LOG(HLE, "sceMpegAvcQueryYCbCrSize: bad w/h %i x %i", width, height); - return -1; + return ERROR_MPEG_INVALID_VALUE; } DEBUG_LOG(HLE, "sceMpegAvcQueryYCbCrSize(%08x, %i, %i, %i, %08x)", mpeg, mode, width, height, resultAddr); @@ -1043,6 +1169,36 @@ int sceMpegAvcQueryYCbCrSize(u32 mpeg, u32 mode, u32 width, u32 height, u32 resu return 0; } +int sceMp3Decode(u32 mp3, u32 outPcmPtr) +{ + ERROR_LOG(HLE, "UNIMPL sceMp3Decoder(%08x,%08x)", mp3, outPcmPtr); + return 0; +} + +int sceMp3ResetPlayPosition(u32 mp3) +{ + ERROR_LOG(HLE, "UNIMPL sceMp3ResetPlayPosition(%08x)", mp3); + return 0; +} + +int sceMp3CheckStreamDataNeeded(u32 mp3) +{ + ERROR_LOG(HLE, "UNIMPL sceMp3CheckStreamDataNeeded(%08x)", mp3); + return 0; +} + +u32 sceMpegQueryUserdataEsSize(u32 mpeg, u32 esSizeAddr, u32 outSizeAddr) +{ + if (Memory::IsValidAddress(esSizeAddr) && Memory::IsValidAddress(outSizeAddr)) { + DEBUG_LOG(HLE, "sceMpegQueryUserdataEsSize(%08x, %08x, %08x)", mpeg, esSizeAddr, outSizeAddr); + Memory::Write_U32(MPEG_DATA_ES_SIZE, esSizeAddr); + Memory::Write_U32(MPEG_DATA_ES_OUTPUT_SIZE, outSizeAddr); + return 0; + } + + ERROR_LOG(HLE, "sceMpegQueryUserdataEsSize - bad pointers(%08x, %08x, %08x)", mpeg, esSizeAddr, outSizeAddr); + return -1; +} const HLEFunction sceMpeg[] = { @@ -1054,15 +1210,16 @@ const HLEFunction sceMpeg[] = {0x21ff80e4,WrapI_UUU,"sceMpegQueryStreamOffset"}, {0x611e9e11,WrapU_UU,"sceMpegQueryStreamSize"}, {0x42560f23,WrapI_UUU,"sceMpegRegistStream"}, - {0x591a4aa2,sceMpegUnRegistStream,"sceMpegUnRegistStream"}, - {0x707b7629,sceMpegFlushAllStream,"sceMpegFlushAllStream"}, + {0x591a4aa2,WrapU_UI,"sceMpegUnRegistStream"}, + {0x707b7629,WrapU_U,"sceMpegFlushAllStream"}, + {0x500F0429,WrapU_UI,"sceMpegFlushStream"}, {0xa780cf7e,WrapI_U,"sceMpegMallocAvcEsBuf"}, {0xceb870b1,WrapI_UI,"sceMpegFreeAvcEsBuf"}, {0x167afd9e,WrapI_UUU,"sceMpegInitAu"}, - {0x682a619b,sceMpegInit,"sceMpegInit"}, + {0x682a619b,WrapU_V,"sceMpegInit"}, {0x606a4649,WrapI_U,"sceMpegDelete"}, - {0x874624d6,sceMpegFinish,"sceMpegFinish"}, - {0x800c44df,sceMpegAtracDecode,"sceMpegAtracDecode"}, + {0x874624d6,WrapU_V,"sceMpegFinish"}, + {0x800c44df,WrapU_UUUI,"sceMpegAtracDecode"}, {0x0e3c2e9d,&WrapU_UUUUU,"sceMpegAvcDecode"}, {0x740fccd1,&WrapU_UUUU,"sceMpegAvcDecodeStop"}, {0x4571cc64,&WrapU_U,"sceMpegAvcDecodeFlush"}, @@ -1073,23 +1230,25 @@ const HLEFunction sceMpeg[] = {0xb240a59e,WrapU_UUU,"sceMpegRingbufferPut"}, {0xb5f6dc87,WrapI_U,"sceMpegRingbufferAvailableSize"}, {0xd7a29f46,WrapU_I,"sceMpegRingbufferQueryMemSize"}, - {0x769BEBB6,sceMpegRingbufferQueryPackNum,"sceMpegRingbufferQueryPackNum"}, + {0x769BEBB6,WrapU_I,"sceMpegRingbufferQueryPackNum"}, {0x211a057c,WrapI_UUUUU,"sceMpegAvcQueryYCbCrSize"}, {0xf0eb1125,WrapI_UUUU,"sceMpegAvcDecodeYCbCr"}, - {0xf2930c9c,sceMpegAvcDecodeStopYCbCr,"sceMpegAvcDecodeStopYCbCr"}, - {0x67179b1b,sceMpegAvcInitYCbCr,"sceMpegAvcInitYCbCr"}, - {0x0558B075,sceMpegAvcCopyYCbCr,"sceMpegAvcCopyYCbCr"}, - {0x31bd0272,sceMpegAvcCsc,"sceMpegAvcCsc"}, - {0x9DCFB7EA,sceMpegChangeGetAuMode,"sceMpegChangeGetAuMode"}, - {0x8C1E027D,sceMpegGetPcmAu,"sceMpegGetPcmAu"}, + {0xf2930c9c,WrapU_UUU,"sceMpegAvcDecodeStopYCbCr"}, + {0x67179b1b,WrapU_UIIIU,"sceMpegAvcInitYCbCr"}, + {0x0558B075,WrapU_UUU,"sceMpegAvcCopyYCbCr"}, + {0x31bd0272,WrapU_UUUIU,"sceMpegAvcCsc"}, + {0x9DCFB7EA,WrapU_UII,"sceMpegChangeGetAuMode"}, + {0x8C1E027D,WrapU_UIUU,"sceMpegGetPcmAu"}, {0xC02CF6B5,WrapI_UUU,"sceMpegQueryPcmEsSize"}, + {0xC45C99CC,WrapU_UUU,"sceMpegQueryUserdataEsSize"}, + {0x234586AE,WrapU_UUI,"sceMpegChangeGetAvcAuMode"}, }; const HLEFunction sceMp3[] = { {0x07EC321A,0,"sceMp3ReserveMp3Handle"}, {0x0DB149F4,0,"sceMp3NotifyAddStreamData"}, - {0x2A368661,0,"sceMp3ResetPlayPosition"}, + {0x2A368661,WrapI_U,"sceMp3ResetPlayPosition"}, {0x354D27EA,0,"sceMp3GetSumDecodedSample"}, {0x35750070,0,"sceMp3InitResource"}, {0x3C2FA058,0,"sceMp3TermResource"}, @@ -1102,10 +1261,12 @@ const HLEFunction sceMp3[] = {0x8AB81558,0,"sceMp3StartEntry"}, {0x8F450998,0,"sceMp3GetSamplingRate"}, {0xA703FE0F,0,"sceMp3GetInfoToAddStreamData"}, - {0xD021C0FB,0,"sceMp3Decode"}, - {0xD0A56296,0,"sceMp3CheckStreamDataNeeded"}, + {0xD021C0FB,WrapI_UU,"sceMp3Decode"}, + {0xD0A56296,WrapI_U,"sceMp3CheckStreamDataNeeded"}, {0xD8F54A51,0,"sceMp3GetLoopNum"}, {0xF5478233,0,"sceMp3ReleaseMp3Handle"}, + {0xAE6D2027,0,"sceMp3GetVersion"}, + {0x3548AEC8,0,"sceMp3GetFrameNum"}, }; void Register_sceMpeg() diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index ec6e7241d9..0bda29ff3a 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -313,7 +313,7 @@ u32 scePsmfGetNumberOfStreams(u32 psmfStruct) ERROR_LOG(HLE, "scePsmfGetNumberOfStreams - invalid psmf"); return ERROR_PSMF_NOT_FOUND; } - INFO_LOG(HLE, "%i=scePsmfGetNumberOfStreams(%08x)", psmf->getNumStreams(), psmf); + INFO_LOG(HLE, "%i=scePsmfGetNumberOfStreams(%08x)", psmf->getNumStreams(), psmfStruct); return psmf->getNumStreams(); } diff --git a/Core/Loaders.cpp b/Core/Loaders.cpp index 6848902266..c51da638a7 100644 --- a/Core/Loaders.cpp +++ b/Core/Loaders.cpp @@ -38,8 +38,12 @@ EmuFileType Identify_File(const char *filename) return FILETYPE_ERROR; } u32 id; - fread(&id,4,1,f); + size_t readSize = fread(&id,4,1,f); fclose(f); + + if(readSize != 1) + return FILETYPE_ERROR; + if (id == 'FLE\x7F') { if (strstr(filename,".plf") || strstr(filename,"BOOT.BIN") || strstr(filename,".elf") || strstr(filename,".prx") ) diff --git a/Core/MIPS/MIPSAnalyst.cpp b/Core/MIPS/MIPSAnalyst.cpp index b05f70ed8d..50889b99d2 100644 --- a/Core/MIPS/MIPSAnalyst.cpp +++ b/Core/MIPS/MIPSAnalyst.cpp @@ -351,7 +351,8 @@ namespace MIPSAnalyst { FILE *file = fopen(filename,"wb"); u32 num = 0; - fwrite(&num,4,1,file); //fill in later + if(fwrite(&num,4,1,file) != 1) //fill in later + WARN_LOG(CPU, "Could not store hash map %s", filename); for (vector::iterator iter = functions.begin(); iter!=functions.end(); iter++) { @@ -363,12 +364,16 @@ namespace MIPSAnalyst strcpy(temp.name, f.name); temp.hash=f.hash; temp.size=f.size; - fwrite((char*)&temp,sizeof(temp),1,file); + if(fwrite((char*)&temp,sizeof(temp),1,file) != 1) { + WARN_LOG(CPU, "Could not store hash map %s", filename); + break; + } num++; } } fseek(file,0,SEEK_SET); - fwrite(&num,4,1,file); //fill in later + if(fwrite(&num,4,1,file) != 1) //fill in later + WARN_LOG(CPU, "Could not store hash map %s", filename); fclose(file); } @@ -380,25 +385,26 @@ namespace MIPSAnalyst FILE *file = fopen(filename, "rb"); int num; - fread(&num,4,1,file); - for (int i=0; i::iterator iter = hashToFunction.find(temp.hash); - if (iter != hashToFunction.end()) + if(fread(&num,4,1,file) == 1) { + for (int i=0; isecond); - if (f.size==temp.size) - { - strcpy(f.name, temp.name); - f.hash=temp.hash; - f.size=temp.size; + HashMapFunc temp; + if(fread(&temp,sizeof(temp),1,file) == 1) { + map::iterator iter = hashToFunction.find(temp.hash); + if (iter != hashToFunction.end()) + { + //yay, found a function! + Function &f = *(iter->second); + if (f.size==temp.size) + { + strcpy(f.name, temp.name); + f.hash=temp.hash; + f.size=temp.size; + } + } } } } - fclose(file); } void CompileLeafs() diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index 47582c2ccc..1b5807ac3c 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -931,7 +931,7 @@ void MIPSInterpret(u32 op) //only for those rare ones // Try to disassemble it char disasm[256]; MIPSDisAsm(op, currentMIPS->pc, disasm); - _dbg_assert_msg_(CPU, 0, disasm); + _dbg_assert_msg_(CPU, 0, "%s", disasm); currentMIPS->pc += 4; } } diff --git a/Qt/Common.pro b/Qt/Common.pro index ee93af7868..ff992a1138 100755 --- a/Qt/Common.pro +++ b/Qt/Common.pro @@ -16,13 +16,11 @@ arm { x86 { SOURCES += ../Common/ABI.cpp \ ../Common/CPUDetect.cpp \ - ../Common/MathUtil.cpp \ ../Common/Thunk.cpp \ ../Common/x64Analyzer.cpp \ ../Common/x64Emitter.cpp HEADERS += ../Common/ABI.h \ ../Common/CPUDetect.h \ - ../Common/MathUtil.h \ ../Common/Thunk.h \ ../Common/x64Analyzer.h \ ../Common/x64Emitter.h @@ -47,10 +45,10 @@ SOURCES += ../Common/ColorUtil.cpp \ ../Common/Hash.cpp \ ../Common/IniFile.cpp \ ../Common/LogManager.cpp \ + ../Common/MathUtil.cpp \ ../Common/MemArena.cpp \ ../Common/MemoryUtil.cpp \ ../Common/Misc.cpp \ - ../Common/MathUtil.cpp \ ../Common/MsgHandler.cpp \ ../Common/StringUtil.cpp \ ../Common/Thread.cpp \ @@ -66,9 +64,9 @@ HEADERS += ../Common/ColorUtil.h \ ../Common/Hash.h \ ../Common/IniFile.h \ ../Common/LogManager.h \ + ../Common/MathUtil.h \ ../Common/MemArena.h \ ../Common/MemoryUtil.h \ - ../Common/MathUtil.h \ ../Common/MsgHandler.h \ ../Common/StringUtil.h \ ../Common/Thread.h \ diff --git a/Qt/Settings.pri b/Qt/Settings.pri index 87d3a408e3..c31a8218aa 100644 --- a/Qt/Settings.pri +++ b/Qt/Settings.pri @@ -1,4 +1,4 @@ -blackberry|symbian: CONFIG += mobile_platform +blackberry|symbian|contains(MEEGO_EDITION,harmattan): CONFIG += mobile_platform unix:!blackberry:!symbian:!macx: CONFIG += linux # Global specific @@ -17,6 +17,7 @@ mobile_platform: DEFINES += USING_GLES2 # Platform specific +contains(MEEGO_EDITION,harmattan): DEFINES += MEEGO_EDITION_HARMATTAN "_SYS_UCONTEXT_H=1" blackberry: { # They try to force QCC with all mkspecs # QCC is 4.4.1, we need 4.6.3