bool parseCinematic(Cinematic * c, const char * data, size_t size) {
	
	const char * cinematicId = safeGetString(data, size);
	if(!cinematicId) {
		LogError << "Error parsing file magic number";
		return false;
	}
	
	if(std::strcmp(cinematicId, "KFA")) {
		LogError << "Wrong magic number";
		return false;
	}
	
	s32 version;
	if(!safeGet(version, data, size)) {
		LogError << "Error reading file version";
		return false;
	}
	LogDebug("version " << version);
	
	if(version < CINEMATIC_VERSION_1_75) {
		LogError << "Too old version " << version << " expected at least " << CINEMATIC_VERSION_1_75;
	}
	
	if(version > CINEMATIC_VERSION_1_76) {
		LogError << "Wrong version " << version << " expected max " << CINEMATIC_VERSION_1_76;
		return false;
	}
	
	// Ignore a string.
	safeGetString(data, size);
	
	// Load bitmaps.
	s32 nbitmaps;
	if(!safeGet(nbitmaps, data, size)) {
		LogError << "Error reading bitmap count";
		return false;
	}
	LogDebug(nbitmaps << " images:");
	
	c->m_bitmaps.reserve(nbitmaps);
	
	for(int i = 0; i < nbitmaps; i++) {
		
		s32 scale = 0;
		if(!safeGet(scale, data, size)) {
			LogError << "Error reading bitmap scale";
			return false;
		}
		
		const char * str = safeGetString(data, size);
		if(!str) {
			LogError << "Error reading bitmap path";
			return false;
		}
		LogDebug(" - " << i << ": \"" << str << '"');
		res::path path = fixTexturePath(str);
		LogDebug("   => " << path << " (scale x" << scale << ')');
		
		
		CinematicBitmap * newBitmap = CreateCinematicBitmap(path, scale);
		if(newBitmap) {
			c->m_bitmaps.push_back(newBitmap);
		}
	}
	
	// Load sounds.
	s32 nsounds;
	if(!safeGet(nsounds, data, size)) {
		LogError << "Error reading sound count";
		return false;
	}
	
	LogDebug(nsounds << " sounds:");
	for(int i = 0; i < nsounds; i++) {
		
		if(version >= CINEMATIC_VERSION_1_76) {
			s16 ignored;
			if(!safeGet(ignored, data, size)) {
				LogError << "Error reading sound id";
				return false;
			}
		}
		
		const char * str = safeGetString(data, size);
		if(!str) {
			LogError << "Error reading sound path";
			return false;
		}
		LogDebug(" - " << i << ": \"" << str << '"');
		std::pair<res::path, bool> path = fixSoundPath(str);
		LogDebug("   => " << path.first << (path.second ? " (speech)" : ""));
		
		AddSoundToList(path.first, path.second);
	}
	
	// Load track and keys.
	
	SavedCinematicTrack t;
	if(!safeGet(t, data, size)) {
		LogError << "Error reading track";
		return false;
	}
	AllocTrack(t.startframe, t.endframe, t.fps);
	
	LogDebug(t.nbkey << " keyframes:");
	for(int i = 0; i < t.nbkey; i++) {
		
		C_KEY k;
		int idsound;
		
		if(version <= CINEMATIC_VERSION_1_75) {
			
			C_KEY_1_75 k175;
			if(!safeGet(k175, data, size)) {
				LogError << "Error reading key v1.75";
				return false;
			}
			
			k.angz = k175.angz;
			k.color = k175.color;
			k.colord = k175.colord;
			k.colorf = k175.colorf;
			k.frame = k175.frame;
			k.fx = k175.fx;
			k.numbitmap = k175.numbitmap;
			k.pos = k175.pos.toVec3();
			k.speed = k175.speed;
			k.typeinterp = k175.typeinterp;
			k.force = k175.force;
			idsound = k175.idsound;
			k.idsound = -1;
			k.light = k175.light;
			k.posgrille = k175.posgrille.toVec3();
			k.angzgrille = k175.angzgrille;
			k.speedtrack = k175.speedtrack;
			
		} else {
			
			C_KEY_1_76 k176;
			if(!safeGet(k176, data, size)) {
				LogError << "Error reading key v1.76";
				return false;
			}
			
			k.angz = k176.angz;
			k.color = k176.color;
			k.colord = k176.colord;
			k.colorf = k176.colorf;
			k.frame = k176.frame;
			k.fx = k176.fx;
			k.numbitmap = k176.numbitmap;
			k.pos = k176.pos.toVec3();
			k.speed = k176.speed;
			k.typeinterp = k176.typeinterp;
			k.force = k176.force;
			k.light = k176.light;
			k.posgrille = k176.posgrille.toVec3();
			k.angzgrille = k176.angzgrille;
			k.speedtrack = k176.speedtrack;
			idsound = k176.idsound[0]; // 0 was the language code for 'French'
			k.idsound = k176.idsound[3]; // 3 was the language code for 'English'
			
		}
		
		if(k.force < 0) {
			k.force = 1;
		}
		
		FillKeyTemp(&k.pos, k.angz, k.frame, k.numbitmap, k.fx, k.typeinterp, k.color, k.colord, k.colorf, k.speed, k.idsound, k.force, &k.light, &k.posgrille, k.angzgrille, k.speedtrack);
		AddKeyLoad(&KeyTemp);
		
		LogDebug(" - " << i << ": frame " << k.frame << " image: " << k.numbitmap);
		if(k.idsound >= 0) {
			LogDebug("   + sound: " << k.idsound);
		}
		
		if(i == 0) {
			c->pos = k.pos;
			c->angz = k.angz;
			c->numbitmap = k.numbitmap;
			c->fx = k.fx;
			c->ti = c->tichoose = k.typeinterp;
			c->color = c->colorchoose = k.color;
			c->colord = c->colorchoosed = k.colord;
			c->colorflash = c->colorflashchoose = k.colorf;
			c->speed = c->speedchoose = k.speed;
			c->idsound = idsound;
			c->force = k.force;
			c->light = c->lightchoose = k.light;
			c->posgrille = k.posgrille;
			c->angzgrille = k.angzgrille;
			c->speedtrack = k.speedtrack;
		}
		
	}
	
	UpDateAllKeyLight();
	
	SetCurrFrame(0);
	
	GereTrackNoPlay(c);
	c->projectload = true;
	
	LogDebug("loaded cinematic");
	
	return true;
}
bool AddKey(const CinematicKeyframe & key) {
	int			num;

	if(!CKTrack || (key.frame < CKTrack->startframe) || (key.frame > CKTrack->endframe))
		return false;

	CinematicKeyframe * k = SearchKey(key.frame, &num);
	if(!k) {
		if(!CKTrack->nbkey) {
			CKTrack->key = k = (CinematicKeyframe *)std::malloc(sizeof(CinematicKeyframe));
		} else {
			CKTrack->key = (CinematicKeyframe *)std::realloc(CKTrack->key, sizeof(CinematicKeyframe) * (CKTrack->nbkey + 1));
			k = SearchAndMoveKey(key.frame);
		}

		CKTrack->nbkey++;

		k->frame = key.frame;
	}

	if(key.numbitmap > -2)
		k->numbitmap = key.numbitmap;

	if(key.fx > -2) {
		k->fx = key.fx;
		
		/* TODO what was this code suppesed to achieve
		if((key.fx > 255) && (k->fx > 0)) {
			k->fx |= key.fx;
		} else {
			if((k->fx >= 255) && (key.fx >= 0)) {
				k->fx |= key.fx;
			} else {
				k->fx = key.fx;
			}
		}
		*/
	}

	if(key.speed > -1.f) {
		k->speed = key.speed;
	}
	
	k->color = key.color;
	k->colord = key.colord;
	k->colorf = key.colorf;
	
	if(key.idsound > -2) {
		k->idsound = key.idsound;
	}

	if(key.force > -2)
		k->force = key.force;

	k->frame = key.frame;
	k->pos = key.pos;
	k->angz = key.angz;

	if(key.typeinterp > -2)
		k->typeinterp = key.typeinterp;

	float a = -2.f;

	if(C_NEQUAL_F32(key.light.intensity, a)) {
		k->light = key.light;
	}

	k->posgrille = key.posgrille;
	k->angzgrille = key.angzgrille;
	k->speedtrack = key.speedtrack;

	UpDateAllKeyLight();

	return true;
}
Example #3
0
bool parseCinematic(Cinematic * c, const char * data, size_t size) {
	
	const char * cinematicId = util::safeGetString(data, size);
	if(!cinematicId) {
		LogError << "Error parsing file magic number";
		return false;
	}
	
	if(std::strcmp(cinematicId, "KFA") != 0) {
		LogError << "Wrong magic number";
		return false;
	}
	
	s32 version;
	if(!util::safeGet(version, data, size)) {
		LogError << "Error reading file version";
		return false;
	}
	LogDebug("version " << version);
	
	if(version < CINEMATIC_VERSION_1_75) {
		LogError << "Too old version " << version << " expected at least " << CINEMATIC_VERSION_1_75;
	}
	
	if(version > CINEMATIC_VERSION_1_76) {
		LogError << "Wrong version " << version << " expected max " << CINEMATIC_VERSION_1_76;
		return false;
	}
	
	// Ignore a string.
	util::safeGetString(data, size);
	
	// Load bitmaps.
	s32 nbitmaps;
	if(!util::safeGet(nbitmaps, data, size)) {
		LogError << "Error reading bitmap count";
		return false;
	}
	LogDebug(nbitmaps << " images:");
	
	c->m_bitmaps.reserve(nbitmaps);
	
	for(int i = 0; i < nbitmaps; i++) {
		
		s32 scale = 0;
		if(!util::safeGet(scale, data, size)) {
			LogError << "Error reading bitmap scale";
			return false;
		}
		
		const char * str = util::safeGetString(data, size);
		if(!str) {
			LogError << "Error reading bitmap path";
			return false;
		}
		LogDebug(" - " << i << ": \"" << str << '"');
		res::path path = fixTexturePath(str);
		LogDebug("   => " << path << " (scale x" << scale << ')');
		
		
		CinematicBitmap * newBitmap = CreateCinematicBitmap(path, scale);
		if(newBitmap) {
			c->m_bitmaps.push_back(newBitmap);
		}
	}
	
	// Load sounds.
	s32 nsounds;
	if(!util::safeGet(nsounds, data, size)) {
		LogError << "Error reading sound count";
		return false;
	}
	
	LogDebug(nsounds << " sounds:");
	for(int i = 0; i < nsounds; i++) {
		
		if(version >= CINEMATIC_VERSION_1_76) {
			s16 ignored;
			if(!util::safeGet(ignored, data, size)) {
				LogError << "Error reading sound id";
				return false;
			}
		}
		
		const char * str = util::safeGetString(data, size);
		if(!str) {
			LogError << "Error reading sound path";
			return false;
		}
		LogDebug(" - " << i << ": \"" << str << '"');
		std::pair<res::path, bool> path = fixSoundPath(str);
		LogDebug("   => " << path.first << (path.second ? " (speech)" : ""));
		
		AddSoundToList(path.first, path.second);
	}
	
	// Load track and keys.
	
	SavedCinematicTrack t;
	if(!util::safeGet(t, data, size)) {
		LogError << "Error reading track";
		return false;
	}
	
	if(t.startframe != 0) {
		LogWarning << "Cinematic startframe is not 0";
	}
	
	AllocTrack(t.endframe, t.fps);
	
	LogDebug(t.nbkey << " keyframes:");
	for(int i = 0; i < t.nbkey; i++) {
		
		CinematicKeyframe k;
		int idsound;
		
		if(version <= CINEMATIC_VERSION_1_75) {
			
			C_KEY_1_75 k175;
			if(!util::safeGet(k175, data, size)) {
				LogError << "Error reading key v1.75";
				return false;
			}
			
			k.angz = k175.angz;
			k.color = Color::fromBGRA(ColorBGRA(k175.color));
			k.colord = Color::fromBGRA(ColorBGRA(k175.colord));
			k.colorf = Color::fromBGRA(ColorBGRA(k175.colorf));
			k.frame = k175.frame;
			k.fx = k175.fx;
			k.numbitmap = k175.numbitmap;
			k.pos = k175.pos.toVec3();
			k.speed = k175.speed;
			k.typeinterp = k175.typeinterp;
			k.force = k175.force;
			idsound = k175.idsound;
			k.idsound = -1;
			k.light = k175.light;
			k.posgrille = k175.posgrille.toVec3();
			k.angzgrille = k175.angzgrille;
			k.speedtrack = k175.speedtrack;
			
			arx_assert(k175.posgrille.toVec3() == Vec3f_ZERO);
			arx_assert(k175.angzgrille == 0.f);
		} else {
			
			C_KEY_1_76 k176;
			if(!util::safeGet(k176, data, size)) {
				LogError << "Error reading key v1.76";
				return false;
			}
			
			k.angz = k176.angz;
			k.color = Color::fromBGRA(ColorBGRA(k176.color));
			k.colord = Color::fromBGRA(ColorBGRA(k176.colord));
			k.colorf = Color::fromBGRA(ColorBGRA(k176.colorf));
			k.frame = k176.frame;
			k.fx = k176.fx;
			k.numbitmap = k176.numbitmap;
			k.pos = k176.pos.toVec3();
			k.speed = k176.speed;
			k.typeinterp = k176.typeinterp;
			k.force = k176.force;
			k.light = k176.light;
			k.posgrille = k176.posgrille.toVec3();
			k.angzgrille = k176.angzgrille;
			k.speedtrack = k176.speedtrack;
			idsound = k176.idsound[0]; // 0 was the language code for 'French'
			k.idsound = k176.idsound[3]; // 3 was the language code for 'English'
			
			arx_assert(k176.posgrille.toVec3() == Vec3f_ZERO);
			arx_assert(k176.angzgrille == 0.f);
		}
		
		if(k.force < 0) {
			k.force = 1;
		}
		
		// The cinematics were authored for 4:3 - if the light only fades off
		// outside of that region, it should never fade off.
		// This fixes ugly transitions when fallin and fallout are close together.
		{
			
			float f = std::min(k.light.fallin, k.light.fallout);
			
			float d0 = glm::distance(Vec2f(k.light.pos), Vec2f(-320.f, -240.f));
			float d1 = glm::distance(Vec2f(k.light.pos), Vec2f(320.f, -240.f));
			float d2 = glm::distance(Vec2f(k.light.pos), Vec2f(320.f,  240.f));
			float d3 = glm::distance(Vec2f(k.light.pos), Vec2f(-320.f,  240.f));
			
			if(f > std::max(std::max(d0, d1), std::max(d2, d3))) {
				k.light.fallin = k.light.fallout = std::numeric_limits<float>::max() / 3;
			}
			
		}
		
		// The final vertex positions were manually scaled to fit the whole screen
		// when rendering cinematics. This applies the same scaling by moving
		// the camera closer. We can do this because all bitmaps are at z == 0.
		{
			arx_assert(k.posgrille.z == 0.f);
			k.pos.z *= 0.8f; // 0.8 == 512/640 == 384/480
		}
		
		AddKeyLoad(k);
		
		LogDebug(" - " << i << ": frame " << k.frame << " image: " << k.numbitmap);
		if(k.idsound >= 0) {
			LogDebug("   + sound: " << k.idsound);
		}
		
		if(i == 0) {
			c->m_pos = k.pos;
			c->angz = k.angz;
			c->numbitmap = k.numbitmap;
			c->fx = k.fx;
			c->ti = k.typeinterp;
			c->color = k.color;
			c->colord = k.colord;
			c->colorflash = k.colorf;
			c->speed = k.speed;
			c->idsound = idsound;
			c->force = k.force;
			c->m_light = k.light;
			c->posgrille = k.posgrille;
			c->angzgrille = k.angzgrille;
			c->speedtrack = k.speedtrack;
		}
		
	}
	
	UpDateAllKeyLight();
	
	SetCurrFrame(0);
	
	GereTrack(c, 0, false, false);
	c->projectload = true;
	
	LogDebug("loaded cinematic");
	
	return true;
}
Example #4
0
/*----------------------------------------------------------------------*/
BOOL LoadProject(CINEMATIQUE * c, char * dir, char * name)
{
	int		nb, version;
	C_TRACK	t;
	C_KEY		k, *kk;
	C_KEY_1_59	k159;
	C_KEY_1_65	k165;
	C_KEY_1_70	k170;
	C_KEY_1_71	k171;
	C_KEY_1_72	k172;
	C_KEY_1_74	k174;
	C_KEY_1_75	k175;
	char	txt[4];

	InitMapLoad(c);
	InitSound(c);

	strcpy(AllTxt, dir);
	strcat(AllTxt, name);
	FCurr = PAK_fopen(AllTxt, "rb");

	if (!FCurr) return FALSE;

	ReadString(txt);

	if (strcmp(txt, "KFA"))
	{
		PAK_fclose(FCurr);
		FCurr = NULL;
		c->New();
		return FALSE;
	}

	PAK_fread(&version, 4, 1, FCurr);

	if (version > VERSION)
	{
		PAK_fclose(FCurr);
		FCurr = NULL;
		c->New();
		return FALSE;
	}

	if (version >= ((1 << 16) | 61))
	{
		char txt[256];
		ReadString(txt);
	}

	//chargement image
	PAK_fread(&nb, 1, 4, FCurr);

	while (nb)
	{
		int echelle = 0;

		if (version >= ((1 << 16) | 71))
		{
			PAK_fread((void *)&echelle, 4, 1, FCurr);
		}

		ReadString(AllTxt);
		strcpy(Dir, AllTxt);
		GetPathDirectory(Dir);
		strcpy(Name, AllTxt);
		ClearDirectory(Name);
		strcpy(Name, FileNameChoose);

		int id = CreateAllMapsForBitmap(Dir, Name, c, -1, 0);

		if (TabBitmap[id].load)
		{
			if (echelle > 1)
			{
				TabBitmap[id].grille.echelle = echelle;
				c->ReInitMapp(id);
			}
			else
			{
				TabBitmap[id].grille.echelle = 1;
			}
		}
		else
		{
			TabBitmap[id].grille.echelle = 1;
		}

		nb--;
	}

	//chargement son
	LSoundChoose = C_LANGUAGE_FRENCH;

	if (version >= ((1 << 16) | 60))
	{
		PAK_fread(&nb, 1, 4, FCurr);

		while (nb)
		{
			if (version >= ((1 << 16) | 76))
			{
				short il;
				PAK_fread((void *)&il, 1, 2, FCurr);
				LSoundChoose = il;
			}

			ReadString(AllTxt);
			strcpy(Dir, AllTxt);
			GetPathDirectory(Dir);
			strcpy(Name, AllTxt);
			ClearDirectory(Name);
			strcpy(Name, FileNameChoose);

			AddSoundToList(Dir, Name, -1, 0);
			nb--;
		}
	}

	//chargement track + key
	PAK_fread(&t, 1, sizeof(C_TRACK) - 4, FCurr);
	AllocTrack(t.startframe, t.endframe, t.fps);

	nb = t.nbkey;

	while (nb)
	{
		if (version <= ((1 << 16) | 59))
		{
			PAK_fread(&k159, 1, sizeof(C_KEY_1_59), FCurr);
			k.angz = k159.angz;
			k.color = k159.color;
			k.colord = k159.colord;
			k.colorf = k159.colorf;
			k.frame = k159.frame;
			k.fx = k159.fx;
			k.numbitmap = k159.numbitmap;
			k.pos = k159.pos;
			k.speed = k159.speed;

			ARX_CHECK_SHORT(k159.typeinterp);
			k.typeinterp = ARX_CLEAN_WARN_CAST_SHORT(k159.typeinterp);
			k.force = 1;
			k.idsound[C_LANGUAGE_FRENCH] = -1;
			k.light.intensite = -1.f;
			k.posgrille.x = k.posgrille.y = k.posgrille.z = 0.f;
			k.angzgrille = 0.f;
			k.speedtrack = 1.f;
		}
		else
		{
			if (version <= ((1 << 16) | 65))
			{
				PAK_fread(&k165, 1, sizeof(C_KEY_1_65), FCurr);
				k.angz = k165.angz;
				k.color = k165.color;
				k.colord = k165.colord;
				k.colorf = k165.colorf;
				k.frame = k165.frame;
				k.fx = k165.fx;
				k.numbitmap = k165.numbitmap;
				k.pos = k165.pos;
				k.speed = k165.speed;

				ARX_CHECK_SHORT(k165.typeinterp);
				k.typeinterp = ARX_CLEAN_WARN_CAST_SHORT(k165.typeinterp);
				k.force = 1;
				k.idsound[C_LANGUAGE_FRENCH] = k165.idsound;
				k.light.intensite = -1.f;
				k.posgrille.x = k.posgrille.y = k.posgrille.z = 0.f;
				k.angzgrille = 0.f;
				k.speedtrack = 1.f;
			}
			else
			{
				if (version <= ((1 << 16) | 70))
				{
					PAK_fread(&k170, 1, sizeof(C_KEY_1_70), FCurr);
					k.angz = k170.angz;
					k.color = k170.color;
					k.colord = k170.colord;
					k.colorf = k170.colorf;
					k.frame = k170.frame;
					k.fx = k170.fx;
					k.numbitmap = k170.numbitmap;
					k.pos = k170.pos;
					k.speed = k170.speed;
					k.typeinterp = k170.typeinterp;
					k.force = k170.force;
					k.idsound[C_LANGUAGE_FRENCH] = k170.idsound;
					k.light.intensite = -1.f;
					k.posgrille.x = k.posgrille.y = k.posgrille.z = 0.f;
					k.angzgrille = 0.f;
					k.speedtrack = 1.f;
				}
				else
				{
					if (version <= ((1 << 16) | 71))
					{
						PAK_fread(&k171, 1, sizeof(C_KEY_1_71), FCurr);
						k.angz = k171.angz;
						k.color = k171.color;
						k.colord = k171.colord;
						k.colorf = k171.colorf;
						k.frame = k171.frame;
						k.fx = k171.fx;
						k.numbitmap = k171.numbitmap;
						k.pos = k171.pos;
						k.speed = k171.speed;
						k.typeinterp = k171.typeinterp;
						k.force = k171.force;
						k.idsound[C_LANGUAGE_FRENCH] = k171.idsound;
						k.light = k171.light;

						if ((k.fx & 0xFF000000) != FX_LIGHT)
						{
							k.light.intensite = -1.f;
						}

						k.posgrille.x = k.posgrille.y = k.posgrille.z = 0.f;
						k.angzgrille = 0.f;
						k.speedtrack = 1.f;
					}
					else
					{
						if (version <= ((1 << 16) | 72))
						{
							PAK_fread(&k172, 1, sizeof(C_KEY_1_72), FCurr);
							k.angz = k172.angz;
							k.color = k172.color;
							k.colord = k172.colord;
							k.colorf = k172.colorf;
							k.frame = k172.frame;
							k.fx = k172.fx;
							k.numbitmap = k172.numbitmap;
							k.pos = k172.pos;
							k.speed = k172.speed;
							k.typeinterp = k172.typeinterp;
							k.force = k172.force;
							k.idsound[C_LANGUAGE_FRENCH] = k172.idsound;
							k.light.pos = k172.light.pos;
							k.light.fallin = k172.light.fallin;
							k.light.fallout = k172.light.fallout;
							k.light.r = k172.light.r;
							k.light.g = k172.light.g;
							k.light.b = k172.light.b;
							k.light.intensite = k172.light.intensite;
							k.light.intensiternd = k172.light.intensiternd;
							k.posgrille.x = k172.posgrille.x;
							k.posgrille.y = k172.posgrille.y;
							k.posgrille.z = k172.posgrille.z;
							k.angzgrille = k172.angzgrille;
							k.speedtrack = 1.f;

							if ((k.fx & 0xFF000000) != FX_LIGHT)
							{
								k.light.intensite = -1.f;
							}
						}
						else
						{
							if (version <= ((1 << 16) | 74))
							{
								PAK_fread(&k174, 1, sizeof(C_KEY_1_74), FCurr);
								k.angz = k174.angz;
								k.color = k174.color;
								k.colord = k174.colord;
								k.colorf = k174.colorf;
								k.frame = k174.frame;
								k.fx = k174.fx;
								k.numbitmap = k174.numbitmap;
								k.pos = k174.pos;
								k.speed = k174.speed;
								k.typeinterp = k174.typeinterp;
								k.force = k174.force;
								k.idsound[C_LANGUAGE_FRENCH] = k174.idsound;
								k.light.pos = k174.light.pos;
								k.light.fallin = k174.light.fallin;
								k.light.fallout = k174.light.fallout;
								k.light.r = k174.light.r;
								k.light.g = k174.light.g;
								k.light.b = k174.light.b;
								k.light.intensite = k174.light.intensite;
								k.light.intensiternd = k174.light.intensiternd;
								k.posgrille.x = k174.posgrille.x;
								k.posgrille.y = k174.posgrille.y;
								k.posgrille.z = k174.posgrille.z;
								k.angzgrille = k174.angzgrille;
								k.speedtrack = 1.f;
							}
							else
							{
								if (version <= ((1 << 16) | 75))
								{
									PAK_fread(&k175, 1, sizeof(C_KEY_1_75), FCurr);
									k.angz = k175.angz;
									k.color = k175.color;
									k.colord = k175.colord;
									k.colorf = k175.colorf;
									k.frame = k175.frame;
									k.fx = k175.fx;
									k.numbitmap = k175.numbitmap;
									k.pos = k175.pos;
									k.speed = k175.speed;
									k.typeinterp = k175.typeinterp;
									k.force = k175.force;
									k.idsound[C_LANGUAGE_FRENCH] = k175.idsound;
									k.light.pos = k175.light.pos;
									k.light.fallin = k175.light.fallin;
									k.light.fallout = k175.light.fallout;
									k.light.r = k175.light.r;
									k.light.g = k175.light.g;
									k.light.b = k175.light.b;
									k.light.intensite = k175.light.intensite;
									k.light.intensiternd = k175.light.intensiternd;
									k.posgrille.x = k175.posgrille.x;
									k.posgrille.y = k175.posgrille.y;
									k.posgrille.z = k175.posgrille.z;
									k.angzgrille = k175.angzgrille;
									k.speedtrack = k175.speedtrack;
								}
								else
								{
									PAK_fread(&k, 1, sizeof(C_KEY), FCurr);
								}
							}
						}
					}
				}
			}
		}

		if (version <= ((1 << 16) | 67))
		{
			if (k.typeinterp == INTERP_NO_FADE)
			{
				k.typeinterp = INTERP_NO;
				k.force = 1;
			}
		}

		if (version <= ((1 << 16) | 73))
		{
			k.light.pos.x = k.light.pos.y = k.light.pos.z = 0.f;
		}

		if (version <= ((1 << 16) | 75))
		{
			for (int i = 1; i < 16; i++) k.idsound[i] = -1;
		}

		if (k.force < 0) k.force = 1;

		FillKeyTemp(&k.pos, k.angz, k.frame, k.numbitmap, k.fx, k.typeinterp, k.color, k.colord, k.colorf, k.speed, -1, k.force, &k.light, &k.posgrille, k.angzgrille, k.speedtrack);
		memcpy(&KeyTemp.idsound, &k.idsound, 16 * 4);
		AddKeyLoad(&KeyTemp);

		if (!(t.nbkey - nb))
		{
			c->pos = k.pos;
			c->angz = k.angz;
			c->numbitmap = k.numbitmap;
			c->fx = k.fx;
			c->ti = c->tichoose = k.typeinterp;
			c->color = c->colorchoose = k.color;
			c->colord = c->colorchoosed = k.colord;
			c->colorflash = c->colorflashchoose = k.colorf;
			c->speed = c->speedchoose = k.speed;
			c->idsound = k.idsound[C_LANGUAGE_FRENCH];
			c->force = k.force;
			c->light = c->lightchoose = k.light;
			c->posgrille = k.posgrille;
			c->angzgrille = k.angzgrille;
			c->speedtrack = k.speedtrack;
		}

		nb--;
	}

	UpDateAllKeyLight();

	PAK_fclose(FCurr);
	FCurr = NULL;

	ActiveAllTexture(c);

	SetCurrFrame(0);

	GereTrackNoPlay(c);
	c->projectload = TRUE;

	InitUndo();

	//precalc
	if (version < ((1 << 16) | 71))
	{
		kk = CKTrack->key;
		nb = CKTrack->nbkey;

		while (nb)
		{
			switch (kk->fx & 0x0000FF00)
			{
				case FX_DREAM:
					TabBitmap[kk->numbitmap].grille.echelle = 4;
					c->ReInitMapp(kk->numbitmap);
					break;
			}

			nb--;
			kk++;
		}
	}

	LSoundChoose = C_LANGUAGE_ENGLISH << 8;

	return TRUE;
}