1

Salut

Y'a un truc que j'ai toujours voulu apprendre à faire : modifier une rom de jeu pour tricher, désactiver l'instruction qui désincrémente le nombre de vies ou de points de vie.

Y'en a ici qui savent faire ça et qui pourraient m'expliquer ? Ou qui connaissent des tutos ?
Les seuls info que je trouve sont pour modifier le texte ou les éléments graphiques, jamais le code.


Je devine comment faire : utiliser un debugger qui va montrer le code ASM du jeu, puis trouver à quel endroit ça retire 1 au nombre de vies, noter l'emplacement de cette instruction, ouvrir la rom dans un éditeur hexadecimal et remplacer l'instruction par un NOP. C'est ça n'est-ce pas ?


Donc voilà ce que j'ai fait :

J'ai trouvé un ému megadrive doté d'un debugger : Gens. J'ai donc lancé Bart vs Space Mutants, j'ai mis Bart en collision avec un ennemi, et j'ai lancé le debugger avant que ça retire un point de vie.

J'ai cherché comment on fait une soustraction en ASM 68000 et apparemment ce que je cherche est un SBCD ou un SUB. (Je ne connais que très peu l'ASM et encore moins l'ASM 68000.)

Je sais que le jeu va tester s'il y a une collision entre la hitbox du joueur et celle d'un ennemi, et s'il la trouve, retirer le point de vie.

J'aurai aimé qu'il y ait une fonction "pas à pas", qui laisserait le processeur executer chaque instruction une par une, ainsi j'aurai pu surveiller en prenant des screenshots, afin de trouver quelle instuction retire le point de vie. Mais pas de "pas à pas", et l'écran du debugger remplace celui du jeu donc je ne peux pas bien surveiller les points de vie...
Bref, ce n'est donc pas comme ça que je dois m'y prendre...


Quelqu'un peut m'éclairer svp ?

2

!call X-death
--- Call : X-death appelé(e) sur ce topic ...
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

3

La tricherie se fait généralement encore plus simplement que ça, mais il faut un support matériel : le Game Genie. Le principe c'est que tu sais où est stocké le nombre de vies en mémoire RAM, ou que tu peux le trouver, car tu sais que c'est un truc qui reste identique quand tu joues, décrémente si tu perds, augmente si tu gagnes ; du coup il suffit d'effectuer ces actions et dire à Game Genie comment la valeur a changé, et après plusieurs fois il pourra déterminer la ou les seules valeurs qui ont suivi exactement le schéma indiqué, et qui sont donc les emplacement potentiels stockant le nombre de vies.
Après tu peux bloquer l'emplacement mémoire à une valeur donnée afin que jamais les vies ou autre ne s'épuisent. En pratique le blocage se fait en remplaçant la valeur par celle désirée environ une fois par frame.
Dernière chose, comme ces valeurs ne sont jamais stockées sur la pile (elles doivent persister toute la partie) et que l'allocation se fait de façon déterministe depuis le boot sur une telle console, tu peux noter l'emplacement mémoire et le réutiliser pour toutes les parties consécutives, même après avoir éteint la console hehe
avatar
Highway Runners, mon jeu de racing à la Outrun qu'il est sorti le 14 décembre 2016 ! N'hésitez pas à me soutenir :)

https://itunes.apple.com/us/app/highway-runners/id964932741

4

Petite question liée (désolé pour le squattage de topic, je forke si besoin smile), j'utilisais il y a longtemps (très longtemps grin) sur PC un utilitaire identique à ce que tu décris : Cheat'O Matic. Après avoir scanné plusieurs fois la valeur recherchée, il finissait par l'identifier et permettre de la modifier ou de fixer sa valeur, exactement sur le même principe que ce que tu expliques. Il indiquait aussi l'adresse mémoire de cette valeur, pour pouvoir éviter de la rechercher une prochaine fois, et là par contre ça m'échappe. Comment cette adresse peut-elle avoir la moindre chance d'être la même entre deux lancement de l'exécutable, sur PC ?
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

5

Sous Windows c'est facile : l'espace d'adressage du processeur est virtuel, donc tu peux avoir des adresses hardcodées pour les variables, même si en RAM physique l'adresse peut être complètement différente d'une exécution à l'autre (note : c'est pas toujours vrai pour les DLL, y'a une adresse de base mais il peut y avoir des relogements, si y'a plusieurs DLLs qui veulent utiliser le même adresse mémoire par exemple).
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

6

Bonjour,
Pour faire ce que tu souhaite je te conseille de procéder comme l'a expliquer Brunni : d'utiliser un Game Genie pour trouver l'adresse en RAM qui va modifier ce que tu souhaite.
Voici par exemple un moyen en deux temps.

1) Trouver l'adresse

-Pour ce faire je te recommande l'utilisation d'un dérivée de Gens : Gens 15 Mhz qui intègre entre autre un traceur de RAM très bien fait , donc tu peut trouver cette ému ici :
http://sega4ever.power-heberg.com/Hacking.html

Je te fait un exemple avec un RPG mais le principe reste le même ( c est juste en régle générel plus facile avec un RPG grin )
Donc moi j'ai pas envie de faire du leveling je veut directement le perso au level 99
donc je fait monter mon perso au level 2 et j regarde tout de suite après les variables RAM qui ont changer:

SMD_Ram1_.png

J'en ai trois c'est normal mes trois persos qui sont passer directement au level 2.
Je vais tester en modifiant la valeur de l'adresse FFE707 , pour ce faire je vais utiliser le Game Genie ( CTRL+G).
La structure est simple : FFE707:6300 | Adresse : Valeur
Donc je Add le code , je lui met un nom pour que ça soit plus simple , un bon cold reset et voici le résultat tongue

SMD_Ram2.png

2) Incruster le code

Alors ça je l'ai jamais fait mais je vais quand même essayer de te renseigner.
Le mieu serait visiblement d'utiliser ce programme ( GG to Hex)
http://www.angelfire.com/games2/codehut/Download.htm
de convertir ton code GG en une adresse Hexa , ensuite tu te rends à l'adresse Héxa avec un éditeur et tu la modfie.
Voici une source assez intéressent ( en anglais) pour le complément d'info
http://www.angelfire.com/games2/codehut/AdvancedGenGGtips.txt

Voila ça devrait t'aider je pense smile

7

darkpig (./1) :
Je devine comment faire : utiliser un debugger qui va montrer le code ASM du jeu, puis trouver à quel endroit ça retire 1 au nombre de vies, noter l'emplacement de cette instruction, ouvrir la rom dans un éditeur hexadecimal et remplacer l'instruction par un NOP. C'est ça n'est-ce pas ?

Plus simle de soustraire 0 à mon avis. L'opcode reste le même, suffit de modifier le dernier ou les deux derniers octets.
Brunni (./3) :
Dernière chose, comme ces valeurs ne sont jamais stockées sur la pile (elles doivent persister toute la partie)

Et pourquoi ? main() peut très bien utiliser un stack frame. smile

J'en connais qui font ça pour simuler des variables globales sans bss ni relogements cheeky

8

Zerosquare (./5) :
Sous Windows c'est facile : l'espace d'adressage du processeur est virtuel, donc tu peux avoir des adresses hardcodées pour les variables, même si en RAM physique l'adresse peut être complètement différente d'une exécution à l'autre

Je comprends pas trop pourquoi l'adressage virtuel assure que les adresses seront identiques d'une exécution à l'autre ? Ou alors à condition que les allocations soient faites dans le même ordre et pour les mêmes tailles à chaque fois, non ? (ce qui me semble pas forcément être garanti dans un jeu)
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

9

En fait, toutes les variables allouées statiquement ont une adresse fixée au linking, pas à l'exécution.

Pour les allocations dynamiques, il n'y a aucune garantie en effet... Si ça marche quand même dans ce cas, je dirais qu'on est tombé sur les conditions que tu as citées et que c'est un coup de pot tongue (d'ailleurs en pratique, sur certains jeux l'adresse n'est pas fixe)
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

10

Merci beaucoup pour toutes ces infos ! heart

Je ne savais même pas qu'on pouvait créer soit-même des codes pour la game genie, c'est énorme !
Mais surtout, grace à tout ça, j'ai réussi très facilement à modifier ma rom. smile


Je raconte comment j'ai intégré la triche dans la rom, pour ceux qui passeront par ici et que ça interressera :

- J'ai suivi l'exemple de X-death et j'ai cherché "2" dans la ram, puis j'ai perdu un point de vie, et j'ai alors cherché "1". Ca m'a révélé l'adresse où est stockée le nombre de points de vie : FF01B5.

- J'ai testé si c'était bien ça en entrant comme code Game Genie FF01B5:0200 , pour bloquer la valeur de cette adresse à 2, et ça marche ! smile

- AdvancedGenGGtips.txt m'a appris que l'instruction qui décrémente la valeur d'une adresse mémoire est 5338 (SUB), suivi de l'adresse.

- J'ai donc ouvert ma rom dans un éditeur hexa, mais je n'ai trouvé que 53 2E 01 B5 . (Je n'ai pas encore compris pourquoi 2E plutot que 38... Je fouillerai plus tard dans la liste des instructions 68000 pour comprendre.) Je l'ai remplacé par 60 02 01 B5 . 60 signifie de sauter par dessus, et 02 qu'il faut sauter les 2 prochains octets : 01 et B5 .

- J'ai enregistré cette rom de triche, je l'ai lancé dans un autre ému, et... miracle : Bart ne perd plus de point de vie quand il se fait toucher !

Je suis trop content, je rêvais de savoir faire ça depuis tout petit. smile

11

pour le SUB, tu es sûr que le code correspondant est identique pour un octet ou un mot ?
avatar
Webmaster du site Ti-FRv3 (et aussi de DevLynx)
Si moins de monde enculait le système, alors celui ci aurait plus de mal à nous sortir de si grosses merdes !
"L'erreur humaine est humaine"©Nil (2006) // topics/6238-moved-jamais-jaurais-pense-faire-ca

12

darkpig (./10) :
- AdvancedGenGGtips.txt m'a appris que l'instruction qui décrémente la valeur d'une adresse mémoire est 5338 (SUB), suivi de l'adresse.

Méfie-toi, ya 10 millions de manières de décrémenter une adresse mémoire. Et ça pourrait très bien ne pas être un entier (soustraction d'un entier contenu ailleurs par exemple, pour permettre de virer plusieurs vies d'un coup).

5338 -> subq.b #1,imm.w

532e -> subq.b #1,x.w(a6)

Donc faut faire gaffe, c'est pas si simple...

13

Zerosquare (./9) :
En fait, toutes les variables allouées statiquement ont une adresse fixée au linking, pas à l'exécution.

Pour les allocations dynamiques, il n'y a aucune garantie en effet... Si ça marche quand même dans ce cas, je dirais qu'on est tombé sur les conditions que tu as citées et que c'est un coup de pot tongue (d'ailleurs en pratique, sur certains jeux l'adresse n'est pas fixe)

Justement, c'est bien ce qui m'étonne : quasiment aucune variable ne doit être allouée statiquement dans un jeu, si ? Enfin peut-être il y a 20 ans quand les jeux avaient une complexité raisonnable, mais dans les productions actuelles j'ai un peu de mal à y croire ?
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

14

Mais t'as testé avec les jeux actuels justement ? Est-ce que l'adresse est vraiment fixe ?

Et puis il ne faut pas oublier que pour les jeux, ce qui compte c'est les perfs, donc pendant longtemps je pense pas qu'ils aient utilisé des trucs de haut niveau, plutôt du C/C++ sans fioritures. Même avec des variables dynamiques, si tu les alloues toujours de la même façon au démarrage, je crois qu'il y'a de bonnes chances que l'algo soit déterministe et que tu obtiennes toujours le même résultat (ce qui est moins probable dans un langage garbage collecté, par exemple).

Faudrait demander à bearbecue, tiens.
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

15

Ca y est je suis bloqué... sad

J'ai essayé avec Belle's Quest puis Aladdin, et je patoge... On dirait que j'ai eu de la chance de commencer avec Bart vs Space Mutants et de trouver tout de suite.

Dans Belle's Quest, j'ai trouvé l'adresse du nombre de vies, 070F , mais je ne vois rien dans la rom qui semble définir ou agir sur cette adresse.
J'ai utilisé un desassembleur pour avoir le code plus lisible, et cherché donc une instruction avec 070F dedans.
Puisqu'on commence avec 5 vies, je pensais trouver un MOV 070F,05 . Mais non, rien ne ressemble à ça... Je ne trouve pas non plus de SUB dessus. C'est bizarre.

Dans Aladdin le nombre de vies n'est pas dans sa vraie valeur, il va de 48 (0) à 57 (9)... confus Déjà je me demande pourquoi, mais en tout cas je ne trouve pas non plus quoi que ce soit qui semble définir ou agir sur cette valeur. :\
vince (./11) :
pour le SUB, tu es sûr que le code correspondant est identique pour un octet ou un mot ?
Vu que je ne comprend pas le sens de la question, je dirai que non.

16

Zerosquare (./14) :
Mais t'as testé avec les jeux actuels justement ? Est-ce que l'adresse est vraiment fixe ?

Nop, faudrait effectivement que je teste avec des jeux moderne pour vérifier.
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

17

la megadrive est une vieille console, et encore elle est 16 bit

la mémoire étais très limité, si tu peu avoir maximum 9 vie, pourquoi utiliser un octet (ou plus) complet juste pour ça ?

il est possible que seul 4 bit soit utilisés pour coder le nombre de vies, et donc ce ne sera pas une instruction de set, d’incrémentation, ou décrémentation qui est utilisé, le jeu peu par exemple récupérer l'octet contenant les vies le trifouiller simplement avec les registres et l’écrire avec un & logique ou autre

le plus simple est de simplement utiliser ton émulateur pour forcer des zones mémoire aux nombre de vies max sans modifier ta rom, mais je le conçoit c'est beaucoup moins fun smile

sinon, désassemble la rom, et comprend son code, la se sera et de loin le plus marrant

pour revenir au 16b, 8b etc, imagine comment l'on devais stocker les scores -par exemple- sur une nes, 8bit == 1 octet == 2⁸ == 0-255 bref pas de quoi stocker 143567 comme score (sur ta 16b non plus soit dit en passant), modifier la rom sera bien plus compliqué
et la le mec il le pécho par le bras et il lui dit '

18

Zerosquare (./5) :
Sous Windows c'est facile : l'espace d'adressage du processeur est virtuel, donc tu peux avoir des adresses hardcodées pour les variables, même si en RAM physique l'adresse peut être complètement différente d'une exécution à l'autre (note : c'est pas toujours vrai pour les DLL, y'a une adresse de base mais il peut y avoir des relogements, si y'a plusieurs DLLs qui veulent utiliser le même adresse mémoire par exemple).

C'est un souci de sécurité, d'ailleurs maintenant avec la protection (ça a un nom du style base address randomization) je crois que ce genre de programme ne peut plus marcher...
Après c'est pas dit que les jeux l'activent, surtout s'ils peuvent gagner des perfs en ne le faisant pas wink
Folco (./7) :
Brunni (./3) :
Dernière chose, comme ces valeurs ne sont jamais stockées sur la pile (elles doivent persister toute la partie)

Et pourquoi ? main() peut très bien utiliser un stack frame. smile

On peut, mais perso j'ai presque toujours vu les variables allouées dans une zone de mémoire fixée à l'avance (et je faisais pareil, sur ARM ça valait le coup en tous cas, sans parler de la vieille GB et ses 3 registres 16 bits*), et la pile était cantonnée à une taille minimum. Et puis ton stack frame si on parle bien de la même chose ça monopolise un registre non ? Après c'est possible que des jeux qui ont plein de gameplays différents le fassent**, mais en tant que joueur j'ai dû tomber une ou deux fois dessus seulement (ça veut dire qu'il faut penser à dynamiquement activer les codes quand tu es dans la phase "jeu", sinon ça faisait planter les special stages par exemple).

* On avait 6 registres 8 bits vraiment "user" (B, C, D, E, H, L), en plus de l'accu (A), le SP et le PC (16 bits) avec lesquels on pouvait pas vraiment jouer car des instructions s'en servent, et on pouvait combiner les registres 8 bits pour faire BC, DE, HL cette fois 16 bits.
** Même si on n'est pas obligé, en ASM c'est facile de réutiliser des adresses mémoire selon le besoin, et en C on pouvait réutiliser un gros tableau du main gameplay pour y stocker autre chose avec une union par exemple.



darkpig (./15) :
Dans Aladdin le nombre de vies n'est pas dans sa vraie valeur, il va de 48 (0) à 57 (9)... confus Déjà je me demande pourquoi, mais en tout cas je ne trouve pas non plus quoi que ce soit qui semble définir ou agir sur cette valeur. :\

C'est de l'ASCII. Ca veut dire que tu n'as probablement pas trouvé l'adresse qui stocke réellement le nombre de vies, mais plutôt celle qui est utilisée pour construire la chaîne à afficher à l'écran. Exemple 03 -> '0' (48) '3' (51) si on veut l'afficher avec une fonction de haut niveau.
Tu as aussi souvent des valeurs stockées en BCD. Ca veut dire 4 bits par chiffre. Par exemple 18 = 0001 1000 en binaire = 24.

Concernant le fait de trouver les instructions référençant une zone mémoire, c'est difficile car rien n'empêche à un programme de charger dans un registre l'adresse de base et de faire un move indexé, style:
move.b #0xff00, a0  ; Variables utilisateur stockées à partir de 0xff00, vies à 0xff04
...
move.b #3, #4(a0)   ; 3 vies

Je sais plus la syntaxe en 68000 mais tu vois l'idée.
avatar
Highway Runners, mon jeu de racing à la Outrun qu'il est sorti le 14 décembre 2016 ! N'hésitez pas à me soutenir :)

https://itunes.apple.com/us/app/highway-runners/id964932741

19

darkpig (./15) :
Dans Aladdin le nombre de vies n'est pas dans sa vraie valeur, il va de 48 (0) à 57 (9)... confus.gif
C'est la valeur en ASCII (48 c'est le caractère '0') qui est utilisée pour l'affichage, c'est pas forcément la même qui est réellement utilisée comme compteur de vies.
r043v (./17) :
la mémoire étais très limité, si tu peu avoir maximum 9 vie, pourquoi utiliser un octet (ou plus) complet juste pour ça ?
Euh, à part sur l'Atari 2600 (et encore), les mecs en étaient pas au point d'utiliser une moitié d'octet pour stocker le nombre de vies quand même tongue
Brunni (./18) :
C'est un souci de sécurité, d'ailleurs maintenant avec la protection (ça a un nom du style base address randomization) je crois que ce genre de programme ne peut plus marcher...
Oui, l'ASLR est une autre raison pour laquelle ça peut ne pas marcher (j'en ai pas parlé parce que c'est assez récent).
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

20

en fait oui, ne cherche pas une valeur exacte (genre ici 5) mais filtre la recherche avec "supérieur à la précédente" ou "inférieure à la précédente", "égale à la précédente" et donc aussi "différente à la précédente" ça marchera beaucoup mieux, l'émulateur sur la xbox1 étais parfait pour ça
Zerosquare (./19) :
Euh, à part sur l'Atari 2600 (et encore), les mecs en étaient pas au point d'utiliser une moitié d'octet pour stocker le nombre de vies quand même tongue.gif

pourtant ca ne m’étonnerais pas tongue
je fait ca pour des flags en général, pas pour des nombres mais sait on jamais, n'oublions pas que les dev sont fou ;- )
et la le mec il le pécho par le bras et il lui dit '

21

Tout le monde n'est pas aussi cinglé que toi hehe
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

22

Pour les chiffres étranges dans Aladdin, c'est pourtant bien ça, d'ailleurs il y a plusieurs lignes testant cette adresse 7E3C :
001B7722 0C39 0039 00FF7E3C CMP.B #$39,$00FF7E3C
Je comprend qu'il teste ici si le nombre de vies est à 39, 0 donc, pour savoir s'il doit juste en retirer une ou si on est mort.

J'ai désactivé les MOV qui touchaient à l'adresse, sauf celui qui donne la valeur de départ, et ça fonctionne.


Par contre pour Belle's Quest je reste coincé...
L'adresse du nombre de vies est 070F. Une autre adresse contient aussi cette valeur : 0711, mais elle semble juste copier la valeur de 070F.

Je ne trouve que ça pour 070F :
00059FC4 0178 070F BCHG D0,$070F

Plus interressant pour 0711 :
000295B6 11C5 0711 MOVE.B D5,$0711
0004E5B8 3170 0711 0711 MOVE.W $07(A0,A0.L),$0711(A0)
000526D6 21C7 0711 MOVE.L D7,$0711

J'ai tout désactivé mais les vies continuent de se décompter.... :\


Ensuite je suis tombé sur des jeux où absolument rien ne touche à l'adresse... confus ( 3 Ninjas Kick Back , Chuck Rock II , Ghouls n Ghosts , les Schtroumpfs... )
Pourtant j'ai vérifié en changeant la valeur de l'adresse et ça change bien le nombre de vies. Mais l'adresse n'apparait nul part dans le code désassemblé.
Là, je n'ai aucune idée de comment ça se passe... Un indice ? Est-ce que le jeu peut utiliser un offset plutot que les vraies adresses en clair, ou un truc comme ça ?


Et pour finir, des jeux qui semblent etre protégés, dès que je modifie quoi que ce soit, le jeu refuse de démarrer et bloque sur un écran tout rouge. confus ( Chiki Chiki Boys, Doraemon... )

23

darkpig (./22) :
qui semblent etre protégés


ça reste peu probable... l'éventualité que quelqu'un "triche" en faisant des accès direct en ram sur un jeu console reste très faible amha... donc ça ne justifierai pas d'obfuscation pour l'empêcher...
avatar
Webmaster du site Ti-FRv3 (et aussi de DevLynx)
Si moins de monde enculait le système, alors celui ci aurait plus de mal à nous sortir de si grosses merdes !
"L'erreur humaine est humaine"©Nil (2006) // topics/6238-moved-jamais-jaurais-pense-faire-ca

24

darkpig (./22) :
Et pour finir, des jeux qui semblent etre protégés, dès que je modifie quoi que ce soit, le jeu refuse de démarrer et bloque sur un écran tout rouge. confus ( Chiki Chiki Boys, Doraemon... )

Tu es sûr que c'est "n'importe quoi" ? Suivant ce que tu modifies ça peut faire planter le jeu, et c'est sûrement ce qui arrive ici.
Typiquement modifier les instructions du style:
move.x d0, (a7)+
(Encore une fois je ne connais plus la syntaxe, mais si une instruction touche à la pile, tu ne peux pas la désactiver comme ça, parce que sinon elle va péter au retour de la fonction en cours)
avatar
Highway Runners, mon jeu de racing à la Outrun qu'il est sorti le 14 décembre 2016 ! N'hésitez pas à me soutenir :)

https://itunes.apple.com/us/app/highway-runners/id964932741

25

Non je n'ai touché qu'à ces instructions :
5338 AF50 SUBQ.B #$1,$AF50
11F8 AF51 AF50 MOVE.B $AF51,$AF50

Je viens de m'attaquer à Sonic et ça fait pareil.
Si je remplace 5338 FE12 par 6002 FE12 ou 4E71 4E71, j'ai un écran rouge...
Si je remplace le 3 par un 9 dans 11FC 0003 FE12 MOVE.B #$03,$FE12 , pour commencer avec 9 vies au lieu de 3, j'ai un écran rouge...

Je ne vois pas en quoi ça peut bloquer le jeu.

26

Certains jeux ont des routines de checksum (plutôt pour détecter les ROMs défectueuses que pour détecter les modifs, je pense), si c'est le cas il faut donc trouver la routine en question pour la désactiver.
darkpig (./22) :
Pourtant j'ai vérifié en changeant la valeur de l'adresse et ça change bien le nombre de vies. Mais l'adresse n'apparait nul part dans le code désassemblé. Là, je n'ai aucune idée de comment ça se passe... Un indice ? Est-ce que le jeu peut utiliser un offset plutot que les vraies adresses en clair, ou un truc comme ça ?
Y'a une infinité de façons d'accéder à la mémoire :
- charger un registre avec l'adresse, et utiliser le registre comme pointeur (lea.l variable, a0 / move.b #valeur, (a0))
- idem, mais en rajoutant un offset immédiat (lea.l blocs_de_variables, a0 / move.b #valeur, 5(a0))
- idem, mais en rajoutant un offset dans un registre (lea.l blocs_de_variables, a0 / move.l #5, d0 / move.b #valeur, (a0,d0))
- combinaison des 2 cas précédents
- les 3 cas précédents, mais en utilisant move.l au lieu de lea.l
- la même chose, en PC-relatif (lea.l variable(pc), a0 / move.b #valeur, (a0))
- les cas précédents, en rajoutant un bout de code qui n'a rien à voir au milieu
- ...

Faut désassembler et tracer, c'est tout tongue (ou avoir un émulateur qui peut faire un point d'arrêt en cas d'accès à un emplacement mémoire, ce qui est beaucoup plus pratique).
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

27

Brunni (./18) :
Et puis ton stack frame si on parle bien de la même chose ça monopolise un registre non ?

Je parle bien de ça, oui.
Zerosquare (./26) :
- idem, mais en rajoutant un offset immédiat (lea.l blocs_de_variables, a0 / move.b #valeur, 5(a0))

Le moyen le plus efficace si tu accèdes à plusieurs variables. Ca ne fait lire une adresse absolue qu'une fois. Et il suffit de maintenir une liste d'offset/equ pour faire des modifs.
Zerosquare (./26) :
- idem, mais en rajoutant un offset dans un registre (lea.l blocs_de_variables, a0 / move.l #5, d0 / move.b #valeur, (a0,d0))

Syntaxiquement faux je crois, x(an,dn) existe, mais pas (an,dn)

28

Folco (./27) :
Syntaxiquement faux je crois, x(an,dn) existe, mais pas (an,dn)
Exact, je viens de vérifier dans la table des opcodes. J'utilise un assembleur assez permissif en ce qui concerne la syntaxe, il doit convertir ça en move.b #valeur, 0(a0,d0).

(au passage, chez moi le premier lien Google pour "Motorola 68000 opcodes" c'est le PDF de GoldenCrystal top)
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

29

Je ne peux pas me passer de son travail en effet hehe Merci encore à toi GC happy

Et oui, sous je ne sais quel assembleur (GAS ou A68k), il y a un switch pour faire ça automatiquement. Et un pour transformer les 0(an) en (an).

ps -> ton abominable move.l #5,d0 se changerait volontiers en moveq.l #5,d0, à moins que ton code soit en ram et que tu prévoies de faire du smc cheeky

30

Je sais, je sais, c'était juste un exemple. De toute façon personne de sensé ne va s'amuser à faire du 0(a0,d0) quand l'offset est fixe cheeky
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo