Ayuda Chocobo Dungeon 2 [Fuente]

Lugar donde se intentarán resolver problemas específicos
Responder
Avatar de Usuario
tchusami
Mensajes: 86
Registrado: 29 Ene 2011, 20:01
Ubicación: Librilla
Contactar:

Ayuda Chocobo Dungeon 2 [Fuente]

Mensaje por tchusami » 03 Jun 2011, 17:25

Pues como me has dicho cue, me paso por aqui y dejo unas imagenes en el post referentes a la fuente, si quieres puedo pasarte el link del juego por mp o cualquier cosa:

Fuente vista con tile molester a 2bpp reverse-order
[img]http://4.bp.blogspot.com/_JRMWgLQ8eF0/T ... ocobo2.png[/img]

Fuente vista en ram
[img]http://4.bp.blogspot.com/_JRMWgLQ8eF0/T ... +Buena.JPG[/img]

Gracias por todo tio!

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

Mensaje por CUE » 03 Jun 2011, 17:42

Necesito dos cosas:
- un savestate con la VRAM para ver "in situ" cómo está la fuente
- el fichero con la fuente, aunque recuerdo que era un fichero 'gordo', pero con el WinRAR se rebajaba bastante, que no se permiten enlaces a descargas de juegos, no sea que luego venga el osito Teddy a darnos por el c*l* ;)

De entrada ya te digo que son 4bpp reverse-order. También que no sale la fuente como tal, pues es una mezcla de 2, como se puede ver en la segunda imagen que has puesto, con la jodienda que cada carácter trae unos bytes de más, no sé si para indicar el ancho o algo por el estilo. Luego lo explico mejor, que ahora ando un poco liado. También busco luego a ver si tengo algo guardado de ese juego, que pasé de él porque por aquella época estaba muy pez y había cosas que no sabía hacer (ahora tampoco, pero no lo comentes a nadie, jeje).

Avatar de Usuario
tchusami
Mensajes: 86
Registrado: 29 Ene 2011, 20:01
Ubicación: Librilla
Contactar:

Mensaje por tchusami » 03 Jun 2011, 18:58

Bien jeje por aqui el archivo que contiene la fuente: http://dl.dropbox.com/u/23705939/ALLBIN.rar
y por aqui el save: http://dl.dropbox.com/u/23705939/SaveState_ChD2.rar

A ver si cuando puedas te aclaras con esto tio que yo voy a seguir estudiando...
Gracias de nuevo :wink:

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

Mensaje por CUE » 03 Jun 2011, 21:09

Por hoy no voy a hacer nada más, que es viernes y me piro a tomarme unas cervezas, mientras otros [s]os jodéis[/s] estudiáis.

Aquí está la VRAM, con la fuente arriba a la derecha a 16bpp. En la parte inferior está a 4bpp, con una paleta buscada a ojo para que se vea cómo se superponen los caracteres:
[img]http://img263.imageshack.us/img263/5619/fnt1.png[/img]

Aquí la fuente sin nada más, con un ligero cambio de paleta para que se note mejor la superposición de caracteres:
[img]http://img718.imageshack.us/img718/1272/fnt2.png[/img]

Así es como está la fuente en el fichero, a 4bpp, con caracteres de 12 pixeles de ancho y 14 de alto (las dos últimas filas de cada carácter no tengo ni idea de lo que son, pero imagino que contendrán el ancho del carácter entre otras cosas):
[img]http://img851.imageshack.us/img851/7066/46096440.png[/img]

Aquí está la fuente separando los caracteres, y sí, son así de feos, igual que salen en el juego:
[img]http://img37.imageshack.us/img37/6296/94224959.png[/img] [img]http://img846.imageshack.us/img846/8743/28176956.png[/img]


¿Por qué se superponen los caracteres? Por comodidad. Al emplear 4bpp lo que hacemos es que cada pixel ocupe 4 bits, los 2 superiores pertenecientes a una parte de los caracteres y los inferiores a la otra. Al mezclarlos es cuando nos da esa imagen que tenemos en la VRAM. Se hace así para no tener que trabajar con 2bpp, que es la resolución real de la fuente, y en el mismo 'gráfico' va todo, encargándose el programa de tomar los bits correspondientes cuando tiene que coger un carácter.

Avatar de Usuario
tchusami
Mensajes: 86
Registrado: 29 Ene 2011, 20:01
Ubicación: Librilla
Contactar:

Mensaje por tchusami » 05 Jun 2011, 23:55

Impresionante, de verdad me tienes que explicar como has hecho eso xD, oye te dejo mi direccion de correo por mp, me agregas y hablamos, ok? aunque hasta el miercoles despues del catastrofico examen de programacion no podre hacer nada... bueno en eso quedamos tio!

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

Mensaje por CUE » 06 Jun 2011, 11:56

¿Tengo que explicar todo o algo en concreto? Es que estoy en época de vaguitis y las ganas que tengo de hacer algo es directamente proporcional a nada ;)

Bueno, pues con lo que dices del examen de programación creo que puedo hacer de cabroncete. Te explicaré cómo sacar la fuente y lo programas tú, que es una chorrada y no me apetece tampoco hacerlo. Así practicas para el siguiente examen :twisted:

Hay un ligero error en lo que he contado. Las dos filas con datos están al principio del carácter y no al final, y, para fastidiar, no llevan el ancho del carácter.

Avatar de Usuario
tchusami
Mensajes: 86
Registrado: 29 Ene 2011, 20:01
Ubicación: Librilla
Contactar:

Mensaje por tchusami » 07 Jun 2011, 21:58

Bueno no todo, tu explicame cosillas de como programar el extractor de la fuente a ver si lo pillo que en cuanto venga de hacer el examen me pongo a calentarme la cabeza jeje

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

Mensaje por CUE » 08 Jun 2011, 12:18

Primero hay que entender cómo está grabada. Como ya he visto que más o menos la has sacado del fichero, me salto la búsqueda. Como curiosidad, puedes usar el tilemolester y decirle que te muestra tiles de 3 de ancho a 4bpp reverse y "verás" los caracteres partidos. Cada uno es de 12 bits de ancho, y nunca me molesté en averiguar si el TM puede mostrar esos valores, pero como muestra los tiles siempre en múltiplos de 8 bits, al usar 3 tiles de ancho estamos mostrando 3*8/12 = 2 líneas de cada carácter en una misma línea, y así podemos ver la fuente, aunque partida.

Los datos de la fuente comienzan en la posición 0xA40000 del fichero ALLBIN.BIN, y se componen de:
-0xA40000: 4 bytes con la cabecera del fichero (0x20000100)
-0xA40004: la paleta de colores en formato ABGR1555, es decir, 2 bytes para cada color
-0xA40044: 4 bytes con el número de caracteres de la fuente
-0xA40048: los datos raw de la fuente

La cabecera puede indicar el número de colores de la fuente (0x20, es decir, 16 para cada semifuente), pero realmente no nos importa lo que signifique.

La paleta es el formato normal de PSX, 2 bytes por color, formato ABGR, con 5 bits para cada intensidad y 1 bit para enmascaramiento. La verdad es que no se necesita para nada pues se puede poner la paleta que se quiera. Hay 32 colores, que corresponden a 16 por cada una de las semifuentes, algo normal pues estamos con gráficos de 16 colores (4bpp).

Los datos de cada carácter siempre están precedidos de 12 bytes:
- 2 bytes con la posición horizontal del carácter en la VRAM
- 2 bytes con la posición vertical del carácter en la VRAM
- 2 bytes con la anchura en la VRAM, siempre 0x0003 (el ancho se mide en múltiplos de 4)
- 2 bytes con la altura en la VRAM, siempre 0x000C
- 2 bytes con el número de bytes del carácter, siempre 0x0048
- 2 bytes de relleno, siempre 0x0000, aunque también pueden indicar el número de millones que me van a dar por explicar esto

Hasta ahora no necesitamos nada de esa información, ni el número de caracteres de la fuente. Es información que nos la trae floja y sólo nos sirve para saber dónde empieza cada carácter realmente y poder escribir todas estas marranadas que, como mucho, interesarán a dos personas (si es que siempre aparecen un par de locos, cachis).

Después de esos 12 bytes ya tenemos los datos del carácter, con la peculiaridad de que siempre van dos caracteres juntos. Como son datos de 4bpp significa que cada 4 bits nos define un punto, pero de esos 4 bits los 2 superiores pertenecen a un carácter y los 2 inferiores a otro.

Un ejemplo para que se vea más claro: Si un byte tiene el valor binario 'abcdefgh', eso indica que un punto es 'abcd' y otro 'efgh', que correponden a los puntos 'ab' y 'ef' de una semifuente y a los puntos 'cd' y 'gh' de la otra.

Con datos numéricos, y tomando un byte que valga 0x74:
- 0x74 es 01110100 en binario
- 01110100 se descompone en dos puntos: 0111 y 0100
- 0111 se descompone en 01 y 11
- 0100 se descompone en 01 y 10
- Así que de ese byte sacamos que 01 y 01 son dos puntos de la primera semifuente y 11 y 10 son dos puntos de la segunda

Para ponerlo más sencillo aún: cada uno de los 0x48 bytes hay que descomponerlo en grupitos de 2 bits, y se van poniendo alternativamente en cada fuente, es decir, se graban 2 bits en un fichero, los 2 siguientes en otro, los 2 siguientes otra vez en el primero, etc. Así podremos sacar dos ficheros raw de 2bpp lineares que se podrán modificar fácilmente. Una vez modificados, se hace la operación inversa, cogiendo alternativamente 2 bits de cada fichero para reinsertarlos en la fuente original.

*** Si vas a utilizar el TM para editar los ficheros recuerda añadir 4 puntos en blanco después de cada 12. Así consigues que los caracteres sean de 16 pixeles de ancho y podrás visualizarlos bien. O eso o que el TM tenga alguna opción que no me molesté en mirar y que permita visualizar anchos que no sean múltiplo de 8 bits.

Hay un problema en estos datos: No se especifica el ancho del carácter, por lo que si se cambia alguno habrá que hacerlo sobre uno que tenga el mismo ancho.

Bueno, pues ahora te lo lees 10-12 veces para sacar algo en claro y las dudas que tengas, que las tendrás, no te quepa duda, me las comentas. Eso sí, a 100 euros la duda o fracción, así que más vale que espabiles ;)

Avatar de Usuario
tchusami
Mensajes: 86
Registrado: 29 Ene 2011, 20:01
Ubicación: Librilla
Contactar:

Mensaje por tchusami » 10 Jun 2011, 00:41

Bueno CUE pues te voy a deber mucho mas de 100€ xD

Vayamos al grano, tengo aqui una duda y es, cuando yo forme un nuevo byte organizando los bits por parejas como me has dicho, creo un byte que contenga las dos parejas y los demas bits a 0, o formo un byte que contega cuatro parejas, dos que pertenecen al primer byte leido y otras dos que pertenecen al segundo?

Tambien tengo problemas con la sintaxis pero creo que en esto conseguire apañarme solito jejeje

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

Mensaje por CUE » 10 Jun 2011, 08:20

Para ponerlo muchísimo más fácil, aquí va una explicación sencilla.

Hasta ahora sabemos, entre otras cosas:
- cada carácter es de 12x12 pixeles
- son 4 bpp, así que en un byte hay 2 pixeles, es decir, se necesitan 6 bytes por fila
- es lo que el TileMolester llama pomposamente "reverse-order", así que hay que intercambiar los dos dígitos hexadecimales
- cada pixel de 4bpp son en realidad 2 pixeles de 2bpp, cada uno correspondendiente a una semifuente

Para hacerlo más sencillo, llamemos a cada pixel con una letra. Así, inicialmente tenemos los 6 bytes de una fila como:

Código: Seleccionar todo

|  abABcdCD efEFghGH  |  ijIJklKL mnMNopOP  |  qrQRstST uvUVwxWX  |
luego se verá por qué los he llamado así y por qué los divido en 3 grupos de 2 bytes

Dividimos cada byte en sus 2 pixeles:

Código: Seleccionar todo

| abAB-cdCD efEF-ghGH | ijIJ-klKL mnMN-opOP | qrQR-stST uvUV-wxWX |
aquí ya vemos los 12 pixeles, separados en 3 grupos de 4 pixeles cada uno

No nos olvidemos que es "reverse":

Código: Seleccionar todo

| cdCD-abAB ghGH-efEF | klKL-ijIJ opOP-mnMN | stST-qrQR wxWX-uvUV |
NOTA: todo el mundo habla del "reverse" pero muy pocos saben realmente lo que es, aunque ahora, después de esta explicación, la mayoría dirá que ya lo sabía

Y ahora "repartimos" esos pixeles entre sus dos semifuentes:

Código: Seleccionar todo

|     cd-ab-gh-ef     |     kl-ij-op-mn     |     st-qr-wx-uv     | <--- semifuente 1
|     CD-AB-GH-EF     |     KL-IJ-OP-MN     |     ST-QR-WX-UV     | <--- semifuente 2
ahora queda claro por qué llamé a los bits de esa manera (mayúsculas para una semifuente, minúsculas para la otra)

Así es cómo se transforman cada dos bytes iniciales en un byte para cada una de las semifuentes. Y hasta aquí puedo leer, así que ahora toca lo de colorín, colorado, esta explicación se ha acabado.

El programa para extraer la fuente es en realidad una chorrada, de pocas líneas. Te lo podría dar hecho, que se tarda 5 minutos en hacer, pero entonces estaríamos como siempre, donde unos pocos tienen que dar las cosas siempre hechas y nunca os molestaríais en intentarlo. Si tienes problemas en hacer el programa, entonces haces un copy&paste de lo que hayas hecho, comentas lo que te pasa, y a partir de ahí se verá cómo solucinarlo.

Avatar de Usuario
tchusami
Mensajes: 86
Registrado: 29 Ene 2011, 20:01
Ubicación: Librilla
Contactar:

Mensaje por tchusami » 12 Jun 2011, 18:19

yo lo estoy haciendo en C# y he conseguido separar el archivo en dos tal y como dice CUE pero no consigo que se vean los caracteres claros T_T

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

Mensaje por CUE » 13 Jun 2011, 11:02

¿¿¿Has probado a limpiarte las gafas??? ;)

Sin saber cómo está hecho no puedo decir cómo arreglarlo. Estas cosas son así, hasta que no se ven no se sabe por qué fallan.

Avatar de Usuario
tchusami
Mensajes: 86
Registrado: 29 Ene 2011, 20:01
Ubicación: Librilla
Contactar:

Mensaje por tchusami » 14 Jun 2011, 18:35

Jajajaja es lógico que no puedas ver lo que esta mal sin tener el codigo xD asi que te lo dejo por aqui xD.
No te asustes que esta bastante chapucero xD

Código: Seleccionar todo

using System;
using System.Collections;
using System.Linq;
using System.Text;
using System.IO;
using System.Data;

namespace ConsoleApplication1
&#123;

    class Program
    &#123;

        static void Main&#40;string&#91;&#93; args&#41;
        &#123;
            Byte leido;
            byte&#91;&#93; leido2;
            BitArray a1 = new BitArray&#40;8&#41;;
            BitArray a2 = new BitArray&#40;8&#41;;
            bool selec = true;
            byte b = 0;
            int n = 0;

            FileStream of = new FileStream&#40;".\\Fuente1.raw",FileMode.Create,FileAccess.Write&#41;;
            FileStream pf = new FileStream&#40;".\\Fuente2.raw",FileMode.Create,FileAccess.Write&#41;;
            FileStream f = new FileStream&#40;".\\ALLBIN.bin",FileMode.Open,FileAccess.Read&#41;;
            BinaryReader reader = new BinaryReader&#40;f&#41;;

            int offset = 10747904; //Offset 0xA40000
            int offsetmod = offset;
            for&#40;int i = 0; i<offset; i++&#41; reader.ReadByte&#40;&#41;;//Avanza hasta el Offset de la fuente
            for &#40;int a = 0; a < 72; a++&#41;
            &#123;
                leido = reader.ReadByte&#40;&#41;;
                of.WriteByte&#40;leido&#41;;
                pf.WriteByte&#40;leido&#41;;
                offsetmod++;
            &#125;
            while &#40;offsetmod < 10779728&#41; //Lee hasta el Offset 0xA47C50 &#40;fin de fuente&#41;
            &#123;
                for &#40;int a = 0; a < 12; a++&#41;//Lee los 12 bytes de cabecera
                &#123;
                    leido = reader.ReadByte&#40;&#41;;
                    of.WriteByte&#40;leido&#41;;
                    pf.WriteByte&#40;leido&#41;;
                    offsetmod++;
                &#125;
                n = 0;
                for &#40;int a = 0; a < 72; a++&#41;//Lee dos caracteres
                &#123;
                    leido2 = reader.ReadBytes&#40;1&#41;;
                    BitArray bits = new BitArray&#40;leido2&#41;;

                    if &#40;selec&#41;
                    &#123;
                        #region AsignaBits&#40;1&#41;
                        a1&#91;0&#93; = bits.Get&#40;4&#41;;
                        a1&#91;1&#93; = bits.Get&#40;5&#41;;
                        a1&#91;2&#93; = bits.Get&#40;0&#41;;
                        a1&#91;3&#93; = bits.Get&#40;1&#41;;
                        a2&#91;0&#93; = bits.Get&#40;6&#41;;
                        a2&#91;1&#93; = bits.Get&#40;7&#41;;
                        a2&#91;2&#93; = bits.Get&#40;2&#41;;
                        a2&#91;3&#93; = bits.Get&#40;3&#41;;
                        selec = false;
                        #endregion
                    &#125;

                    else
                    &#123;
                        #region AsignaBits&#40;2&#41;
                        a1&#91;4&#93; = bits.Get&#40;4&#41;;
                        a1&#91;5&#93; = bits.Get&#40;5&#41;;
                        a1&#91;6&#93; = bits.Get&#40;0&#41;;
                        a1&#91;7&#93; = bits.Get&#40;1&#41;;
                        a2&#91;4&#93; = bits.Get&#40;6&#41;;
                        a2&#91;5&#93; = bits.Get&#40;7&#41;;
                        a2&#91;6&#93; = bits.Get&#40;2&#41;;
                        a2&#91;7&#93; = bits.Get&#40;3&#41;;
                        #endregion

                        #region ArrayBits2Byte&#40;1&#41;
                        if &#40;a1.Get&#40;7&#41;&#41; b++;
                        if &#40;a1.Get&#40;6&#41;&#41; b += 2;
                        if &#40;a1.Get&#40;5&#41;&#41; b += 4;
                        if &#40;a1.Get&#40;4&#41;&#41; b += 8;
                        if &#40;a1.Get&#40;3&#41;&#41; b += 16;
                        if &#40;a1.Get&#40;2&#41;&#41; b += 32;
                        if &#40;a1.Get&#40;1&#41;&#41; b += 64;
                        if &#40;a1.Get&#40;0&#41;&#41; b += 128;
                        #endregion
                        
                        of.WriteByte&#40;b&#41;;
                        b = 0;

                        #region ArrayBits2Byte&#40;2&#41;
                        if &#40;a2.Get&#40;7&#41;&#41; b++;
                        if &#40;a2.Get&#40;6&#41;&#41; b += 2;
                        if &#40;a2.Get&#40;5&#41;&#41; b += 4;
                        if &#40;a2.Get&#40;4&#41;&#41; b += 8;
                        if &#40;a2.Get&#40;3&#41;&#41; b += 16;
                        if &#40;a2.Get&#40;2&#41;&#41; b += 32;
                        if &#40;a2.Get&#40;1&#41;&#41; b += 64;
                        if &#40;a2.Get&#40;0&#41;&#41; b += 128;
                        #endregion

                        pf.WriteByte&#40;b&#41;;
                        b = 0;
                        selec = true;
                    &#125;
                    n++;
                    if &#40;n==24&#41; || &#40;n==48&#41; || &#40;n == 72&#41;
                    &#123;
                        for &#40;int p = 0; p < 4; p++&#41;
                        &#123;
                            of.WriteByte&#40;0&#41;;
                            pf.WriteByte&#40;0&#41;;
                        &#125;
                    &#125;
                    
                    offsetmod++;
                &#125;
            &#125;
            of.Close&#40;&#41;;
            pf.Close&#40;&#41;;
        &#125;
    &#125;
&#125;
Bueno, tu diras jeje

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

Mensaje por CUE » 15 Jun 2011, 09:17

Cuando venga esta tarde-noche explico cómo hacerlo, de una forma sencilla. Espero que no sea eso lo que se enseña hoy día, que eso de avanzar hasta el offset y el tratamiento de números binarios es para colgarte. Como castigo te vas a ver todas las fotos de la Carmen de Mairena que hay en la red y te pones de fondo de pantalla alguna donde esté en bolas.

Avatar de Usuario
tchusami
Mensajes: 86
Registrado: 29 Ene 2011, 20:01
Ubicación: Librilla
Contactar:

Mensaje por tchusami » 15 Jun 2011, 15:01

ok tio xD si es que no me han explicado nada de como trabajar con bytes en la uni, solo me explican mierda xD

Responder