static EERIE_3DOBJ * TheoToEerie_Fast(const res::path & texpath, const res::path & file, bool pbox) { EERIE_3DOBJ * ret = ARX_FTL_Load(file); if(ret) { if(pbox) { EERIE_PHYSICS_BOX_Create(ret); } return ret; } #if !BUILD_EDIT_LOADSAVE ARX_UNUSED(texpath); #else ret = GetExistingEerie(file); if(ret) { ret = Eerie_Copy(ret); } if(!ret) { size_t size = 0; char * adr = resources->readAlloc(file, size); if(!adr) { LogWarning << "Object not found: " << file; return NULL; } ret = TheoToEerie(adr, size, texpath, file); if(!ret) { free(adr); return NULL; } EERIE_OBJECT_CenterObjectCoordinates(ret); free(adr); } CreateNeighbours(ret); EERIEOBJECT_AddClothesData(ret); KillNeighbours(ret); if(ret->cdata) { EERIE_COLLISION_SPHERES_Create(ret); // Must be out of the Neighbours zone } if(pbox) { EERIE_PHYSICS_BOX_Create(ret); } ARX_FTL_Save(fs::paths.user / file.string(), ret); #endif // BUILD_EDIT_LOADSAVE return ret; }
//*********************************************************************************************** // Uses Fast Object Load if FTL file exists //----------------------------------------------------------------------------------------------- // VERIFIED (Cyril 2001/10/15) //*********************************************************************************************** EERIE_3DOBJ * ARX_FTL_Load(const char * file) { // Creates FTL file name char filename[256]; sprintf(filename, "Game\\%s", file); SetExt(filename, ".FTL"); // Checks for FTL file existence if(!PAK_FileExist(filename)) { LogError<<"ARX_FTL_Load: not found in PAK" << filename; return NULL; } // Our file exist we can use it unsigned char * dat; long pos = 0; size_t allocsize; ARX_FTL_PRIMARY_HEADER * afph; ARX_FTL_SECONDARY_HEADER * afsh; ARX_FTL_PROGRESSIVE_DATA_HEADER * afpdh; ARX_FTL_CLOTHES_DATA_HEADER * afcdh; ARX_FTL_COLLISION_SPHERES_DATA_HEADER * afcsdh; ARX_FTL_3D_DATA_HEADER * af3Ddh; char * compressedData = NULL; size_t compressedSize = 0; long NOrelease = 1; long NoCheck = 0; compressedData = MCache_Pop(filename, &compressedSize); if (!compressedData) { compressedData = (char *)PAK_FileLoadMalloc(filename, &compressedSize); NOrelease = MCache_Push(filename, compressedData, compressedSize) ? 1 : 0; } else NoCheck = 1; if(!compressedData) { printf("ARX_FTL_Load: error loading from PAK\n"); return NULL; } long DontCheck = 0; DontCheck = 1; dat = (unsigned char *)STD_Explode(compressedData, compressedSize, &allocsize);//pos,&cpr_pos); // TODO size ignored if(!dat) { printf("ARX_FTL_Load: error decompressing\n"); return NULL; } if (!NOrelease) free(compressedData); // Pointer to Primary Header afph = (ARX_FTL_PRIMARY_HEADER *)dat; pos += sizeof(ARX_FTL_PRIMARY_HEADER); // Verify FTL file Signature if ((afph->ident[0] != 'F') && (afph->ident[1] != 'T') && (afph->ident[2] != 'L')) { printf("ARX_FTL_Load: wrong magic number\n"); free(dat); return NULL; } // Verify FTL file version if (afph->version != CURRENT_FTL_VERSION) { printf("ARX_FTL_Load: wrong version: %f, expected %f\n", afph->version, CURRENT_FTL_VERSION); free(dat); return NULL; } // Verify Checksum if ((!NOCHECKSUM || NoCheck) && !DontCheck) { char check[512]; HERMES_CreateFileCheck(file, check, 512, CURRENT_FTL_VERSION); char * pouet = (char *)(dat + pos); for (long i = 0; i < 512; i++) if (check[i] != pouet[i]) { printf("ARX_FTL_Load: checksum error\n"); free(dat); return NULL; } } // Increases offset by checksum size pos += 512; // Pointer to Secondary Header afsh = (ARX_FTL_SECONDARY_HEADER *)(dat + pos); pos += sizeof(ARX_FTL_SECONDARY_HEADER); EERIE_3DOBJ * obj = NULL; // Check For & Load 3D Data if (afsh->offset_3Ddata != -1) { //todo free obj = (EERIE_3DOBJ *)malloc(sizeof(EERIE_3DOBJ)); memset(obj, 0, sizeof(EERIE_3DOBJ)); af3Ddh = (ARX_FTL_3D_DATA_HEADER *)(dat + afsh->offset_3Ddata); pos = afsh->offset_3Ddata; pos += sizeof(ARX_FTL_3D_DATA_HEADER); obj->nbvertex = af3Ddh->nb_vertex; obj->nbfaces = af3Ddh->nb_faces; obj->nbmaps = af3Ddh->nb_maps; obj->nbgroups = af3Ddh->nb_groups; obj->nbaction = af3Ddh->nb_action; obj->nbselections = af3Ddh->nb_selections; obj->origin = af3Ddh->origin; strcpy(obj->file, af3Ddh->name); // Alloc'n'Copy vertices if (obj->nbvertex > 0) { //todo free obj->vertexlist = (EERIE_VERTEX *)malloc(sizeof(EERIE_VERTEX) * obj->nbvertex); obj->vertexlist3 = (EERIE_VERTEX *)malloc(sizeof(EERIE_VERTEX) * obj->nbvertex); for (long ii = 0; ii < obj->nbvertex; ii++) { memcpy(&obj->vertexlist[ii], dat + pos, sizeof(EERIE_OLD_VERTEX)); memcpy(&obj->vertexlist3[ii], dat + pos, sizeof(EERIE_OLD_VERTEX)); pos += sizeof(EERIE_OLD_VERTEX); } obj->point0.x = obj->vertexlist[obj->origin].v.x; obj->point0.y = obj->vertexlist[obj->origin].v.y; obj->point0.z = obj->vertexlist[obj->origin].v.z; for (long i = 0; i < obj->nbvertex; i++) { obj->vertexlist[i].vert.color = 0xFF000000; obj->vertexlist3[i].vert.color = 0xFF000000; } } // Alloc'n'Copy faces if (obj->nbfaces > 0) { //todo free obj->facelist = (EERIE_FACE *)malloc(sizeof(EERIE_FACE) * obj->nbfaces); for (long ii = 0; ii < af3Ddh->nb_faces; ii++) { EERIE_FACE_FTL * eff = (EERIE_FACE_FTL *)(dat + pos); obj->facelist[ii].facetype = eff->facetype; obj->facelist[ii].texid = eff->texid; obj->facelist[ii].transval = eff->transval; obj->facelist[ii].temp = eff->temp; memcpy(&obj->facelist[ii].norm, &eff->norm, sizeof(EERIE_3D)); for (long kk = 0; kk < IOPOLYVERT; kk++) { memcpy(&obj->facelist[ii].nrmls[kk], &eff->nrmls[kk], sizeof(EERIE_3D)); obj->facelist[ii].vid[kk] = eff->vid[kk]; obj->facelist[ii].u[kk] = eff->u[kk]; obj->facelist[ii].v[kk] = eff->v[kk]; obj->facelist[ii].ou[kk] = eff->ou[kk]; obj->facelist[ii].ov[kk] = eff->ov[kk]; } pos += sizeof(EERIE_FACE_FTL); } } // Alloc'n'Copy textures if (af3Ddh->nb_maps > 0) { char ficc[256]; char ficc2[256]; char ficc3[256]; //todo free obj->texturecontainer = (TextureContainer **)malloc(sizeof(TextureContainer *) * af3Ddh->nb_maps); for (long i = 0; i < af3Ddh->nb_maps; i++) { memcpy(ficc2, dat + pos, 256); strcpy(ficc3, ficc2); File_Standardize(ficc3, ficc); obj->texturecontainer[i] = D3DTextr_CreateTextureFromFile(ficc, 0, 0, EERIETEXTUREFLAG_LOADSCENE_RELEASE); if (GDevice && obj->texturecontainer[i] && !obj->texturecontainer[i]->m_pddsSurface) obj->texturecontainer[i]->Restore(GDevice); MakeUserFlag(obj->texturecontainer[i]); pos += 256; } } // Alloc'n'Copy groups if (obj->nbgroups > 0) { //todo free obj->grouplist = (EERIE_GROUPLIST *)malloc(sizeof(EERIE_GROUPLIST) * obj->nbgroups); memcpy(obj->grouplist, dat + pos, sizeof(EERIE_GROUPLIST) * obj->nbgroups); pos += sizeof(EERIE_GROUPLIST) * obj->nbgroups; for (long i = 0; i < obj->nbgroups; i++) if (obj->grouplist[i].nb_index > 0) { //TO DO: FREE+++++++++++++++++++++++ obj->grouplist[i].indexes = (long *)malloc(sizeof(long) * obj->grouplist[i].nb_index); memcpy(obj->grouplist[i].indexes, dat + pos, sizeof(long)*obj->grouplist[i].nb_index); pos += sizeof(long) * obj->grouplist[i].nb_index; } } // Alloc'n'Copy action points if (obj->nbaction > 0) { //todo free obj->actionlist = (EERIE_ACTIONLIST *)malloc(sizeof(EERIE_ACTIONLIST) * obj->nbaction); memcpy(obj->actionlist, dat + pos, sizeof(EERIE_ACTIONLIST)*obj->nbaction); pos += sizeof(EERIE_ACTIONLIST) * obj->nbaction; } // Alloc'n'Copy selections if (obj->nbselections > 0) { //todo free++ obj->selections = (EERIE_SELECTIONS *)malloc(sizeof(EERIE_SELECTIONS) * obj->nbselections); memcpy(obj->selections, dat + pos, sizeof(EERIE_SELECTIONS)*obj->nbselections); pos += sizeof(EERIE_SELECTIONS) * obj->nbselections; for (long i = 0; i < af3Ddh->nb_selections; i++) { //todo free+++ obj->selections[i].selected = (long *)malloc(sizeof(long) * obj->selections[i].nb_selected); memcpy(obj->selections[i].selected, dat + pos, sizeof(long)*obj->selections[i].nb_selected); pos += sizeof(long) * obj->selections[i].nb_selected; } } obj->pbox = NULL; } if (!obj) { printf("ARX_FTL_Load: error loading data\n"); free(dat); return NULL; } // Alloc'n'Copy Collision Spheres Data if (afsh->offset_collision_spheres != -1) { afcsdh = (ARX_FTL_COLLISION_SPHERES_DATA_HEADER *)(dat + afsh->offset_collision_spheres); pos = afsh->offset_collision_spheres; pos += sizeof(ARX_FTL_COLLISION_SPHERES_DATA_HEADER); obj->sdata = (COLLISION_SPHERES_DATA *)malloc(sizeof(COLLISION_SPHERES_DATA)); obj->sdata->nb_spheres = afcsdh->nb_spheres; obj->sdata->spheres = (COLLISION_SPHERE *)malloc(sizeof(COLLISION_SPHERE) * obj->sdata->nb_spheres); memcpy(obj->sdata->spheres, dat + pos, sizeof(COLLISION_SPHERE)*obj->sdata->nb_spheres); pos += sizeof(COLLISION_SPHERE) * obj->sdata->nb_spheres; } // Alloc'n'Copy Progressive DATA if (afsh->offset_progressive_data != -1) { afpdh = (ARX_FTL_PROGRESSIVE_DATA_HEADER *)(dat + afsh->offset_progressive_data); pos = afsh->offset_progressive_data; pos += sizeof(ARX_FTL_PROGRESSIVE_DATA_HEADER); pos += sizeof(PROGRESSIVE_DATA) * afpdh->nb_vertex; } // Alloc'n'Copy Clothes DATA if (afsh->offset_clothes_data != -1) { obj->cdata = (CLOTHES_DATA *)malloc(sizeof(CLOTHES_DATA)); memset(obj->cdata, 0, sizeof(CLOTHES_DATA)); afcdh = (ARX_FTL_CLOTHES_DATA_HEADER *)(dat + afsh->offset_clothes_data); obj->cdata->nb_cvert = (short)afcdh->nb_cvert; obj->cdata->nb_springs = (short)afcdh->nb_springs; pos = afsh->offset_clothes_data; pos += sizeof(ARX_FTL_CLOTHES_DATA_HEADER); // now load cvert obj->cdata->cvert = (CLOTHESVERTEX *)malloc(sizeof(CLOTHESVERTEX) * obj->cdata->nb_cvert); obj->cdata->backup = (CLOTHESVERTEX *)malloc(sizeof(CLOTHESVERTEX) * obj->cdata->nb_cvert); memcpy(obj->cdata->cvert, dat + pos, sizeof(CLOTHESVERTEX)*obj->cdata->nb_cvert); memcpy(obj->cdata->backup, dat + pos, sizeof(CLOTHESVERTEX)*obj->cdata->nb_cvert); pos += sizeof(CLOTHESVERTEX) * obj->cdata->nb_cvert; // now load springs obj->cdata->springs = (EERIE_SPRINGS *)malloc(sizeof(EERIE_SPRINGS) * obj->cdata->nb_springs); memcpy(obj->cdata->springs, dat + pos, sizeof(EERIE_SPRINGS)*obj->cdata->nb_springs); pos += sizeof(EERIE_SPRINGS) * obj->cdata->nb_springs; } free(dat); if (BH_MODE) EERIE_OBJECT_MakeBH(obj); EERIE_OBJECT_CenterObjectCoordinates(obj); EERIE_CreateCedricData(obj); EERIEOBJECT_CreatePFaces(obj); // Now we can release our cool FTL file EERIE_Object_Precompute_Fast_Access(obj); LogInfo<<"loaded "<< file; return obj; }