WTF, mais ce jeu n’est pas dispo sur Smartphone

En effet, Balatro, n’est pour l’heure pas officiellement sur Smartphone (Android dans mon cas).
Balatro sinon, c’est un super jeu indépendant. Globalement, c’est un rogue-like, basé sur le comptage des points du poker. J’ai résisté jusque-là, car il a l’air sacrément chronophage, mais voilà, j’ai craqué.

Mais pourtant, il tourne bien en natif sur mon OnePlus, sans que j’ai eu à bidouiller mon téléphone plus que ça (sauf si installer un APK est de la bidouille, auquel cas ce billet risque d’être un peu technique pour vous, désolé :/ ).
Alors, non, je ne vais pas vous filer l’APK que j’ai réussi à confectionner, pour deux raisons :

  • Je n’ai pas le droit. Bien que j’ai acheté une copie sur Steam, je n’ai pas les droits légaux de le redistribuer. Donc je ne le ferai pas.
  • Ce n’est pas le but de ce billet, ni même de ma démarche initiale.

Mais alors, pourquoi j’en suis arrivé là ? Bah, c’est très simple, il y avait une feature manquante/un bug dans la version actuelle du jeu, et j’ai essayé de trouver comment corriger ça. Et au final, c’est allé beaucoup plus loin que prévu, et j’ai compris l’étendue des possibilités liées à mes humbles découvertes.
Cette feature, c’est le fait, sous Windows 10, de pouvoir choisir sur quel sortie audio envoyer le son produit par Balatro. Car en fait, il émet toujours sur la sortie par défaut et ce n’est pas configurable dans le jeu, et les options Windows ne sont d’aucun secours. Ouais, j’ai un setup son assez particulier, à base de GoXLR et de micro-casque sans fil branché à cette dernière.

Comprendre le système audio utilisé par Balatro

On se penche sur les fichiers du jeu, et je note une bibliothèque particulière, OpenAL32.dll. Globalement, ça sent bon, mais finalement, pas tant que ça. Le Open de OpenAL ne signifie pas OpenSource. Un peu de recherche plus tard, je tombe sur openal-soft, qui propose des utilitaires pour modifier la configuration et pour donner des infos sur l’état du bousin. Bon, la modification de la config, on ne peut toujours pas forcer le périphérique audio. Et pour l’utilitaire d’affichage d’information, ça me ressort ceci :

Available playback devices:
OpenAL Soft on System (TC-HELICON GoXLR)
OpenAL Soft on Chat (TC-HELICON GoXLR)
OpenAL Soft on Game (TC-HELICON GoXLR)
OpenAL Soft on Haut-parleurs (2- USB AUDIO  CODEC)
OpenAL Soft on PLE2403WS (2- High Definition Audio Device)
OpenAL Soft on Casque (2- Arctis 7 Game)
OpenAL Soft on Z35 (2- High Definition Audio Device)
OpenAL Soft on Casque pour téléphone (2- Arctis 7 Chat)
OpenAL Soft on Sample (TC-HELICON GoXLR)
OpenAL Soft on Music (TC-HELICON GoXLR)
Available capture devices:
OpenAL Soft on Chat Mic (TC-HELICON GoXLR)
OpenAL Soft on Sample (TC-HELICON GoXLR)
OpenAL Soft on Microphone sur casque (2- Arctis 7 Chat)
OpenAL Soft on Ligne (2- USB AUDIO  CODEC)
OpenAL Soft on Broadcast Stream Mix (TC-HELICON GoXLR)
Default playback device: OpenAL Soft on System (TC-HELICON GoXLR)
Default capture device: OpenAL Soft on Chat Mic (TC-HELICON GoXLR)
ALC version: 1.1

Mouais, bon, pas ouf tout ça.

Et le jeu en lui-même, il fonctionne comment ?

Bon, maintenant, c’est bien beau, j’ai la bibliothèque audio utilisée par Balatro, mais les appels sont fait comment ? Car il y a un monde où je peux les surcharger non ?
C’est partit pour un coup de ResourceHacker et de x64dbg. Bon, des icônes, très peu de code. Et surtout, je ne suis pas le plus doué en code bas niveau, donc je n’avance pas.

C’est un peu un retour à la case départ, je ne suis pas vraiment avancé là. Allez, on tente un truc, voir si le jeu utilise un moteur de jeu connu. Alors, du coup, oui et non. Oui, il utilise un moteur de jeu, de là a dire qu’il est connu, bref. Donc je tombe sur LÖVE, qui permet aux développeurs du jeu de coder en lua.
Oh, mais attendez, le moteur du jeu est OpenSource, c’est très bien ça ! Je lis un peu la doc, et regarder rapidement le code, puis tombe sur ça : throw love::Exception("Re-setting output device is not supported.");. Mais en même temps, je ne suis pas le 1er type à demander une telle fonctionnalité. Bon, au pire, je build le moteur, je l’injecte à la place de celui existant de Balatro, et on verra bien ce que ça donne !

Et ben j’ai jamais été aussi heureux que la documentation pour build soit si complète. Après 2-3 modifications de mon installation de VisualStudio, rager contre mon OS qui ne prend pas en compte le changement dans le PATH, j’arrive à un truc plutôt bon, j’ai un moteur tout beau tout propre, qui se lance avec le placeholder du jeu de démo.
C’est partit, j’écrase les DLL de Balatro par celle que je viens de build. Ça ne fonctionne pas. Mais alors pas du tout, rien ne se lance, 0 message en console. Je suis à 2 doigts d’abandonner. En passant, en relisant la doc, je me rends compte que je n’étais pas obligé de tout rebuild, ils publient des versions précompilés assez régulièrement. Bref.

Oh, mais attends, si mon moteur de jeu est contenu dans les DLL, et que pour lancer ma démo (qui ne fait rien), je n’ai même pas d’exécutable nominatif, mais juste une love.exe, c’est que le fichier Balatro.exe, il est spécial non ? D’ailleurs, il est sacrément gros en taille pour si peu de chose à part des icônes et si peu de ligne de code.
Ouvrons-le avec 7zip. OH BORDEL. Des fichiers .lua, des musiques en .ogg , ça va être chiffré non ? AH NON ! Bon, on extrait tout ça, et on le fait lancer par notre love.exe. Ça ne marche pas. Mais ça dit pourquoi. Il manque une bibliothèque.
Bon, je prends les .dll de mon jeu installé qui ne sont pas dans mon build du moteur, et je les rajoute à mon projet. Ça ne marche toujours pas, erreur Steam. Je lance Steam. ÇA FONCTIONNE \o !!!!! Le jeu se lance et est jouable.

Modifions tout ça

Plutôt que de modifier le moteur de jeu ou une DLL, si on ne modifiait pas tout simplement le jeu ? C’est du lua, ça devrait le faire. Je tente un love.audio.setPlaybackDevice(1) dans le sound_manager.lua un peu au pif pour voir comment ça réagit. Déjà, ça ne plante pas. Par contre, ça ne fait rien. Je vous passe les différentes tentatives, pour au final testerlove.audio.setPlaybackDevice("OpenAL Soft on Game (TC-HELICON GoXLR)") car je sais que ça utilise OpenAL derrière. OH BORDEL, ça fonctionne ! J’ai le son sur ma bonne sortie audio. Objectif réussi, j’ai enfin résolu le souci ! Fin. Bonne nuit. On verra pour potentiellement rendre ça configurable et un peu mieux intégré plus tard. Car en l’état, bon, je n’ai pas ma sauvegarde, c’est assez exotique comme lancement, bref. Il est tard.

Le réveil

Et mais j’avais vu que le moteur LÖVE support Android. Non, c’est n’est pas possible, pas comme ça ? Bon, déjà, on commence par relire la doc, histoire d’avoir un truc un peu plus propre pour Windows. J’entoure mon appel à setPlaybackDevice par une condition sur l’OS pour ne pas trop foutre le bordel, et je vois que le packaging sous Windows est assez simple. Et si j’avais commencé par lire ça, je ne me serai pas autant fait chier à tourner en rond au début … C’est en gros l’exécutable love.exe juxtaposé avec un zip des ressources. Et ça fonctionne. Du coup joie, j’ai accès à mes sauvegardes (Car j’ai nommé le binaire Balatro.exe)

Bon, Android. Je pars sur la solution APKTool. Après l’installation du nécessaire sur mon PC, et quelques tentatives infructueuses, bah, ça fonctionne. Je peux jouer à Balatro sur mon téléphone. Bon, il y a sûrement des bugs, parce que sinon, que le studio de dev l’aurai déjà release. D’ailleurs, oui, il y a des bugs, j’ai tenté sur un 2d téléphone qui m’appartient totalement, tousse, et la propriétaire de ce téléphone a une partie de l’écran recouvert de noir. J’ai tenté des trucs, comme par exemple supprimer des icônes dans le jeu, ou même émuler la marque de son téléphone sur mon PC, mais je n’arrive pas à reproduire.

Conclusion

Il parait même que le moteur est exportable pour du Web, bon, j’ai un souci de bibliothèque bit non-compatible avec tout ceci, j’aurai tenté. Idem pour MacOS ou iOS, ça semble compatible, mais je n’ai pas d’appareil pour tester et encore moins pour build le bousin.

Si vous voulez faire un petit jeu 2D sans plus de connaissance en développement que ça, mais que vous avez une chouette idée, penchez-vous du côté de LÖVE.

Et pour en revenir à Balatro, achetez ce jeu bordel. Et amusez-vous à bidouiller les choses que vous aimeriez améliorer. On finit souvent par apprendre un tas de trucs, découvrir des choses sympas.

Mise à jour du 25/06

Petit retour, et des corrections :

  • L’accès à setPlaybackDevice ne fonctionne pas avec la release actuelle de LÖVE, donc en fait, mon build en partant des sources était bien utile !
  • Je l’indiquais à demi-mot, et je n’ai jamais pensé de toute façon être le premier à découvrir ça, mais un projet existe sur le sujet de Balatro pour mobile. Je l’ai découvert aujourd’hui.
  • Toujours pour setPlaybackDevice , en fait ça accepte au choix OpenAL Soft on Game (TC-HELICON GoXLR) et Game (TC-HELICON GoXLR). Comme quoi, les gens qui développent des trucs pensent un peu à tout !