Hola a todos.
Mi inquietud esta vez consiste en que quiero hacer un visualizador de sprites de NES... con Game Maker, obviamente.
El procedimiento es simple: utilizar la función de abrir un archivo binario para su lectura, abrir así la ROM de NES, y que lea una línea de valores de una dirección específica, por ejemplo:
001CE0: 00 00 00 00 00 00 7E 3C 3C 7E 73 FF FF FF 42 00
Eso debe visualizarlo como una tile de 8x8 píxeles.
El método de composición de imágenes de NES es 2BPP, es decir que superpone dos planos de 8x8 píxeles de dos colores posibles, para formar una tile de un máximo de 4 colores.
Esta imagen lo explica claramente:
(http://www.baddesthacks.net/forums/download/file.php?id=154)
Más info aquí:
www.romhacking.net/forum/index.php/topic,20294.msg285382.html
Los colores a usar se especifican aparte, eso no es problema.
Mi gran problema es escribir un código que lea un número binario (en realidad Game Maker lee los valores binarios en decimales, pero creo que para eso puedo utilizar un conversor decimal a binario para GM que creo haber visto en la web), dibuje un píxel cuando lea "1" y deje un espacio o dibuje un pixel del color de fondo cuando lea "0". La pregunta es ¿cómo puedo hacer que lea uno por uno los dígitos de un número binario y no como todo un valor? O sea, necesito que si lee "1100100" pueda separar 1 -1 -0 - 0 -1 - 0 - 0
Si a alguien le interesa este asunto, he visto en el blog de YoYo Games un tipo que está haciendo un emulador de Commodore 64 integramente en GM.
https://www.yoyogames.com/blog/84
Yo no quiero hacer un emulador de NES, sólo un visor de sprites, pero puede servir para entender lo que busco hacer. Es algo parecido, pero no es lo mismo, por eso me resulta complicado.
Con lo sencillo que es hoy en dia con los editores de sprites y los dificil que era aquel entonces por tener que hacerlo a código.
bueno, justamente ahora en el curso de estudio que estoy haciendo implementan una formula para "sacar digitos", se basa en usar el resto y la division entera.
bien, entonces supongamos que tenemos 15302 y queremos sacar el digito menos significativo, es decir el 2, para ello tienes que usar la division entera y quedarte con el resto, en game maker se usa "mod".
Es importante guardar el numero que vamos a operar porque de otra manera no podremos actualizarlo o bien, ir desarmandolo por digitos.
Entonces lo guardamos en alguna variable, en este caso en "numero":
numero = 15302
hacemos la operacion MOD para sacar el digito menos significativo:
digito = numero mod 10
y ahora digito contiene al numero 2.
Ahora bien, necesitamos "actualizar" el numero inicial para que ya no tenga al 2, es decir, para que quede 1530 (sin el 2), para ello se usa el cociente entero, en game maker es "div"
hacemos la operacion DIV para quitar el 2:
numero = numero div 10
ahora "numero" solo contiene 1530
Luego se repiten las operaciones tantas veces sea necesaria para quitar todos los digitos. Generalmente se usa un ciclo while de la siguiente manera:
[GML]
while(numero != 0){
digito = numero mod 10;
numero = numero div 10;
}
[/GML]
Y eso es todo, para desarmar el numero.
saludos :D
He usado este método para crear una matriz 8x8 con valores de 0 a 3 (números de 2 bits):
[gml]
file_bin_seek( ida, drc ); //byte inicial
for( i=0; i<16; i+=1 ) //leer 16 bytes
byte = file_bin_read_byte( ida );
k = 0; //posicion en el array de bytes
for( j=0; j<8; j+=1 ){ //capa 1
for( i=0; i<8; i+=1 ){
mtz[i,j] = (byte[k] >> i) & 1;
}
k += 1;
}
for( j=0; j<8; j+=1 ){ //capa 2
for( i=0; i<8; i+=1 ){
mtz[i,j] += ((byte[k] >> i) & 1) << 1;
}
k += 1;
}
[/gml]
En el editable adjunto se puede ver la matriz, pero no he encontrado los sprites en ninguna rom, espero que te ayude.
Cita de: Clamud en Abril 17, 2016, 12:29:50 AM
He usado este método para crear una matriz 8x8 con valores de 0 a 3 (números de 2 bits):
[gml]
file_bin_seek( ida, drc ); //byte inicial
for( i=0; i<16; i+=1 ) //leer 16 bytes
byte = file_bin_read_byte( ida );
k = 0; //posicion en el array de bytes
for( j=0; j<8; j+=1 ){ //capa 1
for( i=0; i<8; i+=1 ){
mtz[i,j] = (byte[k] >> i) & 1;
}
k += 1;
}
for( j=0; j<8; j+=1 ){ //capa 2
for( i=0; i<8; i+=1 ){
mtz[i,j] += ((byte[k] >> i) & 1) << 1;
}
k += 1;
}
[/gml]
En el editable adjunto se puede ver la matriz, pero no he encontrado los sprites en ninguna rom, espero que te ayude.
Gracias, es exactamente lo que buscaba. El único inconveniente fue que los sprites se veían invertidos horizontalmente, por ejemplo en el juego Super Mario Bros. la letra K es la dirección 9150. Si ingresamos esa dirección vamos a ver una K invertida.
Lo resolví simplemente modificando esta parte del código del evento Draw:
}
x = i*20 + 200;
y = j*20 + 100;
draw_rectangle( x,y, x+20, y+20, false );
}
Le puse un "-" en i*20, así:
}
x = i*-20 + 200;
y = j*20 + 100;
draw_rectangle( x,y, x+20, y+20, false );
}
Entonces ahora dibuja los rectángulos hacia la izquierda.
Gracias nuevamente, también a Black_Cat por su ayuda.
Que bien, entonces sí funciona. Busqué otros sprites en la rom de SMB y encontré el de la imagen de arriba, pero aparece en una dirección diferente.
(http://i.imgur.com/qXxDljV.png)
Cita de: Clamud en Abril 19, 2016, 06:12:50 PM
Que bien, entonces sí funciona. Busqué otros sprites en la rom de SMB y encontré el de la imagen de arriba, pero aparece en una dirección diferente.
(http://i.imgur.com/qXxDljV.png)
Ah, sí, eso es porque la address que aparece arriba es de donde toma los datos para dibujar el sprite este. Un eventual editor de sprites (que tal vez sea mi objetivo final) deberá modificar los bytes de la línea de bits que empieza en 1CE0, y los cambios se verán en el sprite que encontraste.