summaryrefslogtreecommitdiff
path: root/src/core/loader/3dsx.cpp
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2016-09-21 11:29:48 -0700
committerGravatar GitHub2016-09-21 11:29:48 -0700
commitd5d2ca8058a0f1c00ab7ca9fe2c058ba47546c0a (patch)
tree8a22ca73ff838f3f0090b29a548ae81087fc90ed /src/core/loader/3dsx.cpp
parentREADME: Specify master branch for Travis CI badge (diff)
parentFix Travis clang-format check (diff)
downloadyuzu-d5d2ca8058a0f1c00ab7ca9fe2c058ba47546c0a.tar.gz
yuzu-d5d2ca8058a0f1c00ab7ca9fe2c058ba47546c0a.tar.xz
yuzu-d5d2ca8058a0f1c00ab7ca9fe2c058ba47546c0a.zip
Merge pull request #2086 from linkmauve/clang-format
Add clang-format as part of our {commit,travis}-time checks
Diffstat (limited to 'src/core/loader/3dsx.cpp')
-rw-r--r--src/core/loader/3dsx.cpp87
1 files changed, 43 insertions, 44 deletions
diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp
index a16411e14..1c10740a0 100644
--- a/src/core/loader/3dsx.cpp
+++ b/src/core/loader/3dsx.cpp
@@ -4,9 +4,7 @@
4 4
5#include <algorithm> 5#include <algorithm>
6#include <vector> 6#include <vector>
7
8#include "common/logging/log.h" 7#include "common/logging/log.h"
9
10#include "core/file_sys/archive_romfs.h" 8#include "core/file_sys/archive_romfs.h"
11#include "core/hle/kernel/process.h" 9#include "core/hle/kernel/process.h"
12#include "core/hle/kernel/resource_limit.h" 10#include "core/hle/kernel/resource_limit.h"
@@ -37,20 +35,14 @@ namespace Loader {
37 * The BSS section must be cleared manually by the application. 35 * The BSS section must be cleared manually by the application.
38 */ 36 */
39 37
40enum THREEDSX_Error { 38enum THREEDSX_Error { ERROR_NONE = 0, ERROR_READ = 1, ERROR_FILE = 2, ERROR_ALLOC = 3 };
41 ERROR_NONE = 0,
42 ERROR_READ = 1,
43 ERROR_FILE = 2,
44 ERROR_ALLOC = 3
45};
46 39
47static const u32 RELOCBUFSIZE = 512; 40static const u32 RELOCBUFSIZE = 512;
48static const unsigned int NUM_SEGMENTS = 3; 41static const unsigned int NUM_SEGMENTS = 3;
49 42
50// File header 43// File header
51#pragma pack(1) 44#pragma pack(1)
52struct THREEDSX_Header 45struct THREEDSX_Header {
53{
54 u32 magic; 46 u32 magic;
55 u16 header_size, reloc_hdr_size; 47 u16 header_size, reloc_hdr_size;
56 u32 format_ver; 48 u32 format_ver;
@@ -66,11 +58,11 @@ struct THREEDSX_Header
66}; 58};
67 59
68// Relocation header: all fields (even extra unknown fields) are guaranteed to be relocation counts. 60// Relocation header: all fields (even extra unknown fields) are guaranteed to be relocation counts.
69struct THREEDSX_RelocHdr 61struct THREEDSX_RelocHdr {
70{
71 // # of absolute relocations (that is, fix address to post-relocation memory layout) 62 // # of absolute relocations (that is, fix address to post-relocation memory layout)
72 u32 cross_segment_absolute; 63 u32 cross_segment_absolute;
73 // # of cross-segment relative relocations (that is, 32bit signed offsets that need to be patched) 64 // # of cross-segment relative relocations (that is, 32bit signed offsets that need to be
65 // patched)
74 u32 cross_segment_relative; 66 u32 cross_segment_relative;
75 // more? 67 // more?
76 68
@@ -80,21 +72,18 @@ struct THREEDSX_RelocHdr
80}; 72};
81 73
82// Relocation entry: from the current pointer, skip X words and patch Y words 74// Relocation entry: from the current pointer, skip X words and patch Y words
83struct THREEDSX_Reloc 75struct THREEDSX_Reloc {
84{
85 u16 skip, patch; 76 u16 skip, patch;
86}; 77};
87#pragma pack() 78#pragma pack()
88 79
89struct THREEloadinfo 80struct THREEloadinfo {
90{
91 u8* seg_ptrs[3]; // code, rodata & data 81 u8* seg_ptrs[3]; // code, rodata & data
92 u32 seg_addrs[3]; 82 u32 seg_addrs[3];
93 u32 seg_sizes[3]; 83 u32 seg_sizes[3];
94}; 84};
95 85
96static u32 TranslateAddr(u32 addr, const THREEloadinfo *loadinfo, u32* offsets) 86static u32 TranslateAddr(u32 addr, const THREEloadinfo* loadinfo, u32* offsets) {
97{
98 if (addr < offsets[0]) 87 if (addr < offsets[0])
99 return loadinfo->seg_addrs[0] + addr; 88 return loadinfo->seg_addrs[0] + addr;
100 if (addr < offsets[1]) 89 if (addr < offsets[1])
@@ -105,8 +94,8 @@ static u32 TranslateAddr(u32 addr, const THREEloadinfo *loadinfo, u32* offsets)
105using Kernel::SharedPtr; 94using Kernel::SharedPtr;
106using Kernel::CodeSet; 95using Kernel::CodeSet;
107 96
108static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, SharedPtr<CodeSet>* out_codeset) 97static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr,
109{ 98 SharedPtr<CodeSet>* out_codeset) {
110 if (!file.IsOpen()) 99 if (!file.IsOpen())
111 return ERROR_FILE; 100 return ERROR_FILE;
112 101
@@ -118,13 +107,14 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
118 return ERROR_READ; 107 return ERROR_READ;
119 108
120 THREEloadinfo loadinfo; 109 THREEloadinfo loadinfo;
121 //loadinfo segments must be a multiple of 0x1000 110 // loadinfo segments must be a multiple of 0x1000
122 loadinfo.seg_sizes[0] = (hdr.code_seg_size + 0xFFF) &~0xFFF; 111 loadinfo.seg_sizes[0] = (hdr.code_seg_size + 0xFFF) & ~0xFFF;
123 loadinfo.seg_sizes[1] = (hdr.rodata_seg_size + 0xFFF) &~0xFFF; 112 loadinfo.seg_sizes[1] = (hdr.rodata_seg_size + 0xFFF) & ~0xFFF;
124 loadinfo.seg_sizes[2] = (hdr.data_seg_size + 0xFFF) &~0xFFF; 113 loadinfo.seg_sizes[2] = (hdr.data_seg_size + 0xFFF) & ~0xFFF;
125 u32 offsets[2] = { loadinfo.seg_sizes[0], loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] }; 114 u32 offsets[2] = {loadinfo.seg_sizes[0], loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1]};
126 u32 n_reloc_tables = hdr.reloc_hdr_size / sizeof(u32); 115 u32 n_reloc_tables = hdr.reloc_hdr_size / sizeof(u32);
127 std::vector<u8> program_image(loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] + loadinfo.seg_sizes[2]); 116 std::vector<u8> program_image(loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] +
117 loadinfo.seg_sizes[2]);
128 118
129 loadinfo.seg_addrs[0] = base_addr; 119 loadinfo.seg_addrs[0] = base_addr;
130 loadinfo.seg_addrs[1] = loadinfo.seg_addrs[0] + loadinfo.seg_sizes[0]; 120 loadinfo.seg_addrs[1] = loadinfo.seg_addrs[0] + loadinfo.seg_sizes[0];
@@ -149,7 +139,8 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
149 return ERROR_READ; 139 return ERROR_READ;
150 if (file.ReadBytes(loadinfo.seg_ptrs[1], hdr.rodata_seg_size) != hdr.rodata_seg_size) 140 if (file.ReadBytes(loadinfo.seg_ptrs[1], hdr.rodata_seg_size) != hdr.rodata_seg_size)
151 return ERROR_READ; 141 return ERROR_READ;
152 if (file.ReadBytes(loadinfo.seg_ptrs[2], hdr.data_seg_size - hdr.bss_size) != hdr.data_seg_size - hdr.bss_size) 142 if (file.ReadBytes(loadinfo.seg_ptrs[2], hdr.data_seg_size - hdr.bss_size) !=
143 hdr.data_seg_size - hdr.bss_size)
153 return ERROR_READ; 144 return ERROR_READ;
154 145
155 // BSS clear 146 // BSS clear
@@ -157,11 +148,12 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
157 148
158 // Relocate the segments 149 // Relocate the segments
159 for (unsigned int current_segment = 0; current_segment < NUM_SEGMENTS; ++current_segment) { 150 for (unsigned int current_segment = 0; current_segment < NUM_SEGMENTS; ++current_segment) {
160 for (unsigned current_segment_reloc_table = 0; current_segment_reloc_table < n_reloc_tables; current_segment_reloc_table++) { 151 for (unsigned current_segment_reloc_table = 0; current_segment_reloc_table < n_reloc_tables;
152 current_segment_reloc_table++) {
161 u32 n_relocs = relocs[current_segment * n_reloc_tables + current_segment_reloc_table]; 153 u32 n_relocs = relocs[current_segment * n_reloc_tables + current_segment_reloc_table];
162 if (current_segment_reloc_table >= 2) { 154 if (current_segment_reloc_table >= 2) {
163 // We are not using this table - ignore it because we don't know what it dose 155 // We are not using this table - ignore it because we don't know what it dose
164 file.Seek(n_relocs*sizeof(THREEDSX_Reloc), SEEK_CUR); 156 file.Seek(n_relocs * sizeof(THREEDSX_Reloc), SEEK_CUR);
165 continue; 157 continue;
166 } 158 }
167 THREEDSX_Reloc reloc_table[RELOCBUFSIZE]; 159 THREEDSX_Reloc reloc_table[RELOCBUFSIZE];
@@ -173,17 +165,20 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
173 u32 remaining = std::min(RELOCBUFSIZE, n_relocs); 165 u32 remaining = std::min(RELOCBUFSIZE, n_relocs);
174 n_relocs -= remaining; 166 n_relocs -= remaining;
175 167
176 if (file.ReadBytes(reloc_table, remaining * sizeof(THREEDSX_Reloc)) != remaining * sizeof(THREEDSX_Reloc)) 168 if (file.ReadBytes(reloc_table, remaining * sizeof(THREEDSX_Reloc)) !=
169 remaining * sizeof(THREEDSX_Reloc))
177 return ERROR_READ; 170 return ERROR_READ;
178 171
179 for (unsigned current_inprogress = 0; current_inprogress < remaining && pos < end_pos; current_inprogress++) { 172 for (unsigned current_inprogress = 0;
173 current_inprogress < remaining && pos < end_pos; current_inprogress++) {
180 const auto& table = reloc_table[current_inprogress]; 174 const auto& table = reloc_table[current_inprogress];
181 LOG_TRACE(Loader, "(t=%d,skip=%u,patch=%u)", current_segment_reloc_table, 175 LOG_TRACE(Loader, "(t=%d,skip=%u,patch=%u)", current_segment_reloc_table,
182 static_cast<u32>(table.skip), static_cast<u32>(table.patch)); 176 static_cast<u32>(table.skip), static_cast<u32>(table.patch));
183 pos += table.skip; 177 pos += table.skip;
184 s32 num_patches = table.patch; 178 s32 num_patches = table.patch;
185 while (0 < num_patches && pos < end_pos) { 179 while (0 < num_patches && pos < end_pos) {
186 u32 in_addr = static_cast<u32>(reinterpret_cast<u8*>(pos) - program_image.data()); 180 u32 in_addr =
181 static_cast<u32>(reinterpret_cast<u8*>(pos) - program_image.data());
187 u32 addr = TranslateAddr(*pos, &loadinfo, offsets); 182 u32 addr = TranslateAddr(*pos, &loadinfo, offsets);
188 LOG_TRACE(Loader, "Patching %08X <-- rel(%08X,%d) (%08X)", 183 LOG_TRACE(Loader, "Patching %08X <-- rel(%08X,%d) (%08X)",
189 base_addr + in_addr, addr, current_segment_reloc_table, *pos); 184 base_addr + in_addr, addr, current_segment_reloc_table, *pos);
@@ -195,7 +190,7 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
195 *pos = static_cast<u32>(addr - in_addr); 190 *pos = static_cast<u32>(addr - in_addr);
196 break; 191 break;
197 default: 192 default:
198 break; //this should never happen 193 break; // this should never happen
199 } 194 }
200 pos++; 195 pos++;
201 num_patches--; 196 num_patches--;
@@ -209,23 +204,24 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
209 SharedPtr<CodeSet> code_set = CodeSet::Create("", 0); 204 SharedPtr<CodeSet> code_set = CodeSet::Create("", 0);
210 205
211 code_set->code.offset = loadinfo.seg_ptrs[0] - program_image.data(); 206 code_set->code.offset = loadinfo.seg_ptrs[0] - program_image.data();
212 code_set->code.addr = loadinfo.seg_addrs[0]; 207 code_set->code.addr = loadinfo.seg_addrs[0];
213 code_set->code.size = loadinfo.seg_sizes[0]; 208 code_set->code.size = loadinfo.seg_sizes[0];
214 209
215 code_set->rodata.offset = loadinfo.seg_ptrs[1] - program_image.data(); 210 code_set->rodata.offset = loadinfo.seg_ptrs[1] - program_image.data();
216 code_set->rodata.addr = loadinfo.seg_addrs[1]; 211 code_set->rodata.addr = loadinfo.seg_addrs[1];
217 code_set->rodata.size = loadinfo.seg_sizes[1]; 212 code_set->rodata.size = loadinfo.seg_sizes[1];
218 213
219 code_set->data.offset = loadinfo.seg_ptrs[2] - program_image.data(); 214 code_set->data.offset = loadinfo.seg_ptrs[2] - program_image.data();
220 code_set->data.addr = loadinfo.seg_addrs[2]; 215 code_set->data.addr = loadinfo.seg_addrs[2];
221 code_set->data.size = loadinfo.seg_sizes[2]; 216 code_set->data.size = loadinfo.seg_sizes[2];
222 217
223 code_set->entrypoint = code_set->code.addr; 218 code_set->entrypoint = code_set->code.addr;
224 code_set->memory = std::make_shared<std::vector<u8>>(std::move(program_image)); 219 code_set->memory = std::make_shared<std::vector<u8>>(std::move(program_image));
225 220
226 LOG_DEBUG(Loader, "code size: 0x%X", loadinfo.seg_sizes[0]); 221 LOG_DEBUG(Loader, "code size: 0x%X", loadinfo.seg_sizes[0]);
227 LOG_DEBUG(Loader, "rodata size: 0x%X", loadinfo.seg_sizes[1]); 222 LOG_DEBUG(Loader, "rodata size: 0x%X", loadinfo.seg_sizes[1]);
228 LOG_DEBUG(Loader, "data size: 0x%X (including 0x%X of bss)", loadinfo.seg_sizes[2], hdr.bss_size); 223 LOG_DEBUG(Loader, "data size: 0x%X (including 0x%X of bss)", loadinfo.seg_sizes[2],
224 hdr.bss_size);
229 225
230 *out_codeset = code_set; 226 *out_codeset = code_set;
231 return ERROR_NONE; 227 return ERROR_NONE;
@@ -260,17 +256,20 @@ ResultStatus AppLoader_THREEDSX::Load() {
260 Kernel::g_current_process->address_mappings = default_address_mappings; 256 Kernel::g_current_process->address_mappings = default_address_mappings;
261 257
262 // Attach the default resource limit (APPLICATION) to the process 258 // Attach the default resource limit (APPLICATION) to the process
263 Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); 259 Kernel::g_current_process->resource_limit =
260 Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
264 261
265 Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE); 262 Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE);
266 263
267 Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(*this), Service::FS::ArchiveIdCode::RomFS); 264 Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(*this),
265 Service::FS::ArchiveIdCode::RomFS);
268 266
269 is_loaded = true; 267 is_loaded = true;
270 return ResultStatus::Success; 268 return ResultStatus::Success;
271} 269}
272 270
273ResultStatus AppLoader_THREEDSX::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) { 271ResultStatus AppLoader_THREEDSX::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file,
272 u64& offset, u64& size) {
274 if (!file.IsOpen()) 273 if (!file.IsOpen())
275 return ResultStatus::Error; 274 return ResultStatus::Error;
276 275