Skip to content

Commit 9a39760

Browse files
authored
Merge pull request #105984 from bruvzg/sparse_pack
Android: Implement sparse bundle PCK support.
2 parents d89f4ab + 42733a2 commit 9a39760

File tree

11 files changed

+351
-146
lines changed

11 files changed

+351
-146
lines changed

core/config/project_settings.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,8 @@ void ProjectSettings::_convert_to_last_version(int p_from_version) {
614614
* appending '.pck' to the binary name (e.g. 'linux_game' -> 'linux_game.pck').
615615
* o PCK with the same basename as the binary in the current working directory.
616616
* Same as above for the two possible PCK file names.
617+
* - On Android, look for 'assets.sparsepck' and try loading it, if it doesn't work,
618+
* proceed to the next step.
617619
* - On relevant platforms (Android/iOS), lookup project file in OS resource path.
618620
* If found, load it or fail.
619621
* - Lookup project file in passed `p_path` (--path passed by the user), i.e. we
@@ -701,6 +703,11 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
701703
}
702704
}
703705

706+
#ifdef ANDROID_ENABLED
707+
// Attempt to load sparse PCK assets.
708+
_load_resource_pack("res://assets.sparsepck", false, 0, true);
709+
#endif
710+
704711
// Try to use the filesystem for files, according to OS.
705712
// (Only Android -when reading from pck- and iOS use this.)
706713

core/io/file_access.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ Ref<FileAccess> FileAccess::open(const String &p_path, int p_mode_flags, Error *
159159
//try packed data first
160160

161161
Ref<FileAccess> ret;
162-
if (!(p_mode_flags & WRITE) && PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled()) {
162+
if (!(p_mode_flags & WRITE) && !(p_mode_flags & SKIP_PACK) && PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled()) {
163163
ret = PackedData::get_singleton()->try_open_path(p_path);
164164
if (ret.is_valid()) {
165165
if (r_error) {
@@ -170,7 +170,7 @@ Ref<FileAccess> FileAccess::open(const String &p_path, int p_mode_flags, Error *
170170
}
171171

172172
ret = create_for_path(p_path);
173-
Error err = ret->open_internal(p_path, p_mode_flags);
173+
Error err = ret->open_internal(p_path, p_mode_flags & ~SKIP_PACK);
174174

175175
if (r_error) {
176176
*r_error = err;

core/io/file_access.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class FileAccess : public RefCounted {
5858
WRITE = 2,
5959
READ_WRITE = 3,
6060
WRITE_READ = 7,
61+
SKIP_PACK = 16,
6162
};
6263

6364
enum UnixPermissionFlags : int32_t {

core/io/file_access_pack.cpp

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,15 @@ Error PackedData::add_pack(const String &p_path, bool p_replace_files, uint64_t
4545
return ERR_FILE_UNRECOGNIZED;
4646
}
4747

48-
void PackedData::add_path(const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted) {
48+
void PackedData::add_path(const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted, bool p_bundle) {
4949
String simplified_path = p_path.simplify_path().trim_prefix("res://");
5050
PathMD5 pmd5(simplified_path.md5_buffer());
5151

5252
bool exists = files.has(pmd5);
5353

5454
PackedFile pf;
5555
pf.encrypted = p_encrypted;
56+
pf.bundle = p_bundle;
5657
pf.pack = p_pkg_path;
5758
pf.offset = p_ofs;
5859
pf.size = p_size;
@@ -268,6 +269,7 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
268269
uint32_t pack_flags = f->get_32();
269270
bool enc_directory = (pack_flags & PACK_DIR_ENCRYPTED);
270271
bool rel_filebase = (pack_flags & PACK_REL_FILEBASE); // Note: Always enabled for V3.
272+
bool sparse_bundle = (pack_flags & PACK_SPARSE_BUNDLE);
271273

272274
uint64_t file_base = f->get_64();
273275
if ((version == PACK_FORMAT_VERSION_V3) || (version == PACK_FORMAT_VERSION_V2 && rel_filebase)) {
@@ -320,7 +322,7 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
320322
if (flags & PACK_FILE_REMOVAL) { // The file was removed.
321323
PackedData::get_singleton()->remove_path(path);
322324
} else {
323-
PackedData::get_singleton()->add_path(p_path, path, file_base + ofs, size, md5, this, p_replace_files, (flags & PACK_FILE_ENCRYPTED));
325+
PackedData::get_singleton()->add_path(p_path, path, file_base + ofs, size, md5, this, p_replace_files, (flags & PACK_FILE_ENCRYPTED), sparse_bundle);
324326
}
325327
}
326328

@@ -360,7 +362,7 @@ void PackedSourceDirectory::add_directory(const String &p_path, bool p_replace_f
360362
for (const String &file_name : da->get_files()) {
361363
String file_path = p_path.path_join(file_name);
362364
uint8_t md5[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
363-
PackedData::get_singleton()->add_path(p_path, file_path, 0, 0, md5, this, p_replace_files, false);
365+
PackedData::get_singleton()->add_path(p_path, file_path, 0, 0, md5, this, p_replace_files, false, false);
364366
}
365367

366368
for (const String &sub_dir_name : da->get_directories()) {
@@ -467,13 +469,19 @@ void FileAccessPack::close() {
467469
f = Ref<FileAccess>();
468470
}
469471

470-
FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file) :
471-
pf(p_file),
472-
f(FileAccess::open(pf.pack, FileAccess::READ)) {
473-
ERR_FAIL_COND_MSG(f.is_null(), vformat("Can't open pack-referenced file '%s'.", String(pf.pack)));
472+
FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file) {
473+
pf = p_file;
474+
if (pf.bundle) {
475+
String simplified_path = p_path.simplify_path();
476+
f = FileAccess::open(simplified_path, FileAccess::READ | FileAccess::SKIP_PACK);
477+
off = 0; // For the sparse pack offset is always zero.
478+
} else {
479+
f = FileAccess::open(pf.pack, FileAccess::READ);
480+
f->seek(pf.offset);
481+
off = pf.offset;
482+
}
474483

475-
f->seek(pf.offset);
476-
off = pf.offset;
484+
ERR_FAIL_COND_MSG(f.is_null(), vformat("Can't open pack-referenced file '%s'.", String(pf.pack)));
477485

478486
if (pf.encrypted) {
479487
Ref<FileAccessEncrypted> fae;

core/io/file_access_pack.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
enum PackFlags {
4949
PACK_DIR_ENCRYPTED = 1 << 0,
5050
PACK_REL_FILEBASE = 1 << 1,
51+
PACK_SPARSE_BUNDLE = 1 << 2,
5152
};
5253

5354
enum PackFileFlags {
@@ -70,6 +71,7 @@ class PackedData {
7071
uint8_t md5[16];
7172
PackSource *src = nullptr;
7273
bool encrypted;
74+
bool bundle;
7375
};
7476

7577
private:
@@ -114,7 +116,7 @@ class PackedData {
114116

115117
public:
116118
void add_pack_source(PackSource *p_source);
117-
void add_path(const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted = false); // for PackSource
119+
void add_path(const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted = false, bool p_bundle = false); // for PackSource
118120
void remove_path(const String &p_path);
119121
uint8_t *get_file_hash(const String &p_path);
120122
HashSet<String> get_file_paths() const;

0 commit comments

Comments
 (0)