/*
===========================================================================
ARX FATALIS GPL Source Code
Copyright (C) 1999-2010 Arkane Studios SA, a ZeniMax Media company.
This file is part of the Arx Fatalis GPL Source Code ('Arx Fatalis Source Code').
Arx Fatalis Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Arx Fatalis Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Arx Fatalis Source Code. If not, see
.
In addition, the Arx Fatalis Source Code is also subject to certain additional terms. You should have received a copy of these
additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Arx
Fatalis Source Code. If not, please request a copy in writing from Arkane Studios at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing Arkane Studios, c/o
ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//////////////////////////////////////////////////////////////////////////////////////
// @@ @@@ @@@ @@ @@@@@ //
// @@@ @@@@@@ @@@ @@ @@@@ @@@ @@@ //
// @@@ @@@@@@@ @@@ @@@@ @@@@ @@ @@@@ //
// @@@ @@ @@@@ @@@ @@@@@ @@@@@@ @@@ @@@ //
// @@@@@ @@ @@@@ @@@ @@@@@ @@@@@@@ @@@ @ @@@ //
// @@@@@ @@ @@@@ @@@@@@@@ @@@@ @@@ @@@@@ @@ @@@@@@@ //
// @@ @@@ @@ @@@@ @@@@@@@ @@@ @@@ @@@@@@ @@ @@@@ //
// @@@ @@@ @@@ @@@@ @@@@@ @@@@@@@@@ @@@@@@@ @@@ @@@@ //
// @@@ @@@@ @@@@@@@ @@@@@@ @@@ @@@@ @@@ @@@ @@@ @@@@ //
// @@@@@@@@ @@@@@ @@@@@@@@@@ @@@ @@@ @@@ @@@ @@@ @@@@@ //
// @@@ @@@@ @@@@ @@@ @@@@@@@ @@@ @@@ @@@@ @@@ @@@@ @@@@@ //
//@@@ @@@@ @@@@@ @@@ @@@@@@ @@ @@@ @@@@ @@@@@@@ @@@@@ @@@@@ //
//@@@ @@@@@ @@@@@ @@@@ @@@ @@ @@ @@@@ @@@@@@@ @@@@@@@@@ //
//@@@ @@@@ @@@@@@@ @@@@ @@ @@ @@@@ @@@@@ @@@@@ //
//@@@ @@@@ @@@@@@@ @@@@ @@ @@ @@@@ @@@@@ @@ //
//@@@ @@@ @@@ @@@@@ @@ @@@ //
// @@@ @@@ @@ @@ STUDIOS //
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
// ARX_FTL
//////////////////////////////////////////////////////////////////////////////////////
//
// Description:
// ARX FTL file loading and saving
// FTL files contains Optimised/Pre-computed versions of objects for faster loads
//
// Updates: (date) (person) (update)
// 2001/10/14 Cyril Some Verifications
// 2001/10/14 Cyril Now FTL Allocsize is REALLY computed...
//
// Initial Code: Cyril Meynier
//
// Copyright (c) 1999-2001 ARKANE Studios SA. All rights reserved
//////////////////////////////////////////////////////////////////////////////////////
#include
#include
#include "ARX_FTL.h"
#include "HERMESMain.h"
#define _CRTDBG_MAP_ALLOC
#include
//***********************************************************************************************
// FTL FILE Structure:
//***********************************************************************************************
// ARX_FTL_PRIMARY_HEADER
// Checksum
// -->All the following data is then compressed and must be expanded
// ARX_FTL_SECONDARY_HEADER;
// -> Then depending on offsets just read data directly.
//***********************************************************************************************
// WARNING: FTL Files uses directly some DANAE internal file formats...
// beware of dependencies...
//***********************************************************************************************
//***********************************************************************************************
// Sets Current FTL Version
#define CURRENT_FTL_VERSION 0.83257f
//***********************************************************************************************
//***********************************************************************************************
// FTL File Structures Definitions
//
typedef struct
{
char ident[4]; // FTL
float version; // starting with version 1.0f
} ARX_FTL_PRIMARY_HEADER;
typedef struct
{
long offset_3Ddata; // -1 = no
long offset_cylinder; // -1 = no
long offset_progressive_data; // -1 = no
long offset_clothes_data; // -1 = no
long offset_collision_spheres; // -1 = no
long offset_physics_box; // -1 = no
} ARX_FTL_SECONDARY_HEADER;
typedef struct
{
long nb_vertex;
} ARX_FTL_PROGRESSIVE_DATA_HEADER;
typedef struct
{
long nb_cvert;
long nb_springs;
} ARX_FTL_CLOTHES_DATA_HEADER;
typedef struct
{
long nb_spheres;
} ARX_FTL_COLLISION_SPHERES_DATA_HEADER;
typedef struct
{
long nb_vertex; // ...
long nb_faces; // ...
long nb_maps; // ...
long nb_groups; // ...
long nb_action; // ...
long nb_selections; // data will follow this order
long origin;
char name[256];
} ARX_FTL_3D_DATA_HEADER;
// End of Structures definitions
//***********************************************************************************************
extern long NOCHECKSUM;
//***********************************************************************************************
// Saves an FTL File
// Must pass the original name of the theo file
//-----------------------------------------------------------------------------------------------
// VERIFIED (Cyril 2001/10/15)
//***********************************************************************************************
BOOL ARX_FTL_Save(char * incomplete_fic, char * complete_fic, EERIE_3DOBJ * obj)
{
// Need an object to be saved !
if (obj == NULL) return FALSE;
// Generate File name/path and create it
char path[256];
char gamefic[256];
sprintf(gamefic, "%sGame%s", Project.workingdir, incomplete_fic);
SetExt(gamefic, ".FTL");
strcpy(path, gamefic);
RemoveName(path);
if (!CreateFullPath(path)) return NULL;
// create some usefull vars
ARX_FTL_PRIMARY_HEADER * afph;
ARX_FTL_SECONDARY_HEADER * afsh;
ARX_FTL_CLOTHES_DATA_HEADER * afcdh;
ARX_FTL_3D_DATA_HEADER * af3Ddh;
ARX_FTL_COLLISION_SPHERES_DATA_HEADER * afcsdh;
unsigned char * dat = NULL;
long pos = 0;
long allocsize = 8000000; // need to compute it more precisely
// Compute allocsize...
allocsize = sizeof(ARX_FTL_PRIMARY_HEADER)
+ 512 //checksum
+ sizeof(ARX_FTL_SECONDARY_HEADER)
+ sizeof(ARX_FTL_3D_DATA_HEADER)
+ sizeof(EERIE_OLD_VERTEX) * obj->nbvertex
+ sizeof(EERIE_FACE_FTL) * obj->nbfaces
+ obj->nbmaps * 256 // texturecontainernames
+ sizeof(EERIE_ACTIONLIST) * obj->nbaction
+ 128000; // just in case...
if (obj->nbgroups > 0)
{
allocsize += sizeof(EERIE_GROUPLIST) * obj->nbgroups;
for (long i = 0; i < obj->nbgroups; i++)
{
if (obj->grouplist[i].nb_index > 0)
{
allocsize += sizeof(long) * obj->grouplist[i].nb_index;
}
}
}
if (obj->nbselections > 0)
{
allocsize += sizeof(EERIE_SELECTIONS) * obj->nbselections;
for (long i = 0; i < obj->nbselections; i++)
{
allocsize += sizeof(long) * obj->selections[i].nb_selected;
}
}
if (obj->sdata && obj->sdata->nb_spheres) // Collision Spheres Data
{
allocsize += sizeof(ARX_FTL_COLLISION_SPHERES_DATA_HEADER);
allocsize += sizeof(COLLISION_SPHERE) * obj->sdata->nb_spheres;
}
if (obj->cdata) // Clothes DATA
{
allocsize += sizeof(ARX_FTL_CLOTHES_DATA_HEADER);
allocsize += sizeof(CLOTHESVERTEX) * obj->cdata->nb_cvert;
allocsize += sizeof(EERIE_SPRINGS) * obj->cdata->nb_springs;
}
// Finished computing allocsize Now allocate it...
dat = (unsigned char *)malloc(allocsize);
if (!dat)
HERMES_Memory_Emergency_Out();
memset(dat, 0, allocsize);
// Primary Header
afph = (ARX_FTL_PRIMARY_HEADER *)dat;
pos += sizeof(ARX_FTL_PRIMARY_HEADER);
if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
afph->ident[0] = 'F';
afph->ident[1] = 'T';
afph->ident[2] = 'L';
afph->version = CURRENT_FTL_VERSION;
// Identification
char check[512];
MakeUpcase(complete_fic);
HERMES_CreateFileCheck(complete_fic, check, 512, CURRENT_FTL_VERSION);
memcpy(dat + pos, check, 512);
pos += 512;
if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
// Secondary Header
afsh = (ARX_FTL_SECONDARY_HEADER *)(dat + pos);
pos += sizeof(ARX_FTL_SECONDARY_HEADER);
if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
// 3D Data
afsh->offset_3Ddata = pos; //-1;
af3Ddh = (ARX_FTL_3D_DATA_HEADER *)(dat + afsh->offset_3Ddata);
pos += sizeof(ARX_FTL_3D_DATA_HEADER);
if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
af3Ddh->nb_vertex = obj->nbvertex;
af3Ddh->nb_faces = obj->nbfaces;
af3Ddh->nb_maps = obj->nbmaps;
af3Ddh->nb_groups = obj->nbgroups;
af3Ddh->nb_action = obj->nbaction;
af3Ddh->nb_selections = obj->nbselections;
af3Ddh->origin = obj->origin;
// vertexes
if (af3Ddh->nb_vertex > 0)
{
for (long ii = 0; ii < af3Ddh->nb_vertex; ii++)
{
memcpy(dat + pos, &obj->vertexlist[ii], sizeof(EERIE_OLD_VERTEX));
pos += sizeof(EERIE_OLD_VERTEX);
}
if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
}
// faces
if (af3Ddh->nb_faces > 0)
{
for (long ii = 0; ii < af3Ddh->nb_faces; ii++)
{
EERIE_FACE_FTL * eff = (EERIE_FACE_FTL *)(dat + pos);
eff->facetype = obj->facelist[ii].facetype;
eff->texid = obj->facelist[ii].texid;
eff->transval = obj->facelist[ii].transval;
eff->temp = obj->facelist[ii].temp;
memcpy(&eff->norm, &obj->facelist[ii].norm, sizeof(EERIE_3D));
for (long kk = 0; kk < IOPOLYVERT; kk++)
{
memcpy(&eff->nrmls[kk], &obj->facelist[ii].nrmls[kk], sizeof(EERIE_3D));
eff->vid[kk] = obj->facelist[ii].vid[kk];
eff->u[kk] = obj->facelist[ii].u[kk];
eff->v[kk] = obj->facelist[ii].v[kk];
eff->ou[kk] = obj->facelist[ii].ou[kk];
eff->ov[kk] = obj->facelist[ii].ov[kk];
eff->rgb[kk] = 0;
}
pos += sizeof(EERIE_FACE_FTL);
if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
}
}
// textures
for (long i = 0; i < af3Ddh->nb_maps; i++)
{
char ficc[256];
memset(ficc, 0, 256);
if (obj->texturecontainer[i])
strcpy(ficc, obj->texturecontainer[i]->m_texName);
memcpy(dat + pos, ficc, 256);
pos += 256;
if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
}
// groups
if (af3Ddh->nb_groups > 0)
{
memcpy(dat + pos, obj->grouplist, sizeof(EERIE_GROUPLIST)*af3Ddh->nb_groups);
pos += sizeof(EERIE_GROUPLIST) * af3Ddh->nb_groups;
if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
for (int i = 0; i < af3Ddh->nb_groups; i++)
{
if (obj->grouplist[i].nb_index > 0)
{
memcpy(dat + pos, obj->grouplist[i].indexes, sizeof(long)*obj->grouplist[i].nb_index);
pos += sizeof(long) * obj->grouplist[i].nb_index;
if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
}
}
}
// actionpoints
if (af3Ddh->nb_action > 0)
{
memcpy(dat + pos, obj->actionlist, sizeof(EERIE_ACTIONLIST)*af3Ddh->nb_action);
pos += sizeof(EERIE_ACTIONLIST) * af3Ddh->nb_action;
if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
}
// selections
if (af3Ddh->nb_selections > 0)
{
memcpy(dat + pos, obj->selections, sizeof(EERIE_SELECTIONS)*af3Ddh->nb_selections);
pos += sizeof(EERIE_SELECTIONS) * af3Ddh->nb_selections;
if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
for (int i = 0; i < af3Ddh->nb_selections; i++)
{
memcpy(dat + pos, obj->selections[i].selected, sizeof(long)*obj->selections[i].nb_selected);
pos += sizeof(long) * obj->selections[i].nb_selected;
if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
}
strcpy(af3Ddh->name, obj->file);
}
// Progressive DATA
afsh->offset_progressive_data = -1;
// Collision Spheres Data
if (obj->sdata && obj->sdata->nb_spheres)
{
afsh->offset_collision_spheres = pos; //-1;
afcsdh = (ARX_FTL_COLLISION_SPHERES_DATA_HEADER *)(dat + afsh->offset_collision_spheres);
pos += sizeof(ARX_FTL_COLLISION_SPHERES_DATA_HEADER);
if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
afcsdh->nb_spheres = obj->sdata->nb_spheres;
memcpy(dat + pos, obj->sdata->spheres, sizeof(COLLISION_SPHERE)*obj->sdata->nb_spheres);
pos += sizeof(COLLISION_SPHERE) * obj->sdata->nb_spheres;
if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
}
else afsh->offset_collision_spheres = -1;
// Clothes DATA
if (obj->cdata == NULL)
{
afsh->offset_clothes_data = -1;
}
else
{
afsh->offset_clothes_data = pos;
afcdh = (ARX_FTL_CLOTHES_DATA_HEADER *)(dat + afsh->offset_clothes_data);
afcdh->nb_cvert = obj->cdata->nb_cvert;
afcdh->nb_springs = obj->cdata->nb_springs;
pos += sizeof(ARX_FTL_CLOTHES_DATA_HEADER);
if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
// now save cvert
memcpy(dat + pos, obj->cdata->cvert, sizeof(CLOTHESVERTEX)*obj->cdata->nb_cvert);
pos += sizeof(CLOTHESVERTEX) * obj->cdata->nb_cvert;
if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
// now saves springs
memcpy(dat + pos, obj->cdata->springs, sizeof(EERIE_SPRINGS)*obj->cdata->nb_springs);
pos += sizeof(EERIE_SPRINGS) * obj->cdata->nb_springs;
if (pos > allocsize) ShowPopup("Invalid Allocsize in ARX_FTL_Save");
}
afsh->offset_physics_box = -1;
afsh->offset_cylinder = -1;
// Now we can flush our cool FTL file to the hard drive
unsigned long handle;
char _error[512];
if (pos > allocsize)
{
sprintf(_error, "Badly Allocated SaveBuffer...%s", gamefic);
goto error;
}
char * compressed;
compressed = NULL;
long cpr_pos;
cpr_pos = 0;
compressed = STD_Implode((char *)dat, pos, &cpr_pos);
// Now Saving Whole Buffer
if (!(handle = FileOpenWrite(gamefic)))
{
sprintf(_error, "Unable to Open %s for Write...", gamefic);
goto error;
}
if (FileWrite(handle, compressed, cpr_pos) != cpr_pos)
{
sprintf(_error, "Unable to Write to %s", gamefic);
goto error;
}
FileCloseWrite(handle);
free(compressed);
free(dat);
return TRUE;
error:
;
ShowPopup(_error);
free(dat);
return FALSE;
}
//***********************************************************************************************
// MESH cache structure definition & Globals
//***********************************************************************************************
typedef struct
{
char * name;
char * data;
long size;
} MCACHE_DATA;
MCACHE_DATA * MCache = NULL;
long MCache_Number = 0;
long MCache_GetSize()
{
long tot = 0;
for (long i = 0; i < MCache_Number; i++)
{
tot += MCache[i].size;
}
return tot;
}
//***********************************************************************************************
// Checks for Mesh file existence in cache
//-----------------------------------------------------------------------------------------------
// VERIFIED (Cyril 2001/10/15)
//***********************************************************************************************
long MCache_Get(char * file)
{
char fic[256];
File_Standardize(file, fic);
for (long i = 0; i < MCache_Number; i++)
if (!stricmp(MCache[i].name, fic)) return i;
return -1;
}
//***********************************************************************************************
// Pushes a Mesh In Mesh Cache
//-----------------------------------------------------------------------------------------------
// VERIFIED (Cyril 2001/10/15)
//***********************************************************************************************
bool MCache_Push(char * file, char * data, long size)
{
char fic[256];
File_Standardize(file, fic);
if (MCache_Get(fic) != -1) return false; // already cached
MCache = (MCACHE_DATA *)realloc(MCache, sizeof(MCACHE_DATA) * (MCache_Number + 1));
MCache[MCache_Number].name = (char *)malloc(strlen(file) + 1);
strcpy(MCache[MCache_Number].name, fic);
MCache[MCache_Number].data = data;
MCache[MCache_Number].size = size;
MCache_Number++;
return true;
}
//-----------------------------------------------------------------------------
// memory leak
// added tsu 2001/10/16
//-----------------------------------------------------------------------------
void MCache_ClearAll()
{
for (long i(0); i < MCache_Number; i++)
{
free(MCache[i].name), MCache[i].name = NULL;
free(MCache[i].data), MCache[i].data = NULL;
}
free(MCache), MCache = NULL, MCache_Number = 0;
}
//***********************************************************************************************
// Retreives a Mesh File pointer from cache...
//-----------------------------------------------------------------------------------------------
// VERIFIED (Cyril 2001/10/15)
//***********************************************************************************************
char * MCache_Pop(char * file, long * size)
{
long num = MCache_Get(file);
if (num == -1) return NULL;
*size = MCache[num].size;
return MCache[num].data;
}
void EERIE_OBJECT_MakeBH(EERIE_3DOBJ * obj)
{
}
long BH_MODE = 0;
//***********************************************************************************************
// Uses Fast Object Load if FTL file exists
//-----------------------------------------------------------------------------------------------
// VERIFIED (Cyril 2001/10/15)
//***********************************************************************************************
EERIE_3DOBJ * ARX_FTL_Load(char * incomplete_fic, char * complete_fic, EERIE_3DOBJ * obj)
{
// Creates FTL file name
char gamefic[256];
sprintf(gamefic, "%sGame%s", Project.workingdir, incomplete_fic);
SetExt(gamefic, ".FTL");
// Checks for FTL file existence
if (!PAK_FileExist(gamefic)) return NULL;
// Our file exist we can use it
unsigned char * dat;
long pos = 0;
long 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 * compressed = NULL;
long cpr_pos = 0;
long NOrelease = 1;
long NoCheck = 0;
compressed = MCache_Pop(gamefic, &cpr_pos);
if (!compressed)
{
compressed = (char *)PAK_FileLoadMalloc(gamefic, &cpr_pos);
NOrelease = MCache_Push(gamefic, compressed, cpr_pos) ? 1 : 0;
}
else NoCheck = 1;
if (!compressed) return NULL;
long DontCheck = 0;
if (CURRENT_LOADMODE != LOAD_TRUEFILE) DontCheck = 1;
dat = (unsigned char *)STD_Explode(compressed, cpr_pos, &allocsize);//pos,&cpr_pos);
if (!dat) return NULL;
if (!NOrelease) free(compressed);
// 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'))
{
free(dat);
return NULL;
}
// Verify FTL file version
if (afph->version != CURRENT_FTL_VERSION)
{
free(dat);
return NULL;
}
// Verify Checksum
if ((!NOCHECKSUM || NoCheck) && !DontCheck)
{
char check[512];
MakeUpcase(complete_fic);
HERMES_CreateFileCheck(complete_fic, check, 512, CURRENT_FTL_VERSION);
char * pouet = (char *)(dat + pos);
for (long i = 0; i < 512; i++)
if (check[i] != pouet[i])
{
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);
// Check For & Load 3D Data
if (afsh->offset_3Ddata != -1)
{
if (obj) ReleaseEERIE3DObj(obj), obj = NULL;
//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, Project.workingdir);
strcat(ficc3, ficc2);
File_Standardize(ficc3, ficc);
obj->texturecontainer[i] = D3DTextr_CreateTextureFromFile(ficc, Project.workingdir, 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)
{
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);
return obj;
}