Comment est-ce qu’on codait un jeu vidéo au milieu des années 90 ?

La réponse dans le code source de LBA (Little Big Adventure) et LBA2, tous deux libérés sous licence GPLv2

Ce mercredi 27 octobre 2021, le studio [2.21] (c’est leur nom) a libéré le code source de Little Big Adventure 1 et 2 sous licence GPLv2.

Ça en fait des documents intéressants sur la façon de programmer un jeu entre 1994 et 1997, avec des pratiques qui paraissent totalement absurdes en 2021, malgré un code plutôt clair (dans le sens où c’est facile de s’y retrouver). Par exemple, le fichier PERSO.C de LBA semble gérer à la fois la boucle principale de jeu et l’inventaire. Dans le code source de LBA2, on trouve des fichiers en version C et C++. Ah, et bien entendu, il y a des routines en assembleur. D’une façon générale, il y a beaucoup de choses très « manuelles » dans la façon de gérer le code.

Comme le studio à l’origine de ces jeux était français, le code est commenté en… franglais.

On y voit aussi que les fix horribles, ça n’est pas récent :

void	DoDirWagon( T_OBJET *ptrobj )
{
	S32	brick	;

	// ATTENTION : Grosse Magouille :
	// Le champ Sprite des objets de type Wagon (forcement des
	// objets 3D) est utilis‚ dans les aiguillages pour savoir
	// dans quel sens on le prend. Cela repare un bug lorqu'on
	// tournait dans un aiguillage et qu'on modifiait en meme
	// temps le sens de l'aiguillage !

	// Autres champs utilises :

	// Info: Type de d‚placement: 0 --> droit
	//			      1 --> Virage Gauche
	//			      2 --> Virage Droite

	// Info2 et Info3: Coordonnees du point de rotation
	// Info1: Flag d'init
	// SizeShit: Num de la brick sur laquelle est le wagon

	// depend du block sur lequel on se trouve
	brick = GetBlockBrick( ptrobj->Obj.X,ptrobj->Obj.Y-1,ptrobj->Obj.Z ) ;
	// depend du style actuel (planete TWINSUN ou ESMER)
	brick = GetNumBrickWagon( brick ) ;

	switch( brick )
	{

(Le switch est immense, parce qu’il gère tous les cas possibles de type de brick sur lesquels peut rouler le wagon !)

Bref, c’est instructif à lire si vous lisez un peu le code (même sans connaitre spécifiquement le C ou le C++).



Icône d’après cette capture d’écran, CC BY-SA Adeline Software International (developer) et Didier Chanfray S.a.r.l. (copyright holder).

7 commentaires

C’est pourtant des jeux qui sont sortis dans des états très propres techniquement.

Les speed runs utilisent pas mal d’exploits, il y avait des trucs chiants d’un point de vue gameplay, mais j’ai pas souvenir de bugs à proprement parler.

Dans les autres perles, j’ai :

Ce moment où tu dois coder un truc à l’arrache pour la démo :

S32     DialNbLine ;    // pour la version demo le 02/08/96

Et :

#ifdef	DEMO
		// Grosse rustine pour ne pas voir les plaques d'‚gouts
		ListVarGame[164] = 1 ;
		ListVarGame[165] = 1 ;
#endif

Quand la fin de projet est là et qu’il faut livrer, donc tu codes du scénario parce qu’on est en 1997 et le patch day 1, c’est un fantasme  :

        // Grosse Rustine crade LBA2 (fin de projet oblige...) pour la
        // scene finale dans le desert (on avait un transfert de voix
        // alors qu'il n'y a pas de dialogue !)

        if( PLAY_THE_END
        AND Island==2 )// desert
        {
                return ;
        }

Tellement que tu n’as même plus le temps d’expliquer c’est quoi ta magouille (mais c’est pas grave, ça marche et le projet est fini

	// grosse rustine scenarique
	if( (NewCube == 4) AND (ListFlagGame[30]!=0) )
	{
		NewCube = 118 ;
	}

Ou quand tu te bats avec ton collègue par commentaires interposés :

	ObjectClear( &(ptrobj->Obj) ) ;		// init structure 3D: TRES
						// IMPORTANT, A NE PAS VIRER !!!!

Très sympa à regarder.

Très marrants ce fichier : https://github.com/2point21/lba1-classic/blob/main/SOURCES/MESSAGE.C

J’ai bien aimé le :

LONG	TryCopyFileCD_HD( char *filecd, char *filehd )
{
	ULONG	freesize	;

	freesize = GetHDFreeSize()-(1024L*1024L) ;//	1 Mega de marge

	if (!GetFileCDR( filecd ))	return(0);// Ne doit Jamais Arriver!

	if ( freesize > FileCD_Size )		// Y a la place :-)
		return( CopyFileCD_HD( filecd, filehd ))	;

//------------------------------ Ok, y a pas la place for the moment :-(

	if ( !NbFileOnHD )	return(0)	;// Nothing to delete :-<

	if ( TotalSizeFileHD+freesize < FileCD_Size )
				return(0)	;// We can't do nothing :-[

	while( freesize < FileCD_Size )		 // Keep hope... ;-)
	{
		DeleteOlderFileHD()			;
		freesize = GetHDFreeSize()-(1024L*1024L);
	}

//----------------------------- Ok, maintenant on a forc‚ment la place...

	return( CopyFileCD_HD( filecd, filehd ))	;//  :-)
}
+0 -0

Mon préféré dans ce fichier ça reste quand même :

	for ( i = 0 ; i < NbFileOnHD ; i++, pt++ )
	{
		if ( FileSize( pt->NameHD ))//	On ne sait jamais,
			Delete( pt->NameHD );// un bug est si vite arrive :-o
	}

D’une manière générale, c’était le tout début des programmes sur CD (et pas forcément distribués sur CD d’ailleurs), ça avait des effets de bords bizarres. Par exemple, certaines pistes musicales étaient directement sur le CD (c’était fréquent, tu pouvais le mettre dans une chaine HiFi, et c’est le moment de l’histoire du jeu vidéo où les musiques ont été les meilleures). Mais il y avait des effets de bords étranges ; par exemple dans LBA2 le chargement du thème était synchrone, donc le jeu était bloqué le temps que le CD se lance !

PS : celui-ci est bien aussi (toujours le même fichier) :

LONG	TestSpk( LONG fd )
{
	if ( !FlagSpeak )	return(0)	;//     Le joueur ne veut pas
	if ( !fd )		return(0)	;//     Le programme ne peut pas

	if ( WaveInList( SPEAK_SAMPLE ))	return(1)	;// ‡a joue...

	if ( FlagNextVoc )			// Ya une suite...
	{
		PlaySpeakVoc( fd )  		;//	Scratch Screen
		return(1)			;// Ca continue de jouer...
	}

	return(0)	;			// A plus, snif... :-(
}

Cela dit, je crois qu’il n’y avait qu’un développeur principal sur ce projet (LBA le premier)

D’ailleurs, je vois que dans le fichier ci-dessous, ils ont réécris les fonctions d’allocation et de désallocation de mémoire (juste pour la version debug).. c’est pour avoir un oeil en continu sur la mémoire je suppose ?

https://github.com/2point21/lba1-classic/blob/main/SOURCES/MALLOC.C

Tonio

En supposant que l’utilisation d’outils tels que valgrind ou encore dr memory n’était pas courante à cette époque, oui.

Ça leur permettait aussi très certainement de savoir à quel moment il y avait combien de blocks alloués, de quelle quantité de mémoire, et sans doute pourquoi.

Plus un logiciel est gros, plus c’est difficile de ne pas laisser de fuites de mémoire et surtout de les traquer !

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte