Edito
Le seul blog qui fait un carton sur les visiteurs mais qui n'a aucun feedback \ô/.
(Et en plus il change de nom!)
(Et en plus il change de nom!)
Mercredi 08 Mai 2013
Le retour des canvas
Pour mon dernier demi-billet lié aux canvas, direction ici. L'autre partie ayant été envoyée sur un site désormais décédé, il se pourrait que je me décide, dans un futur plus ou moins proche, à la réécrire (
) ici. Pour l'heure, parlons d'un sujet un peu plus intéressant.
Les canvas, donc. Ces merveilles de l'HTML5. Ils vous permettent de tracer des graphiques avec une facilité déconcertante via un peu de JavaScript.
Le canvas disposait, à l'époque de mon précédent billet, d'un seul mode de rendu: "2d". Les choses ont bien évolué en deux ans, avec l'arrivée du mode "webgl", qui permet d'utiliser l'API OpenGL ... en JavaScript. Je ne connais pas les détails, n'ayant pas encore eu la chance d'y toucher, mais je le ferais peut-être dans un futur plus ou moins prochain. En revanche, le mode "3d" n'a toujours pas été défini.
Eh bien, c'est justement de 3D que je vais vous parler. Pas de véritable 3D, mais d'une 3D qu'on pourra qualifier de "laminaire", parce qu'elle se base sur différentes "couches" de pixels, un peu comme une pile de feuilles transparents. Le principe m'était nécéssaire pour un projet de jeu d'échecs en JavaScript, aussi bien serveur que client, que vous pourrez aller admirer à la fin de ce billet.
Alors, vous allez, me dire, c'est bien beau, mais comment fait-on pour avoir ça dans son browser?
J'avais commencé par me pencher sur une implémentation purement basée sur différentes instances de l'objet CanvasRenderingContext2d, qui est en fait l'objet interne à Javascript utilisé pour représenter les pixels du canvas auquel il est associé. Ainsi, pour une image de 40x40 pixels, CanvasRenderingContext2d contient un tableau d'entiers de 8 bits de .. 6400 entrées! Pourquoi autant? Chaque pixel est représenté par quatre entiers: la composante R, G, B, et la composante alpha, qui gère la transparence du pixel.
Admettons. Maintenant, aventurons-nous un peu plus sur le chemin de la réflexion. On veut pouvoir avoir autant de couches que nécessaire. On va donc devoir itérer sur chacune de ces couches, les lier en une seule couche, en associant tous les entiers dans chaque tableau ? On aura donc n * 6400 itérations de tableau pour notre image de 40x40 pixels, où n est le nombre de couches! Hors de question d'aboutir à ça! (Surtout que mon échiquier fait 480x480 pixels...)
Alors comment faire? Après quelques minutes de réflexion, il sera bien plus efficace d'utiliser des canvas créés en JavaScript pur, qui ne seront jamais dans le DOM. On va donc définir un objet JavaScript, judicieusement appelé Layer, qui représentera une couche de notre canvas. On définit également un objet MultiLayerCanvas, qui est construit en lui passant la largeur, la longueur du canvas en pixels, ainsi que le nombre de couches. Il suffit ensuite de redéfinir, au niveau de notre objet MultiLayerCanvas, des fonctions réimplémentant les fonctions standards du CanvasRenderingContext2d, à la seule différence qu'elles prendront l'index de la couche en paramètre supplémentaire.
Très bien, mais quid du rendu? Pour ce faire, on associe le canvas de sortie (celui qui est dans le DOM) à notre MultiLayerCanvas, et on dessine nos couches successivement dans son contexte. Pour comprendre pourquoi ça fonctionne, il faut s'intéresser à CanvasRenderingContext2d.globalCompositeOperation. Cette propriété définit la façon dont les appels à CanvasRenderingContext2d.putImageData, CanvasRenderingContext2d.drawImage et d'autres insèrent leurs tableaux d'octets dans celui du canvas de sortie. La documentation Mozilla est particulièrement claire à ce sujet, je vous y renvoie donc ici. La valeur par défaut de cette propriété est source-over, qui signifie que chaque ajout de pixels se fait en remplacement des anciens. Seuls les pixels transparents qui sont ajoutés ne modifient pas les pixels d'origine. Ainsi, il nous suffit d'ajouter les différentes couches de notre MultiLayerCanvas de la première à la dernière. Voilà, notre canvas est affiché!
Voici le code auquel j'ai abouti: https://gist.github.com/Warpten/5543530
(@Zephyr: Le bouton "code" est cassé sur les blogs
)
Quelques remarques:
- Les 3/4 des fonctions de MultiLayerCanvas ne sont pas error-prone, car aucune vérification n'est faite sur les index des couches. Le but est simple: accélérer autant que possible.
- Ce code a été écrit il y a quelques minutes, en quelques minutes, il n'est donc pas exempt de bêtises et éventuelles redondances. En l'état, il fonctionne, et remarquablement bien (Je prépare un benchmark en ce moment, il sera disponible en commentaires).
À vous!
P.S.: Comme promis, le jeu d'échecs est disponible ici. La connexion peut être lente (Cloud9 n'est pas un serveur de prod), ne vous laissez donc pas avoir par l'absence apparente de réaction du serveur. Si le code source vous intéresse, il est disponible ici.
Les canvas, donc. Ces merveilles de l'HTML5. Ils vous permettent de tracer des graphiques avec une facilité déconcertante via un peu de JavaScript.
Le canvas disposait, à l'époque de mon précédent billet, d'un seul mode de rendu: "2d". Les choses ont bien évolué en deux ans, avec l'arrivée du mode "webgl", qui permet d'utiliser l'API OpenGL ... en JavaScript. Je ne connais pas les détails, n'ayant pas encore eu la chance d'y toucher, mais je le ferais peut-être dans un futur plus ou moins prochain. En revanche, le mode "3d" n'a toujours pas été défini.
Eh bien, c'est justement de 3D que je vais vous parler. Pas de véritable 3D, mais d'une 3D qu'on pourra qualifier de "laminaire", parce qu'elle se base sur différentes "couches" de pixels, un peu comme une pile de feuilles transparents. Le principe m'était nécéssaire pour un projet de jeu d'échecs en JavaScript, aussi bien serveur que client, que vous pourrez aller admirer à la fin de ce billet.
Alors, vous allez, me dire, c'est bien beau, mais comment fait-on pour avoir ça dans son browser?
J'avais commencé par me pencher sur une implémentation purement basée sur différentes instances de l'objet CanvasRenderingContext2d, qui est en fait l'objet interne à Javascript utilisé pour représenter les pixels du canvas auquel il est associé. Ainsi, pour une image de 40x40 pixels, CanvasRenderingContext2d contient un tableau d'entiers de 8 bits de .. 6400 entrées! Pourquoi autant? Chaque pixel est représenté par quatre entiers: la composante R, G, B, et la composante alpha, qui gère la transparence du pixel.
Admettons. Maintenant, aventurons-nous un peu plus sur le chemin de la réflexion. On veut pouvoir avoir autant de couches que nécessaire. On va donc devoir itérer sur chacune de ces couches, les lier en une seule couche, en associant tous les entiers dans chaque tableau ? On aura donc n * 6400 itérations de tableau pour notre image de 40x40 pixels, où n est le nombre de couches! Hors de question d'aboutir à ça! (Surtout que mon échiquier fait 480x480 pixels...)
Alors comment faire? Après quelques minutes de réflexion, il sera bien plus efficace d'utiliser des canvas créés en JavaScript pur, qui ne seront jamais dans le DOM. On va donc définir un objet JavaScript, judicieusement appelé Layer, qui représentera une couche de notre canvas. On définit également un objet MultiLayerCanvas, qui est construit en lui passant la largeur, la longueur du canvas en pixels, ainsi que le nombre de couches. Il suffit ensuite de redéfinir, au niveau de notre objet MultiLayerCanvas, des fonctions réimplémentant les fonctions standards du CanvasRenderingContext2d, à la seule différence qu'elles prendront l'index de la couche en paramètre supplémentaire.
Très bien, mais quid du rendu? Pour ce faire, on associe le canvas de sortie (celui qui est dans le DOM) à notre MultiLayerCanvas, et on dessine nos couches successivement dans son contexte. Pour comprendre pourquoi ça fonctionne, il faut s'intéresser à CanvasRenderingContext2d.globalCompositeOperation. Cette propriété définit la façon dont les appels à CanvasRenderingContext2d.putImageData, CanvasRenderingContext2d.drawImage et d'autres insèrent leurs tableaux d'octets dans celui du canvas de sortie. La documentation Mozilla est particulièrement claire à ce sujet, je vous y renvoie donc ici. La valeur par défaut de cette propriété est source-over, qui signifie que chaque ajout de pixels se fait en remplacement des anciens. Seuls les pixels transparents qui sont ajoutés ne modifient pas les pixels d'origine. Ainsi, il nous suffit d'ajouter les différentes couches de notre MultiLayerCanvas de la première à la dernière. Voilà, notre canvas est affiché!
Voici le code auquel j'ai abouti: https://gist.github.com/Warpten/5543530
(@Zephyr: Le bouton "code" est cassé sur les blogs
Quelques remarques:
- Les 3/4 des fonctions de MultiLayerCanvas ne sont pas error-prone, car aucune vérification n'est faite sur les index des couches. Le but est simple: accélérer autant que possible.
- Ce code a été écrit il y a quelques minutes, en quelques minutes, il n'est donc pas exempt de bêtises et éventuelles redondances. En l'état, il fonctionne, et remarquablement bien (Je prépare un benchmark en ce moment, il sera disponible en commentaires).
À vous!
P.S.: Comme promis, le jeu d'échecs est disponible ici. La connexion peut être lente (Cloud9 n'est pas un serveur de prod), ne vous laissez donc pas avoir par l'absence apparente de réaction du serveur. Si le code source vous intéresse, il est disponible ici.
Dimanche 21 Octobre 2012
Exe & DLL unpacking
Alors ouais ... Aujourd'hui, un petit problème chiant, comment unpacker une DLL pour la reverse... Eh ben en fait c'est pas tellement difficile.
D'abord, c'est quoi l'(un)packing ?
L'unpacking d'un exécutable c'est utilisé quand le fichier à reverse engineer a sa table d'importation est détruite, et que certains segments du binaire sont ... moches.
En général quand on regarde la table d'imports tout de même, on voit trois références à des fonctions kernel32.dll, à savoir LoadLibraryA, GetProcAddress et ExitAddress. Ces fonctions sont utilisées par le packer pour décompresser l'exécutable à l'exécution.
Alors vous allez me dire que c'est bien mais comment on obtient un listing ASM correct et compréhensible ?
Pas compliqué. IDA intègre un plugin appelé "Universal PE Unpacker" (PE signifie Portable Executable) L'idée, c'est de lancer le programme cible, de réaliser une capture de son code en mémoire et de vous le fournir.
Après ça, le listing ASM généré est parfaitement compréhensible. Il se peut que certains segments soient tout de même ignorés, mais l'essentiel du programme est sous vos yeux.
Bon alors maintenant, comment on unpack une DLL ?
Simple: On modifie son header PE pour la transformer en un bête fichier exécutable. On le charge dans IDA, on lance le plugin, et voilà le travail. C'est bête, et ça fonctionne très bien.
De nombreux outils permettent de manipuler les headers d'exécutables / DLLs / autres possédant un header PE. Une simple recherche sur google vous renverra vers divers logiciels payants, mais pas besoin de très perfectionné. LordPE suffira (Ici).
Un billet assez court, peut-être pas assez développé. Juste histoire de me garder le cerveau frais.
(Comment ça, j'ai changé de pseudo?
)
D'abord, c'est quoi l'(un)packing ?
L'unpacking d'un exécutable c'est utilisé quand le fichier à reverse engineer a sa table d'importation est détruite, et que certains segments du binaire sont ... moches.
En général quand on regarde la table d'imports tout de même, on voit trois références à des fonctions kernel32.dll, à savoir LoadLibraryA, GetProcAddress et ExitAddress. Ces fonctions sont utilisées par le packer pour décompresser l'exécutable à l'exécution.
Alors vous allez me dire que c'est bien mais comment on obtient un listing ASM correct et compréhensible ?
Pas compliqué. IDA intègre un plugin appelé "Universal PE Unpacker" (PE signifie Portable Executable) L'idée, c'est de lancer le programme cible, de réaliser une capture de son code en mémoire et de vous le fournir.
Après ça, le listing ASM généré est parfaitement compréhensible. Il se peut que certains segments soient tout de même ignorés, mais l'essentiel du programme est sous vos yeux.
Bon alors maintenant, comment on unpack une DLL ?
Simple: On modifie son header PE pour la transformer en un bête fichier exécutable. On le charge dans IDA, on lance le plugin, et voilà le travail. C'est bête, et ça fonctionne très bien.
De nombreux outils permettent de manipuler les headers d'exécutables / DLLs / autres possédant un header PE. Une simple recherche sur google vous renverra vers divers logiciels payants, mais pas besoin de très perfectionné. LordPE suffira (Ici).
Un billet assez court, peut-être pas assez développé. Juste histoire de me garder le cerveau frais.
(Comment ça, j'ai changé de pseudo?
Dimanche 23 Septembre 2012
À nouvelle CSS, nouveau nom !
Bon bha voilà... Nouvelle CSS, nouveau nom, nouvel an
Si quelqu'un saurait me dire pourquoi les pseudo-classes :odd et :even ne fonctionnent pas sur les div.date et div.news, je suis preneur, ca m'énerve.
@Bovido: et de une!
Si quelqu'un saurait me dire pourquoi les pseudo-classes :odd et :even ne fonctionnent pas sur les div.date et div.news, je suis preneur, ca m'énerve.
@Bovido: et de une!
Dimanche 16 Septembre 2012
Le comeback
Bon ca fait deux ans qu'j'ai rien posté ici. Alors ... (re)bonjour.
Au programme: diverses choses mais dans la grande majorité on va causer un peu de reverse engineering (Ouech comment ça fait pro) sur World of Warcraft. Un peu de développement Web aussi, j'ai pas mal évolué sur ce genre de trucs même si mes codes deviennent assez vite moche quand il s'agit de gros projets, et du C, C++, sans oublier les joies des cours à la fac.
La skin arriver d'ici quelques jours, je cherche un thème qui me plaît.
Au programme: diverses choses mais dans la grande majorité on va causer un peu de reverse engineering (Ouech comment ça fait pro) sur World of Warcraft. Un peu de développement Web aussi, j'ai pas mal évolué sur ce genre de trucs même si mes codes deviennent assez vite moche quand il s'agit de gros projets, et du C, C++, sans oublier les joies des cours à la fac.
La skin arriver d'ici quelques jours, je cherche un thème qui me plaît.
Samedi 11 Septembre 2010
On déménage !
Je suis auteur sur un autre blog, donc je vais déménager. De toute façon ce blog ne fera et n'ai jamais fait de tabac.
http://oenix.net
Zou les loulous.
Ah, et pour ceux que ça intéresse, l'article sur les canvas tel que je voulais le faire est dessus et complet.
http://oenix.net
Zou les loulous.
Ah, et pour ceux que ça intéresse, l'article sur les canvas tel que je voulais le faire est dessus et complet.
Lundi 06 Septembre 2010
HTML 5 : Canvas et joie ( 1 / 2 )
Dites donc, le dernier billet date un peu ...
Comme je n'ai pas envie de tout dépoussiérer maintenant, je vais ranger l'article après le lien suivant ce « paragraphe ». Je vais juste, comme vous le devinez, vous parler des canvas en HTML5 et des formidables (oui, vous avez bien lu) applications qui en découlent.
Accrochez vos ceintures !
Comme je n'ai pas envie de tout dépoussiérer maintenant, je vais ranger l'article après le lien suivant ce « paragraphe ». Je vais juste, comme vous le devinez, vous parler des canvas en HTML5 et des formidables (oui, vous avez bien lu) applications qui en découlent.
Accrochez vos ceintures !
Jeudi 22 Juillet 2010
JS et opacité, une belle histoire
J'me suis rendu compte que ça faisait une plombe que j'avais pas écrit de billet ici (et en fait, aucun billet constructif, dans le lot \ò ). J'était probablement trop occupé par du codage .... <o/. Parlons-en tiens ....
Dimanche 30 Mai 2010
Bah tiens
Avec un peu de retard ... Ça y est, je suis légalement responsable de mes actes. Yeah ! A moi la plage, l'eau, le sexe et les nanas ! les joies des évènements nocturnes et la future vie d'étudiant trépidante dans un taudis sans nom au cœur de Montréal, sans compter les joies des partiels et autres examens du même acabit ...
Samedi 01 Mai 2010
Rubik's Solve
Bon, comme j'me sens plus de faire le Rubik's Cube, je vais vous expliquer la méthode. Je sais, y a déjà des tas de sites qui les expliquent, mais j'espère être le plus clair possible.
Mardi 13 Avril 2010
Dimanche 04 Avril 2010
Joyeuses Pâques !
J'vais pas vous filer de chocolat, ou des oeufs, mais trois fonctions mathématiques ^^
Dessinez, sur [-1,0], :
Dessinez, sur [0,√2] :
Dessinez sur [√2, 3-√2] :
Ensuite, placez les points A[-1,0] et B[3-√2,0].
Joyeuses Pâques !
Le rendu © The Pro avec PrettyPrint
Dessinez, sur [-1,0], :
Dessinez, sur [0,√2] :
Dessinez sur [√2, 3-√2] :
Ensuite, placez les points A[-1,0] et B[3-√2,0].
Le rendu © The Pro avec PrettyPrint
