Patch binaire MonochromeLib pour Graph 35+E II
Posté le 22/10/2021 17:20
Dépôt Gitea : Lephenixnoir/g35pe2-ml-patch.
Il est bien connu que l'écran de la Graph 35+E II a un protocole différent de ses prédécesseurs, ce qui pose des
problèmes de compatibilité sur les add-ins. Il y a déjà
un outil d'Inikiwi (
dépôt) qui attaque ce problème, mais malheureusement plusieurs cas particuliers lui échappent.
Quand on a les sources :
version Graph 35+E II de MonochromeLib (pas compatible autres SH4)
Cet outil se veut 100% correct, 100% automatique pour tous les patchs de MonochromeLib pour Graph 35+E II. J'espère pouvoir le déployer sur le serveur v5 avec une interface dans le style du SH4 Compatibility Tool.
Instructions d'utilisation
% python g35pe2_ml_patch.py Addin.g1a AddinE2.g1a
Fonctionnalités :
- Détecte les instructions accédant à l'écran via 0xb4000000 et 0xb4010000.
- Détecte précisément les fonctions avec une heuristique (position des rts).
- Indépendant de l'allocation de registres avec un système de pattern matching.
- Indépendant de l'ordre des instructions dans chaque fonction (un peu trop même).
- Détecte et patche ML_display_vram, ML_set_contrast et ML_get_contrast.
Exemple de sortie sur
Evasion Survival. D'abord l'outil cherche la constante
0xb4000000 et les instructions qui la chargent :
% python g35pe2_ml_patch.py ~/Downloads/Evasions{,E2}.g1a
T6K11 reference address b4000000 found at 0x000017d8
0x0000172c: Load into r5
0x00001768: Load into r2
0x00001774: Load into r2
Ensuite il cherche les fonctions à proximité, et une fois les fonctions délimitées il détermine dans quel registre
0xb4000000 et
0xb4010000 sont chargés (s'ils le sont).
Looking for function around 0x0000172c...
Starting at 0x0000171a after rts
Stopping at 0x00001766 after rts
0xb4000000 loaded in r5
0xb4010000 loaded in r4
Looking for function around 0x00001768...
Starting at 0x00001766 after rts
Stopping at 0x00001772 after rts
0xb4000000 loaded in r2
0xb4010000 loaded in r1
Looking for function around 0x00001774...
Starting at 0x00001772 after rts
Stopping at 0x0000177e after rts
0xb4000000 loaded in r2
0xb4010000 loaded in r1
Puis, chaque fonction est testée pour identifier les fonctions connues de MonochromeLib. Ça se fait avec des motifs ; chaque fonction de MonochromeLib a un certain ensemble d'instructions connues. Les motifs recherchent ces constantes tout en laissant de la latitude à l'allocation de registres.
Ici, la première fonction est identifiée comme
ML_display_vram ; vous pouvez voir chaque "Matched" qui correspond à une instruction trouvée. les "<A>" sont des variables du matching, ici on a trouvé A=0xb par exemple.
Les instructions trouvées sont ensuite patchées avec un équivalent compatible Graph 35+E II.
Function analysis for 0x0000171a ... 0x00001766:
Identified ML_display_vram with [D0=5 D1=4 A=b B=1 C=7 D=0 E=3]:
Matched e<A>07 at 0x00001734: eb 07
Matched e<B>00 at 0x00001736: e1 00
Matched e<C>04 at 0x00001738: e7 04
Matched 6<D><B>3 at 0x0000173a: 60 13
Matched e<E>c0 at 0x0000173e: e3 c0
Patching at 0x00001734: eb 07 -> eb 0a
Patching at 0x00001736: e1 00 -> e1 04
Patching at 0x00001738: e7 04 -> e7 08
Patching at 0x0000173a: 60 13 -> e0 00
Patching at 0x0000173e: e3 c0 -> e3 80
Ici les deux autres fonctions sont identifiées comme étant
ML_set_contrast et
ML_get_contrast respectivement.
Function analysis for 0x00001766 ... 0x00001772:
Identified ML_set_contrast with [D0=2 D1=1 A=3 B=4]:
Matched e<A>06 at 0x00001766: e3 06
Matched 2<D0><A>0 at 0x0000176a: 22 30
Matched 2<D1><B>0 at 0x00001770: 21 40
Patching at 0x00001766: e3 06 -> e3 06
Patching at 0x0000176a: 22 30 -> 00 09
Patching at 0x00001770: 21 40 -> 00 09
Function analysis for 0x00001772 ... 0x0000177e:
Identified ML_get_contrast with [D0=2 D1=1 A=3]:
Matched e<A>06 at 0x00001772: e3 06
Matched 2<D0><A>0 at 0x00001776: 22 30
Matched 60<D1>0 at 0x0000177c: 60 10
Patching at 0x00001772: e3 06 -> e3 06
Patching at 0x00001776: 22 30 -> 00 09
Patching at 0x0000177c: 60 10 -> e0 00
Enfin, des statistiques sont affichées. Le script considère le patch un succès si
ML_display_vram a été trouvée et patchée.
References found to b4000000: 1
References found to b4010000: 1
Functions: 3 hints, 3 analyzed, 3 patched
ML_display_vram found: True
Success!
S'il y a des add-ins qui ne passent pas ou des bugs, faites-moi signe. Je maintiendrai le script pour garantir que la conversion soit consistante et instantanée.
Interface graphique
Si le script est lancé sans argument, une interface graphique Tkinter est utilisée.
% python g35pe2_ml_patch.py
Add-ins portés de façon automatique par ce patch
- 10 second run (Dodormeur, 2013)
- 2048 Deluxe (Kirafi, 2014)
- Agenda (Shadow15510, 2018)
- Alien Escape (Dark Storm, 2012)
- Angry Birds (Louloux, 2012)
- Astrobot (Louloux, 2012)
- Bomberman (Dodormeur, 2013)
- Curve Fever (BTL, 2014)
- Dark Laby (Louloux, 2013)
- Evasion Survival (Dodormeur, 2013)
- Fall Down (Darkysun, 2014)
- Flappy Bird (Dark Storm, 2014)
- Fourmizz (TheProg, 2014)
- Fruit Ninja (Dark Storm, 2013)
- FX4K (Chenzhanming, 2021)
- Geometry Dash (Fife86, 2016)
- Gravity Guy (Nitrosax, 2012)
- IPod Dextris (Kirafi, 2014)
- IPod FallBlocs (Kirafi, 2015)
- IPod Graviton (Kirafi, 2014)
- IPod Spin (Kirafi, 2016)
- I Robot (Nitrosax, 2012)
- Jump (Canta, 2013)
- Jump Evolution (Tenmatx, 2014)
- Kirby's Dream Land (Fife86, 2016)
- Man vs. Rocks (P.o, 2012)
- Mario et Sonic (Aragorn, 2015)
- Matris (Casimo, 2013)
- Metro Siberia 2 (Dark Storm, 2013)
- Mipjabok (Louloux, 2013)
- Multitask (BTL, 2013)
- Pac-Man (Fife86, 2016)
- Poke. néphrite (Dodormeur, 2014)
- Pokémon Stadium (Dodormeur, 2013)
- Portal2D (JavierXD, 2012)
- Rainpack (Nitrosax, 2013)
- Runner (Az, 2015)
- Saviors 2 (Dodormeur, 2013)
- SeaRush (Kirafi, 2016)
- Starwars 3D (Louloux, 2012)
- Street Fighter (Fife86, 2015)
- Swing Copters (Az, 2015)
- Test Andropov (BTL, 2012)
- Test Andropov 2 (BTL, 2013)
Fichier joint
Citer : Posté le 11/11/2021 19:11 | #
Pour info pour l'instant ça marche sans souci, je viens d'y passer FX4K (dans lequel ML_display_vram a été trouvé deux fois, je sais pas pourquoi xD) et ça a marché instantanément. Dès que ce sera assez mature je regarderai pour en faire un outil en ligne.
Aoctus Invité
Citer : Posté le 20/11/2021 14:53 | #
Re-bonjour,
J'ai donc téléchargé quelques jeux sur ma Graph 35+E II mais qui n'ont pas fonctionné comme :
- Fruit Ninja
- Angry Birds
- 2048
- Pac Man
- Morpion
- Flappy Bird
- Geometry Dash
(sinon Jetpack Joyride par exemple fonctionne très bien)
J'ai lu plusieurs messages expliquant qu'avec les changements de processeur, beaucoup d'addins étaient incompatibles et c'est donc mon cas... Même en essayant ce site (qui était proposé dans le message d'un administrateur) cela ne fonctionne toujours pas...
Et y'aurait-il un moyen pour que des jeux comme Zelda ou Dragon Ball Z soient compatibles ? Enfin c'est surtout que la calculatrice ne détecte que les extensions .g1a et pas les .g1r.
Merci d'avance pour votre aide et bon après-midi.
Citer : Posté le 20/11/2021 14:59 | #
Bonjour,
Le problème est d'une part le changement de processeur, mais ce changement est maintenant assez ancien. La page dont tu donnes le lien permet effectivement de régler plusieurs problèmes liés au changement de processeur.
Maintenant il faut ajouter à cela un autre problème beaucoup plus récent qui est celui du changement d'écran. Ça peut paraître un peu bête, mais le changement d'écran à rendu obsolète tous les add-ins, et l'outil linké ne patche pas ce problème. Il faut donc utiliser l'outil de Lephé (but de ce topic) ou alors recompiler les sources (souvent impossible, car on ne les a pas).
Pour les extensions en *.g1r, c'est pas trop l'endroit, mais je crois que tu peux simplement changer l'extension à la main en mettant *.g1m à la place…
Citer : Posté le 20/11/2021 15:01 | #
Merci Aoctus. Je m'occupe de patcher ces jeux. Avec un peu de chance ce sera tout automatique. Repasse ce soir !
Ajouté le 20/11/2021 à 18:10 :
Voilà j'ai tout fait sauf Morpion et Pacman pour lesquels je ne vois pas de quel add-in tu parles.
Note que les .g1m et .g1r sont vraiment identiques. Tu dois vraiment pouvoir envoyer les .g1m dans la mémoire principale ; à défaut, tu peux les envoyer dans la mémoire de stockage et faire COPY (F2) ; ou bien tu peux les renommer .g1r vu que c'est le même format.
Plus de détails sur toutes ces histoires dans ce topic.
Aoctus Invité
Citer : Posté le 20/11/2021 20:52 | #
C'est bon tous les jeux marchent merci beaucoup !
Et pour le Morpion c'est bon aussi ! Je le mettais juste pas dans la bonne mémoire
Et Pacman je peux lancer le jeu mais juste après j'ai un message d'erreur qui me dit "erreur de dimension" et donc je ne peux pas y jouer mais cela ne fait rien.
Encore merci pour votre aide !
Bonne soirée
Citer : Posté le 26/12/2021 10:46 | #
J'ai corrigé un problème repéré sur Pokémon Stadium (avec l'aide d'Inikiwi entre autres).
En gros, pour identifier les fonctions, l'outil cherche une correspondance entre certains motifs d'instructions et les instructions réelles du programme. Il cherche une occurrence de chaque motif dans le code et ensuite unifie (en gros il vérifie que les registres sont les mêmes d'une instruction à la suivante).
Sauf que jusqu'ici il ne prenait pour chaque instruction à chercher que le premier résultat. Et dans Pokémon Stadium, le code compilé de ML_display_vram contient deux occurrences possibles pour une des instructions à chercher, et la bonne occurrence à utiliser est la deuxième.
J'ai modifié l'outil pour qu'il teste toutes les occurrences qu'il trouve jusqu'à tomber sur une solution au problème d'unification. Notons que s'il y a plusieurs solutions il faudrait le détecter et dire "help, la fonction est trop compliquée, je suis perdu" mais actuellement ce n'est pas le cas.
Par chance le code compilé pour cet add-in était tout pile ce que l'outil d'Inikiwi attendait donc lui a marché tout seul, ce qui a gagné un peu de temps pour diagnostiquer le problème
Citer : Posté le 12/02/2022 01:02 | # | Fichier joint
Je passe par là, juste pour informer que j'ai fait une petite version Tkinter (GUI) en PJ !
C'est très moche mais ça marche
Assez simple ; il faut sélectionner l'add-in, mettre le nom du nouvel add-in (celui patché), cliquer sur "PATCHER L'ADD-IN !" et une fois qu'il y a écrit "PATCH FINI", le fichier patché a été créé avec le nom donné dans le répertoire où est exécuté le programme !
Citer : Posté le 12/02/2022 01:21 | #
J'avais aussi fais ca!
Citer : Posté le 12/02/2022 11:04 | #
Merci. C'est une bonne idée mais j'aimerais bien que l'état succès/échec soit au moins indiqué. Je devrais peut-être fusionner l'interface dans ma branche existante et la lancer automatiquement quand il n'y a pas d'arguments de ligne de commande.
Et aussi faudrait mettre le truc en prod sur la v5...
Citer : Posté le 12/02/2022 11:06 | #
Oui pas faux, il faut que je règle certains bugs et que j’indique l’état.
J’ai fait ça hier à 1h donc bon..
Citer : Posté le 12/02/2022 11:07 | #
Tkt je vais le fusionner et comme ça ce sera officiel
Citer : Posté le 12/02/2022 11:08 | #
Cool, merci !
Citer : Posté le 12/02/2022 13:23 | #
Voilà c'est fait, j'ai ajouté un screen dans le post principal. C'est pas tout à fait facile à faire joli Tkinter.
Citer : Posté le 12/02/2022 13:25 | #
Ahah oui, tu as vraiment bossé ! Franchement, bravo, c'est super !