summaryrefslogtreecommitdiff
path: root/src/core/loader/ncch.cpp
diff options
context:
space:
mode:
authorGravatar Emmanuel Gil Peyrot2015-01-06 21:30:40 +0000
committerGravatar Emmanuel Gil Peyrot2015-01-15 21:21:26 +0000
commitb5237e885df72f6c37532fc8af9573966e7b07e5 (patch)
treefdfd4da299cc2779f35fcc30e770b85b9e710166 /src/core/loader/ncch.cpp
parentLoader: Initialize the default NCCH values in the class declaration, not in t... (diff)
downloadyuzu-b5237e885df72f6c37532fc8af9573966e7b07e5.tar.gz
yuzu-b5237e885df72f6c37532fc8af9573966e7b07e5.tar.xz
yuzu-b5237e885df72f6c37532fc8af9573966e7b07e5.zip
Loader: Keep a reference to the file and pass it to the correct AppLoader, instead of loading it multiple times.
Diffstat (limited to 'src/core/loader/ncch.cpp')
-rw-r--r--src/core/loader/ncch.cpp190
1 files changed, 84 insertions, 106 deletions
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp
index 883a0f753..eca57d14b 100644
--- a/src/core/loader/ncch.cpp
+++ b/src/core/loader/ncch.cpp
@@ -4,8 +4,6 @@
4 4
5#include <memory> 5#include <memory>
6 6
7#include "common/file_util.h"
8
9#include "core/loader/ncch.h" 7#include "core/loader/ncch.h"
10#include "core/hle/kernel/kernel.h" 8#include "core/hle/kernel/kernel.h"
11#include "core/mem_map.h" 9#include "core/mem_map.h"
@@ -99,15 +97,6 @@ static bool LZSS_Decompress(u8* compressed, u32 compressed_size, u8* decompresse
99//////////////////////////////////////////////////////////////////////////////////////////////////// 97////////////////////////////////////////////////////////////////////////////////////////////////////
100// AppLoader_NCCH class 98// AppLoader_NCCH class
101 99
102/// AppLoader_NCCH constructor
103AppLoader_NCCH::AppLoader_NCCH(const std::string& filename) {
104 this->filename = filename;
105}
106
107/// AppLoader_NCCH destructor
108AppLoader_NCCH::~AppLoader_NCCH() {
109}
110
111ResultStatus AppLoader_NCCH::LoadExec() const { 100ResultStatus AppLoader_NCCH::LoadExec() const {
112 if (!is_loaded) 101 if (!is_loaded)
113 return ResultStatus::ErrorNotLoaded; 102 return ResultStatus::ErrorNotLoaded;
@@ -123,108 +112,100 @@ ResultStatus AppLoader_NCCH::LoadExec() const {
123 112
124ResultStatus AppLoader_NCCH::LoadSectionExeFS(const char* name, std::vector<u8>& buffer) const { 113ResultStatus AppLoader_NCCH::LoadSectionExeFS(const char* name, std::vector<u8>& buffer) const {
125 // Iterate through the ExeFs archive until we find the .code file... 114 // Iterate through the ExeFs archive until we find the .code file...
126 FileUtil::IOFile file(filename, "rb"); 115 if (!file->IsOpen())
127 if (file.IsOpen()) { 116 return ResultStatus::Error;
128 LOG_DEBUG(Loader, "%d sections:", kMaxSections); 117
129 for (int i = 0; i < kMaxSections; i++) { 118 LOG_DEBUG(Loader, "%d sections:", kMaxSections);
130 // Load the specified section... 119 for (int i = 0; i < kMaxSections; i++) {
131 if (strcmp((const char*)exefs_header.section[i].name, name) == 0) { 120 // Load the specified section...
132 LOG_DEBUG(Loader, "%d - offset: 0x%08X, size: 0x%08X, name: %s", i, 121 if (strcmp((const char*)exefs_header.section[i].name, name) == 0) {
133 exefs_header.section[i].offset, exefs_header.section[i].size, 122 LOG_DEBUG(Loader, "%d - offset: 0x%08X, size: 0x%08X, name: %s", i,
134 exefs_header.section[i].name); 123 exefs_header.section[i].offset, exefs_header.section[i].size,
135 124 exefs_header.section[i].name);
136 s64 section_offset = (exefs_header.section[i].offset + exefs_offset + 125
137 sizeof(ExeFs_Header)+ncch_offset); 126 s64 section_offset = (exefs_header.section[i].offset + exefs_offset +
138 file.Seek(section_offset, 0); 127 sizeof(ExeFs_Header)+ncch_offset);
139 128 file->Seek(section_offset, 0);
140 // Section is compressed... 129
141 if (i == 0 && is_compressed) { 130 // Section is compressed...
142 // Read compressed .code section... 131 if (i == 0 && is_compressed) {
143 std::unique_ptr<u8[]> temp_buffer; 132 // Read compressed .code section...
144 try { 133 std::unique_ptr<u8[]> temp_buffer;
145 temp_buffer.reset(new u8[exefs_header.section[i].size]); 134 try {
146 } catch (std::bad_alloc&) { 135 temp_buffer.reset(new u8[exefs_header.section[i].size]);
147 return ResultStatus::ErrorMemoryAllocationFailed; 136 } catch (std::bad_alloc&) {
148 } 137 return ResultStatus::ErrorMemoryAllocationFailed;
149 file.ReadBytes(&temp_buffer[0], exefs_header.section[i].size);
150
151 // Decompress .code section...
152 u32 decompressed_size = LZSS_GetDecompressedSize(&temp_buffer[0],
153 exefs_header.section[i].size);
154 buffer.resize(decompressed_size);
155 if (!LZSS_Decompress(&temp_buffer[0], exefs_header.section[i].size, &buffer[0],
156 decompressed_size)) {
157 return ResultStatus::ErrorInvalidFormat;
158 }
159 // Section is uncompressed...
160 } 138 }
161 else { 139 file->ReadBytes(&temp_buffer[0], exefs_header.section[i].size);
162 buffer.resize(exefs_header.section[i].size); 140
163 file.ReadBytes(&buffer[0], exefs_header.section[i].size); 141 // Decompress .code section...
142 u32 decompressed_size = LZSS_GetDecompressedSize(&temp_buffer[0],
143 exefs_header.section[i].size);
144 buffer.resize(decompressed_size);
145 if (!LZSS_Decompress(&temp_buffer[0], exefs_header.section[i].size, &buffer[0],
146 decompressed_size)) {
147 return ResultStatus::ErrorInvalidFormat;
164 } 148 }
165 return ResultStatus::Success; 149 // Section is uncompressed...
166 } 150 }
151 else {
152 buffer.resize(exefs_header.section[i].size);
153 file->ReadBytes(&buffer[0], exefs_header.section[i].size);
154 }
155 return ResultStatus::Success;
167 } 156 }
168 } else {
169 LOG_ERROR(Loader, "Unable to read file %s!", filename.c_str());
170 return ResultStatus::Error;
171 } 157 }
172 return ResultStatus::ErrorNotUsed; 158 return ResultStatus::ErrorNotUsed;
173} 159}
174 160
175ResultStatus AppLoader_NCCH::Load() { 161ResultStatus AppLoader_NCCH::Load() {
176 LOG_INFO(Loader, "Loading NCCH file %s...", filename.c_str());
177
178 if (is_loaded) 162 if (is_loaded)
179 return ResultStatus::ErrorAlreadyLoaded; 163 return ResultStatus::ErrorAlreadyLoaded;
180 164
181 FileUtil::IOFile file(filename, "rb"); 165 if (!file->IsOpen())
182 if (file.IsOpen()) { 166 return ResultStatus::Error;
183 file.ReadBytes(&ncch_header, sizeof(NCCH_Header));
184 167
185 // Skip NCSD header and load first NCCH (NCSD is just a container of NCCH files)... 168 file->ReadBytes(&ncch_header, sizeof(NCCH_Header));
186 if (0 == memcmp(&ncch_header.magic, "NCSD", 4)) {
187 LOG_WARNING(Loader, "Only loading the first (bootable) NCCH within the NCSD file!");
188 ncch_offset = 0x4000;
189 file.Seek(ncch_offset, 0);
190 file.ReadBytes(&ncch_header, sizeof(NCCH_Header));
191 }
192 169
193 // Verify we are loading the correct file type... 170 // Skip NCSD header and load first NCCH (NCSD is just a container of NCCH files)...
194 if (0 != memcmp(&ncch_header.magic, "NCCH", 4)) 171 if (0 == memcmp(&ncch_header.magic, "NCSD", 4)) {
195 return ResultStatus::ErrorInvalidFormat; 172 LOG_WARNING(Loader, "Only loading the first (bootable) NCCH within the NCSD file!");
173 ncch_offset = 0x4000;
174 file->Seek(ncch_offset, 0);
175 file->ReadBytes(&ncch_header, sizeof(NCCH_Header));
176 }
196 177
197 // Read ExHeader... 178 // Verify we are loading the correct file type...
179 if (0 != memcmp(&ncch_header.magic, "NCCH", 4))
180 return ResultStatus::ErrorInvalidFormat;
198 181
199 file.ReadBytes(&exheader_header, sizeof(ExHeader_Header)); 182 // Read ExHeader...
200 183
201 is_compressed = (exheader_header.codeset_info.flags.flag & 1) == 1; 184 file->ReadBytes(&exheader_header, sizeof(ExHeader_Header));
202 entry_point = exheader_header.codeset_info.text.address;
203 185
204 LOG_INFO(Loader, "Name: %s", exheader_header.codeset_info.name); 186 is_compressed = (exheader_header.codeset_info.flags.flag & 1) == 1;
205 LOG_DEBUG(Loader, "Code compressed: %s", is_compressed ? "yes" : "no"); 187 entry_point = exheader_header.codeset_info.text.address;
206 LOG_DEBUG(Loader, "Entry point: 0x%08X", entry_point);
207 188
208 // Read ExeFS... 189 LOG_INFO(Loader, "Name: %s", exheader_header.codeset_info.name);
190 LOG_DEBUG(Loader, "Code compressed: %s", is_compressed ? "yes" : "no");
191 LOG_DEBUG(Loader, "Entry point: 0x%08X", entry_point);
209 192
210 exefs_offset = ncch_header.exefs_offset * kBlockSize; 193 // Read ExeFS...
211 u32 exefs_size = ncch_header.exefs_size * kBlockSize;
212 194
213 LOG_DEBUG(Loader, "ExeFS offset: 0x%08X", exefs_offset); 195 exefs_offset = ncch_header.exefs_offset * kBlockSize;
214 LOG_DEBUG(Loader, "ExeFS size: 0x%08X", exefs_size); 196 u32 exefs_size = ncch_header.exefs_size * kBlockSize;
215 197
216 file.Seek(exefs_offset + ncch_offset, 0); 198 LOG_DEBUG(Loader, "ExeFS offset: 0x%08X", exefs_offset);
217 file.ReadBytes(&exefs_header, sizeof(ExeFs_Header)); 199 LOG_DEBUG(Loader, "ExeFS size: 0x%08X", exefs_size);
218 200
219 LoadExec(); // Load the executable into memory for booting 201 file->Seek(exefs_offset + ncch_offset, 0);
202 file->ReadBytes(&exefs_header, sizeof(ExeFs_Header));
220 203
221 is_loaded = true; // Set state to loaded 204 LoadExec(); // Load the executable into memory for booting
222 205
223 return ResultStatus::Success; 206 is_loaded = true; // Set state to loaded
224 } else { 207
225 LOG_ERROR(Loader, "Unable to read file %s!", filename.c_str()); 208 return ResultStatus::Success;
226 }
227 return ResultStatus::Error;
228} 209}
229 210
230ResultStatus AppLoader_NCCH::ReadCode(std::vector<u8>& buffer) const { 211ResultStatus AppLoader_NCCH::ReadCode(std::vector<u8>& buffer) const {
@@ -244,29 +225,26 @@ ResultStatus AppLoader_NCCH::ReadLogo(std::vector<u8>& buffer) const {
244} 225}
245 226
246ResultStatus AppLoader_NCCH::ReadRomFS(std::vector<u8>& buffer) const { 227ResultStatus AppLoader_NCCH::ReadRomFS(std::vector<u8>& buffer) const {
247 FileUtil::IOFile file(filename, "rb"); 228 if (!file->IsOpen())
248 if (file.IsOpen()) { 229 return ResultStatus::Error;
249 // Check if the NCCH has a RomFS...
250 if (ncch_header.romfs_offset != 0 && ncch_header.romfs_size != 0) {
251 u32 romfs_offset = ncch_offset + (ncch_header.romfs_offset * kBlockSize) + 0x1000;
252 u32 romfs_size = (ncch_header.romfs_size * kBlockSize) - 0x1000;
253 230
254 LOG_DEBUG(Loader, "RomFS offset: 0x%08X", romfs_offset); 231 // Check if the NCCH has a RomFS...
255 LOG_DEBUG(Loader, "RomFS size: 0x%08X", romfs_size); 232 if (ncch_header.romfs_offset != 0 && ncch_header.romfs_size != 0) {
233 u32 romfs_offset = ncch_offset + (ncch_header.romfs_offset * kBlockSize) + 0x1000;
234 u32 romfs_size = (ncch_header.romfs_size * kBlockSize) - 0x1000;
256 235
257 buffer.resize(romfs_size); 236 LOG_DEBUG(Loader, "RomFS offset: 0x%08X", romfs_offset);
237 LOG_DEBUG(Loader, "RomFS size: 0x%08X", romfs_size);
258 238
259 file.Seek(romfs_offset, 0); 239 buffer.resize(romfs_size);
260 file.ReadBytes(&buffer[0], romfs_size);
261 240
262 return ResultStatus::Success; 241 file->Seek(romfs_offset, 0);
263 } 242 file->ReadBytes(&buffer[0], romfs_size);
264 LOG_DEBUG(Loader, "NCCH has no RomFS"); 243
265 return ResultStatus::ErrorNotUsed; 244 return ResultStatus::Success;
266 } else {
267 LOG_ERROR(Loader, "Unable to read file %s!", filename.c_str());
268 } 245 }
269 return ResultStatus::Error; 246 LOG_DEBUG(Loader, "NCCH has no RomFS");
247 return ResultStatus::ErrorNotUsed;
270} 248}
271 249
272u64 AppLoader_NCCH::GetProgramId() const { 250u64 AppLoader_NCCH::GetProgramId() const {