Examinar direcciones de la memoria es útil en la creación de un TAS para encontrar valores importantes que están ocultos para el usuario o difícil de determinarlo con solo verlo en la pantalla. Son importantes también para la creación de bots para ayudarlos en el juego, que está cubierto en la página de Scripts Lua.
Buscar RAM también se conoce como "buscar trampa", que es un nombre engañoso.

Buscando una dirección

Escogiendo la configuración correcta

Uno de los primeros pasos más importantes es usar la configuración más adecuada para buscar direcciones (por ejemplo, no es buena idea usar 2-byte en sistemas 8-bit). Mira las configuraciones por defecto para mostrar las mejores configuraciones en cada plataforma.
Hay más direcciones de los que uno podría imaginar, así que para encontrar el que buscamos, debemos filtrar las direcciones de memoria usando el cuadro de búsqueda.
Primero, ve hacia algún punto relevante en el juego, uno en el que está a punto de cambiar el valor que buscas. Abre el cuadro de búsqueda. No busques nada aún, pero clickea "Comenzar" (Start) o "Reiniciar" (Reset). Esto inicia las direcciones que ya están en juego. Si quieres buscar direcciones con un valor específico, escribe el valor, selecciona "igual qué" (equal to), y clickea buscar.
Ahora juega hasta que el valor haya cambiado presumiblemente. Ahora regresa al cuadro de búsqueda. Ahora selecciona "menor qué" (less than), "igual qué" (equal to) o "distinto a" (not equal to) y así sucesivamente. Si comparas con el valor anterior, selecciona "valor anterior" (previous value) y clickea buscar. Si tratas de buscar direcciones con un valor específico, escribe el valor y selecciona "igual qué" (equal to) y clickea buscar. Clickea "Actualizar valores" (update values) si el emulador no lo hace automáticamente.
Sigue haciéndolo hasta que hayan bajado las posibilidades y puedas saber fácilmente cual es. A veces hay dos o más direcciones que son similares al que tratas de buscar.
Cuando hayas encontrado las direcciones o por ahí quedan varias direcciones y no figuras cual es, mira las direcciones en la memoria. Juega, y la dirección o las direcciones saldrán.

Un ejemplo útil - Encontrar la posición X

El más simple y a su vez el más útil que uno puede encontrar es la posición X de un personaje. Supervisando la posición X uno se puede asegurar de maximizar la distancia cubierta dada en un periodo de tiempo dado. Lo siguiente podría ser un proceso aplicable en todos los juegos donde la posición X podría ser necesariamente encontrado.
Super Mario Bros. (Japan, USA) será usado para el ejemplo.
El emulador ordena los bytes basado en como cambian los valores. Al permanecer de pie la posición x debe permanecer 'igual'. Una vez te muevas a una dirección diferente, la posición X ya no es igual. Debes tener en cuenta que la búsqueda por defecto siempre se compara con el valor anterior y no con el valor original. Otra opción es comparar el valor con un valor conocido.
Siguiendo este método, deben reducir las posibilidades a unos 20 bytes. Observando estos bytes mientras se juega en tiempo real se podría concluir que la posición X se encuentra en 0400. Una investigación adicional puede encontrar la subposición X en 0086, el subpixel es el valor decimal de la posición X de Mario fuera de 256, estas direcciones de memoria se pueden colocar en "Herramientas" > "Observar RAM" (Tools > Ram Watch) para la observación conveniente mientras se juega.

Otros consejos

Generalmente, moverse a la derecha hace un valor "mayor qué" (greater than) el valor anterior y moverse a la izquierda hace un valor "menor qué" (less than) el valor anterior. Esto depende de la convención de la programación del juego, y no siempre será cierto. Por ejemplo, algunos juegos no tienen direcciones constantes de la coordinación de un objeto, pero se calculan por la pantalla y la posición del sprite.
Puedes guardar fácilmente el trabajo, revisando las direcciones que encontraste. Por ejemplo, si encuentras la posición X a menudo es razonable asumir que la posición Y tiene dos o cuatro bytes por delante.
Cuando buscar el valor de la velocidad, moverse a la derecha generalmente será positivo y moverse a la izquierda generalmente sería negativo. En este caso, usualmente necesitas usar comparaciones "Con signo" (signed).
Los números negativos son interpretados diferente dependiendo si el valor se lee "Con signo" (signed) o "Sin signo" (unsigned). Cuando un byte se lee entre 0 a 255 sin interpretar el signo (Sin signo), un número positivo se cuenta hasta 0 y un número negativo se cuenta desde 255. Cuando el emulador busca valores con signo, se te interpretarán los valores en un rango entre -128 hasta 127. En las comparaciones se toma en cuenta esto.
En los emuladores más recientes uno puede escoger el tamaño de los datos de 1, 2 o 4 bytes, uno puede predecir si el byte mantiene menos o igual que 255, 65535 o 4294967295 intervalos de precisión. Un paso por un personaje podría ser entre 1 unidad y 10.000 unidades, así que una prueba y error con el tamaño del dato podría ser necesario. Usualmente no es necesario verificar valores desalineados.
Un buen método de comenzar podría ser seleccionando 2-bytes para la búsqueda. Esto evita confusiones cerca de los límites del byte (como cuando 127 va a -128, o 255 va a 0). Si no funciona, intenta con 1-byte o 4-bytes.
Para las plataformas relativamente simples, como NES, puedes utilizar el editor hexadecimal incorporado para observar la RAM, viendo que direcciones están cambiando mientras estás actuando. Por ejemplo, nunca se sabe cómo cambia exactamente el valor de subpixel, por lo que puede ser más fácil buscar valores, que cambia cada fotograma cuando funciona la aceleración y se mantiene quieto cuando no. Además, es más útil cambiar las páginas enteras (con las teclas "Page Up" y "Page Down") mientras observas la RAM, no desplazarlas.

Memoria asignada dinámicamente

Los juegos a veces asignan datos durante su ejecución, significa que las direcciones exactas de las cosas pueden cambiar con el paso de los niveles, en el comienzo del juego e incluso en cada fotograma. Esto podría realmente complicarte el trabajo, pero siempre puedes encontrar un punto a las direcciones ya usadas.
El caso más simple sería que una dirección fija siempre tiene la dirección exacta del valor que te importa.
Pero más frecuentemente el puntero mantiene una dirección base y el valor que buscas se almacena en un desplazamiento conocido de la dirección base.
Por supuesto, no hay ninguna regla que el puntero se almacenará en una dirección fija, pero habrá un puntero al puntero en esos casos.
La pila de llamadas es una ubicación especialmente popular para los punteros directos.

Arreglos, listas enlazadas y otras estructuras divertidas de datos

Los juegos a veces almacenan colecciones de artículos similares, como la lista de los enemigos activos. Estas colecciones a menudo se almacenan como arreglos o listas enlazadas.
Los arreglos son sólo regiones de memoria en donde varias instancias del mismo tipo de datos se almacenan en secuencia. Son muy populares con los juegos simples, puesto que se pueden asignar estáticamente en un punto fijo todo el tiempo.
Las listas enlazadas son más comunes en sistemas más modernos, pero todavía pueden encontrarse en plataformas más antiguas. Se construyen como una cadena de regiones de memoria formadas de forma similar que están unidas entre sí usando punteros. Las listas enlazadas suelen estar enlazadas por dobles, cada elemento tiene un puntero tanto al elemento siguiente como al elemento anterior de la lista.
También puedes encontrar hashmaps. Los Hashmaps actúan como un arreglo, pero permiten la recuperación rápida de datos con una clave específica. Con el fin de trabajar con estos tendrás que hacer ingeniería inversa de la función exacta hash el juego utiliza.
En todos los casos para estas estructuras de datos, no sólo necesitarás saber dónde se encuentran la estructura de datos, sino también como encontrar el elemento específico de la colección que quieras conocer. A menudo puedes encontrar punteros o índices para el valor específico en otra parte de la memoria.

La pila de llamadas (callstack)

Prácticamente todos los sistemas informáticos utilizados en práctica utilizan un enfoque de la pila de llamadas.
La pila de llamadas es una región dedicada de memoria utilizada para implementar llamadas de función. La pila de llamadas comúnmente crece hacia abajo, la dirección de los nuevos datos van disminuyendo.
Cuando se llaman funciones en el programa, se añaden valores a la pila de llamadas. Algunos de estos valores pueden ser muy interesantes, ya que podrían ser el valor que estás buscando.
El problema con la pila de llamadas es que los valores son sobrescritos a menudo. Las funciones que regresan y las nuevas funciones que se están llamando hacen que la reutilización de la memoria sea excepcionalmente alta y pueden complicar bastante la observación de la memoria, ya que puede requerirse un tiempo muy exacto para ver la memoria cuando se está usando para el propósito deseado.
La ventaja de observar la pila es que los valores muy interesantes tienden a almacenarse en ella, como los valores intermedios utilizados en la lógica del juego.

Espejos, duplicados, valores que sobran y otras copias

Los datos son muy frecuentemente extraídos de una ubicación y almacenados en otra. La dirección que encuentres podrían no ser la versión actual del valor, podrían ser sólo una copia hecha para el procesamiento posterior.
Ejemplos de estos duplicados incluyen valores utilizados para los propósitos de visualización, la memoria previa asignada y argumentos en la pila de llamadas, pero hay infinitas razones para que un juego duplique datos.
Sea variable que estas copias pueden laguearse detrás del valor real, podrían ser más o menos estables en su dirección y pueden tener reglas sutilmente diferentes sobre el valor real almacenado.

Otros recursos


Enlaces

Expand/Collapse collapse-content-_448488cee8b24dedab2d376cd635a71a

ES/MemorySearch last edited by adelikat on 8/7/2022 8:32 PM
Page History Latest diff List referrers View Source