#include "pck_packer.h" #include "core/os/file_access.h" static uint64_t _align(uint64_t p_n, int p_alignment) { if (p_alignment == 0) return p_n; uint64_t rest = p_n % p_alignment; if (rest == 0) return p_n; else return p_n + (p_alignment - rest); }; static void _pad(FileAccess* p_file, int p_bytes) { for (int i=0; istore_8(0); }; }; void PCKPacker::_bind_methods() { ObjectTypeDB::bind_method(_MD("pck_start","pck_name","alignment"),&PCKPacker::pck_start); ObjectTypeDB::bind_method(_MD("add_file","pck_path","source_path"),&PCKPacker::add_file); ObjectTypeDB::bind_method(_MD("flush"),&PCKPacker::flush); }; Error PCKPacker::pck_start(const String& p_file, int p_alignment) { file = FileAccess::open(p_file, FileAccess::WRITE); if (file == NULL) { return ERR_CANT_CREATE; }; alignment = p_alignment; file->store_32(0x43504447); // MAGIC file->store_32(0); // # version file->store_32(0); // # major file->store_32(0); // # minor file->store_32(0); // # revision for (int i=0; i<16; i++) { file->store_32(0); // reserved }; files.clear(); return OK; }; Error PCKPacker::add_file(const String& p_file, const String& p_src) { FileAccess* f = FileAccess::open(p_src, FileAccess::READ); if (!f) { return ERR_FILE_CANT_OPEN; }; File pf; pf.path = p_file; pf.src_path = p_src; pf.size = f->get_len(); pf.offset_offset = 0; files.push_back(pf); f->close(); memdelete(f); return OK; }; Error PCKPacker::flush(bool p_verbose) { if (!file) { ERR_FAIL_COND_V(!file, ERR_INVALID_PARAMETER); return ERR_INVALID_PARAMETER; }; // write the index file->store_32(files.size()); for (int i=0; istore_pascal_string(files[i].path); files[i].offset_offset = file->get_pos(); file->store_64(0); // offset file->store_64(files[i].size); // size // # empty md5 file->store_32(0); file->store_32(0); file->store_32(0); file->store_32(0); }; uint64_t ofs = file->get_pos(); ofs = _align(ofs, alignment); _pad(file, ofs - file->get_pos()); const uint32_t buf_max = 65536; uint8_t *buf = memnew_arr(uint8_t, buf_max); int count = 0; for (int i=0; i 0) { int read = src->get_buffer(buf, MIN(to_write, buf_max)); file->store_buffer(buf, read); to_write -= read; }; uint64_t pos = file->get_pos(); file->seek(files[i].offset_offset); // go back to store the file's offset file->store_64(ofs); file->seek(pos); ofs = _align(ofs + files[i].size, alignment); _pad(file, ofs - pos); src->close(); memdelete(src); count += 1; if (p_verbose) { if (count % 100 == 0) { printf("%i/%i (%.2f\%)\r", count, files.size(), float(count) / files.size() * 100); }; }; }; if (p_verbose) printf("\n"); file->close(); return OK; }; PCKPacker::PCKPacker() { file = NULL; }; PCKPacker::~PCKPacker() { if (file != NULL) { memdelete(file); }; file = NULL; };