4 changed files with 260 additions and 20 deletions
-
2src/core/CMakeLists.txt
-
102src/core/hle/romfs.cpp
-
22src/core/hle/romfs.h
-
154src/core/hle/service/apt/apt.cpp
@ -0,0 +1,102 @@ |
|||
// Copyright 2017 Citra Emulator Project
|
|||
// Licensed under GPLv2 or any later version
|
|||
// Refer to the license.txt file included.
|
|||
|
|||
#include <cstring>
|
|||
#include "common/swap.h"
|
|||
#include "core/hle/romfs.h"
|
|||
|
|||
namespace RomFS { |
|||
|
|||
struct Header { |
|||
u32_le header_length; |
|||
u32_le dir_hash_table_offset; |
|||
u32_le dir_hash_table_length; |
|||
u32_le dir_table_offset; |
|||
u32_le dir_table_length; |
|||
u32_le file_hash_table_offset; |
|||
u32_le file_hash_table_length; |
|||
u32_le file_table_offset; |
|||
u32_le file_table_length; |
|||
u32_le data_offset; |
|||
}; |
|||
|
|||
static_assert(sizeof(Header) == 0x28, "Header has incorrect size"); |
|||
|
|||
struct DirectoryMetadata { |
|||
u32_le parent_dir_offset; |
|||
u32_le next_dir_offset; |
|||
u32_le first_child_dir_offset; |
|||
u32_le first_file_offset; |
|||
u32_le same_hash_next_dir_offset; |
|||
u32_le name_length; // in bytes
|
|||
// followed by directory name
|
|||
}; |
|||
|
|||
static_assert(sizeof(DirectoryMetadata) == 0x18, "DirectoryMetadata has incorrect size"); |
|||
|
|||
struct FileMetadata { |
|||
u32_le parent_dir_offset; |
|||
u32_le next_file_offset; |
|||
u64_le data_offset; |
|||
u64_le data_length; |
|||
u32_le same_hash_next_file_offset; |
|||
u32_le name_length; // in bytes
|
|||
// followed by file name
|
|||
}; |
|||
|
|||
static_assert(sizeof(FileMetadata) == 0x20, "FileMetadata has incorrect size"); |
|||
|
|||
static bool MatchName(const u8* buffer, u32 name_length, const std::u16string& name) { |
|||
std::vector<char16_t> name_buffer(name_length / sizeof(char16_t)); |
|||
std::memcpy(name_buffer.data(), buffer, name_length); |
|||
return name == std::u16string(name_buffer.begin(), name_buffer.end()); |
|||
} |
|||
|
|||
const u8* GetFilePointer(const u8* romfs, const std::vector<std::u16string>& path) { |
|||
constexpr u32 INVALID_FIELD = 0xFFFFFFFF; |
|||
|
|||
// Split path into directory names and file name
|
|||
std::vector<std::u16string> dir_names = path; |
|||
dir_names.pop_back(); |
|||
const std::u16string& file_name = path.back(); |
|||
|
|||
Header header; |
|||
std::memcpy(&header, romfs, sizeof(header)); |
|||
|
|||
// Find directories of each level
|
|||
DirectoryMetadata dir; |
|||
const u8* current_dir = romfs + header.dir_table_offset; |
|||
std::memcpy(&dir, current_dir, sizeof(dir)); |
|||
for (const std::u16string& dir_name : dir_names) { |
|||
u32 child_dir_offset; |
|||
child_dir_offset = dir.first_child_dir_offset; |
|||
while (true) { |
|||
if (child_dir_offset == INVALID_FIELD) { |
|||
return nullptr; |
|||
} |
|||
const u8* current_child_dir = romfs + header.dir_table_offset + child_dir_offset; |
|||
std::memcpy(&dir, current_child_dir, sizeof(dir)); |
|||
if (MatchName(current_child_dir + sizeof(dir), dir.name_length, dir_name)) { |
|||
current_dir = current_child_dir; |
|||
break; |
|||
} |
|||
child_dir_offset = dir.next_dir_offset; |
|||
} |
|||
} |
|||
|
|||
// Find the file
|
|||
FileMetadata file; |
|||
u32 file_offset = dir.first_file_offset; |
|||
while (file_offset != INVALID_FIELD) { |
|||
const u8* current_file = romfs + header.file_table_offset + file_offset; |
|||
std::memcpy(&file, current_file, sizeof(file)); |
|||
if (MatchName(current_file + sizeof(file), file.name_length, file_name)) { |
|||
return romfs + header.data_offset + file.data_offset; |
|||
} |
|||
file_offset = file.next_file_offset; |
|||
} |
|||
return nullptr; |
|||
} |
|||
|
|||
} // namespace RomFS
|
|||
@ -0,0 +1,22 @@ |
|||
// Copyright 2017 Citra Emulator Project |
|||
// Licensed under GPLv2 or any later version |
|||
// Refer to the license.txt file included. |
|||
|
|||
#pragma once |
|||
|
|||
#include <string> |
|||
#include <vector> |
|||
#include "common/common_types.h" |
|||
|
|||
namespace RomFS { |
|||
|
|||
/** |
|||
* Gets the pointer to a file in a RomFS image. |
|||
* @param romfs The pointer to the RomFS image |
|||
* @param path A vector containing the directory names and file name of the path to the file |
|||
* @return the pointer to the file |
|||
* @todo reimplement this with a full RomFS manager |
|||
*/ |
|||
const u8* GetFilePointer(const u8* romfs, const std::vector<std::u16string>& path); |
|||
|
|||
} // namespace RomFS |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue