Browse Source
Merge pull request #2784 from wwylele/font-archive
Merge pull request #2784 from wwylele/font-archive
load shared font from system archivence_cpp
committed by
GitHub
5 changed files with 264 additions and 22 deletions
-
2src/core/CMakeLists.txt
-
102src/core/hle/romfs.cpp
-
22src/core/hle/romfs.h
-
154src/core/hle/service/apt/apt.cpp
-
6src/core/hle/service/apt/bcfnt/bcfnt.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