mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-26 00:20:14 +00:00
implemented basic cia loader
This commit is contained in:
parent
26979cd6ef
commit
8b4d0c5d8d
@ -141,7 +141,7 @@ void GameList::LoadInterfaceLayout() {
|
||||
}
|
||||
|
||||
const QStringList GameList::supported_file_extensions = {"3ds", "3dsx", "elf", "axf",
|
||||
"cci", "cxi", "app"};
|
||||
"cci", "cxi", "app", "cia"};
|
||||
|
||||
static bool HasSupportedFileExtension(const std::string& file_name) {
|
||||
QFileInfo file = QFileInfo(file_name.c_str());
|
||||
|
@ -113,6 +113,7 @@ static std::unique_ptr<AppLoader> GetFileLoader(FileUtil::IOFile&& file, FileTyp
|
||||
// NCCH/NCSD container formats.
|
||||
case FileType::CXI:
|
||||
case FileType::CCI:
|
||||
case FileType::CIA:
|
||||
return std::make_unique<AppLoader_NCCH>(std::move(file), filepath);
|
||||
|
||||
default:
|
||||
|
@ -26,6 +26,44 @@ namespace Loader {
|
||||
static const int kMaxSections = 8; ///< Maximum number of sections (files) in an ExeFs
|
||||
static const int kBlockSize = 0x200; ///< Size of ExeFS blocks (in bytes)
|
||||
|
||||
static u32 FindNCCHOffsetInCIA(FileUtil::IOFile& file) {
|
||||
// Reset read pointer in case this file has been read before.
|
||||
file.Seek(0, SEEK_SET);
|
||||
CIAHeader cia_header;
|
||||
|
||||
file.ReadBytes(&cia_header, sizeof(CIAHeader));
|
||||
u32 certs_offset = Common::AlignUp(cia_header.header_size, 64);
|
||||
u32 tik_offset = Common::AlignUp(certs_offset + cia_header.cert_size, 64);
|
||||
u32 tmd_offset = Common::AlignUp(tik_offset + cia_header.ticket_size, 64);
|
||||
u32 content_offset = Common::AlignUp(tmd_offset + cia_header.tmd_size, 64);
|
||||
return content_offset;
|
||||
}
|
||||
|
||||
static bool IsValidCia(FileUtil::IOFile& file) {
|
||||
// Reset read pointer in case this file has been read before.
|
||||
file.Seek(0, SEEK_SET);
|
||||
|
||||
bool is_valid = false;
|
||||
u32 magic;
|
||||
u32 offset = FindNCCHOffsetInCIA(file);
|
||||
file.Seek(offset, SEEK_SET);
|
||||
file.ReadArray<u32>(&magic, 1);
|
||||
if (MakeMagic('N', 'C', 'C', 'H') != magic) {
|
||||
// this additional if check was made to account for the possible
|
||||
// padding which always seems to exist as 256 extra bytes
|
||||
// TODO: see if the padding can be other sizes as well as 256
|
||||
file.Seek(offset + 256, SEEK_SET);
|
||||
file.ReadArray<u32>(&magic, 1);
|
||||
if (MakeMagic('N', 'C', 'C', 'H') == magic) {
|
||||
is_valid = true;
|
||||
}
|
||||
} else {
|
||||
is_valid = true;
|
||||
}
|
||||
|
||||
return is_valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the decompressed size of an LZSS compressed ExeFS file
|
||||
* @param buffer Buffer of compressed file
|
||||
@ -117,6 +155,9 @@ FileType AppLoader_NCCH::IdentifyType(FileUtil::IOFile& file) {
|
||||
if (MakeMagic('N', 'C', 'C', 'H') == magic)
|
||||
return FileType::CXI;
|
||||
|
||||
if (IsValidCia(file))
|
||||
return FileType::CIA;
|
||||
|
||||
return FileType::Error;
|
||||
}
|
||||
|
||||
@ -260,6 +301,17 @@ ResultStatus AppLoader_NCCH::LoadExeFS() {
|
||||
file.ReadBytes(&ncch_header, sizeof(NCCH_Header));
|
||||
}
|
||||
|
||||
if (IsValidCia(file)) {
|
||||
LOG_DEBUG(Loader, "Loading CIA");
|
||||
ncch_offset = FindNCCHOffsetInCIA(file);
|
||||
file.Seek(ncch_offset, SEEK_SET);
|
||||
file.ReadBytes(&ncch_header, sizeof(NCCH_Header));
|
||||
// the padding check
|
||||
if (MakeMagic('N', 'C', 'C', 'H') != ncch_header.magic) {
|
||||
ncch_offset += 256;
|
||||
}
|
||||
}
|
||||
|
||||
// Verify we are loading the correct file type...
|
||||
if (MakeMagic('N', 'C', 'C', 'H') != ncch_header.magic)
|
||||
return ResultStatus::ErrorInvalidFormat;
|
||||
|
@ -5,10 +5,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include "common/alignment.h"
|
||||
#include "common/bit_field.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/loader/loader.h"
|
||||
struct CIAHeader {
|
||||
u32_le header_size;
|
||||
u8 type[2];
|
||||
u8 version[2];
|
||||
u32_le cert_size;
|
||||
u32_le ticket_size;
|
||||
u32_le tmd_size;
|
||||
u32_le meta_size;
|
||||
u64_le content_size;
|
||||
u8 content_index[0x2000];
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// NCCH header (Note: "NCCH" appears to be a publicly unknown acronym)
|
||||
@ -251,5 +263,4 @@ private:
|
||||
|
||||
std::string filepath;
|
||||
};
|
||||
|
||||
} // namespace Loader
|
||||
|
Loading…
Reference in New Issue
Block a user