diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/loader/3dsx.cpp | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index d288486f2..e57d7274c 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | 19 | ||
| 20 | namespace Loader { | 20 | namespace Loader { |
| 21 | 21 | ||
| 22 | /** | 22 | /* |
| 23 | * File layout: | 23 | * File layout: |
| 24 | * - File header | 24 | * - File header |
| 25 | * - Code, rodata and data relocation table headers | 25 | * - Code, rodata and data relocation table headers |
| @@ -39,13 +39,16 @@ namespace Loader { | |||
| 39 | * The entrypoint is always the start of the code segment. | 39 | * The entrypoint is always the start of the code segment. |
| 40 | * The BSS section must be cleared manually by the application. | 40 | * The BSS section must be cleared manually by the application. |
| 41 | */ | 41 | */ |
| 42 | |||
| 42 | enum THREEDSX_Error { | 43 | enum THREEDSX_Error { |
| 43 | ERROR_NONE = 0, | 44 | ERROR_NONE = 0, |
| 44 | ERROR_READ = 1, | 45 | ERROR_READ = 1, |
| 45 | ERROR_FILE = 2, | 46 | ERROR_FILE = 2, |
| 46 | ERROR_ALLOC = 3 | 47 | ERROR_ALLOC = 3 |
| 47 | }; | 48 | }; |
| 49 | |||
| 48 | static const u32 RELOCBUFSIZE = 512; | 50 | static const u32 RELOCBUFSIZE = 512; |
| 51 | static const unsigned int NUM_SEGMENTS = 3; | ||
| 49 | 52 | ||
| 50 | // File header | 53 | // File header |
| 51 | #pragma pack(1) | 54 | #pragma pack(1) |
| @@ -116,13 +119,13 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) | |||
| 116 | loadinfo.seg_sizes[1] = (hdr.rodata_seg_size + 0xFFF) &~0xFFF; | 119 | loadinfo.seg_sizes[1] = (hdr.rodata_seg_size + 0xFFF) &~0xFFF; |
| 117 | loadinfo.seg_sizes[2] = (hdr.data_seg_size + 0xFFF) &~0xFFF; | 120 | loadinfo.seg_sizes[2] = (hdr.data_seg_size + 0xFFF) &~0xFFF; |
| 118 | u32 offsets[2] = { loadinfo.seg_sizes[0], loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] }; | 121 | u32 offsets[2] = { loadinfo.seg_sizes[0], loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] }; |
| 119 | u32 n_reloc_tables = hdr.reloc_hdr_size / 4; | 122 | u32 n_reloc_tables = hdr.reloc_hdr_size / sizeof(u32); |
| 120 | std::vector<u8> all_mem(loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] + loadinfo.seg_sizes[2] + 3 * n_reloc_tables); | 123 | std::vector<u8> program_image(loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] + loadinfo.seg_sizes[2]); |
| 121 | 124 | ||
| 122 | loadinfo.seg_addrs[0] = base_addr; | 125 | loadinfo.seg_addrs[0] = base_addr; |
| 123 | loadinfo.seg_addrs[1] = loadinfo.seg_addrs[0] + loadinfo.seg_sizes[0]; | 126 | loadinfo.seg_addrs[1] = loadinfo.seg_addrs[0] + loadinfo.seg_sizes[0]; |
| 124 | loadinfo.seg_addrs[2] = loadinfo.seg_addrs[1] + loadinfo.seg_sizes[1]; | 127 | loadinfo.seg_addrs[2] = loadinfo.seg_addrs[1] + loadinfo.seg_sizes[1]; |
| 125 | loadinfo.seg_ptrs[0] = &all_mem[0]; | 128 | loadinfo.seg_ptrs[0] = program_image.data(); |
| 126 | loadinfo.seg_ptrs[1] = loadinfo.seg_ptrs[0] + loadinfo.seg_sizes[0]; | 129 | loadinfo.seg_ptrs[1] = loadinfo.seg_ptrs[0] + loadinfo.seg_sizes[0]; |
| 127 | loadinfo.seg_ptrs[2] = loadinfo.seg_ptrs[1] + loadinfo.seg_sizes[1]; | 130 | loadinfo.seg_ptrs[2] = loadinfo.seg_ptrs[1] + loadinfo.seg_sizes[1]; |
| 128 | 131 | ||
| @@ -130,10 +133,9 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) | |||
| 130 | file.Seek(hdr.header_size, SEEK_SET); | 133 | file.Seek(hdr.header_size, SEEK_SET); |
| 131 | 134 | ||
| 132 | // Read the relocation headers | 135 | // Read the relocation headers |
| 133 | u32* relocs = (u32*)(loadinfo.seg_ptrs[2] + hdr.data_seg_size); | 136 | std::vector<u32> relocs(n_reloc_tables * NUM_SEGMENTS); |
| 134 | 137 | for (unsigned int current_segment = 0; current_segment < NUM_SEGMENTS; ++current_segment) { | |
| 135 | for (unsigned current_segment : {0, 1, 2}) { | 138 | size_t size = n_reloc_tables * sizeof(u32); |
| 136 | size_t size = n_reloc_tables * 4; | ||
| 137 | if (file.ReadBytes(&relocs[current_segment * n_reloc_tables], size) != size) | 139 | if (file.ReadBytes(&relocs[current_segment * n_reloc_tables], size) != size) |
| 138 | return ERROR_READ; | 140 | return ERROR_READ; |
| 139 | } | 141 | } |
| @@ -150,7 +152,7 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) | |||
| 150 | memset((char*)loadinfo.seg_ptrs[2] + hdr.data_seg_size - hdr.bss_size, 0, hdr.bss_size); | 152 | memset((char*)loadinfo.seg_ptrs[2] + hdr.data_seg_size - hdr.bss_size, 0, hdr.bss_size); |
| 151 | 153 | ||
| 152 | // Relocate the segments | 154 | // Relocate the segments |
| 153 | for (unsigned current_segment : {0, 1, 2}) { | 155 | for (unsigned int current_segment = 0; current_segment < NUM_SEGMENTS; ++current_segment) { |
| 154 | for (unsigned current_segment_reloc_table = 0; current_segment_reloc_table < n_reloc_tables; current_segment_reloc_table++) { | 156 | for (unsigned current_segment_reloc_table = 0; current_segment_reloc_table < n_reloc_tables; current_segment_reloc_table++) { |
| 155 | u32 n_relocs = relocs[current_segment * n_reloc_tables + current_segment_reloc_table]; | 157 | u32 n_relocs = relocs[current_segment * n_reloc_tables + current_segment_reloc_table]; |
| 156 | if (current_segment_reloc_table >= 2) { | 158 | if (current_segment_reloc_table >= 2) { |
| @@ -158,7 +160,7 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) | |||
| 158 | file.Seek(n_relocs*sizeof(THREEDSX_Reloc), SEEK_CUR); | 160 | file.Seek(n_relocs*sizeof(THREEDSX_Reloc), SEEK_CUR); |
| 159 | continue; | 161 | continue; |
| 160 | } | 162 | } |
| 161 | static THREEDSX_Reloc reloc_table[RELOCBUFSIZE]; | 163 | THREEDSX_Reloc reloc_table[RELOCBUFSIZE]; |
| 162 | 164 | ||
| 163 | u32* pos = (u32*)loadinfo.seg_ptrs[current_segment]; | 165 | u32* pos = (u32*)loadinfo.seg_ptrs[current_segment]; |
| 164 | const u32* end_pos = pos + (loadinfo.seg_sizes[current_segment] / 4); | 166 | const u32* end_pos = pos + (loadinfo.seg_sizes[current_segment] / 4); |
| @@ -177,7 +179,7 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) | |||
| 177 | pos += table.skip; | 179 | pos += table.skip; |
| 178 | s32 num_patches = table.patch; | 180 | s32 num_patches = table.patch; |
| 179 | while (0 < num_patches && pos < end_pos) { | 181 | while (0 < num_patches && pos < end_pos) { |
| 180 | u32 in_addr = (char*)pos - (char*)&all_mem[0]; | 182 | u32 in_addr = (u8*)pos - program_image.data(); |
| 181 | u32 addr = TranslateAddr(*pos, &loadinfo, offsets); | 183 | u32 addr = TranslateAddr(*pos, &loadinfo, offsets); |
| 182 | LOG_TRACE(Loader, "Patching %08X <-- rel(%08X,%d) (%08X)\n", | 184 | LOG_TRACE(Loader, "Patching %08X <-- rel(%08X,%d) (%08X)\n", |
| 183 | base_addr + in_addr, addr, current_segment_reloc_table, *pos); | 185 | base_addr + in_addr, addr, current_segment_reloc_table, *pos); |
| @@ -200,7 +202,7 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) | |||
| 200 | } | 202 | } |
| 201 | 203 | ||
| 202 | // Write the data | 204 | // Write the data |
| 203 | memcpy(Memory::GetPointer(base_addr), &all_mem[0], loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] + loadinfo.seg_sizes[2]); | 205 | memcpy(Memory::GetPointer(base_addr), program_image.data(), program_image.size()); |
| 204 | 206 | ||
| 205 | LOG_DEBUG(Loader, "code size: 0x%X", loadinfo.seg_sizes[0]); | 207 | LOG_DEBUG(Loader, "code size: 0x%X", loadinfo.seg_sizes[0]); |
| 206 | LOG_DEBUG(Loader, "rodata size: 0x%X", loadinfo.seg_sizes[1]); | 208 | LOG_DEBUG(Loader, "rodata size: 0x%X", loadinfo.seg_sizes[1]); |
| @@ -235,7 +237,8 @@ ResultStatus AppLoader_THREEDSX::Load() { | |||
| 235 | // Attach the default resource limit (APPLICATION) to the process | 237 | // Attach the default resource limit (APPLICATION) to the process |
| 236 | Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); | 238 | Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); |
| 237 | 239 | ||
| 238 | Load3DSXFile(*file, Memory::PROCESS_IMAGE_VADDR); | 240 | if (Load3DSXFile(*file, Memory::PROCESS_IMAGE_VADDR) != ERROR_NONE) |
| 241 | return ResultStatus::Error; | ||
| 239 | 242 | ||
| 240 | Kernel::g_current_process->Run(Memory::PROCESS_IMAGE_VADDR, 48, Kernel::DEFAULT_STACK_SIZE); | 243 | Kernel::g_current_process->Run(Memory::PROCESS_IMAGE_VADDR, 48, Kernel::DEFAULT_STACK_SIZE); |
| 241 | 244 | ||