Recherche de l'offset d'un jeu

Pages: 1 [2]

M@T

  • Membre
  • 15146 posts
24 mai 2011, 23:06
C'est exactement ça, tu apprends vite.  ;D

Pokedeus

  • Membre
  • 38 posts
25 mai 2011, 15:06
Merci.
J'ai compris le fonctionnement total du code, mais tu pourrais s'il te plaît m'éclairer un peu sur le fonctionnement en général des data registers ?? Est-ce que ce sont des variables ? des tableaux ? Et généralement, comment savoir s'il faut les utiliser ??
Encore merci.

M@T

  • Membre
  • 15146 posts
25 mai 2011, 17:37
L'Action Replay gère 2 registres principaux : le "Dx Data" et l'"offset" (il y en a d'autres utilisés pour le fonctionnement interne mais on ne peut pas y toucher).

Le "Dx Data" est une variable unique, pouvant contenir un entier 32 bits (de 0 à 0xFFFFFFFF).
On ne peut pas avoir d'autres variables dans les codes, donc on s'en sert dès qu'on doit utiliser une valeur temporairement.
Si jamais il devait y avoir plusieurs variables, alors il faudrait les stocker quelque part dans une zone inutilisée de la RAM.

La seule opération possible sur cette variable est l'addition (avec le code de type 0xD4).
Bien entendu, ajouter un nombre très grand revient à soustraire.

Par exemple, le code suivant soustrait 1 à la valeur 32 bits située à l'adresse 0x02345678 et la réécrit à la même adresse :

D9000000 02345678
D4000000 FFFFFFFF
D6000000 02345678
D2000000 00000000


En effet, si la valeur était 1, alors elle devient 1 + 0xFFFFFFFF = 0x100000000, or c'est une valeur 32 bits, donc seuls les 4 octets de poids faible sont conservés (en bleu), ce qui donne bien 0 = 1 - 1.

Si la valeur était 0x12345678, elle devient 0x12345678 + 0xFFFFFFFF = 0x112345677, ce qui vaut bien 0x12345677 = 0x12345678 - 1.

Et ainsi de suite.


L'autre registre, l'offset, permet de "décaler" les adresses mémoire.
Je t'explique quelques trucs au passage, même si ce n'était pas vraiment ta question.

Il s'agit également d'une valeur 32 bits, mais on ne peut pas utiliser sa valeur directement, on peut juste la définir.
L'addition sur l'offset se fait grâce au code de type 0xDC.

Par le même principe que précédemment, on peut décaler "négativement" une adresse en définissant un offset suffisamment grand.

Exemple avec un code qui écrit une valeur 16 bits à l'adresse 0x02345678 :

D3000000 FFFFF678
12346000 0000CAFE
D2000000 00000000


L'AR va écrire 0xCAFE à l'adresse [0x02346000 + 0xFFFFF678 = 0x102345678], ce qui revient bien au code suivant : 102345678 0000CAFE.

Mais cette utilisation de l'offset négatif n'est pas vraiment utile ; c'est plutôt le contraire qui est utilisé.

Ce code, par exemple, charge l'offset du pointeur à l'adresse 0x02101F20 et écrit à une adresse située avant l'adresse pointée :

B2101F20 00000000
DC000000 FFFFF000
10000000 0000CAFE
D2000000 00000000


Explications : tout d'abord, on définit l'offset comme étant la valeur à l'adresse 0x02101F20.
Disons qu'elle vaut 0x02345678.

Ensuite, on ajoute 0xFFFFF000 à la valeur de l'offset, ce qui donne 0x02345678 + 0xFFFFF000 = 0x102344678, donc la valeur de l'offset est désormais 0x02344678 (ça revient à soustraire 0x1000).

Enfin, on écrit une valeur 16 bits à l'adresse [0x00000000 + offset], c'est-à-dire [0x00000000 + 0x02344678 = 0x02344678].

Et voilà, on a écrit une valeur à une adresse située 0x1000 octets avant l'adresse indiquée par le pointeur.
« Modifié: 25 mai 2011, 17:38 par M@T »

Pokedeus

  • Membre
  • 38 posts
25 mai 2011, 19:31
Merci énormément !
Pour voir si j'ai bien compris, est-ce que tu pourrais me dire s'il te plaît si le code ci-dessous est correct ??

B2101F20 00000000 <- On définit l'offset.
D3000000 02345678 <- L'offset vaut 0x02345678.
DC000000 FFFFFEAC <- On rajoute 0xFFFFFEAC à l'offset, soit on lui soustrait 0x154.
10000000 0000CAFE <- On écrit la valeur 16 bits 0xCAFE 0x154 octets avant la valeur indiquée par le pointeur (soit à l'adresse 0x0000000 + (0x02345678+0xFFFFFEAC) = 0x00000000 + 0x102345524 donc à l'adresse 0x02345524).
D9000000 02345524 <- On charge la valeur à l'adresse 0x02345524 dans le Dx Data.
D4000000 FFFFFFF2 <- On ajoute 0xFFFFFFF2 à 0xCAFE et on obtient donc 0xCAF0.
D6000000 02345524 <- On remet la nouvelle valeur du Dx Data à l'adresse 0x02345524.
D2000000 00000000

Est-ce que mon code est correct et est-ce que les différentes lignes effectuent ce que j'ai écrit à côté d'elles ??
Merci encore.

« Modifié: 25 mai 2011, 19:32 par Pokedeus »

M@T

  • Membre
  • 15146 posts
25 mai 2011, 19:41
Ça m'a l'air correct, mais la 1ère ligne est inutile, puisque tu redéfinis l'offset juste après.

Par contre, garde bien en tête que ce genre d'utilisation des offsets, ça n'existe pas en vrai, car c'est extrêmement peu efficace.
Quand on peut écrire directement l'adresse, on le fait.
Mais c'est très bien pour les exemples.

L'instruction 0xD3 est surtout utilisée pour remettre l'offset à zéro sans passer par l'instruction 0xD2, qui remet TOUT à zéro alors qu'il se peut qu'on ait besoin de conserver des choses comme le registre Data.

Pokedeus

  • Membre
  • 38 posts
25 mai 2011, 22:55
Merci.
Excuse-moi, mais j'ai quand même l'impression de m'être trompé : j'ai à un moment écrit ça :
Citer
D9000000 02345524 <- On charge la valeur à l'adresse 0x02345524 dans le Dx Data.
D4000000 FFFFFFF2 <- On ajoute 0xFFFFFFF2 à 0xCAFE et on obtient donc 0xCAF0.
D6000000 02345524 <- On remet la nouvelle valeur du Dx Data à l'adresse 0x02345524.
Je ne devrais pas plutôt mettre :
D9000000 00000000
D4000000 FFFFFFF2
D6000000 00000000

Vu que quasiment tous les Data Register Codes de la forme DZ000000 XXXXXXXX vont pour effectuer leurs manipulations prendre [XXXXXXXX + offset] et comme l'offset vaut justement 0x02345524, il faut mettre 0x00000000 pour les instructions du Dx Data, non ?? J'ai lu ça sur EnHacklopedia en tout cas...
« Modifié: 25 mai 2011, 23:01 par Pokedeus »

M@T

  • Membre
  • 15146 posts
25 mai 2011, 23:52
Tu as totalement raison, j'avais pas fait gaffe, excuse-moi.  ;D

Pokedeus

  • Membre
  • 38 posts
26 mai 2011, 17:50
Merci.
Excuse-moi encore une fois mais quand tu dis pour le code :

B2101F20 00000000
DC000000 FFFFF000
10000000 0000CAFE
D2000000 00000000

Citer
Et voilà, on a écrit une valeur à une adresse située 0x1000 octets avant l'adresse indiquée par le pointeur.
Tu veux dire 0x1000 octets avant l'adresse indiquée par le pointeur au début ??
Parce que au début, l'offset vaut en effet 0x02345678 mais après la ligne DC000000 FFFFF000, il vaut 0x02344678 et avec la ligne 10000000 0000CAFE, on écrit 0xCAFE à l'adresse 0x02344678, qui est le nouveau offset. Donc en fait, 0xCAFE est écrit 0x1000 octets avant l'ancienne valeur de l'offset (0x02345678), pas la nouvelle (0x02344678), non ?? Est-ce que j'ai bien compris ??
 

M@T

  • Membre
  • 15146 posts
26 mai 2011, 17:59
Le pointeur, c'est l'adresse 0x02101F20.
Dans mon exemple, il pointe vers 0x02345678, et ça ne change pas, même quand on modifie l'offset par la suite.

Pokedeus

  • Membre
  • 38 posts
26 mai 2011, 20:01
Merci.
Ah, donc en fait l'instruction BXXXXXXX 00000000 définit l'offset comme étant la valeur située à l'adresse 0XXXXXXX et toutes les modifications ultérieures sur la valeur de l'offset n'affectent pas cette instruction ?? En fait c'est comme si on copiait le contenu d'une variable x dans une variable y et qu'on modifiait y, ce qui fait que la valeur de x ne change pas, c'est cela ??
Merci encore.

M@T

  • Membre
  • 15146 posts
26 mai 2011, 20:15
Ouais, c'est bien ça.

On pourrait écrire ça comme ça (en disant qu'une adresse mémoire entre [crochets] signifie "valeur à cette adresse") :

B2101F20 00000000  <-  offset = [0x02101F20]  //  L'offset vaut la valeur à l'adresse 0x02101F20
DC000000 FFFFF000  <-  offset = offset - 0x1000  //  On soustrait 0x1000 à la valeur de l'offset (ça ne modifie pas la valeur à l'adresse 0x02101F20)
10000000 0000CAFE  <-  [offset] = 0xCAFE  //  La valeur 16 bits située à l'adresse mémoire "offset" vaut maintenant 0xCAFE
D2000000 00000000  <-  offset = 0; fin du code

Pokedeus

  • Membre
  • 38 posts
27 mai 2011, 16:20
Merci !
Maintenant, je souhaiterais savoir, si posssible, comment fais tu pour des codes qui sont encore plus éloignés des chiffres (pour les objets, ça va encore, il y avait les quantités, les numéros des objets, etc. donc il étaient encore assez "chiffrés" ;) ) : mais par exemple, pour le code pour faire du vélo dans les bâtiments :

94000130 FFFE0000
B2101F20 00000000
20001324 00000001
D2000000 00000000

J'ai compris que pour ce cas (tout comme pour le sexe du personnage), 0x0 veut dire pas de vélo et 0x1 veut dire vélo. Mais après, comment fais-tu pour trouver l'adresse 0x00001324 ?? Parce que on ne peut pas chercher la valeur, vu qu'il y en a pas, à part ce 0x0 et 0x1 (et beaucoup d'autres variables risquent d'avoir les mêmes valeurs...) ??
Merci encore.

Pokedeus

  • Membre
  • 38 posts
27 mai 2011, 18:10
En fait, excuse-moi : j'ai réussi à trouver par moi-même le code pour faire le vélo dans les bâtiments.
Par contre, pourrais-tu m'aider s'il te plaît à comprendre comment trouver le code pour traverser les murs :

94000130 FCFD0200
12060CC4 00002000
D0000000 00000000
94000130 FCFD0100
12060CC4 00001C20
D2000000 00000000

Dans ce code, j'ai cru comprendre que l'adresse 0x02060CC4 indiquait l'état du terrain sur lequel se trouve le personnage (traversable, pas traversable) et 0x2000 indiquait que le terrain était traversable et 0x1C20 que le terrain ne l'était pas. Est-ce que j'ai bien compris ??
Si oui, pourrais-tu s'il te plaît me dire comment tu t'y prendrais pour trouver cette adresse et ces valeurs (vu que dans le jeu, il ne traverse jamais les murs, on ne peut pas changer d'état comme pour le vélo...) ??
Merci encore de ton aide.

M@T

  • Membre
  • 15146 posts
28 mai 2011, 04:04
Pour le vélo, il s'agit d'une valeur booléenne, qui vaut soit 0 (personnage pas sur le vélo), soit 1 (personnage sur le vélo).
Afin de trouver l'adresse, pas le choix : monter sur le vélo, rechercher une valeur 8 bits valant 1 ; descendre du vélo, rechercher "0" ; monter, rechercher "1" ; etc.

Concernant le code pour traverser les murs, c'est de l'ASM.
Tout ne fonctionne pas uniquement avec des variables, il y a également un programme derrière pour faire fonctionner le jeu.

En l'occurrence, il s'agit d'une routine (ou "procédure", "fonction", appelle ça comme tu veux) qui renvoie un booléen (0 ou 1 donc) selon si le joueur est bloqué ou non.
Ça calcule sûrement des trucs par rapport à la case du terrain sur laquelle il se dirige et ça vérifie si il peut y aller ("0", il n'est pas bloqué) ou pas ("1", il est bloqué).

L'instruction d'origine est "1C20", soit, traduit en ARM Thumb : mov r0, r4 (r0 est le registre de retour de la procédure).
En fait, juste avant dans la RAM, la routine fait quelques calculs dont le résultat est placé dans le registre r4.
Là, ça copie la valeur de r4 et la place dans r0, qui est la valeur de retour.
Dans beaucoup de langages de plus haut niveau, ça pourrait s'écrire "return r4;".

Le code remplace l'instruction par "2000", ce qui signifie : mov r0, 0 (placer "0" dans le registre r0).
En clair, la routine retournera toujours 0, quel que soit le résultat du calcul précédent, ce qui fera croire au jeu que le joueur n'est jamais bloqué ("return 0;").

Tu peux essayer ce code-ci, qui aura pour effet de toujours renvoyer 1, ce qui fera que le joueur est toujours bloqué ("2001" -> "mov r0, 1" -> "return 1;") :

12060CC4 00002001


Pour trouver ces adresses-là, c'est beaucoup plus compliqué ; il faut un débogueur et savoir l'utiliser (breakpoints et tout le tralala).
« Modifié: 28 mai 2011, 04:06 par M@T »

Pokedeus

  • Membre
  • 38 posts
28 mai 2011, 10:10
Merci !
Et pour le code pour passer du héros masculin au héros féminin :

94000130 FCFF0000
B2101F20 00000000
20000094 00000001
D2000000 00000000

Est-ce qu'on peut trouver l'adresse de 0x94 avec Emucheat ou bien il faut utiliser aussi un débogueur (vu que l'on ne se transforme pas  facilement en fille dans le jeu...) ??
Vu que c'est quand même juste une valeur booléenne, je serais tenter de dire que Emucheat suffirait, mais je sèche complètement pour savoir comment la trouver...
Merci encore de ton aide.

M@T

  • Membre
  • 15146 posts
28 mai 2011, 10:57
C'est en effet une valeur booléenne (0 -> garçon et 1 -> fille) ; pour la trouver le débogueur ne sert à rien, et EmuCheat non plus à vrai dire.
Ça se passe plutôt du côté de la sauvegarde à mon avis ; COM (l'auteur de Pokesav) a dû comparer deux sauvegardes similaires avec chacune le personnage de sexe opposé à l'autre.

Avec quelques essais il a dû trouver l'offset dans la sauvegarde, et à partir de là c'est assez facile de retrouver l'offset dans la RAM (il y a une correspondance entre certaines zones de la sauvegarde avec certaines zones dans la RAM).

Il ne faut pas se leurrer, pas mal de codes comme celui-ci sont générés par Pokesav ; COM nous mâche pas mal de boulot.
« Modifié: 28 mai 2011, 10:58 par M@T »

Pokedeus

  • Membre
  • 38 posts
28 mai 2011, 22:59
Merci !
Excuse-moi, je reviens un petit peu en arrière, mais j'aurais encore une question pour le code des objets : en cherchant les adresses et les identités des objets (pour faire les codes) sur celui-ci, je ne les ai pas trouvés. Dans le menu "Editer" des objets, il y avait juste le nom des objets et rien d'autre... Est-ce qu'il faut utiliser la fonction codes AR du Pokésav pour cela ?? Mais il me donne alors un code bien plus long et qui semble écrit en ARM Thumb (ici le code pour les médocs en 998) :

94000130 FCFF0000
B2101F20 00000000
E0000B60 000000A0
03E60011 03E60017
03E60018 03E60019
03E6001A 03E6001E
03E6001F 03E60020
03E60021 03E60022
03E60023 03E6002B
03E6002C 03E60026
03E60027 03E60028
03E60029 03E60012
03E60013 03E60014
03E60015 03E60016
03E6001B 03E60024
03E6002A 03E6001C
03E6001D 03E60025
03E6002D 03E6002E
03E6002F 03E60030
03E60031 03E60032
03E60033 03E60034
03E60035 03E60036
00000000 00000000
D2000000 00000000

On reconnaît des éléments comme le début de la liste des médocs en 0xB06 et les ID des objets mais pourquoi certains ID sont sautés et à quoi sert la ligne E0000B60 000000A0 ??
C'est donc de ce code qu'il faut s'aider pour faire le code "réduit" , c'est cela ??
Merci encore de ton aide !

M@T

  • Membre
  • 15146 posts
29 mai 2011, 04:09
En effet, il faut exporter un code AR pour trouver l'ID de l'objet.

Sinon, c'est pas de l'ARM, c'est juste un code de type "E", qui sert à écrire un grand nombre d'octets consécutifs d'un coup.

La ligne "EXXXXXXX YYYYYYYY" copie les YYYYYYYY octets qui suivent cette ligne vers l'adresse [0XXXXXXX + offset].

Par exemple, ce code-ci :

E2345678 00000010
00010203 04050607
08090A0B 0C0D0E0F


Équivaut à celui-ci :

02345678 00010203
0234567C 04050607
02345680 08090A0B
02345684 0C0D0E0F


Pour un nombre d'octets relativement faible comme là, on ne voit pas vraiment l'utilité, mais plus ça augmente, plus le ratio entre la longueur du code en utilisant le type "E" et celle en utilisant "0" (écriture de valeurs 32 bits) se rapproche de 1:2.

C'est donc une bonne méthode pour réduire les codes où on a besoin d'écrire des plages de données (octets consécutifs).


Sinon, certains ID sont "sautés" parce que les objets que tu choisis avec Pokesav ne sont pas toujours consécutifs ; là par exemple tu passes de 0x11 à 0x17 au début, puis tu refais ceux de 0x12 à 0x16 plus tard vers la moitié du code.

Pokedeus

  • Membre
  • 38 posts
29 mai 2011, 20:12
Merci.
Encore une fois, pourrais-tu s'il te plaît m'aider à comprendre le code pour qu'à l'adversaire il reste 1 PV :

94000130 FCFF0000
621BEA80 00000000
B21BEA80 00000000
10005EC8 00000001
D2000000 00000000

Merci encore de ton aide.

EDIT: Désolé de ne pas avoir précisé plus ma question, j'étais pressé.
En fait, je souhaitais juste savoir comment tu faisais pour trouver l'adresse de 0x00005EC8 car en effet, on ne connaît pas les PV initials ?? Est-ce qu'il faut par exemple capturer un Pokémon, regarder ses PV, essayer d'en rencontrer un qui est du même niveau et du même sexe et avec cela tenter de trouver la bonne adresse ??
Est-ce que c'est la bonne technique ??
Merci encore de ton aide !
« Modifié: 29 mai 2011, 22:28 par Pokedeus »

M@T

  • Membre
  • 15146 posts
30 mai 2011, 08:09
Non, de toute façon tu ne connaîtras jamais les PV exacts, parce que les IV les font varier (contrairement au sexe qui n'a aucune influence).

Il ne faut pas rechercher une valeur exacte mais une valeur qui diminue.
Dans EmuCheat, faut d'abord rechercher "?" au début du combat (valeur initiale inconnue), puis "-" (ou "<", ça revient au même) à chaque fois que l'adversaire perd des PV.

Pokedeus

  • Membre
  • 38 posts
31 mai 2011, 15:56
Merci M@T !
Je m'étais justement demandé comment chercher des valeurs dont on sait juste si elles ont augmenté ou baissé par exemple.
Donc, les signes seront les suivants, c'est cela ??
"?" -> Valeur inconnue.
">" ou "+" -> Valeur qui a augmenté.
"<" ou "-" -> Valeur qui a baissé.
"=" -> Valeur restée identique.
"!=" -> Valeur qui a changé.
Est-ce que c'est cela qu'il faut utiliser pour rechercher des valeurs dont on connait uniquement les variations ?? Parce que j'étais parfois confronté à ce problème avec Emucheat...
Merci encore de ton aide !

M@T

  • Membre
  • 15146 posts
31 mai 2011, 16:51
Ouaip, c'est bien ça.  :)

Pokedeus

  • Membre
  • 38 posts
01 juin 2011, 17:44
Merci encore !
Je viens de remarquer aujourd'hui que le code pour les events (Arceus, Darkrai, etc.) dans Pokémon Platine est assez spécial, et je ne le comprends pas du tout. Pourrais-tu s'il te plaît "éclairer
ma lanterne" :) ?? J'ai pris ici le code pour débloquer l'event de la Flûte Azurée :

94000130 FCFF0000
621BFCD0 00000000
B21BFCD0 00000000
B0000004 00000000
0000B600 EDB88320
2000B62C 0000000A
D2000000 00000000

D'abord, ce qui m'étonne et m'intrigue énormément, c'est que on n'utilise pas le même pointeur que dans les autres codes, soit 0x02101F20, mais bien 0x021BFCD0... Je ne comprends absolument pas, d'autant que ce n'est même pas un autre pointeur que nous donne NDS PC&BT lors de sa recherche. Il avait en effet trouvé ces trois pointeurs chez moi :

02101F20:0227E3D0
021C0974:0227E3D0
0227E3A8:0227E3B0

Et ce qui est utilisé ici ne correspond à aucun d'eux. Pourrais tu s'il te plaît m'expliquer pour quelle raison ??
D'autre part, le reste du code m'est presque aussi obscur : pourquoi après avoir défini le pointeur à la ligne B21BFCD0 00000000, on en redéfinit un autre (assez étrange d'ailleurs) à la ligne d'après (B0000004 00000000) ?? D'autre part, j'avoue franchement ignorer la "raison d'existence" ;) de la ligne 0000B600 EDB88320 et je ne comprends qu'à moitié la ligne 2000B62C 0000000A (j'ai juste compris que le 0xA est le type de l'événement (Arceus, Shaymin, etc.) et 0xB62C l'adresse où le mettre, mais pour trouver cette adresse...).
Je suppose que ce code fait encore une fois appel à de l'ARM thumb, mais je ne suis pas sûr.
Merci encore de ton aide M@T !

Pokedeus

  • Membre
  • 38 posts
02 juin 2011, 08:44
Excuse-moi encore une fois, j'ai trop écrit et je me suis peut-être mal expliqué.
En fait, je ne comprends tout simplement pas le code en entier cette fois-ci. Pourrais-tu, s'il te plaît, me l'expliquer rapidement ??
Merci beaucoup pour ton aide, M@T !

Pages: 1 [2]    En haut ↑