Documentación sobre ASM orientado a romhacking (?)

Lugar donde se intentarán resolver problemas específicos
Responder
Avatar de Usuario
Leeg
Mensajes: 379
Registrado: 20 Mar 2014, 00:25

Documentación sobre ASM orientado a romhacking (?)

Mensaje por Leeg » 26 Ago 2014, 10:22

Hola.

Os escribo para pediros un favor: ¿conocéis algún recurso interesante que explique cómo utilizar / leer un desensamblador y dónde poner breakpoints para obtener información de un programa? Si es orientado a ROM mejor, pero si no, me es lo mismo.


Es que estoy atascado con una cosa (descubrir qué compresión se esta usando en un archivo) y además me gustaría meterme un poco en este tema, aunque soy consciente de que es un lenguaje de bajo nivel y complicadísimo.

Yo lo único que he encontrado por el estilo ha sido esto:
http://lparchive.org/Policenauts/Update%2051/

Eso es todo, gracias.

Un saludo.

Avatar de Usuario
CUE
Administrador
Administrador
Mensajes: 5521
Registrado: 24 Ene 2011, 16:52

Mensaje por CUE » 26 Ago 2014, 10:33

De eso encontrarás muy poco, y siempre orientado a casos concretos, que, por norma, no te van a servir para nada más.

Lo primero es conocer el lenguaje, así que si preguntas cómo leer el ensamblador es como decir que quieres traducir un juego pero sólo sabes usar un editor hexadecimal :twisted:

Después tienes que conocer la consola, que una simple instrucción te dice mucho más de lo que se supone. Por ejemplo, si estás en PSX sabes que un offset 0x80xxxxxx se refiere a una dirección de memoria, o si estás en GB escribir un valor en 0x2100 indica cambiar de página. Esas cosas no te van a venir en manuales de ensamblador porque son específicas de la máquina.

Y, por supuesto, necesitas un emulador en condiciones para poder hacer todas esas cosas. En algunas consolas los hay que son muy buenos (GB, NES), en otras no tanto (NDS, GBA), y en otras es un suplicio (PSX). Hay otras formas para leer/desensamblar, pero son peores si no estás metido en el tema.

Después es cuestión de paciencia, poniendo breakpoints a diestro y siniestro intentando acotar lo que buscar. Te puedo decir que yo, a veces, encuentro cosas enseguida en GB, pero en otras lo dejo por imposible.

Al final se suele recurrir a la solución más simple: preguntar a ver si alguien sabe algo del juego/compresión para no perder tiempo.

Avatar de Usuario
Leeg
Mensajes: 379
Registrado: 20 Mar 2014, 00:25

Mensaje por Leeg » 26 Ago 2014, 10:48

Aunque sea material específico me es igual, si es por ver cómo se trabaja de esa forma, más que nada.

Lo que estoy tratando de averiguar es la compresión en una imagen de un juego de genesis/megadrive. Hay un emulador buenísimo que se llama Exodus que viene con desensamblador para todos los procesadores de la consola. También está en RHDN la documentación oficial de la consola para desarrolladores filtrada y le he estado echando un vistazo estos días.

La cuestión es que tengo esa imagen perfectamente localizada y acotada en la ROM, con su paleta y todo, pero no logro sacar información de ahí. Una cosa que se me ha ocurrido es ponerme a comparar el código hexadecimal de esa parte de la ROM con el de la RAM en el momento de mostrar la imagen en pantalla, pero no he llegado a muchas conclusiones más allá de que es seguro que se trata de algún tipo de compresión, pero ni idea de cuál (he probado los formatos más famosos de genesis que son Saxman, Enigma, Nemesis y Kosinski pero ninguno ha dado resultado). La cosa es que como tampoco sé cómo trabajan todos los formatos de compresión que existen por ahí, no voy a saber identificarlo ni siquiera comparando el código de la ROM con el de la RAM. Por eso estoy un poco perdidillo.

Avatar de Usuario
CUE
Administrador
Administrador
Mensajes: 5521
Registrado: 24 Ene 2011, 16:52

Mensaje por CUE » 26 Ago 2014, 11:41

Primero mira si hay alguna traducción de ese juego, por si alguien ha hecho alguna cosilla en algún idioma y puede decir algo.

Si tienes los datos en ROM y en RAM postéalos para ver si alguien puede hacer algo.

Avatar de Usuario
Leeg
Mensajes: 379
Registrado: 20 Mar 2014, 00:25

Mensaje por Leeg » 26 Ago 2014, 12:08

Esta imagen es del logo de sega.

ROM

RAM


En el archivo sacado de la ROM yo identifico hasta tres partes o cuatro.

Desde 0x00 hasta 0x1F es la paleta de la imagen.

En 0x80 empieza la imagen comprimida. Y creo que hay una especie de cabecera que serían estos primeros bytes:

0310 0000 0620 FC11 0F23 0F00

Creo que es una cabecera porque mirando en el comienzo de otras imágenes comprimidas en esa misma ROM hay algo parecido:

1340 0000 2680 E811 0F23 0F32

1EE0 0000 3DC0 4411 0F23 0F33


Esto es lo que cutremente he podido identificar yo en las primeras líneas de lo que es el archivo en sí para saber que está comprimido:

[img]http://i.imgur.com/GsdJ18o.png[/img]

Y después desde 0x0890 hasta el final del archivo hay una especie de esqueleto de la imagen formado por bytes ordenados desde 01 hasta 2F...

Mi teoría es que el bloque ese de datos comprimidos es una especie de diccionario que después se llama por partes desde este último bloque final de bytes ordenados... pero de ahí no saco más.

Avatar de Usuario
CUE
Administrador
Administrador
Mensajes: 5521
Registrado: 24 Ene 2011, 16:52

Mensaje por CUE » 26 Ago 2014, 12:38

Pues a simple vista parece alguna variante de LZ, y mirando un poco más se confirma que es una LZSS normal y corriente.

FF es el byte de flags, con todos a 1, que indican que se copie un byte tal como está. Como están los 8 activos, pues se copian 8 bytes.
EF tiene 7 bits a 1 y uno a 0. Los que están a 1 indican lo mismo, y el que está a 0 indica que se tomen 2 bytes, de donde se toma la longitud y el offset de donde se copian las cosas (llámalo diccionario, ventana, anillo o lo que sea).

Lo que hay que buscar es dónde empieza realmente. En los ficheros que has posteado parece que el primer byte con flags es el que está en 0x0086:
- FC 11-0F-23-0F-00-00-01-11-00-01
- FF 16-67-00-15-66-66-01-55
- FE 1C-01-56-66-15-55-56-61-14 <--- 1C-01
- EF 55-55-16-00-43-00-11-11-11 <--- 43-00
- FF 11-77-78-88-89-77-77-88
- BD 88-3A-01-67-77-78-88-32-01-66 <-- 3A-01, 32-01
- F7 ...
Parece ser que el bit de flags se lee de derecha a izquierda, así que los dos bytes del flag 0 son los que he indicado.

Lo que hay antes podría ser la longitud, que el 0620 se aproxima al tamaño de los datos de la RAM, y, si no recuerdo mal, en Megadrive se usa big endian porque lleva una cpu Motorola. Tampién puede que los bytes iniciales indiquen el inicio de los datos, que sería muy útil para buscar más cosas comprimidas.

El resto, cómo separar los 2 bytes en longitud y offset de la ventana, etc., te lo dejo a ti.

Avatar de Usuario
Leeg
Mensajes: 379
Registrado: 20 Mar 2014, 00:25

Mensaje por Leeg » 26 Ago 2014, 12:48

Vaya, pues qué mala suerte XDD Estaba intentando este verano hacerme un descompresor de LZSS para otra ROM en PHP y no lo he conseguido. Pues nada, voy a intentar a ver si lo logro.

Muchísimas gracias ;)

Avatar de Usuario
CUE
Administrador
Administrador
Mensajes: 5521
Registrado: 24 Ene 2011, 16:52

Mensaje por CUE » 26 Ago 2014, 13:00

Pues debería ser al contrario. Que sea una LZSS es lo mejor que puede pasar porque es muy simple de hacer, y parece que aquí se usa el método clásico.

~~~ AÑADIDO ~~~
He modificado el LZSS clásico original. Sólo he quitado las inicializaciones, que las hace con espacios en blanco, para que las haga con ceros, y en la línea 189 he puesto que se sitúe en el offset 0x86. Obviamente, es para trabajar con los ficheros que me has dado. Sólo tienes que poner lzss d "Comparar - Logo Sega Original.bin" nuevo.bin y el fichero generado, salvo unos bytes más al inicio, es idéntico al que has posteado, así que ya tienes programa para la compresión. La codificación no la he tocado, eso todo para ti.

Fuente y ejecutable: https://www.mediafire.com/?izt9yg99j7t7xvw

~~~ MÁS AÑADIDO ~~~
Si pones if (!i && !j) break; en la línea 203 descomprime solo lo necesario, cortando con el clásico método de poner a cero el doble byte cuando el flag es 0.

Si en 211 pones printf("%08X %08X\n", ftell(infile), ftell(outfile)); te muestra el offset final de lo codificado y de lo decodificado, para saber las longitudes.

Avatar de Usuario
Leeg
Mensajes: 379
Registrado: 20 Mar 2014, 00:25

Mensaje por Leeg » 26 Ago 2014, 19:50

Oh vaya, muchas gracias tío. Te debo una. Voy a cotillear el código fuente a ver si entiendo cómo va XD


PD: Para compilarlo en VS Studio 2013 y posteriores hay que añadirle

Código: Seleccionar todo

#define _CRT_SECURE_NO_DEPRECATE
Microsoft se ha vuelto quisquilloso en temas de seguridad.

Avatar de Usuario
CUE
Administrador
Administrador
Mensajes: 5521
Registrado: 24 Ene 2011, 16:52

Mensaje por CUE » 27 Ago 2014, 09:52

¿Y quién os manda usar esos compiladores? Teniendo el MinGW (GCC), gratuito, que te hace todo y más, sin necesidad de instalar Framework ni Internet Explorer (que me expliquen por qué cojones tengo que instalar eso) ni nada innecesario. Tener que añadir cosas a programas sobradamente probados y compatibles es otra muestra de la prepotencia de Microsoft, que tiene que hacer todo como ellos quieren.


La decodificación es simple de entender. La codificación no tanto porque ese programa usa árboles binarios de búsqueda, y creo que debo de ser de los pocos que usan cosas de ésas. Por algún sitio está explicado el funcionamiento de la LZSS, que fue de las primeras cosas publicadas en este [s]antro de mala muerte[/s] foro, aunque creo que lo hacía al revés, tomando los flags en sentido inverso y cosas así.

Creo que tengo por algún sitio la versión "normal", sin árboles de búsqueda, un pelín más lenta pero más entendible. Si tengo ganas la buscaré, pero tengo una dejadez encima que no veas.

Avatar de Usuario
Leeg
Mensajes: 379
Registrado: 20 Mar 2014, 00:25

Mensaje por Leeg » 27 Ago 2014, 11:17

No te preocupes, encontré un PDF en este foro en el que se explica el uso de LZSS para el texto de Bahamut Lagoon. Será lo mismo, ¿no?

Avatar de Usuario
Leeg
Mensajes: 379
Registrado: 20 Mar 2014, 00:25

Mensaje por Leeg » 27 Ago 2014, 16:26

Una pregunta... ¿Por qué cuando descomprimo un archivo con este ejecutable LZSS y lo vuelvo a comprimir no se parece en nada al original?
Lo de editar el offset 0x86 es solo para la descompresión pero no para la compresión, ¿no? ¿O me estoy olvidando de algún parámetro?

Avatar de Usuario
CUE
Administrador
Administrador
Mensajes: 5521
Registrado: 24 Ene 2011, 16:52

Mensaje por CUE » 27 Ago 2014, 17:36

Porque la compresión la harán de una forma ligeramente diferente. Normalmente se debe a lo que he comentado, que nadie suele trabajar con árboles binarios de búsqueda. Además, si te fijas, al comprimirlo te sale un fichero más pequeño que el original, lo que demuestra que lo hacen de una forma menos óptima. Eso puede dar problemas porque a lo mejor no usan el anillo correctamente, el "text_buf[]".

Si descomprimes ese fichero que has comprimido te saldrá un fichero decodificado idéntico al que tienes.

Lo del 0x86 es para decodificar el ejemplo que pusiste. Ahí tendrás que pedir un offset para que el programa comience a decodificar desde una posición determinada de la rom.

Avatar de Usuario
Leeg
Mensajes: 379
Registrado: 20 Mar 2014, 00:25

Mensaje por Leeg » 27 Ago 2014, 18:14

Pero en teoría sigue siendo el mismo sistema de compresión y debería ser compatible con los datos de la ROM y no dar problemas... ¿o eso es mucho pedir? XD

Avatar de Usuario
CUE
Administrador
Administrador
Mensajes: 5521
Registrado: 24 Ene 2011, 16:52

Mensaje por CUE » 28 Ago 2014, 09:50

Es la misma compresión pero no tiene por qué funcionar.

El inicio de los datos comprimidos es 11-0F (F-011)y 23-0F (F-023), que significa copiar (0x0F+3) bytes desde (0x011+1) bytes antes y copiar (0x0F+3) bytes desde (0x023+1) bytes antes. Eso significa que el anillo/buffer/ventana comienza 0x12 bytes antes de donde se pongan los datos decodificados, y deben estar a cero. Pero lo normal, como lo hace el programa, es que esos 0x12 bytes sean 0x1000-0x12, de ahí que ponga DF-FF (F-FDF) y FF-FF (F-FFF), y en ambos casos tomará 0x0F+3 ceros. Al programa le da igual porque le da lo mismo tener 1, 100 o 10000000 bytes a cero antes, pero para la consola es todo un mundo e imagino que en el juego lo tendrán simplificado para usar el mínimo de memoria posible. La única forma de saber cómo hacerlo bien es ver cómo lo decodifica la consola para saber si inicializa 0x12 bytes a cero o si lo hace con 0x1000-0x12 o como lo haga.

Responder