Esempio n. 1
0
String ResourceInteractiveLoaderBinary::recognize(FileAccess *p_f) {

	error=OK;


	f=p_f;
	uint8_t header[4];
	f->get_buffer(header,4);
	if (header[0]=='R' && header[1]=='S' && header[2]=='C' && header[3]=='C') {
		//compressed
		FileAccessCompressed *fac = memnew( FileAccessCompressed );
		fac->open_after_magic(f);
		f=fac;

	} else if (header[0]!='R' || header[1]!='S' || header[2]!='R' || header[3]!='C') {
		//not normal
		error=ERR_FILE_UNRECOGNIZED;
		return "";
	}

	bool big_endian = f->get_32();
#ifdef BIG_ENDIAN_ENABLED
	endian_swap = !big_endian;
#else
	bool endian_swap = big_endian;
#endif

	bool use_real64 = f->get_32();

	f->set_endian_swap(big_endian!=0); //read big endian if saved as big endian

	uint32_t ver_major=f->get_32();
	uint32_t ver_minor=f->get_32();
	uint32_t ver_format=f->get_32();

	if (ver_format<FORMAT_VERSION ||  ver_major>VERSION_MAJOR) {

		f->close();
		return "";
	}

	String type=get_unicode_string();

	return type;
}
void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) {


	error=OK;

	f=p_f;
	uint8_t header[4];
	f->get_buffer(header,4);
	if (header[0]=='R' && header[1]=='S' && header[2]=='C' && header[3]=='C') {
		//compressed
		FileAccessCompressed *fac = memnew( FileAccessCompressed );
		fac->open_after_magic(f);
		f=fac;

	} else if (header[0]!='R' || header[1]!='S' || header[2]!='R' || header[3]!='C') {
		//not normal

		error=ERR_FILE_UNRECOGNIZED;
		ERR_EXPLAIN("Unrecognized binary resource file: "+local_path);
		ERR_FAIL_V();
	}

	bool big_endian = f->get_32();
#ifdef BIG_ENDIAN_ENABLED
	endian_swap = !big_endian;
#else
	bool endian_swap = big_endian;
#endif

	bool use_real64 = f->get_32();

	f->set_endian_swap(big_endian!=0); //read big endian if saved as big endian

	uint32_t ver_major=f->get_32();
	uint32_t ver_minor=f->get_32();
	uint32_t ver_format=f->get_32();

	print_bl("big endian: "+itos(big_endian));
	print_bl("endian swap: "+itos(endian_swap));
	print_bl("real64: "+itos(use_real64));
	print_bl("major: "+itos(ver_major));
	print_bl("minor: "+itos(ver_minor));
	print_bl("format: "+itos(ver_format));

	if (ver_format<FORMAT_VERSION ||  ver_major>VERSION_MAJOR || (ver_major==VERSION_MAJOR && ver_minor>VERSION_MINOR)) {

		f->close();
		ERR_EXPLAIN("File Format '"+itos(FORMAT_VERSION)+"."+itos(ver_major)+"."+itos(ver_minor)+"' is too new! Please upgrade to a a new engine version: "+local_path);
		ERR_FAIL();

	}

	type=get_unicode_string();

	print_bl("type: "+type);

	importmd_ofs = f->get_64();
	for(int i=0;i<14;i++)
		f->get_32(); //skip a few reserved fields

	uint32_t string_table_size=f->get_32();
	string_map.resize(string_table_size);
	for(uint32_t i=0;i<string_table_size;i++) {

		StringName s = get_unicode_string();
		string_map[i]=s;
	}

	print_bl("strings: "+itos(string_table_size));

	uint32_t ext_resources_size=f->get_32();
	for(uint32_t i=0;i<ext_resources_size;i++) {

		ExtResoucre er;
		er.type=get_unicode_string();
		er.path=get_unicode_string();
		external_resources.push_back(er);

	}

	print_bl("ext resources: "+itos(ext_resources_size));
	uint32_t int_resources_size=f->get_32();

	for(uint32_t i=0;i<int_resources_size;i++) {

		IntResoucre ir;
		ir.path=get_unicode_string();
		ir.offset=f->get_64();
		internal_resources.push_back(ir);
	}

	print_bl("int resources: "+itos(int_resources_size));


	if (f->eof_reached()) {

		error=ERR_FILE_CORRUPT;
		ERR_EXPLAIN("Premature End Of File: "+local_path);
		ERR_FAIL();
	}

}
Error ResourceFormatSaverBinaryInstance::save(const String &p_path,const RES& p_resource,uint32_t p_flags) {

	Error err;
	if (p_flags&ResourceSaver::FLAG_COMPRESS) {
		FileAccessCompressed *fac = memnew( FileAccessCompressed );
		fac->configure("RSCC");
		f=fac;
		err = fac->_open(p_path,FileAccess::WRITE);
		if (err)
			memdelete(f);

	} else {
		f=FileAccess::open(p_path,FileAccess::WRITE,&err);
	}


	ERR_FAIL_COND_V(err,err);
	FileAccessRef _fref(f);


	relative_paths=p_flags&ResourceSaver::FLAG_RELATIVE_PATHS;
	skip_editor=p_flags&ResourceSaver::FLAG_OMIT_EDITOR_PROPERTIES;
	bundle_resources=p_flags&ResourceSaver::FLAG_BUNDLE_RESOURCES;
	big_endian=p_flags&ResourceSaver::FLAG_SAVE_BIG_ENDIAN;
	no_extensions=p_flags&ResourceSaver::FLAG_NO_EXTENSION;

	local_path=p_path.get_base_dir();
	//bin_meta_idx = get_string_index("__bin_meta__"); //is often used, so create

	_find_resources(p_resource,true);

	if (!(p_flags&ResourceSaver::FLAG_COMPRESS)) {
		//save header compressed
		static const uint8_t header[4]={'R','S','R','C'};
		f->store_buffer(header,4);
	}

	if (big_endian) {
		f->store_32(1);
		f->set_endian_swap(true);
	} else
		f->store_32(0);

	f->store_32(0); //64 bits file, false for now
	f->store_32(VERSION_MAJOR);
	f->store_32(VERSION_MINOR);
	f->store_32(FORMAT_VERSION);

	//f->store_32(saved_resources.size()+external_resources.size()); // load steps -not needed
	save_unicode_string(p_resource->get_type());
	uint64_t md_at = f->get_pos();
	f->store_64(0); //offset to impoty metadata
	for(int i=0;i<14;i++)
		f->store_32(0); // reserved


	List<ResourceData> resources;


	{


		for(List<RES>::Element *E=saved_resources.front();E;E=E->next()) {


			ResourceData &rd = resources.push_back(ResourceData())->get();
			rd.type=E->get()->get_type();

			List<PropertyInfo> property_list;
			E->get()->get_property_list( &property_list );

			for(List<PropertyInfo>::Element *F=property_list.front();F;F=F->next()) {

				if (skip_editor && F->get().name.begins_with("__editor"))
					continue;
				if (F->get().usage&PROPERTY_USAGE_STORAGE || (bundle_resources && F->get().usage&PROPERTY_USAGE_BUNDLE)) {
					Property p;
					p.name_idx=get_string_index(F->get().name);
					p.value=E->get()->get(F->get().name);
					if (F->get().usage&PROPERTY_USAGE_STORE_IF_NONZERO && p.value.is_zero())
						continue;
					p.pi=F->get();										

					rd.properties.push_back(p);

				}
			}



		}
	}


	f->store_32(strings.size()); //string table size
	for(int i=0;i<strings.size();i++) {
		//print_bl("saving string: "+strings[i]);
		save_unicode_string(strings[i]);
	}

	// save external resource table
	f->store_32(external_resources.size()); //amount of external resources
	for(Set<RES>::Element *E=external_resources.front();E;E=E->next()) {

		save_unicode_string(E->get()->get_save_type());
		String path = E->get()->get_path();
		if (no_extensions)
			path=path.basename()+".*";
		save_unicode_string(path);
	}
	// save internal resource table
	f->store_32(saved_resources.size()); //amount of internal resources
	Vector<uint64_t> ofs_pos;
	for(List<RES>::Element *E=saved_resources.front();E;E=E->next()) {

		RES r = E->get();
		if (r->get_path()=="" || r->get_path().find("::")!=-1)
			save_unicode_string("local://"+itos(ofs_pos.size()));
		else
			save_unicode_string(r->get_path()); //actual external
		ofs_pos.push_back(f->get_pos());
		f->store_64(0); //offset in 64 bits
	}

	Vector<uint64_t> ofs_table;
//	int saved_idx=0;
	//now actually save the resources

	for(List<ResourceData>::Element *E=resources.front();E;E=E->next()) {

		ResourceData & rd = E->get();

		ofs_table.push_back(f->get_pos());
		save_unicode_string(rd.type);
		f->store_32(rd.properties.size());

		for (List<Property>::Element *F=rd.properties.front();F;F=F->next()) {

			Property &p=F->get();
			f->store_32(p.name_idx);
			write_variant(p.value,F->get().pi);
		}

	}

	for(int i=0;i<ofs_table.size();i++) {
		f->seek(ofs_pos[i]);
		f->store_64(ofs_table[i]);
	}

	f->seek_end();
	if (p_resource->get_import_metadata().is_valid()) {
		uint64_t md_pos = f->get_pos();
		Ref<ResourceImportMetadata> imd=p_resource->get_import_metadata();
		save_unicode_string(imd->get_editor());
		f->store_32(imd->get_source_count());
		for(int i=0;i<imd->get_source_count();i++) {
			save_unicode_string(imd->get_source_path(i));
			save_unicode_string(imd->get_source_md5(i));
		}
		List<String> options;
		imd->get_options(&options);
		f->store_32(options.size());
		for(List<String>::Element *E=options.front();E;E=E->next()) {
			save_unicode_string(E->get());
			write_variant(imd->get_option(E->get()));
		}

		f->seek(md_at);
		f->store_64(md_pos);
		f->seek_end();
	}


	f->store_buffer((const uint8_t*)"RSRC",4); //magic at end

	f->close();


	return OK;
}