#include #include "Cafe/OS/RPL/rpl.h" #include "Cafe/OS/RPL/rpl_structs.h" #include "util/VirtualHeap/VirtualHeap.h" #include "Cafe/HW/Espresso/Recompiler/PPCRecompiler.h" #include "Cafe/HW/Espresso/Debugger/Debugger.h" typedef struct { /* +0x00 */ uint32be magic; /* +0x04 */ uint8 eiClass; /* +0x05 */ uint8 eiData; /* +0x06 */ uint8 eiVersion; /* +0x07 */ uint8 eiOSABI; /* +0x08 */ uint8 eiOSABIVersion; /* +0x09 */ uint8 eiPadding[7]; /* +0x10 */ uint16be eType; /* +0x12 */ uint16be eMachine; /* +0x14 */ uint32be eVersion; /* +0x18 */ uint32be entrypoint; /* +0x1C */ uint32be phOffset; /* +0x20 */ uint32be shOffset; /* +0x24 */ uint32be eFlags; /* +0x28 */ uint16be eHeaderSize; /* +0x2A */ uint16be ePHEntrySize; /* +0x2C */ uint16be ePHNum; /* +0x2E */ uint16be eSHEntrySize; /* +0x30 */ uint16be eSHNum; /* +0x32 */ uint16be eShStrIndex; }elfHeader_t; static_assert(sizeof(elfHeader_t) == 0x34, ""); typedef struct { /* +0x00 */ uint32be nameOffset; /* +0x04 */ uint32be shType; /* +0x08 */ uint32be shFlags; /* +0x0C */ uint32be shAddr; /* +0x10 */ uint32be shOffset; /* +0x14 */ uint32be shSize; /* +0x18 */ uint32be shLink; /* +0x1C */ uint32be shInfo; /* +0x20 */ uint32be shAddrAlign; /* +0x24 */ uint32be shEntSize; }elfSectionEntry_t; static_assert(sizeof(elfSectionEntry_t) == 0x28, ""); // Map elf into memory uint32 ELF_LoadFromMemory(uint8* elfData, sint32 size, const char* name) { elfHeader_t* header = (elfHeader_t*)elfData; uint32 sectionCount = header->eSHNum; uint32 sectionTableOffset = header->shOffset; uint32 sectionTableEntrySize = header->eSHEntrySize; elfSectionEntry_t* sectionTable = (elfSectionEntry_t*)(elfData + (uint32)header->shOffset); memory_enableHBLELFCodeArea(); for (uint32 i = 0; i < sectionCount; i++) { debug_printf("%02d Addr %08x Size %08x Offs %08x Flags %08x Type %08x EntSize %08x\n", i, (uint32)sectionTable[i].shAddr, (uint32)sectionTable[i].shSize, (uint32)sectionTable[i].shOffset, (uint32)sectionTable[i].shFlags, (uint32)sectionTable[i].shType, (uint32)sectionTable[i].shEntSize); uint32 shAddr = (uint32)sectionTable[i].shAddr; uint32 shSize = (uint32)sectionTable[i].shSize; uint32 shOffset = (uint32)sectionTable[i].shOffset; uint32 shType = (uint32)sectionTable[i].shType; if (shOffset > (uint32)size) { cemuLog_log(LogType::Force, "ELF section {} out of bounds", i); continue; } uint32 copySize = std::min(shSize, size - shOffset); // 0x00802000 if (shAddr != 0) { if (shType == SHT_NOBITS) { memset(memory_getPointerFromVirtualOffset(shAddr), 0, shSize); } else { memcpy(memory_getPointerFromVirtualOffset(shAddr), elfData + shOffset, copySize); } // SHT_NOBITS } } return header->entrypoint; } // From Homebrew Launcher: //#define MEM_BASE (0x00800000) //#define ELF_DATA_ADDR (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x00)) //#define ELF_DATA_SIZE (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x04)) //#define HBL_CHANNEL (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x08)) //#define RPX_MAX_SIZE (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x0C)) //#define RPX_MAX_CODE_SIZE (*(volatile unsigned int*)(MEM_BASE + 0x1300 + 0x10)) //#define MAIN_ENTRY_ADDR (*(volatile unsigned int*)(MEM_BASE + 0x1400 + 0x00)) //#define OS_FIRMWARE (*(volatile unsigned int*)(MEM_BASE + 0x1400 + 0x04)) // //#define OS_SPECIFICS ((OsSpecifics*)(MEM_BASE + 0x1500)) // //#define MEM_AREA_TABLE ((s_mem_area*)(MEM_BASE + 0x1600)) //typedef struct _OsSpecifics //{ // unsigned int addr_OSDynLoad_Acquire; // unsigned int addr_OSDynLoad_FindExport; // unsigned int addr_OSTitle_main_entry; // // unsigned int addr_KernSyscallTbl1; // unsigned int addr_KernSyscallTbl2; // unsigned int addr_KernSyscallTbl3; // unsigned int addr_KernSyscallTbl4; // unsigned int addr_KernSyscallTbl5; // // int(*LiWaitIopComplete)(int, int *); // int(*LiWaitIopCompleteWithInterrupts)(int, int *); // unsigned int addr_LiWaitOneChunk; // unsigned int addr_PrepareTitle_hook; // unsigned int addr_sgIsLoadingBuffer; // unsigned int addr_gDynloadInitialized; // unsigned int orig_LiWaitOneChunkInstr; //} OsSpecifics;