mirror of
				https://github.com/godotengine/godot.git
				synced 2025-11-03 23:21:15 +00:00 
			
		
		
		
	-=-=-=-=-=-=-=-=-=-=-=-=-= -Begin work on Navigation Meshes (simple pathfinding for now, will improve soon) -More doc on theme overriding -Upgraded OpenSSL to version without bugs -Misc bugfixes
		
			
				
	
	
		
			162 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			162 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#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; i<p_bytes; i++) {
 | 
						|
 | 
						|
		p_file->store_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; i<files.size(); i++) {
 | 
						|
 | 
						|
		file->store_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<files.size(); i++) {
 | 
						|
 | 
						|
		FileAccess* src = FileAccess::open(files[i].src_path, FileAccess::READ);
 | 
						|
		uint64_t to_write = files[i].size;
 | 
						|
		while (to_write > 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;
 | 
						|
};
 |