Journal Patch de binaire pour faire tourner Medal of Honor: Allied Assault sous Linux

Posté par (page perso) .
Tags : aucun
23
23
oct.
2010
Bonjour à tous,

je voulais vous raconter ce que j'ai fait pour faire fonctionner le jeu Medal of Honor: Allied Assault (MoHAA) sous Linux.

Ce jeu est supposé fonctionner avec wine, mais malheureusement je n'ai pas pu aller plus loin que l'installation, et après avoir un peu insisté que ce soit avec wine ou Crossover Games, j'ai abandonné et me suis tourné vers un portage plus ou moins officiel du jeu sous Linux : http://icculus.org/~ravage/mohaa/

Donc, on télécharge cet installeur, on le lance, rien ne se passe - on décompresse le "self extract", on finit par trouver le binaire setup.gtk de l'installeur, et l'installation se passe à peu près normalement à partir de là.

Le jeu se lance et fonctionne à peu près... Le son est tout de même mauvais, on entend pas les dialogues, il n'y a du son que dans le haut-parleur gauche, mais ça reste jouable.
Sauf que passée la première mission, les choses se gâtent. Le jeu freeze complètement au bout de trois pas.

Mais moi, j'avais vraiment envie de jouer à ce jeu !

Par chance, les binaires sont distribués avec (certains) symboles de debug, donc lancer le jeu dans gdb donne des résultats à peu près lisibles, ce qui facilite le désassemblage.

Je passe le jeu en mode fenêtré, je désactive le "grab" du pointeur de la souris (afin de pouvoir taper des commandes gdb une fois le crash arrivé), et je reproduis le crash.
Il s'agit d'un segfault - je n'ai pas gardé de copie de la backtrace, mais la fonction dans laquelle le crash se produit s'appelle void ClientGameCommandManager::PlaySound(str *, float, int, float, float, float, int) et se trouve à l'adresse 0x0004b0f0.

J'ai donc sorti l'artillerie lourde, à savoir objdump -d, pour désassembler la fonction, et étant donné que le son ne marchait de toute façon pas très bien, je me suis dit que je m'en passerais complètement.
Il faut savoir que le son n'est pas désactivable dans MoHAA : on peut baisser le volume, mais c'est tout - ce qui évidemment n'empêchait pas le crash de se produire.

Voici le début de la fonction, il s'agit d'un prologue classique de fonction x86:


0004b0f0 <_ZN24ClientGameCommandManager9PlaySoundE3strPfifffi>:
4b0f0: 55 push %ebp
4b0f1: 89 e5 mov %esp,%ebp
4b0f3: 57 push %edi
4b0f4: 56 push %esi
4b0f5: 53 push %ebx
4b0f6: 83 ec 4c sub $0x4c,%esp
4b0f9: c7 45 dc 00 00 00 00 movl $0x0,-0x24(%ebp)
4b100: 80 3d 40 a1 26 00 00 cmpb $0x0,0x26a140
4b107: 0f 84 53 04 00 00 je 4b560 <_ZN24ClientGameCommandManager9PlaySoundE3strPfifffi+0x470>


Un moyen très simple d'empêcher le crash, c'est d'empêcher cette fonction de s'exécuter - la solution la plus simple c'est de mettre un "ret" (return) au tout début du prologue.

Un coup d'éditeur hexa et on obtient :


4b0f0: c3 ret
4b0f1: 89 e5 mov %esp,%ebp
4b0f3: 57 push %edi
4b0f4: 56 push %esi
4b0f5: 53 push %ebx


... ce qui fait amplement l'affaire.

Après avoir relancé le jeu, plus aucun son ne sort, et plus aucun crash n'est à déplorer.

C'est la deuxième fois dans ma vie que je fais un patch directement sur un binaire pour corriger un bug (une autre fois c'était sur le driver Intel DRI pour corriger un crash sur mon EeePC sans recompiler tout), et globalement c'est assez simple. Par contre, l'absence de symboles de debug aurait été un problème, car ne pas avoir le nom de la fonction (PlaySound) ne m'aurait pas permis de savoir qu'il s'agissait du son. Je n'aurais alors pas pu avoir une approche aussi aggressive pour contourner le crash.

J'ai donc pu jouer pendant deux heures avant de rencontrer des bugs dans le portage de la machine virtuelle qui exécute les scripts de mission, ce qui m'a bloqué sur une mission. Mais ça, c'est une autre histoire ! :)

Voila, j'espère que ça donne envie à ceux qui ont les CD de MoHAA dans un coin de réinstaller le jeu sous leur OS favori !
  • # ou pas

    Posté par . Évalué à 3.

    Voila, j'espère que ça donne envie à ceux qui ont les CD de MoHAA dans un coin de réinstaller le jeu sous leur OS favori !
    OU PAS ;)

    parce jouer à un jeu sans le son, c'est peut-etre tres WAF
    mais pas super pratique non plus.

    de plus comme tu le dis il faut sortir l'artillerie lourde pour patcher, pour perdre le son.
    • [^] # Re: ou pas

      Posté par . Évalué à 5.

      J'ai connu exactement le même problème, mais j'avoue avoir lâchement installé par la suite, le jeu sous ouin ouin.
      En tout cas, respects mec parce-que sortir objdump pour débugger un jeu fermé et sorti il y a 7 ou 8 ans, chapeau bas!
  • # Patch en deux parties

    Posté par (page perso) . Évalué à 10.

    Pour le premier bug désactiver le son (le geek raté que je suis te salue)
    Pour le second désactiver l'affichage vidéo, le jeu tourne toujours mais c'est, comment dire, moins ludique....
  • # en plus fin

    Posté par (page perso) . Évalué à 3.

    Tu aurais gardé le dump complet de la fonction ainsi que l'adresse exacte du crash quelque part ?

    pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

    • [^] # Re: en plus fin

      Posté par (page perso) . Évalué à 2.

      Le son marchait de toute facon tellement mal que ce n'était pas une grande perte. Mon objectif était de jouer, pas de corriger le bug, donc je n'ai pas passé beaucoup de temps dessus.

      Je n'ai pas conservé la backtrace, ni un dump des registres.
      Le crash se déroule à l'intérieur de vfprintf() qui est appelé par la fonction dont le nom est indiqué dans mon journal, dans le fichier fgame.so. C'est juste une question de désassembler ce fichier et de chercher le nom de la fonction dedans.

      Le crash est facilement reproductible, donc si tu veux bosser dessus pour je ne sais quelle raison, peut-être que je partagerai ta motivation :)
  • # lmdsptdvidljqstds

    Posté par . Évalué à 6.

    Rahahah ca me rappelle ma jeunesse sous Amstrad CPC ou on devait chercher dans un binaire le decrement de l'accumulateur et un saut si celui-ci est nul et remplacer tout ca par pas grand chose... juste pour avoir des vies infinies, parce que de tourte facon Rick Dangerous 2 c'etait assez chaud a finir :)

    Je suis sur qu'avec les symbols de debug y aurait moyens de faire la meme chose, doit bien y avoir une methode qui fait la meme chose....
    • [^] # Re: lmdsptdvidljqstds

      Posté par . Évalué à 4.

      Ca fait un bail qu'on a plus de vies dans les jeux, c'est credit infini :)
      A moins d'avoir un genre d'action replay qui bloque la barre de vie au max, ca va pas être tres utile.

      Après, de memoire a la fin de la grande époque des patches, les devs de jeux se sont mit empecher ce genre de pratiques, chiffrement, emplacements dynamiques et autres.

      De plus ce genre de techniques marchent uniquement si les membres des objets sont toujours a la meme adresse memoires, a une époque ou les jeux bouffant 1go de ram et ou les devs doivent defragmenter la ram en deplacant les pointeurs, ca va commencer a etre couillu a faire :-p

      C'etait marrant en tout cas a l'epoque, c'est comme ca que j'ai appris a compter en hexa :)

      If you can find a host for me that has a friendly parrot, I will be very very glad. If you can find someone who has a friendly parrot I can visit with, that will be nice too.

      • [^] # Re: lmdsptdvidljqstds

        Posté par (page perso) . Évalué à 5.

        defragmenter la ram en deplacant les pointeurs,

        Tu es codeurz chez MultiDeskOS ?

        * Ils vendront Usenet^W les boites noires quand on aura fini de les remplir.

        • [^] # Re: lmdsptdvidljqstds

          Posté par . Évalué à 1.

          Autant pour moi, le terme approprie est compacter la ram.

          If you can find a host for me that has a friendly parrot, I will be very very glad. If you can find someone who has a friendly parrot I can visit with, that will be nice too.

    • [^] # Re: lmdsptdvidljqstds

      Posté par (page perso) . Évalué à 5.

      >parce que de tourte facon Rick Dangerous 2 c'etait assez chaud a finir :)

      C'est un jeux où il faut chercher des ouiches lorraines ??
    • [^] # Re: lmdsptdvidljqstds

      Posté par (page perso) . Évalué à 5.

      Histoire d'expliciter le titre ;
      "La Méthode De Septh Pour Trouver Des Vies Infinies Dans Les Jeux Qui Sont Trop Difficiles Sinon" (LMDSPTDVIDLIQSTDS)

      Mentionnée notamment dans
      http://sid.cpc.free.fr/doc/revues/Amstrad%20100%25/CPC%20100(...)
    • [^] # Re: lmdsptdvidljqstds

      Posté par (page perso) . Évalué à 1.

      Mais, mais mais mais et ho c'est moi qui avait envoyé les octets à modifier à amstrad cent pour cent pour Rick Dangerous 2 !!!

      Bon j'avoue j'avais pas le même pseudo ( d'ailleurs on l'avait fait à 2 ) et je m'étais servi de cette méthode mais quand même.

      \_o<

  • # Bravo !

    Posté par (page perso) . Évalué à -5.

    Medal of Honnor...

    Un journal sur un jeu de guerre en pleine révélations wikileaks, fallait oser...

    Ça me rappelle cette citation de maître Yoda: "Un grand guerrier ? Personne par la guerre ne devient grand."

    <p mode="sarcastic">
    Oui, je sais, la seconde guerre mondiale, c'est pas pareil, il y avait vraiment un grand méchant, et il n'y a pas eu d'exactions...
    </mode>

    Bon jeu quand même ;-)
    • [^] # Re: Bravo !

      Posté par (page perso) . Évalué à -3.

      Ah,mais je me suis trompé !

      C'est la version 2010, avec les nouveaux grands méchants et les gentils Américains.

      Autant pour moi, c'est vraiment une question d'honneur, alors.
    • [^] # Re: Bravo !

      Posté par (page perso) . Évalué à 3.

      <p mode="sarcastic">
      [...]
      </mode>


      passera pas la validation ton message
  • # debug.com

    Posté par . Évalué à 3.

    Ça me rappelle le temps où j'utilisais debug.com pour modifier quelques fonctionnalités gênantes des programmes de l'école.

    Certains n'ont jamais dû comprendre pourquoi leurs programmes ne faisaient plus rien de ce qu'ils devaient faire (mov ax,4C00h; int 21h pow4!).

    The capacity of the human mind for swallowing nonsense and spewing it forth in violent and repressive action has never yet been plumbed. -- Robert A. Heinlein

    • [^] # Re: debug.com

      Posté par (page perso) . Évalué à 1.

      Ça me rappelle le temps où j'utilisais debug.com

      J'ai voulu tester mais le site a été racheté depuis…
      ---> []

      Moi c'était un programme résident qui faisait tomber les lettres dans le DOS et les laissaient s'accumuler en bas de l'écran… Qu'est ce que c'était bon enfant à l'époque (avant que je découvre que les programmes résident pouvaient faire BEAUCOUP d'autre choses) !
      • [^] # Re: debug.com

        Posté par (page perso) . Évalué à 3.

        >> Moi c'était un programme résident qui faisait tomber les lettres dans le DOS et les laissaient s'accumuler en bas de l'écran…

        Le virus waterfall, si ma mémoire est bonne.
        • [^] # Re: debug.com

          Posté par (page perso) . Évalué à 1.

          Merci je savais pas que c'était un virus, j'avais entendu parler de l'effet et je m'étais amusé à le refaire…

          Je vais essayer de voir si je peux retrouver mon code est celui du virus pour comparer. :)
          • [^] # Re: debug.com

            Posté par (page perso) . Évalué à 2.

            Ma mémoire me jouait des tours, c'est « cascade » le nom du virus.
            On trouve des vidéos de ce virus sur les interwebs.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.