From d60a9be5c6332da6e6ff82125e53b1365a389ae0 Mon Sep 17 00:00:00 2001 From: Cruel Date: Mon, 21 Sep 2015 01:30:06 -0400 Subject: Implement 3dsx RomFS --- src/core/loader/3dsx.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ src/core/loader/3dsx.h | 14 ++++++++++++-- src/core/loader/loader.cpp | 10 +++++++++- 3 files changed, 61 insertions(+), 3 deletions(-) (limited to 'src/core/loader') diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index 530837d08..111b6a409 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp @@ -62,6 +62,10 @@ struct THREEDSX_Header // Sizes of the code, rodata and data segments + // size of the BSS section (uninitialized latter half of the data segment) u32 code_seg_size, rodata_seg_size, data_seg_size, bss_size; + // offset and size of smdh + u32 smdh_offset, smdh_size; + // offset to filesystem + u32 fs_offset; }; // Relocation header: all fields (even extra unknown fields) are guaranteed to be relocation counts. @@ -267,4 +271,40 @@ ResultStatus AppLoader_THREEDSX::Load() { return ResultStatus::Success; } +ResultStatus AppLoader_THREEDSX::ReadRomFS(std::shared_ptr& romfs_file, u64& offset, u64& size) { + if (!file.IsOpen()) + return ResultStatus::Error; + + // Reset read pointer in case this file has been read before. + file.Seek(0, SEEK_SET); + + THREEDSX_Header hdr; + if (file.ReadBytes(&hdr, sizeof(THREEDSX_Header)) != sizeof(THREEDSX_Header)) + return ResultStatus::Error; + + if (hdr.header_size != sizeof(THREEDSX_Header)) + return ResultStatus::Error; + + // Check if the 3DSX has a RomFS... + if (hdr.fs_offset != 0) { + u32 romfs_offset = hdr.fs_offset; + u32 romfs_size = file.GetSize() - hdr.fs_offset; + + LOG_DEBUG(Loader, "RomFS offset: 0x%08X", romfs_offset); + LOG_DEBUG(Loader, "RomFS size: 0x%08X", romfs_size); + + // We reopen the file, to allow its position to be independent from file's + romfs_file = std::make_shared(filepath, "rb"); + if (!romfs_file->IsOpen()) + return ResultStatus::Error; + + offset = romfs_offset; + size = romfs_size; + + return ResultStatus::Success; + } + LOG_DEBUG(Loader, "3DSX has no RomFS"); + return ResultStatus::ErrorNotUsed; +} + } // namespace Loader diff --git a/src/core/loader/3dsx.h b/src/core/loader/3dsx.h index a0aa0c533..365ddb7a5 100644 --- a/src/core/loader/3dsx.h +++ b/src/core/loader/3dsx.h @@ -17,8 +17,8 @@ namespace Loader { /// Loads an 3DSX file class AppLoader_THREEDSX final : public AppLoader { public: - AppLoader_THREEDSX(FileUtil::IOFile&& file, std::string filename) - : AppLoader(std::move(file)), filename(std::move(filename)) {} + AppLoader_THREEDSX(FileUtil::IOFile&& file, std::string filename, const std::string& filepath) + : AppLoader(std::move(file)), filename(std::move(filename)), filepath(filepath) {} /** * Returns the type of the file @@ -33,8 +33,18 @@ public: */ ResultStatus Load() override; + /** + * Get the RomFS of the application + * @param romfs_file Reference to buffer to store data + * @param offset Offset in the file to the RomFS + * @param size Size of the RomFS in bytes + * @return ResultStatus result of function + */ + ResultStatus ReadRomFS(std::shared_ptr& romfs_file, u64& offset, u64& size) override; + private: std::string filename; + std::string filepath; }; } // namespace Loader diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 74eb6e871..c4b4f5a5d 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -116,7 +116,15 @@ ResultStatus LoadFile(const std::string& filename) { //3DSX file format... case FileType::THREEDSX: - return AppLoader_THREEDSX(std::move(file), filename_filename).Load(); + { + AppLoader_THREEDSX app_loader(std::move(file), filename_filename, filename); + // Load application and RomFS + if (ResultStatus::Success == app_loader.Load()) { + Service::FS::RegisterArchiveType(Common::make_unique(app_loader), Service::FS::ArchiveIdCode::RomFS); + return ResultStatus::Success; + } + break; + } // Standard ELF file format... case FileType::ELF: -- cgit v1.2.3