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; }