PROJET AUTOBLOG


blog.fevrierdorian.com

source: blog.fevrierdorian.com

⇐ retour index

Powerslide sur GOG en full HD avec AA et tout et tout!

mercredi 16 janvier 2013 à 10:28

Powerslide_GOG_tn.pngJ'ai acheté Powerslide sur GOG il y a quelques temps. :gniarkgniark:

Pour info, GOG était l’abréviation de Good Old Games et proposait (et propose toujours) des jeux sans DRM, à des prix attractifs et surtout une compatibilité avec les nouveaux systèmes.

C'est précisément ça qui m'a amené à dépenser la moitié moins du prix d'une peinte parisienne (c'est le premier argument qui m'est passé par la tête au moment de payer, allez savoir pourquoi...) pour ce jeu dont j'ai dû passer plus de temps sur la démo que sur la plupart des autres jeux que j'avais pu acheter à l’époque. :baffed:

Envie de rejouer aux jeux de ton enfance? Ça y est, t'est vieux!

Tout commence par un screenshot du jeu sur lequel je tombe totalement par hasard sur un forum (sur un thread inspiré du genre "Un screenshot, devinez le jeu"). Je me dis "tiens il était cool ce jeu, ça serait bien d'y rejouer, juste pour voir" :siffle: .

Après pas mal de recherches, je trouve quelques isos du CD original et lance une installation.

Et paf! C'est la que tu te prend dix ans d’évolution des OS dans la tronche... Faire fonctionner correctement ce jeu en version original relève de l'exploit (au sens français comme au sens informatique). Certains semblent y être arrivé. Ne m'étant jamais vraiment tourné vers du "revival" de jeux fonctionnant via 3dfx j'ai du me contenter d’échecs à répétition... :pasClasse:

Après plusieurs soirées (parce que oui, quand quelque chose comme ça me résiste, je suis du genre assez bête pour insister) à tenter par tout les moyens de faire fonctionner ce jeu, j'ai du me résilier à abandonner. Powerslide allait rejoindre la longue liste des jeux qu'il n'est plus possible de faire fonctionner sans prise de tête (Shadow Of The Empire... Snif...).

Puis je réalise que GOG (que je connaissais déjà) propose une version. Il faut savoir que GOG fait un gros travaille pour rendre les anciens jeu jouable sur les nouveaux systèmes sans que l'utilisateur ait justement à bricoler. T'installe, tu lance, tu enjoy! :banaeyouhou:

4.74 euros plus tard (tant pis, je boirai un verre d'eau à ma prochaine sortie... :dentcasse: ) + le temps régler le wrapper nGlide intégré, je branche mon pad, lance le même circuit + la même voiture que la démo et m'affale dans mon siège, détendu, pour profiter des quelques minutes de nostalgie qui s'offre à moi.

Powerslide_GOG_nGlide_001.png

Powerslide_GOG_nGlide_002.png Ces vieux jeux étant pensés pour être projetés sur tube cathodique, n'hésitez pas à monter le Gamma de à 1.2. Pensez aussi à conserver les proportions en 4:3, sinon, ça risque de vous donner le mal de mer durant les virages.

Pour le reste: A fond!

Powerslide_GOG_amd_override_001.png

J'ai également overridé tous les paramètres à fond au niveau du driver, ça coute pas cher.

Powerslide_GOG_menu.png

Le circuit. Souvenirs souvenirs... :hehe:

Powerslide_GOG_logo_3dfx_en_aa.png

Avouez que vous l'aviez oublié celui là. :sourit:

Mais aussitôt l'accelerateur poussé, je déchante.

Powerslide_GOG_001.jpg

Premier virage: Bim! Raté. Second virage: Bim! Reraté... (Je me redresse sur mon siège: putain... o_O).

Powerslide_GOG_002.jpg

Après 30 minutes de jeu, le constat est sans appel: Les jeux étaient bien plus durs AAAAAvant, alors que j'étais beaucoup plus jeune et que je n'avais pas noté de difficulté particulière. Au contraire, j'avais gardé le sentiment d'un jeu d'arcade... Et le pire c'est que c'est cette combinaison (voiture/circuit) qui était utilisé pour te "vendre" le jeu. :seSentCon:

Powerslide_GOG_003.jpg

Sur le premier tour d'un nouveau circuit, il y a de forte chance que vous passiez plus de temps sur le dos que sur les roues. Au début ça fait bizarre mais après on se surprend à se lancer un défi à chaque découverte d'un circuit: "Celui là, je roule doucement et je me ramasse pas!", et puis non... :onSeFendLaPoire:

Powerslide_GOG_004.jpg

Et c'est au bout d'une première heure qu'on commence à comprendre que négocier un virage est en fait une affaire de maitre et c'est ce que ce jeu exige: De la maitrise.

Puis tout devient naturel, on se met à sourire lorsqu'on double un adversaire sans le toucher sur un virage pris a la perfection.

Powerslide_GOG_005.jpg

Là, ça ne se voit pas mais je suis en train de partir completement à droite... :nevroz:

Powerslide_GOG_006.jpg

Notez qu'un mode multijoueur est dispo en IPX, Modem (des trucs de vieux) mais surtout: TCP/IP. Vous devriez donc pouvoir jouer contre un/des amis (à qui vous aurez suffisamment bourré le mou je suppose) sur internet en bricolant un peu. :smileFou:

Lapin d'musiques?

Durant mes premières parties, j'ai pu constater que la musique était absente (les mauvaises langues diront qu'aux vues de la qualité musicale du titre ce n'est pas plus mal :trollface: ), malgré mes allez-retour dans les options. En fouillant le dossier du jeu, je vois des mp3 contenants, justement, les musiques. J’envoie un mail au support pour leur faire remarquer mon soucis sans trop y croire (après tout, je m'en fout, quand je joue à des jeux comme ça c'est du Nirvanna ou du Vitalic qui tourne derrière).

Et c'est à ma grande surprise que quelques heures plus tard, le support m'indique avoir corrigé le soucis et m'invite a retélécharger le jeu...

Et ça fonctionne! :banaeyouhou:

C'est donc avec plaisir que je me suis plongé quelques soirées dans ce jeu bien fun qui s'apparente plus a un jeu de dérapage qu'un "jeu de voiture" et que j'ai pu apprécier le travail et la réactivité de GOG.

GOG c'est bien mais...

...la liste des jeux en français est finalement assez maigre. C'est bien dommage d'ailleurs...

Je vous propose donc un site alternatif français qui c'est lancé dans le même business: DotEmu.

Bon, le catalogue est moins fournit (je trouve qu'il complète bien celui de GOG), mais la plupart des jeux proposés le sont en français (Les Fallout, Gobliiins, Les Commandos, etc...).

En espérant que ce billet coup de cœur rappel des souvenirs à certains...

A bientôt!

:marioCours:

Liens

Resolve network slowdowns due to Nuke, After Effects and others software like them (English Translation)

vendredi 19 octobre 2012 à 10:31

nuke_reseau_tn.pngThis is an english translation of a ticket I wrote (in french :franceHappy: ) few days ago.

Nuke, After Effects and probably others, can be very "greedy" in terms of disk accesses. So much so they can break network performances drastically if several stations are renderings.

In this ticket I purpose a quick explanation of the why and how and a small Python class that can be used as a prototype to solve the problem.

What's the problem?

Nothing better than a concrete case to state the thing:

At the end of Lorax, there was a big number of "compers" (compositors) who was rendering their images all at the same time and time estimations given by Nuke was sometime surprising (3h-4h left for a simple nuke script). Monitoring a file being written, I realized it weight was increasing very slowly. It was 100ko, then 300ko, then after 10 minutes it became 400ko etc... I concluded the network was overloaded... :reflexionIntense:

I remembered that we had the same worries on Tales Of The Night. Our infrastructure was certainly much smaller but 3 After Effect render was "pumping" the entire network. The found solution at that time was to render the file in local and copy it once finished. The effects were immediate: No more slowdown with the network. :sauteJoie:

So I tried to render the nuke script of a CG artist locally to see if it reduce the problem. The largest files to read were source files (because they are many), and the final image weight was actually very light so I was under no illusions. But once again, the conclusion was clear: The rendering was finished in 10-15 minutes (I'm not kidding) instead of 3-4hrs... :laClasse:

I've thought it was maybe the writing process which was a problem. However, when I copied the newly calculated image sequence to the server disks, the copy was very fast. So I've done this with every artist, one by one, and in a big afternoon, the network has no bottleneck anymore and all render ended up.

But that was not a solution. We had to understand why Nuke couldn't write it images quickly through the network. After have asked on the nuke-users mailing list (where I could see I was not alone but The Foundry doesn't seemed able to change this), I've started to "profile" Nuke to know how it does the job (strace and inotifywatch are you friends :dentcasse: ).

Conclusions seems obvious but it's always good to check in practice what you suspect:

With Nuke, if you write a zip 1 line compressed EXR, in 1920x1080, Nuke will do a little less than 900 (approximately) write accesses on the file. If you are in zip 16 lines, it will do about 70 accesses (1080/16). And in uncompressed, that's really 1080 accesses. :trollface:

In facts, compress in zip 16 line is not efficient if images should be read by Nuke. And depending of your network infrastructure, write line by line can put it completely down. It's difficult to explain how finally few Nuke rendering can fill a network, even if this one is strong. I feel this is related to multithreading: Nuke reads images (often, many at the same time) on the network while it is writing through it.

The most obvious solution is therefore to write the rendered image(s) on the local disk and to copy it in one time (one access) on the network disk. If you don't have technical resources (or just time), it's the simplest approach, but on larger projects it can quickly become daunting and (lest we forget) source of errors.

There are several solutions and I was leaning on a prototype that I found interesting because it's easy to implement.

problems.jpg

The principle

As you can see, this method requires that you create a ".finished" file each time an images is finished. This is because it's impossible for the thread to know when an image is actually completed. The creation of this ".finished" file can be handled in a thousand different ways (For Maya, a simple "Post render frame" should do the job) so I will not go into details. :siffle:

The code

Here it is:

import os, threading, re, time
 
class MoverThread( threading.Thread ) :
 
	def __init__( self, dirTocheck, dirToMoveIn, patternToCheck, force=False ) :
		threading.Thread.__init__( self )
 
		self._terminate = False
		self.dirTocheck = dirTocheck
		self.dirToMoveIn = dirToMoveIn
		self.force = force
 
		# regex pattern
		self.patternToCheck = patternToCheck
		self.rePattern = re.compile( patternToCheck )
 
		# sanity check
		if not os.path.isdir(self.dirTocheck) :
			raise Exception( "The given directory (dirTocheck) is not a valid directory -> %s" %  self.dirTocheck )
 
		if not os.path.isdir(self.dirToMoveIn) :
			raise Exception( "The given directory (dirToMoveIn) is not a valid directory -> %s" %  self.dirToMoveIn )
 
	def run( self ) :
 
		filesNotMoved = []
 
		while not self._terminate :
 
			# we wait 3 seconds before do anything
			time.sleep( 3 )
 
			# for every "entry" (file or folder) in the folder we check it have the good pattern. If it has, we check for a ".finished" file
			for entry in os.listdir( self.dirTocheck ) :
 
				# check the current entry is "compliant" with the given regex
				if not self.rePattern.match( entry ) :
					continue
 
				srcFilePath = os.path.join( self.dirTocheck, entry )
				dstFilePath = os.path.join( self.dirToMoveIn, entry )
 
				if os.path.isfile( srcFilePath+".finished" ) :
 
					# destination file aready exist?
					if os.path.isfile( dstFilePath ) and not self.force:
 
						# don't add the entry if it is already in the list
						if not entry in filesNotMoved :
							filesNotMoved.append( entry )
 
						continue
 
					# move the file to it new location
					os.rename( srcFilePath, dstFilePath )
					os.remove( srcFilePath+".finished" )
 
					print "File %s moved to %s" % ( entry, self.dirToMoveIn )
 
					break	# restart the while loop to avoid to continue the list of file we maybe have removed: ".finished"
 
		print "Terminated!"
 
		for fileNotMoved in filesNotMoved :
			print "Already exists: Can't move %s to %s" % ( fileNotMoved, self.dirToMoveIn )
 
 
 
	def join( self ) :
 
		self._terminate = True
 
		threading.Thread.join( self )

As you can see (or not), everything happen in a thread.

It's used like this:

import waitFinishAndCopy
myMoverThread = waitFinishAndCopy.MoverThread("/a/local/path/", "/a/network/path/", "^toto\.[0-9]{4}\.exr$")
myMoverThread.start()
# start rendering, do rendering, end rendering.
myMoverThread.join()

And voila!

Conclusion

I hope this modest prototype will inspire you if you are experiencing delays on your network. :mechantCrash:

I also suggest to do some profiling on your core network applications, especially if they are used by many people. Their behavior is always interesting (and sometimes surprising).

Have a nice day!

Dorian

:marioCours:

Résoudre les ralentissements réseaux dûs a Nuke, After Effect et autres logiciels du genre

dimanche 14 octobre 2012 à 12:46

nuke_reseau_tn.pngNuke, After Effect et surement d'autres, peuvent se révéler très "gourmand" en terme d’accès disque. A tel point qu'ils peuvent rapidement mettre des disques réseaux à genoux si plusieurs stations font des rendus.

Dans ce billet je vous propose une explication rapide du comment du pourquoi ainsi qu'une petite classe Python qui fait office de prototype pour solutionner le probleme.

C'est quoi le problème?

Rien de mieux qu'un cas concret pour énoncer la chose:

Sur la fin de Lorax, il y avait un grand nombre de "compeurs" (compositeurs) qui rendaient leurs images en même temps et les estimations affichées par Nuke étaient parfois surprenantes (3h-4h restantes pour des compos simples). En surveillant un fichier en train de s’écrire, je me suis rendu compte qu'il montait très lentement. Il était à 100ko, puis passait à 300ko, puis au bout de dix secondes passait à 400ko etc... J'en ai conclu que le réseau était surchargé... :reflexionIntense:

Je me suis rappelé que nous avions eu le même soucis sur Les Contes De La Nuit. Notre infrastructure était, certes, beaucoup plus modeste mais 3 After Effect en rendu plombaient l’intégralité du réseau. La solution trouvé à ce moment la fut de rendre en local puis de copier les fichier une fois finis. Les effets furent immédiats: Le réseau ne ramait plus. :sauteJoie:

J'ai donc tenté de rendre le compo d'un graphiste en local pour voir si cela diminuait le problème. Les plus gros fichiers à lires étant les fichiers sources, car plus nombreux, et l'image rendu étant relativement légère, je ne me faisais pas trop d'illusions. Et pourtant, une fois de plus, le constat est sans appel: Le rendu se finissait en 10-15 minutes (je ne rigole pas) au lieu de 3-4h... :laClasse:

Je me suis dis que c’était l’écriture qui devait poser problème. Pourtant, quand je copiais la séquence d'image fraichement calculée, la copie était très rapide. Je suis donc passé voir les graphistes les uns après les autres et en un gros après midi, le réseau était complètement désengorgé et les rendus passèrent tous.

Mais ce n’était pas une solution. Il fallait comprendre pourquoi Nuke n'arrivait pas à écrire ces images rapidement sur le réseau. Après avoir posé la question sur la mailing list nuke-users (ou j'ai pu constater que je n’étais pas seul mais que The Foundry semblait ne rien pouvoir faire), j'ai commencé à "profiler" Nuke pour savoir comment ils s'y prenait (strace et inotifywatch sont tes amis :dentcasse: ).

Les conclusions semblent évidentes mais il est toujours bon de vérifier par la pratique ce qu'on soupçonne:

Sous Nuke, si vous écrivez un EXR compressé zip 1 line, en 1920x1080, Nuke fera un peu moins de 900 (et des brouettes) accès en écriture sur le fichier. Si vous êtes en zip 16 lines, il fera environs 70 accès (1080/16). Et en non compressé c'est réellement 1080 accès. :trollface:

Dans les fait, compresser en zip 16 line n'est pas super efficace si les images doivent être lus par Nuke. Et suivant l'infrastructure de votre réseau, écrire ligne à ligne peut le mettre complètement à plat. Il est difficile d'expliquer comment finalement peu de rendus Nuke sont nécessaires pour plomber un réseau, même si ce dernier est costaud. J'ai la sensation que c'est lié au multithreading: Nuke lit des images (souvent beaucoup en même temps) sur le réseau pendant qu'il y écrit.

La solution la plus évidente reste donc d’écrire l'image (les images) rendu sur le disque local et de la copier en une fois (un seul accès) sur le disque réseau. Si vous ne disposez pas des ressources techniques nécessaires ou bien tout simplement de temps, c'est l'approche la plus simple mais sur des projets plus conséquents ça peut rapidement devenir rébarbatif et (ne l'oublions pas) source d'erreurs.

Il y a plusieurs solutions et je m’étais penché sur un prototype que je trouvais intéressant car facile à mettre en place.

problems.jpg

Le principe

Comme vous pouvez le voir, ce système nécessite que vous créiez un fichier ".finished" à chaque fois qu'une image est fini. C'est dû au fait qu'il est impossible pour le thread de savoir à quel moment une image est fini de calculer et complète (et ducoup, quand il peut le lancer la copie). La création de ce ".finished" peut être géré de mille façons différentes (Pour Maya, un "Post render frame" fait l'affaire) donc je ne rentre pas dans les détails. :siffle:

Le code

Voici le code brut de décoffrage:

import os, threading, re, time
 
class MoverThread( threading.Thread ) :
 
	def __init__( self, dirTocheck, dirToMoveIn, patternToCheck, force=False ) :
		threading.Thread.__init__( self )
 
		self._terminate = False
		self.dirTocheck = dirTocheck
		self.dirToMoveIn = dirToMoveIn
		self.force = force
 
		# regex pattern
		self.patternToCheck = patternToCheck
		self.rePattern = re.compile( patternToCheck )
 
		# sanity check
		if not os.path.isdir(self.dirTocheck) :
			raise Exception( "The given directory (dirTocheck) is not a valid directory -> %s" %  self.dirTocheck )
 
		if not os.path.isdir(self.dirToMoveIn) :
			raise Exception( "The given directory (dirToMoveIn) is not a valid directory -> %s" %  self.dirToMoveIn )
 
	def run( self ) :
 
		filesNotMoved = []
 
		while not self._terminate :
 
			# we wait 3 seconds before do anything
			time.sleep( 3 )
 
			# for every "entry" (file or folder) in the folder we check it have the good pattern. If it has, we check for a ".finished" file
			for entry in os.listdir( self.dirTocheck ) :
 
				# check the current entry is "compliant" with the given regex
				if not self.rePattern.match( entry ) :
					continue
 
				srcFilePath = os.path.join( self.dirTocheck, entry )
				dstFilePath = os.path.join( self.dirToMoveIn, entry )
 
				if os.path.isfile( srcFilePath+".finished" ) :
 
					# destination file aready exist?
					if os.path.isfile( dstFilePath ) and not self.force:
 
						# don't add the entry if it is already in the list
						if not entry in filesNotMoved :
							filesNotMoved.append( entry )
 
						continue
 
					# move the file to it new location
					os.rename( srcFilePath, dstFilePath )
					os.remove( srcFilePath+".finished" )
 
					print "File %s moved to %s" % ( entry, self.dirToMoveIn )
 
					break	# restart the while loop to avoid to continue the list of file we maybe have removed: ".finished"
 
		print "Terminated!"
 
		for fileNotMoved in filesNotMoved :
			print "Already exists: Can't move %s to %s" % ( fileNotMoved, self.dirToMoveIn )
 
 
 
	def join( self ) :
 
		self._terminate = True
 
		threading.Thread.join( self )

Comme vous pouvez le voir (ou pas), tout ce passe dans une thread.

Ca s'utilise comme ça:

import waitFinishAndCopy
myMoverThread = waitFinishAndCopy.MoverThread("/a/local/path/", "/a/network/path/", "^toto\.[0-9]{4}\.exr$")
myMoverThread.start()
# start rendering, do rendering, end rendering.
myMoverThread.join()

Et voila!

Conclusion

J’espère que ce modeste prototype vous inspirera si vous rencontrez des lenteurs sur votre réseau. :mechantCrash:

Je vous conseille de faire un peu de profilage réseau sur vos principales applications, surtout si elles sont utilisées par beaucoup de monde. Leurs comportements est toujours intéressant (et parfois surprenant).

Passez une bonne journée!

Dorian

:marioCours:

Neo N64 Myth: Douleur, pleurs, joie!

dimanche 30 septembre 2012 à 21:13

IMG_2231_tn.jpgEt un petit billet détente pour vous parler non pas de pipeline mais de retrogaming et plus spécifiquement d'une console qui me tiens particulièrement à cœur: La Nintendo 64. :dentcasse:

Ici je vais vous parler du Neo N64 Myth et des galères que j'ai rencontrées en l'utilisant.

On est déjà loin des problématiques de displacement mapping et de render pass là!

Ma vie

Ma première console fut la Super Nintendo (SNES). Je vous passe la nostalgie des interminables parties de Super Mario World/Super Mario Kart/ISS Deluxe/Donkey Kong Country/etc... Quelques années plus tard, nous achetâmes une Nintendo 64 (N64) qui restera surement la console sur laquelle je passa (perdis? :seSentCon: ) le plus de temps.

Début 2010, l'envie me revint de faire une partie de Super Mario 64. :joue: La recherche d'un émulateur open source de qualité m'amena à mupen64plus sur lequel je codais brièvement. Puis à la suite d'une bonne affaire sur Priceminister je me rachetais quelques titres (le marché de l'occasion de la N64 étant bien fourni et très accessible financièrement parlant).

Vivant à Paris, j'ai pris l'habitude d’économiser l'espace et un énième joujou, aussi nécessaire soit il (forcement :sourit: ), n'allait pas dans ce sens. Je me suis donc demandé si il n'existait pas un moyen d'avoir tout ses jeux sur une seule et même cartouche.

Ceci m'amena sur le chemin tortueux des linkers N64 (le mot est lâché).

Linkers N64?

En fait, il y en a eu très peu (ça change doucement, le retrogaming étant un vrai marché) et ça existe depuis longtemps, c'est juste cher et introuvable.

Le premier fut le Doctor V64 (ou V64) sorti grosso modo en même temps que la N64 (1996):

Dv64-n64.jpg

V'la le pavé!

Review en français ici.

Le second fut Mr. Backup Z64 (ou Z64):

Z64-1.jpg

Très jolie sur une cheminée...

Notez que si vous avez déjà eu affaire à des roms de jeux N64, vous avez surement déjà dut tomber sur les extensions .z64 et .v64. Ces extensions viennent de la machine qui a servi à "dumper" les cartouches. Les roms .v64 ayant l'alignement des bits du Doctor V64 (little endian) et les .z64 l'alignement des bits du Mr. Backup Z64 (big endian). Ça vous la coupe hein! :dentcasse:

En dehors de ces deux gros objets qui ne sont plus fabriqués depuis longtemps, sont très rare et donc hors de prix, il n'y avait rien. Nada. Que dalle. Peanut. Peau de balle. :triste:

Mais les choses ont changé avec l'arrivée du Neo N64 Myth. D’après mes recherches, il semble qu'ils bossaient déjà dessus en 2006!

C'est un produit qui s'est fait attendre et qui est sorti pile-poil au moment ou j'en cherchais un...

Neo N64 Myth, c'est bien?

Autant le dire tout de suite: C'est galère! Si vous comptez brancher vos jeux, vous affaler dans votre canapé à tapoter le bouton START d'impatience avec un paquet de chips entre les jambes vous n'y êtes pas du tout! Sérieusement, il marche impeccablement bien mais le temps nécessaire pour le rendre utilisable et la douleur qu'il a fallu est sans nom. :nervous:

Pour comprendre pourquoi tant de pleurs, il faut revoir l'historique de ce linker, que j'ai subi, bien malgré moi...

Quand le Neo N64 Myth est sorti, c’était une hardware "vide". Juste un truc avec des connecteurs qui pouvait faire booter des roms N64... Un truc cher pour bidouilleurs avertis.

Comme je suis du genre tête brulée (c'est pas toujours une qualité hein! :nannan: ), je me suis renseigné vite fait, ça avait l'air de marcher, j'ai foncé!

Quand j'ai reçu le bouzin, j'ai vite déchanté. Aucun manuel, aucune doc, rien! Les adeptes du retrogaming sont surement habitués à recevoir des bidules électroniques sans mode d'emploi mais ça fait quand même tout drôle quand on voit le prix. :bete:

NEON64MythCartPackaging.jpg

Avouez que ça ne donne pas confiance pour la suite... :seSentCon:

IMG_2223.jpg

Au moins on ne peut pas leur reprocher de claquer de la tune en marketing...

IMG_2225.jpg

Le slot pour brancher la mémoire flash (on y reviendra), le connecteur USB à gauche et un bouton inutile à droite.

IMG_2224.jpg

Et un slot pour brancher une cartouche N64 d'origine.

Sur cette dernière image, je vais parler d'un point qui me semble important: Pour lutter contre le piratage, Nintendo a toujours utilisé des puces "certifiées" (dont le fonctionnement était gardé secret) intégrées aux cartouches. Bien qu'il semble que des bidouilleurs aient récemment réussi à émuler certaines de ces puces par rétroingénierie, il n'y a pour l'instant pas beaucoup de possibilités pour réussir à booter un programme sur la N64... C'est la raison pour laquelle vous devez brancher un jeu officiel. Juste pour pouvoir faire booter le linker. :sourit:

Je me suis donc mis à déambuler sur le forum officiel (qui ramait comme pas permis à l’époque) et commençais à me faire la main sur le truc.

Comme vous le savez (ou pas, dans ce cas vous allez apprendre des choses :hehe: ), la N64 utilise des cartouches à base de mémoire flash pour avoir un accès rapide aux données (pas de loading sur N64!).

La team à l'origine du Neo N64 Myth a donc décidé de séparer le hardware flash du circuit principale (une bonne chose) et de livrer la cartouche avec un "bloc" de mémoire flash (le machin blanc sur l'image) de 512Mb, soit 64Mo ce qui est très peu si vous comptez mettre toutes vos roms dessus. La ou ils n'ont pas été malin (ça peut se comprendre, ils ont été les premiers et ont donc eu à "tâter" le marché), c'est qu'il n'y a pas de slot pour carte SD ou de truc simple à manipuler, juste une mémoire flash brute.

IMG_2222.jpg

IMG_2220.jpg

IMG_2227.jpg

Le problème c'est que mettre une rom la dessus relève du chemin de croix. :grenadelauncher: Il faut utiliser un soft moisi avec des drivers moisis qui chient dans la colle avec Vista et plus (oui, sur le forum officiel on m'a conseillé d’utiliser XP... :pasClasse: ). Bref, c'est dur, très dur.

Neo2_Ultra_Menu_N64.png

Le premier soft.

Neo2_Pro_Manager_N64.png

Le second...

Les choses ont évolué au fil du temps et un nouveau produit est sorti: Le NEO2 Pro 1024M Flash Cart.

IMG_2228.jpg

IMG_2229.jpg

IMG_2230.jpg

C'est Inception...

IMG_2231.jpg

La cartouche dans la cartouche dans la...

Ce produit est une mémoire flash qui dispose d'un slot pour carte SD. Bien entendu, un second passage en caisse est nécessaire (de toute façon, le retrogaming c'est un truc de riche! :redface: ).

Avec lui est livré le "USB SlimLoader IV". Un truc qu'on est sensé utiliser pour brancher le Neo2 Pro sur son PC mais qui n'a jamais marché chez moi (on peut utiliser directement le Neo N64 Myth à la place)...

Le dev: ChillyWilly (je n'ai aucune idée de si il s'agit d'un dev de l’équipe principale mais il est en tout cas très respecté) proposa donc ce qui aurait du être en standard depuis le début: Un menu directement sur la N64 qui va chercher les roms sur la carte SD, les copie dans la mémoire flash de la carte et lance le jeu! (Rien que de le dire ça fait du bien).

Mais voila, à force de développer son menu, il se retrouva bloqué par le design du firmware du Neo N64 Myth. Qu'a cela ne tienne, la team qui écoutait ces remarques, proposa un nouveau firmware pour la carte... Le problème c'est que pour pouvoir flasher sa carte, il faut encore acheter quelque chose: Le Neo Dual Programmer. (Putain mais... :grenadelauncher: ).

IMG_2236.jpg

Et si vous voulez avoir une idée de la procédure:

Elle est encore loin la partie de Mario Kart 64 dans mon canap'... T_T

Mais on commence à voir le bout de notre compte bancaire. Encore une fois, rien n'est expliqué nulle part et on chope les infos et les binaires sur le forum. D'ailleurs, pour les heureux possesseurs de ce linker, je vous conseille de suivre cette FAQ. Elle est très bien faite, très bien expliqué. Dès que je dois faire une modif sur le truc je repasse par là.

Le dernier soucis que j'ai eu a failli définitivement me décourager (en fait il m'a découragé quelques mois). J'ai trouvé la solution récemment après une énième tentative et ça m'a fait bien bizarre:

Si vous branchez le Neo2 Pro trop "fort" sur le Neo N64 Myth (jusqu'au "click" qui peut naturellement vous faire croire que "c'est bon!"), il n'est plus reconnu par votre PC... En fait, il est reconnu une fraction de seconde et s’éteint directement après. Personne d'autre ne semble avoir eu le soucis et je suis bien content d'avoir trouvé le truc. Mais voila... Encore une fois: Galère...

Pourquoi je vous parle de tout ça?

C'est une question qu'on peut se poser... Si le Neo N64 Myth est si mauvais que ça, pourquoi en parler? :jdicajdirien:

Et bien parce qu'une fois que vous avez fait le plus dur: Ça marche! Vous mettez vos backups de jeu sur votre carte SD, vous branchez le tout ensemble, vous allumez et vous enjoyez! (J'adore cet anglicisme!).

Le second point, et pas des moindres, c'est que le succès du Neo N64 Myth malgré le prix a lancé pas mal de team sur des projets similaires.

Il semble que les plus connus soient:

En plus d’être constamment en rupture de stock, le Everdrive 64 et le 64drive proposent des modèles sans CIC, il faut bien se renseigner avant. Le ED64PLUS semble fonctionner comme le Neo N64 Myth. C'est donc à vous de brancher un jeux original disposant d'une puce CIC.

Le Everdrive 64 et le 64drive se valent. Le ED64PLUS semble être une pale copie des deux premiers. Le Neo N64 Myth est a oublier. Trop compliqué. Il aura eu le mérite d'être le premier du genre mais, en tant que tel, souffre de soucis de maturité.

Avec le recul, si je devais en prendre un maintenant, je choisirai le 64drive. Le (les?) gars de Retroactive est réputé et fiable. Dans tout les cas, s'inscrire sur un forum avec des users utilisant le même linker que vous ne sera pas du luxe si vous galérez.

Intérêt

L’intérêt de tels Linkers, est a relativiser.

Voici grosso modo mon avis:

Points positifs:

Points négatifs:

Conclusion

J’espère que ce petit billet vous aura apprit des choses et servira aux aficionados de la Nintendo 64 qui souhaiteraient s'y remettre.

A bientôt!

Dorian

:marioCours:

Liens intéressants

Python: multiprocessing vs threading

mercredi 4 avril 2012 à 22:52

threadingVSmultiprocess_tn.pngCe billet va tenter de montrer, principalement par l'exemple les différences entre le module threading et le module... multiprocessing! Je vous propose donc deux petits codes pour démarrer rapidement.

La plupart des TD Maya on déjà entendu parler du threading. Non pas pour savoir a quoi ça servait exactement mais parce que Maya a toujours eu du mal avec ce machin la. :gne:

Cela dit, ce billet est très général et n'aborde pas les problèmes de threading dans Maya. :cayMal: Juste les différences entre le module threading et multiprocessing.

Le module threading

Pour faire simple, avec ce module vous "fabriquez" des objets de type Thread, chacun ayant une tache a accomplir. Vous lancez ces objets dans la nature et vous attendez qu'ils reviennent...

Comment ça se passe dans la pratique? :reflechi:

Déjà, il vous faut une fonction suffisamment lourde pour mettre à genoux votre machine:

K = 50
 
def CostlyFunction(z):
	result = 0
	for k in xrange(1, K+2):
		result += z ** (1 / k**1.5)
	return result

Honteusement pompée du fil Stack Overflow: multiprocess or threading in python?.

Comme je vous disais, il vous faut un objet de type Thread:

import threading
 
K = 50
 
class CostlyThread(threading.Thread):
 
	def __init__(self, value):
 
		threading.Thread.__init__(self)
		self.value = value
 
	def run(self):
		# notre fonction
		result = 0
		z = self.value
		for k in xrange(1, K+2):
			result += z ** (1 / k**1.5)
		self.value = result

Et on balance tout!

import time
 
# timer
startTime = time.time()
 
# va stocker les threads qu'on va lancer.
threadList = []
 
for i in xrange(100000) :	# on lance cent milles threads
 
	curThread = CostlyThread(i)
	curThread.start()	# on lance le thread
	threadList.append(curThread)	# on ajoute le thread a la list
 
# maintenant qu'on a tout lance, on récupère tout!
resultList = []
 
for curThread in threadList :
 
	curThread.join()	# on attend que le thread ait fini
	result = curThread.value	# on récupère sa valeur
	resultList.append(result)
 
print time.time() - startTime

Sauvez tout ça dans un fichier python puis lancez un moniteur système et regardez bien ce que Python va faire...

21.4 secondes plus tard... :siffle:

threadingVSmultiprocess_002.png

Vous remarquerez que Python n'a pas tous les processeurs à fond. :redface:

En fait, le threading n'a pas pour vocation de faire "beaucoup de petits calculs". Il n'est pas efficace pour ce genre de chose (je ne rentre pas dans les détails, c'est très bien expliqué dans le fil Stack Overflow: Are Python threads buggy?).

Un des principal intérêt du threading c'est sa mise en place. Il est très simple à utiliser. On va principalement s'en servir pour faire des opérations nécessitant de la "latence".

Je pense qu'on doit pouvoir aller plus loin mais personnellement, je l'utilise souvent quand je dois faire plusieurs appels réseaux dans une boucle (récupérer la date de modification d'une liste de fichiers) c'est beaucoup plus efficace que d'attendre a chaque fois que le réseau nous donne la main pour redemander une informations similaire juste après.

Pas convaincu?

25709 existences de fichier vérifiées en 38.35 secondes :IFuckTheWorld:

J'ose même pas imaginer le temps que ça aurait pris si j'avais fait la même chose en récursif...

Après, le réseau en question était solide (c'est pas du routeur de promotion Carrefour! :baffed: ). Cela dit, suivant l’opération faite par le thread vous pouvez plomber le réseau (ce sera toujours moins pire que Nuke et After Effect en rendu cela dit :trollface: )... Donc faite attention.

Viens maintenant le problème de "calcul brut". Si le threading ne permet pas d'utiliser l’intégralité de son processeur, comment puis-je faire des calculs très lourds?

C'est la seconde partie de ce billet! :hehe:

Le module multiprocessing

Ce module est un petit peu plus subtil à utiliser et il y a plusieurs façons de faire.

La méthode que nous allons voir est l'une des (la?) plus efficace:

import multiprocessing as mp
 
# timer
startTime = time.time()
 
pool = mp.Pool()
asyncResult = pool.map_async(CostlyFunction, xrange(100000))	# on lance aussi cent milles operations
resultList = asyncResult.get()	# asyncResult.get() is a list of values
print time.time() - startTime

0.9 secondes plus tard (Et ouai, faut suivre...)

Vous n'avez peut être rien vu mais si vous avez toujours votre moniteur système d'ouvert avec un graph de charge processeur, vous verrez que pendant ce court laps de temps, tous les processeurs étaient en pleine activité...

threadingVSmultiprocess_001.png

Ajoutez un zéro et regardez comment votre processeur il pleure sa maman (on gaspille aussi plein d’énergie hein! :seSentCon: ).

Je m’arrête la. Le module multiprocessing offre beaucoup plus de possibilités (gestion d'une queue). Mais pour l'instant, je n'ai jamais eu a l'utiliser. :pasClasse:

Conclusion

J’espère que ce petit billet vous aura donné des bouts de code suffisant pour débuter. Personnellement, j’apprécie beaucoup la simplicité du module threading qu'on peut sortir dans pas mal de situations des lors qu'on touche au fichiers.

A bientôt!

Dorian

:marioCours: