Edito

Bienvenue à toi, noble visiteur.

Si tu t'attends à trouver ici des récits épiques passionnants, tu risques d'être déçu.
Si par contre tu n'as rien a faire de tes journées, peut-être ce blog t'aidera-t-il à écouler quelques secondes de ton temps.
Les sujets abordés ici peuvent être divers et variés, mais comme il n'y a qu'un seul rédacteur, il se pourrait que cela ne soit pas le cas.

Bon voyage :D

Dimanche 25 Aout 2013
J'ai toujours du mal avec les "design pattern" et autres trucs tordus…
Franchement, je ne comprends pas cette manie qu’ont beaucoup trop de développeurs de vouloir rendre complexe quelque chose de tout à fait simple.
Je voulais jeter un œil au code de .LESS¹, histoire de voir s’il y avait moyen de bosser dessus et de faire en sorte qu’il puisse parser la dernière version de Bootstrap sans soucis. Le projet ayant l’air de tourner au ralenti, je me suis dit que j’aurai sans doute pu apporter ma petite pierre à l’édifice.

Le projet est hébergé sur Git (bouh :( ) qui a l’air d’être très à la mode de nos jours. (Beaucoup trop à mon gout)
Mais heureusement, la dernière version de Visual Studio incorpore un support « Git pour les débiles profonds », ce qui correspond parfaitement à mes besoins, donc tout se passe bien. À l’ouverture du projet, tout fonctionne nickel… Mais ce fut de courte durée. Voilà déjà que la solution ne compile pas. Il manque des fichiers (AssemblyInfo.cs), et un innocent warning suggère qu’un truc pas très net s’opère dans les fichiers (MSBuild) du projet…

Ben non, voyez-vous, c’eût été trop beau. J’étais vraiment trop bête (y-a-t-il une limite à ma stupidité ?) de m’attendre à ce que la solution se compile en appuyant simplement sur un bouton dans Visual Studio, cela n’aurait sans doute pas été très Pro… #gol#
En fait, pour compiler la solution, il faut utiliser un sombre outilscript du nom de PSake. Apparemment c’est un truc hype qui fait la même chose que MSBuild mais différemment (basé sur PowerShell au lieu de fichiers xml), et en moins bien. Mais c’est vachement cool ! #triso#
Donc en gros juste pour le hype je vais aller me faire chier à apprendre à utiliser un outil pour faire quelque chose qui à la base ne nécessite aucun outil ? (Car en plus, cet outil ne fonctionne pas out-of-the-box, il faut taper une ligne de commande PowerShell à la con pour autoriser l’exécution -_-)
C’est bien la peine que Microsoft se soit emmerdé à coder MSBuild, qui malgé sa relative complexité (en réalité, je ne dirais pas que c’est complexe, mais juste assez mal documenté ), est incroyablement simple d’utilisation… Et surtout le standard de facto. Ça permet juste à des mecs visiblement très intelligents (mais pas encore assez) de coder un outil un peu plus compliqué juste pour le principe de le faire. Apparemment se compliquer la vie est une pratique à la mode.

Pas grave, en attendant je vais regarder un peu le code de cette librairie qui, à priori ne devrait pas être trop compliquée. (Oui, ça traite de CSS, mais ça ne nécessite pas pour autant une architecture incroyablement complexe). Quelle ne fut pas ma surprise en constatant le bordel présent dans le projet principal. Plein d’interfaces dans tous les sens, à ne plus quoi savoir en faire, du code totalement impossible à suivre… Mais oui mais oui, c’est de l’inversion de contrôle ! (IoC) #trioui#
Alors la je crois avoir atteint le summum du ridicule. J’ai beau parfaitement comprendre le concept de la chose; c’est vrai que dans certains cas c’est très pratique de rendre l’application modulaire en découplant les différents composants de l’application entre eux… Mais c’est une putain de librairie de parsing CSS ! Quelqu’un peut-il m’expliquer ce qui est passé par la tête complètement tordue de l’auteur pour avoir choisi de mettre de l’IoC partout dans son projet qui n'en nécessite pas un gramme ? :|
Qui plus est, ce n’est pas une des grosses librairie à la mode (je n’arrive pas à savoir si c’est un mal, ou un bien, d’avoir évité une de ces usines à gaz…), mais un truc obscur codé par celui qui l’a intégré au projet…

Parcourant un peu le code, je tombe sur la classe Logger… Pardon, l'interface ILogger, et après un peu de fouille, sur la classe Logger et ses semblables…
Encore un autre mécanisme totalement inutile, qui n'apporte rien de plus que ce que propose déjà Microsoft en mieux avec Trace et TraceListener
Ça a sans doute été le coup de grâce pour moi, à supposer que le reste n'ait pas déjà été suffisant…

Au final, le code est totalement illisible. Il y a plus de code pour cacher l'exécution du vrai code que de vrai code. À vrai dire je n'ai même pas encore réussi à localiser le vrai code. (Celui qui fait quelque chose de concret…)
L’utilisation d’interfaces de toutes part rend le flux d’exécution du code quasiment impossible à tracer, et la complexité du système de build m’ôte toute envie d’essayer d’aller plus loin…
Je ne suis pas con, avec quelques efforts je pourrais parfaitement comprendre le fonctionnement du code, en connaissance de ces éléments. Mais après le peu j’en aie vu, je n’ai juste même plus envie d’essayer. Je devrais alors apprendre à maîtriser tous ces outils tiers qui n’apportent concrètement rien. Cela n’en vaut pas la peine².

Me voilà un peu frustré³, mais surtout très déçu.

Je crois que j’aurai meilleur temps à recoder un concurrent plutôt que de m'attarder sur ce projet. Mais cela n'est pas sur la liste de mes projets, donc il est plus probable que j'attende que quelqu'un fasse tout le boulot dans un temps fini… Avec un peu d'espoir, cela pourrait toujours arriver.


En tout cas, il ne faut pas s'étonner que "personne" ne contribue à ce genre projets. S'ils passaient moins de temps à la branlette intellectuelle et plus de temps à rendre l'expérience de développement aussi simple que l'expérience d'utilisation, beaucoup de projets iraient dans doute beaucoup mieux.



¹ less c'est cool, et apparemment, c'est un peu à la mode dernièrement. Et .LESS fonctionne en .NET donc c'est mieux que SASS. :p
² C'est surtout que si je passais par là je risquerais de faire gicler beaucoup de lignes de code, mais un refactoring intégral ne serait sans doute pas très conforme à la politique de ceux qui gèrent le projet… #trivil#
³ À la base, mon but était juste d'ouvrir le projet pour voir si les modifications étaient dans mes cordes. Cela impliquait de localiser le vrai code et d'arriver à le compiler simplement. Chose qui s'est avérée impossible. Cela demande trop d'efforts pour peut-être me rendre compte par la suite que pour une raison x ou y, modifier ce code en particulier n'est pas dans mes cordes.
Posté à
16:35
 par GoldenCrystal - | Programmation
Vendredi 28 Juin 2013
Et on remet un peu de couleur…
Vous savez sans doute déjà ce que j'en pense, alors inutile de trop détailler…

Behold the new Visual Studio interface !

En gros, on améliore l'interface en la rendant plus proche de celle de la version précédente… #tritop#

(C'est bien… Enfin, c'est mieux, mais c'est ridicule d'en arriver là… -_-)
Posté à
19:37
 par GoldenCrystal - | Programmation
Lundi 29 Avril 2013
L'art du rendu du texte sous WinRT…
Ceux qui auront déjà eu l'occasion d'utiliser WPF savent sans doute à quel point le modèle de rendu du texte basé sur FlowDocument était puissant…
Nous aurions donc pu nous attendre à un modèle aussi évolué pour nos applications XAML WinRT, mais il n’en est rien.
Nous aurions pu également nous attendre à un modèle similaire à celui de Silverlight… C'eût été bien plus proche de la vérité, mais ce n’est pas encore exactement ça.

Vous ne vous en doutiez sans doute pas, mais le modèle de rendu du texte en XAML/WinRT est… Tout pourri ! -_-

Voyez vous, en Silverlight, il existe deux moyens d'afficher du texte. On peut utiliser TextBlock ou RichTextBlock. La différence entre les deux vient du type des éléments qui sont directement dontenus par le contrôle. TextBlock contiendra des éléments Inline, qui contiendront le texte, tandis que RichTextBlock contiendra des éléments Block, qui seront souvent des Paragraph contenant des éléments Inline. Jusque là, avec WinRT, c'est pareil… (Ce qui semble confirmer que WinRT/XAML est basé sur une version dénaturée de Silverlight)
En Silverlight, on peut définir l’essentiel des propriétés du texte sur le seul élément Run, ce qui rend les éléments Bold, Italic et Underline quelque peu superflus. (Mais pas complètement, car ceux-ci dérivent de Span. Ils contiennent donc plusieurs autres éléments Inline.)
Mais avec WinRT… Vous perdez l’élément Hyperlink. Vous perdez la propriété TextDecorations.
Bref, c’est la fête, quoi… Des fonctionnalités ont été coupées, sans raison logique.

Bien sûr, avec Silverlight, on ne peut pas appliquer de couleur d’arrière plan à une plage de texte, vous vous doutez donc bien qu’avec WinRT/XAML, on ne peut pas non plus ;)



Je me permet un petit aparté pour vous laisser comparer le niveau de la documentation Silverlight/.NET 4.5 avec la documentation « Windows APIs »
Cela laisse rêveur, n'est-ce pas ?



Pour résumer où nous en sommes pour l'instant, WPF avait un système de rendu de texte tellement évolué (je n'ai pas jugé utile de détailler ici) qui a servi de référence à ce qui a été fait pour Silverlight. (Bien que similaires sur de nombreux point, les deux API ont été développés séparément #triso# )
Et l'API de Silverlight a été plus ou moins repris au cœur de WinRT pour donner ce qu'on a aujourd’hui avec les applications « natives » (non HTML5/JS) pour Windows 8.

N'existe-t-il pas au moins un truc qui puisse afficher du texte de manière convenable là dedans ? Réfléchissons y bien… Oui, il y a un truc. Il y a WebView, autrement dit internet explorer…
Oui, internet explorer, c'est bien, mais c'est complètement overkill si vous voulez afficher quelques caractères avec des couleurs et des polices variées. En plus, il y a des problèmes de partage de surface de rendu à gérer… WebView sera toujours par dessus XAML donc il faut le masquer au bon moment et le remplacer par une image statique de lui-même…


À ce moment là, vous devriez commencer à comprendre que les applications de base de Microsoft sont toutes codées en HTML5/JavaScript, et que si vous voulez faire une application un peu évoluée, vous allez peut-être être contrait de coder dans ce HTML5/JS bâtard basé sur une partie des API WinRT… (Ça n'a pas grand chose à voir avec du HTML5/JS basique en réalité, il y a donc beaucoup d'apprentissage malgré tout)

Car oui, au moins, vous aurez un moteur de rendu digne de ce nom. Qui ne vous contraindra pas de manière arbitraire. Vous aurez avec vous la puissance des CSS. Sentez-vous comme moi que Microsoft a réellement envisagé, l'espace d'un instant, de totalement évincer le développement de vraies applications sur son système Windows 8 ? La qualité de la réalisation des API laisse fort à y penser. On est très loin du niveau habituel de Microsoft.

Quoi qu'il en soit, il était nécessaire de fournir une API native. Pour permettre aux développeurs de s'exprimer en C++ avec DirectX, il fallait que le système soit utilisable. C'est peut-être là où les API sont *potentiellement* intéressants. En se basant sur ce qui a été fait pour WPF mais pas pour Silverlight, Microsoft a permi de faire interagir le moteur XAML avec un rendu personnalisé DirectX.
Ne vous faites pas d'illusions à ce sujet, c'est quand même diablement compliqué à mettre en place, surtout quand on y combine la gestion d'erreurs « super informative » de WinRT/XAML. Mais c'est possible, et vous devriez vous en sortir en suivant à la lettre le quelques rares exemples qui existe.

D'ailleurs, voilà peut-être une solution pour supplanter le rendu de texte tout pourri de WinRT… Pourquoi ne pas utiliser DirectWrite comme le fait lui-même Internet Explorer… ?
Avec un peu d'aide de SharpDX, on peut s'en sortir en C#… Ça semble quand même un peu overkill pour un simple rendu de texte.

C'est là qu'on entre dans la partie intéressante qui est de réussir à créer un contrôle XAML avec un rendu Direct2D qui fonctionne de manière raisonnable. (Ne bouffe pas toute la mémoire et tout le CPU de la machine)

Et là, les API d'interopérabilité XAML/DirectX ont le mérite d'exister, mais là encore, c'est diablement complexe à mettre en place. Vous serez certainement obligé de coder vous-même une surcouche aux API pour pouvoir les utiliser correctement, car en l'état (de base), ils ne présentent aucun intérêt…

Je reviendrai sur les détails une prochaine fois, mais voilà encore un truc frustrant.

Oui, en fait, WinRT/XAML est frustrant. C'est exactement ça…
Posté à
02:23
 par GoldenCrystal - | Programmation
Samedi 12 Mai 2012
Tout espoir n'est pas perdu…
Après s'être pris une quantité inimaginable de retours négatifs dans la figure, les développeurs de Visual Studio ont finalement revu leur copie… La couleur est de retour.

Ce n'est toujours pas franchement à mon gout, mais c'est quand même beaucoup moins moche que la première version qu'ils avaient proposé… À part pour la barre de menus.
L'interface est plus claire (le gris était vraiment abominable), et les icônes ont été recolorés en partie.

Même si (pour moi) ce n'est pas encore parfait, il devrait y avoir moyen de travailler avec ça.
Dans l'état des choses je pense qu'il y a peu de chances qu'il y ait de gros changements à présent, et il faudra de toutes façons s'en contenter…

En tout cas, nous avons échappé au pire.
Posté à
19:23
 par GoldenCrystal - | Programmation
Lundi 23 Avril 2012
Implémentations privées d'interfaces
Zephyr pose une question très intéressante, qui est de savoir pourquoi l'implémentation de IConvertible est privée. (puisque c'est de ça qu'il est question)

Comme on peut s'en douter, cela est forcément issu d'un choix délibéré de design de la BCL.
En effet, contrairement à Java ( :p ), .NET permet d'implémenter chaque méthode d'une interface de manière explicite. C'est à dire, de manière privée.
Le choix est laissé à celui qui implémente l'interface, de présenter ou non les méthodes de l'interface dans l'interface publique du type.
Cela permet par exemple d'implémenter simultanément plusieurs interfaces qui implémentent une méthode avec le même nom et la même signature, sans nécessairement avoir à provoquer un conflit.
(On peut par exemple citer IEnumerable et IEnumerable<T>)

L'intérêt peut aussi être de ne pas montrer les méthodes qui ne sont pas (encore) implémentées ou pas supportées. (Par exemple, une collection en lecture seule n'a aucune raison de supporter les méthode Add et Remove…)

On retrouve des interfaces implémentées de manière privées à de nombreux endroits dans le framework.


Avant de regarder du côté de IConvertible sur les types primitifs, je propose d'aller regarder du côté de System.Array.
Là aussi, on voit que le type implémente un certain nombre d'interfaces, dont les membres ne sont pas nécessairement visibles publiquement.
Par exemple IList.Remove est implémentée de manière privée. Sur le type System.Array, ça n'aurait aucun sens. Un tableau a une taille fixe, donc on ne peut pas supprimer un élément. Aussi, si on appelle IList.Remove sur un tableau, nous aurons droit à un joli NotSupportedException.
Plus intéressant encore, le type Array implémente aussi IList<T> au runtime, en fonction du type des éléments du tableau.
Pour autant, on ne verra pas apparaître un seul des membres de IList<T> (la version générique de IList) lorsqu'on écrira le code. En revanche, ils seront parfaitement accessibles si je cast par exemple un string[] en IList<string>.


Ce qu'on peut remarquer, pour un tableau unidimensionnel, c'est que la propriété Count de IList<T> fait double emploi avec la propriété Length de Array. (Hé oui, hé oui… Je trouve ça un peu con d'avoir appelé ça de manière différente à deux endroits, mais c'était probablement pour que le Array de .NET soit compatible avec celui de Java :( )

Pour accéder à un élément sur IList<T>, je vais utiliser l'indexeur IList<T>.Item (le seul indexeur possible en C#), qui, comme n'importe quelle propriété, sera utilisé de manière interne à l'aide de deux méthodes IList<T>.get_Item(int index) et IList<T>.set_Item(int index, T value).

Dans le cas d'un tableau unidimensionnel, on utilise traditionnellement tout un ensemble d'opcodes CIL qui se nomment ldelem, ldelem.i4, etc. ou ldelema en fonction du type des éléments contenus dans le tableau.

De même, l'opcode ldlen est utilisé en lieu et place d'un appel à la propriété Length, pour accéder à la longueur d'un tableau.
Cela sera bien évidemment toujours plus rapide que de passer via une interface.


En fait, si on y regarde bien, on se rend compte que la plupart des fonctionnalités implémentées par les interfaces de System.Array (et ses dérivées) sont accessible directement, avec peu, sinon aucun effort, en utilisant l'interface naturelle du type.
Dans le cas de System.Array, les interfaces implémentées, permettent de passer un tableau comme une liste (générique ou non), ou comme un objet comparable de manière structurelle (c'est nouveau en .NET 4.0, je n'ai pas encore eu l'occasion de m'en servir).

Ce qui compte au final, ce n'est pas de passer un Array en sachant un IList<T>, mais de passer un IList en ne sachant pas que c'est un Array. (PS: Je parle de System.Array ici, mais c'est en réalité une classe abstraite dont toutes les implémentations concrètes sont fournies au runtime)
En effet, si je sais déjà que mon objet et un tableau, alors j'ai tout à y gagner à utiliser directement ce tableau, sans jamais passer par une quelconque interface. De cette manière, toutes les opérations sont plus simples, et le compilateur peut alors utiliser les instructions CIL natives pour accéder à des éléments ou connaître la longueur du tableau. Je pourrais aussi utiliser toutes les méthodes statiques implémentées par la classe Array, comme par exemple Array.Sort.


Et bien, pour IComparable, il en va de même. La interface définit plusieurs méthodes de conversion. Soit.
Si nous partons du postulat de base, où connais le type de données primitif sur lequel je travaille… Ce qui est en général le cas.
Dans ce cas je n'ai pas besoin de TypeCode.
Si je sais que je travaille avec un Int32, alors je sais par avance que TypeCode est TypeCode.Int32.
De même si je travaille avec System.String, alors je sais par avance que TypeCode est TypeCode.String.
Et ainsi de suite. Bref, cela ne me set à rien.

Si je veux convertir n'importe quel type primitif en chaîne de caractères, la émthode .ToString() est là pour moi (S'il vous-plaît, n'oubliez jamais de fournir le paramètre CultureInfo lorsque c'est possible (et nécessaire)).
Si je veux convertir une chaîne de caractères en un type primitif connu, je peux utiliser la méthode statique .Parse de ce type.

Et si je veux convertir une valeur numérique en une autre, il y a là également toute une petite famille d'opcodes CIL qui servent à la conversion (cast en C#) d'un type primitif vers un autre.
C'est toute la famille d'opcodes conv, avec conv.i4 et ses amis, qui permettent de convertir un type numérique en un autre. Il y a juste une exception pour le type Decimal, qui est un cas à part (le pauvre :( ).

D'autre part, on pourra remarquer un détail intéressant qui est que Double.ToInt32 ne retourne pas nécessairement le même résultat qu'un cast bête et méchant (et rapide) de double vers int en C#.
La méthode Convert.ToDouble procède en effet à un arrondi afin de minimiser les différences visibles du nombre malgré son changement physique de format. (Si vous aviez 15,5 formaté en "16" quand c'était un double, vous aurez 16 formaté en "16" quand ça sera un int…)

Au final, tout ce dont je peux avoir besoin est déjà fourni par le système de types basique, je n'ai donc pas besoin des méthodes de IConvertible, quand j'agis sur une valeur dont je connais déjà le type.
Comme pour les tableaux, ce n'est pas tant d'utiliser un type primitif en sachant que c'est un IConvertible qui est intéressant, mais passer un IConvertible en ne sachant pas si c'est un type primitif ou n'importe quel autre type.


En soi, les méthodes d'IConvertible sont plus encombrantes et aptes à porter confusion qu'autre chose, et il est à mon avis fort heureux qu'elles aient été cachées.




En annexe, j'indiquerai qu'effectuer un cast en IConvertible sur un type primitif (ou plus généralement, caster n'importe quelle valeur d'un type valeur vers une interface implémentée par ce type), peut potentiellement provoquer un boxing explicite de la valeur, ce qui est peu désirable si l'on veut obtenir un code performant.
Posté à
23:45
 par GoldenCrystal - | Programmation
Vendredi 20 Avril 2012
System.Convert, c'est génial, mais c'est mal
Mieux vaut tard que jamais, alors voilà un sujet sur la programmation. Comme aujourd'hui je suis un peu triste du fait que Bakuman soit terminé, je vais me changer les idées en rédigeant ce post que je songeais à écrire depuis un certain temps.
Comme à mon habitude, c'est écrit en freestyle (ce qui me prends déjà suffisamment de temps), donc je vais juste espérer que ce soit écrit à peu près convenablement.
Vous pouvez sauter la première moitié du post si vous êtes déjà bien familier avec .NET (Et désolé pour le post un peu long :p )

Donc, voyez-vous, il existe en .NET, une super classe appelée Convert.
Cette classe possède des méthodes permettant de convertir un objet en un type primitif, et c'est vraiment bien pensé. Comme beaucoup de choses en .NET d'ailleurs.
Posté à
00:09
 par GoldenCrystal - | Programmation
Lundi 13 Juin 2011
CrystalBoy reloaded
Il y a quelques semaines, je me suis aperçu que mon émulateur ne fonctionnait plus ( #eek# ) sur Windows 7… Parce que Microsoft n'a jamais fait de version 64 bits de Managed DirectX.

Je me suis donc un peu replongé dans le code et j'ai ajouté un rendu avec SlimDX qui lui au moins supporte le 64 bits. #oui#
Puis, pour ne pas m'arrêter en si bonne route, j'en ai profité pour nettoyer un peu le code, utiliser des template T4 pour générer le code auto-généré à la place de la méthode artisanale que j'utilisais auparavant.

Du coup, mon code se modifie plus facilement, et ça m'a permis d'améliorer l'émulation CPU. Apparemment il y a certaines instructions que j'émulais mal (dont l'immonde DAA… Mais maintenant il fonctionne parfaitement… Et en à peine quelques lignes :) ), soit parce qu'elles donnaient le mauvais résultat (assez rare) soit parce que les flags étaient mal émulés. (mais il n'y en avait pas tant que ça non plus)

Pour ne pas m'arrêter en si bon chemin, j'ai corrigé plusieurs défauts (visibles) au niveau de mon rendu vidéo, et corrigé plusieurs bugs par-ci par là.
J'ai aussi ajouté une méthode de rendu utilisant Direct2D, et qui pour l'instant est supérieure aux autres. (Ouais bon hein… c'est comme ça et puis c'est tout ! :p )
J'ai même réussi à corriger mon implémentation du RTC (qui en fait ne fonctionnait pas du tout à cause d'un bug qui se trouvait ailleurs, mais qui n'aurait de toutes façons pas bien fonctionné tel quel), et j'ai fini par implémenter les fichiers de sauvegarde (.sav) permettant de charger et sauvegarder la RAM sur batterie de certains jeux.

img
KIRBYXXL permet de vérifier que la priorité des sprites est bien respectée…


…Oui bon, j'aurai pu le faire avant, certes, mais là je l'ai fait dans les règles ! Grâce à un mécanisme astucieux (enfin, je pense :p ), il est possible de détecter lorsque des changements ont été effectués dans la RAM de sauvegarde, avec un coût moindre niveau performance.
En fait, pour accéder à la RAM externe, les jeux doivent tout d'abord activer celle-ci, puis la désactiver une fois qu'ils ont fini de faire leur boulot. Une implémentation se basant uniquement sur les désactivations pour sauvegarder la RAM sur le disque fonctionnerait parfaitement (c'était ma première implémentation, pour au moins vérifier que ça fonctionnait), mais cela génère énormément d’écritures inutiles sur le disque, car la RAM peut être activée et désactivée plusieurs fois par seconde.
La solution est de placer un gestionnaire d'écritures sur la RAM à chaque activation. Cela ne ralentit en aucun cas les accès en lecture, mais à la première écriture sur la RAM, le gestionnaire est appelé et note que la RAM a été modifiée (que ce soit vrai ou non… je pourrais encore améliorer la détection), puis le gestionnaire se désactive.
Une fois la RAM désactivée, il suffit de vérifier l'information produite par le gestionnaire pour savoir si la RAM a été modifiée, et le tour est joué. :)

Bon, et on en profite aussi pour sauvegarder l'état RTC lorsque c'est nécessaire… ;)

Mais encore mieux, j'ai ajouté l'émulation du "BIOS" de la Game Boy (enfin des 3 ROM qui ont été dumpées)
Après quelques recherches google, j'ai appris que le BIOS GBC avait été dumpé… Mais que celui de la Super Game Boy et de la Game Boy classique 'lavaient été aussi…

Ayant toujours été curieux de voir comment fonctionnait la chose sur une GBC, je me suis donc plongé dans le code désassemblé par un certain Duo, ce qui m'a permis de comprendre le fonctionnement caché d'une GBC, et d'améliorer un peu mon émulation.

J'ai attendu d'avoir complété le support des fichiers de sauvegarde (.sav) pour m'y attaquer sérieusement, mais à présent, j'ai ajouté le support pour la ROM de démarrage.

La ROM de la GBC est la plus intéressante puisqu'elle manipule beaucoup plus de choses que celle de la Game Boy N&B. On apprend quelques petites choses sur les registres cachés qui permettent de basculer la Game Boy en mode "noir et blanc". (Qui n'en est pas vraiment un vu qu'il y a quand même des couleurs)
À la fin de l'exécution de la ROM, si le test du logo Nintendo est validé, celle-ci se désactive et fait place au code du jeu inséré. C'est à peu près la seule chose commune entre la version noir et blanc et la version couleur :p

Mais le plus important est que ça fonctionne:

img
Woohoo…

img
img
The Legend of Zelda: Link's Awakening, avec sa palette de couleurs… spéciale…

img
Les couleurs sont étranges, mais ce n'est pas moi qui les ai choisies !


L'avantage d’utiliser le "BIOS" est qu'il permet d'avoir ces "magnifiques" palettes couleur sur les jeux originellement en noir & blanc. Mais j'ai prévu d'émuler la détection des palettes, afin de pouvoir s'en passer… :)

Bon voilà, il y a encore des petits bugs à corriger, mais comme d'habitude, il manque surtout le son. (#flemme#)

En tout cas, j'ai beau avoir repris ce code après presque 3 ans, je n'ai eu aucun mal à me souvenir de son fonctionnement, malgré la quantité de commentaires assez faible… Comme quoi :p
Posté à
16:28
 par GoldenCrystal - | Programmation
Dimanche 13 Février 2011
Hmm…
J'éditerai sans doute ce post pour le remettre plus en forme par la suite
J'ai commencé à creuser du côté de ASP.NET après mon avant dernier post (en fait, même avant, mais j'ai fait une pause entre deux… ^^)
D'ailleurs entre temps, ASP.NET MVC 3 est sorti j'y ai donc jeté un coup d'eil, c'est assez intéressant…
J'ai passé pas mal de temps à me documenter, donc, et à chaque fois je découvrais les possibilités intéressantes de ASP.NET. Et en même temps, ça me permettait de réfléchir à la manière dont je voulais faire ce que j'avais en tête.
Ayant un peu l'habitude du développement Web, j'avais déjà mon schéma de bases de données tout chaud dans la tête, qui a été assez rapide à transcrire en base de données SQL. (D'ailleurs à ce propos, l'outil MySQL Workbench est vraiment génial, je vous conseille de le tester si vous n'en avez jamais eu l'occasion)
Une des choses qui est assez standard en ASP.NET, c'est d'utiliser un ORM. Déjà là ça coince, il existe un milliard de solutions différentes… (Bon j'exagère, je sais :) ) Le choix naturel est à priori le Entity framework de ADO.NET qui est la solution Microsoft, et qui est sensé remplacer le « très célèbre » Linq To SQL (Hé oui, à peine sorti, il était déjà obsolète). Mais Entity framework n'est pas géré par Mono. Supposons que je veuilles utiliser Mono, il faudrait que je me tourne vers NHibernate.
Donc là le problème devient EF vs NHibernate, le consensus général est que EF pue des pieds et que NHibernate déchire sa mère (apparemment), mais pas trop quand même. Avoir des détails sur ce que ça changerait de mon côté ou non, en dehors de cela, c'est quasiment impossible.

Du côté de NHibernate, aussi adoré soit-il, soyons clair, on voit clairement que ça n'a pas été fait pour du .NET (Oui si j'ai compris, et ça se voit de toutes façons dans la manière de l'utiliser, c'est un portage de Hibernate). Cette solution est la préférée en partie parce qu'elle repose sur une base solide qui fonctionnait très bien sur une plateforme similaire à .NET, mais quand même très différente… (Je vous rappelle que C# a tout un tas de fonctionnalités cool qui sont là depuis le début comme les Attributs, tandis qu'en Java cela a été ajouté bien plus tardivement…)
Bref, c'est compliqué à mettre en place, non trivial d'utilisation et ça s'intègre mal dans le langage. De mon côté, je trouve ça vraiment très crade. Et comprenez mon point de vue, le code source de NHibernate est peut être très propre, mais NHibernate en lui-même, est une solution crade. Il y a des alternatives à la configuration XML chiante, mais elles-mêmes ne sont pas bien fichues. Bref, poubelle.

Tenant compte de mon expérience avec Mono, je sais de toutes façons qu'il est largement moins performant que .NET.1, donc j'ai fini par éliminer l'éventualité d'utiliser mono un jour, et je me suis tourné de nouveau vers Entity Framework. L'outil est assez simple d'utilisation, il y a des connecteurs pour MySQL et tout un tas d'autres SGBD (qui sont fournis par les vendeurs bien sûr… D'ailleurs les extensions MySQL pour Visual Studio sux un peu au niveau de la conception, mais SQL Workbench est là :) ). Bref, pour mettre en place une base de données standard, cela ne pose pas trop de problèmes et le mapping se fait assez bien. On a la possibilité de concevoir la base de données à l'avance, ou bien de concevoir les objets d'abord (avec EF CodeFirst) et laisser le système mettre ne place la BDD (c'est assez prometteur… Et au pire cela ne fait que ralentir le temps de démarrage, cela dit je ne suis pas très chaud pour utiliser un truc de ce type en production sur un site web… ^^).
Mais forcément, Entity Framework, dans sa conception, a une vision assez limitée de ce qui est faisable, et mon schéma de données, non simplifiable (Dans sa déjà très grande simplicité… Je déteste faire compliqué là où je peux faire simple… ), ne pouvait être mappé simplement… Pour les utilisations avancées, on peut accéder directement au fichier XML de mappings et faire tout à sa manière (mais du coup de ce côté là ça ne vaut plus mieux que NHibernate… Sauf que ça reste quand même mieux…2) On a même la possibilité de modifier la génération des mappings en écrivant des template (T4) soi-même. Chose sur laquelle je ne suis même pas vraiment penché, ayant éliminé EF avant de pouvoir en avoir eu besoin.

La conclusion de tout cela est que… Ah non il est encore trop tôt pour en arriver là ! ;)
Une des choses qui m'a gêné tout le long dans le fait d'utiliser un ORM, c'est que l'on a quasiment aucun contrôle sur les requêtes3, et quand on l'a, c'est de manière carrément crade et non objet. Et je n'ai jamais vraiment trouvé de sources lisible clairement qui aurait pu m'amener à croire le contraire (donc par défaut…)
Simultanément à ces recherches, je réfléchissais bien évidemment à d'autres choses (C'est fou ce que le cerveau est bien parallélisé…4, 5), ce qui m'a donc amené à comprendre ce qui me gênais tout ce temps. En fait utiliser un ORM, ça me fait chier. Profondément. Enfin, plus exactement, ce qui me fait chier, c'est qu'on objet ne représente absolument pas ce que j'attends de la base de données. La conclusion de cela, c'est qu'en fait, je n'ai pas besoin d'un ORM. Ouah, tout ce temps perdu pour rien…
Parallèlement à cela, j'ai aussi réalisé que la couche données serait le point central de ce que je voulais faire (enfin je le savais déjà mais il fallait que je l'exprime d'une manière différente, que je ne vous transcrirai pas ici :p ), et que si facteur limitant il doit y avoir, cela sera la couche données bien avant le reste… En fait je n'avais donc vraiment pas besoin d'objets, et certainement pas d'un ORM !
Pour finir, le point le plus important de tout cela concerne ASP.NET MVC 2+. De tout ce que j'ai pu en voir, c'est un framework vraiment bien conçu. Il rend très simples (et propre au niveau du code !) les tâches habituellement rébarbatives lorsque l'on utilise un langage comme PHP, ce qui est vraiment un bon point positif. Il rend également très simple certaines tâches compliquées, comme les accès à la base de données et la gestion des utilisateurs (que l'on utilise ou non un ORM, le plus simple pour cela étant d'utiliser la configuration de base pour SQL Server, mais MySQL fournit aussi son implémentation équivalente). Et puis le nouveau moteur Razor (cshtml) déchire vraiment. En revanche, derrière ces fonctionnalités bien complètes (regroupant les besoins de la majorité des sites Web, soyons réalistes ;) ), si l'on veut dévier du comportement standard pour faire les choses un peu (ou totalement) différemment, il faut tout de suite écrire du code plus compliqué qui se penche sur les détails internes de la technologie… (Ça reste toujours très flexible ^^)
Au final, je me suis rendu compte que par rapport à PHP, je n'y gagne pas forcément. Comprenez moi bien, encore une fois, j'adore .NET et le C#, mais en ASP.NET, c'est juste utiliser du C# pour utiliser du C#, les fonctionnalités intéressantes du C# (celles qui le distinguent vraiment d'un autre langage) ne servent quasiment à rien… Si vous voulez, c'est même utiliser de l'objet pour utiliser de l'objet… Comme en PHP. (Oui, je n'ai jamais compris l'intérêt des objets en PHP6, mais si quelqu'un veut un jour me l'expliquer il est le bien venu…)
En PHP, il faut peut-être écrire toutes les fonction à chaque fois (si possible de manière propre, pitié :D ), et rédiger le comportement de la page de A à Z, mais la difficulté d'écriture du code est linéaire. Il n'y a pas de tâche plus facile qu'une autre. Par contre le langage est vraiment crade (il manque des types int32 et int64…) et il faut bien faire attention à tous les petits pièges qui heureusement commencent à être bien documentés.
Question performance, si le facteur limitant est la couche données, que j'utilise du ASP.NET ou du PHP ne devrait pas faire différences. En plus, il y a la possibilité d'utiliser HipHop de Facebook si jamais le besoin s'en fait sentir…

En conclusion — et cette fois-ci, c'est la vraie — j'utiliserai du PHP, comme je l'ai toujours fait… Et bien sûr, du MySQL, car la rapidité des requêtes SQL, c'est important ! Bien évidemment pas de clés étrangères, parce que ça pue…7 :p



1. Sur une app que j'avais codée spécialement pour la faire tourner sous OSX (en mode console hein) le temps d'exécution était multiplié par 5 ou plus entre Windows et OSX… Ce qui m'a appris que l'implémentation des tables de hachage sous Mono était loin d'être comparable à celle de Microsoft… Mais pas seulement… ;) )
2. Entity Framework fait de la génération de code statique, contrairement à NHibernate. Les trucs hot-swappable c'est bien gentil, mais dans la pratique, quitte à arrêter un serveur pour le redémarrer avec une config différente, je peux aussi simplement recompiler le code en même temps… -_- Les trucs qui ne vont pas bouger n'ont pas à être générés dynamiquement, merde.
3. Par exemple, si je veux rechercher un utilisateur dans ma base de données, je ne veux pas forcément récupérer son nom de famille, son numéro de sécurité sociale et son adresse à chaque fois… Et inversement, si je veux récupérer son nom de famille et sa date de naissance, j'aimerais bien que ça se fasse en une seule requête… vous savez, histoire d'éviter de diviser les performances par deux…
4. On ne peut pas toujours en dire autant de nos systèmes actuels. %)
5. Ma fonctionnalité préférée, c'est celle qui trouve des réponses simples à des questions compliquées pendant que je suis en train de rêver à des trucs complètement cons… #love#
6. Enfin disons qu'il y a des cas légitimes, mais la plupart du temps, les objets sont utilies pour conserver des informations, une hiérarchie d'objets, en mémoire. Bref, en technologie Web, qui est stateless, et en dehors des librairies (type imagick, mysqli) je ne vois absolument pas l'utilité de créer 50 objets au début de la page pour les détruire à la fin… En ASP.NET ça se justifie un peu plus car on peut conserver des informations en mémoire (c'est ce qui m'avait séduit au départ…) qui seront partagées par tous les thread. Et encore…
7. Oui, conceptuellement, c'est très bien, ça permet d'assurer une intégrité des données forte, mais c'est dans ce cas au prix des performances… Il y a des cas où l'on a pas besoin d'intégrité forte des données (si les tables sont relativement indépendantes des autres… je ne vais pas vous faire un dessin ^^), et même des cas où ça ne peut pas s'appliquer du tout. J'en ai trouvé un, mais peut-être me suis-je penché sur un mauvais design, qui sait… (Mais sérieusement, je ne pense pas…)
Posté à
23:03
 par GoldenCrystal - | Programmation
Vendredi 29 Octobre 2010
Le C# 4.0 fait à peine ses débuts…
On parle déjà de C# 5.0…
http://blogs.msdn.com/b/ericlippert/archive/2010/10/28/asynchrony-in-c-5-part-one.aspx
Dire que je n'ai même pas pris le temps de tester les fonctionnalités de C# 4.0… %)
Bon, il faut dire que je n'en ai pas vraiment l'utilité actuellement. J'avais aussi mis longtemps à utiliser les fonctionnalités de C# 3.0, mais je ne peux à présent plus me passer de var et des méthodes d'extension.
Donc ce qui est annoncé ce sont deux nouveaux mots-clefs async et await… Ça peut vraiment être utile. Je pense déjà avoir une idée d'où utiliser ça quand ça sortira officiellement. ^^
On verra comment tout ça va évoluer d'ici la sortie, mais… #love#

(Ah, si seulement Apple pouvait décider d'adopter le C# comme langage pour remplacer l'Objective-C… :])
Posté à
21:49
 par GoldenCrystal - | Programmation
Lundi 25 Octobre 2010
La subtile différence entre les technologies OpenSource et propriétaires…
Afin de mener à bien un projet de site web que je muris depuis déjà plusieurs mois je me suis récemment mis à réfléchir au choix de technologies le plus adéquat.

Les choix que j'ai considérés au départ étaient les suivants:
- PHP + MySQL (Windows ou Linux, Apache, nginx ou IIS, peu importe…)
- ASP.NET MVC 2 + SQL Server (Windows IIS donc…)

Mettant de côté le prix de mise en place du serveur (j'ai failli poster un topic là dessus, mais ça ne sera sans doute pas nécessaire) il me semble logique qu'une technologie précompilée telle que ASP.NET sera plus efficace au niveau de la montée en charge que du PHP. Il semble n'y avoir aucun test fiable (voire aucun test tout court) sur le sujet, donc tout cela restera à l'état de suppositions fondées.
Le doute étant malgré tout faible dans mon esprit, c'est plutôt la question du prix qui m'a amené à pousser la comparaison plus loin.
Posté à
21:04
 par GoldenCrystal - | Programmation
Lundi 12 Juillet 2010
Monoxide… mais pas de carbone.
J'ai mis du code là http://code.google.com/p/monoxide/ si ça amuse certains de le tester. (GPLv3)
En ce moment j'ai un peu la flemme de bosser dessus, donc ça avançait pas trop. C'est donc un bon moment pour héberger le code ailleurs, et me permet d'assurer une sauvegarde non locale.
Il suffit de OSX, Mono et MonoDevelop pour compiler et éxécuter pour ceux que ça amuserait.
Posté à
22:10
 par GoldenCrystal - | Programmation

 RSS  - ©yNBlogs 2004