diff --git a/Core/ELF/ElfReader.cpp b/Core/ELF/ElfReader.cpp index 2969b975e5..dd0cf8247a 100644 --- a/Core/ELF/ElfReader.cpp +++ b/Core/ELF/ElfReader.cpp @@ -271,6 +271,7 @@ bool ElfReader::LoadInto(u32 loadAddress) } DEBUG_LOG(LOADER,"Relocations:"); + bool oldRelocs = false; // Second pass: Do necessary relocations for (int i=0; ish_info; - if (!(sections[sectionToModify].sh_flags & SHF_ALLOC)) - { - ERROR_LOG(LOADER,"Trying to relocate non-loaded section %s, ignoring",GetSectionName(sectionToModify)); - continue; - } - ERROR_LOG(LOADER,"Traditional relocations unsupported."); + oldRelocs = true; } } } + if (oldRelocs) + { + INFO_LOG(LOADER, "Game uses old relocations (often for debugging, should be harmless)"); + } // Segment relocations (a few games use them) if (GetNumSections() == 0) diff --git a/Core/ELF/PrxDecrypter.cpp b/Core/ELF/PrxDecrypter.cpp index 8541c0358c..38ddc980f9 100644 --- a/Core/ELF/PrxDecrypter.cpp +++ b/Core/ELF/PrxDecrypter.cpp @@ -6,6 +6,7 @@ extern "C" } #include "../../Globals.h" +#include "PrxDecrypter.h" // Thank you PSARDUMPER & JPCSP keys @@ -287,6 +288,22 @@ static const TAG_INFO g_tagInfo[] = { 0xBB67C59F, g_key_GAMESHARE2xx, 0x5E, 0x5E } }; +bool HasKey(int key) +{ + switch (key) + { + case 0x02: case 0x03: case 0x04: case 0x05: case 0x07: case 0x0C: case 0x0D: case 0x0E: case 0x0F: + case 0x10: case 0x11: case 0x12: + case 0x38: case 0x39: case 0x3A: case 0x44: case 0x4B: + case 0x53: case 0x57: case 0x5D: + case 0x63: case 0x64: + return true; + default: + INFO_LOG(HLE, "Missing key %02X, cannot decrypt module", key); + return false; + } +} + static const TAG_INFO *GetTagInfo(u32 tagFind) { for (u32 iTag = 0; iTag < sizeof(g_tagInfo)/sizeof(TAG_INFO); iTag++) @@ -341,6 +358,11 @@ static int DecryptPRX1(const u8* pbIn, u8* pbOut, int cbTotal, u32 tag) { return -1; } + if (!HasKey(pti->code) || + (pti->codeExtra != 0 && !HasKey(pti->codeExtra))) + { + return MISSING_KEY; + } retsize = *(u32*)&pbIn[0xB0]; @@ -589,6 +611,10 @@ static int DecryptPRX2(const u8 *inbuf, u8 *outbuf, u32 size, u32 tag) { return -1; } + if (!HasKey(pti->code)) + { + return MISSING_KEY; + } int retsize = *(int *)&inbuf[0xB0]; u8 tmp1[0x150], tmp2[0x90+0x14], tmp3[0x90+0x14], tmp4[0x20]; @@ -724,6 +750,10 @@ int pspDecryptPRX(const u8 *inbuf, u8 *outbuf, u32 size) { kirk_init(); int retsize = DecryptPRX1(inbuf, outbuf, size, *(u32 *)&inbuf[0xD0]); + if (retsize == MISSING_KEY) + { + return MISSING_KEY; + } if (retsize <= 0) { diff --git a/Core/ELF/PrxDecrypter.h b/Core/ELF/PrxDecrypter.h index 23cbedbc1a..afb4f2d555 100644 --- a/Core/ELF/PrxDecrypter.h +++ b/Core/ELF/PrxDecrypter.h @@ -19,6 +19,8 @@ #include "../../Globals.h" +#define MISSING_KEY -10 + #ifdef _MSC_VER #pragma pack(push, 1) #endif diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 4f5ff5c8a4..5daa4d89f1 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -20,7 +20,6 @@ #undef DeleteFile #endif -#include "../System.h" #include "../Config.h" #include "../Host.h" #include "../SaveState.h" @@ -121,43 +120,6 @@ struct dirent { }; #endif -class FileNode : public KernelObject { -public: - FileNode() : callbackID(0), callbackArg(0), asyncResult(0), pendingAsyncResult(false), sectorBlockMode(false) {} - ~FileNode() { - pspFileSystem.CloseFile(handle); - } - const char *GetName() {return fullpath.c_str();} - const char *GetTypeName() {return "OpenFile";} - void GetQuickInfo(char *ptr, int size) { - sprintf(ptr, "Seekpos: %08x", (u32)pspFileSystem.GetSeekPos(handle)); - } - static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_BADF; } - int GetIDType() const { return PPSSPP_KERNEL_TMID_File; } - - virtual void DoState(PointerWrap &p) { - p.Do(fullpath); - p.Do(handle); - p.Do(callbackID); - p.Do(callbackArg); - p.Do(asyncResult); - p.Do(pendingAsyncResult); - p.Do(sectorBlockMode); - p.DoMarker("File"); - } - - std::string fullpath; - u32 handle; - - u32 callbackID; - u32 callbackArg; - - u32 asyncResult; - - bool pendingAsyncResult; - bool sectorBlockMode; -}; - void __IoInit() { INFO_LOG(HLE, "Starting up I/O..."); diff --git a/Core/HLE/sceIo.h b/Core/HLE/sceIo.h index d05c00df06..cd88521401 100644 --- a/Core/HLE/sceIo.h +++ b/Core/HLE/sceIo.h @@ -18,9 +18,48 @@ #pragma once #include + +#include "../System.h" #include "HLE.h" #include "sceKernel.h" +class FileNode : public KernelObject { +public: + FileNode() : callbackID(0), callbackArg(0), asyncResult(0), pendingAsyncResult(false), sectorBlockMode(false) {} + ~FileNode() { + pspFileSystem.CloseFile(handle); + } + const char *GetName() {return fullpath.c_str();} + const char *GetTypeName() {return "OpenFile";} + void GetQuickInfo(char *ptr, int size) { + sprintf(ptr, "Seekpos: %08x", (u32)pspFileSystem.GetSeekPos(handle)); + } + static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_BADF; } + int GetIDType() const { return PPSSPP_KERNEL_TMID_File; } + + virtual void DoState(PointerWrap &p) { + p.Do(fullpath); + p.Do(handle); + p.Do(callbackID); + p.Do(callbackArg); + p.Do(asyncResult); + p.Do(pendingAsyncResult); + p.Do(sectorBlockMode); + p.DoMarker("File"); + } + + std::string fullpath; + u32 handle; + + u32 callbackID; + u32 callbackArg; + + u32 asyncResult; + + bool pendingAsyncResult; + bool sectorBlockMode; +}; + void __IoInit(); void __IoDoState(PointerWrap &p); void __IoShutdown(); diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 8f35526859..dc99ba1f4d 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -39,6 +39,7 @@ #include "sceKernelModule.h" #include "sceKernelThread.h" #include "sceKernelMemory.h" +#include "sceIo.h" enum { PSP_THREAD_ATTR_USER = 0x80000000 @@ -100,7 +101,7 @@ struct NativeModule { class Module : public KernelObject { public: - Module() : memoryBlockAddr(0) {} + Module() : memoryBlockAddr(0), isFake(false) {} ~Module() { if (memoryBlockAddr) { userMemory.Free(memoryBlockAddr); @@ -129,6 +130,7 @@ public: NativeModule nm; u32 memoryBlockAddr; + bool isFake; }; KernelObject *__KernelModuleObject() @@ -212,6 +214,10 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro kernelObjects.Create(module); u8 *newptr = 0; + if (*(u32*)ptr == 0x4543537e) { // "~SCE" + INFO_LOG(HLE, "~SCE module, skipping header"); + ptr += *(u32*)(ptr + 4); + } if (*(u32*)ptr == 0x5053507e) { // "~PSP" // Decrypt module! YAY! @@ -225,20 +231,20 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro } newptr = new u8[head->elf_size + head->psp_size]; ptr = newptr; - pspDecryptPRX(in, (u8*)ptr, head->psp_size); + int ret = pspDecryptPRX(in, (u8*)ptr, head->psp_size); + if (ret == MISSING_KEY) + { + *error_string = "Missing key"; + delete [] newptr; + module->isFake = true; + return module; + } + else if (ret <= 0) + { + ERROR_LOG(HLE, "Failed decrypting PRX! That's not normal!\n"); + } } - if (*(u32*)ptr == 0x4543537e) { // "~SCE" - ERROR_LOG(HLE, "Wrong magic number %08x (~SCE, kernel module?)",*(u32*)ptr); - *error_string = "Kernel module?"; - if (newptr) - { - delete [] newptr; - } - kernelObjects.Destroy(module->GetUID()); - return 0; - } - if (*(u32*)ptr != 0x464c457f) { ERROR_LOG(HLE, "Wrong magic number %08x",*(u32*)ptr); @@ -688,9 +694,6 @@ u32 sceKernelLoadModule(const char *name, u32 flags) void sceKernelStartModule(u32 moduleId, u32 argsize, u32 argAddr, u32 returnValueAddr, u32 optionAddr) { - ERROR_LOG(HLE,"UNIMPL sceKernelStartModule(%d,asize=%08x,aptr=%08x,retptr=%08x,%08x)", - moduleId,argsize,argAddr,returnValueAddr,optionAddr); - // Dunno what these three defaults should be... u32 priority = 0x20; u32 stacksize = 0x40000; @@ -707,12 +710,15 @@ void sceKernelStartModule(u32 moduleId, u32 argsize, u32 argAddr, u32 returnValu u32 error; Module *module = kernelObjects.Get(moduleId, error); if (!module) { - // TODO: Try not to lie so much. - /* RETURN(error); return; - */ + } else if (module->isFake) { + INFO_LOG(HLE,"sceKernelStartModule(%d,asize=%08x,aptr=%08x,retptr=%08x,%08x): faked (undecryptable module)", + moduleId,argsize,argAddr,returnValueAddr,optionAddr); } else { + ERROR_LOG(HLE,"UNIMPL sceKernelStartModule(%d,asize=%08x,aptr=%08x,retptr=%08x,%08x)", + moduleId,argsize,argAddr,returnValueAddr,optionAddr); + u32 entryAddr = module->nm.entry_addr; if (entryAddr == -1) { entryAddr = module->nm.module_start_func; @@ -785,10 +791,44 @@ void sceKernelFindModuleByName() RETURN(1); } -u32 sceKernelLoadModuleByID(u32 id, u32 flags, u32 lmoptionPtr) { - ERROR_LOG(HLE,"UNIMPL %008x=sceKernelLoadModuleById(%08x, %08x)",id,id,lmoptionPtr); - // Apparenty, ID is a sceIo File UID. So this shouldn't be too hard when needed. - return id; +u32 sceKernelLoadModuleByID(u32 id, u32 flags, u32 lmoptionPtr) +{ + u32 error; + FileNode *f = kernelObjects.Get < FileNode > (id, error); + if (!f) { + ERROR_LOG(HLE,"sceKernelLoadModuleByID(%08x, %08x, %08x): could not open file id",id,flags,lmoptionPtr); + return error; + } + SceKernelLMOption *lmoption = 0; + if (lmoptionPtr) { + lmoption = (SceKernelLMOption *)Memory::GetPointer(lmoptionPtr); + } + u32 pos = pspFileSystem.SeekFile(f->handle, 0, FILEMOVE_CURRENT); + u32 size = pspFileSystem.SeekFile(f->handle, 0, FILEMOVE_END); + std::string error_string; + pspFileSystem.SeekFile(f->handle, pos, FILEMOVE_BEGIN); + Module *module = 0; + u8 *temp = new u8[size]; + pspFileSystem.ReadFile(f->handle, temp, size); + module = __KernelLoadELFFromPtr(temp, 0, &error_string); + delete [] temp; + + if (!module) { + // Module was blacklisted or couldn't be decrypted, which means it's a kernel module we don't want to run. + // Let's just act as if it worked. + NOTICE_LOG(LOADER, "Module %d is blacklisted or undecryptable - we lie about success", id); + return 1; + } + + if (lmoption) { + INFO_LOG(HLE,"%i=sceKernelLoadModuleByID(%d,flag=%08x,%08x,%08x,%08x,position = %08x)", + module->GetUID(),id,flags, + lmoption->size,lmoption->mpidtext,lmoption->mpiddata,lmoption->position); + } else { + INFO_LOG(HLE,"%i=sceKernelLoadModuleByID(%d,flag=%08x,(...))", module->GetUID(), id, flags); + } + + return module->GetUID(); } u32 sceKernelLoadModuleDNAS(const char *name, u32 flags)