Posiblemente no tienes mucha idea de que estamos haciendo en esta serie de posts. No te preocupes amigo/a/e que vamos a intentar explicarlo brevemente.
Vamos con ello:
¿Qué es FCEUX? – Se trata de algo más que un emulador de la NES de Nintendo. Incorpora funcionalidades para poder grabar las partidas en formato fm2 (Tool-assisted game movies) y poder extender los juegos programando scripts en Lua.
¿Se pueden jugar juegos de NES con este emulador? Si dispones de la rom de un juego de NES podrás cargarlo y disfrutarlo.
¿Necesito tener FCEUX instalado para seguir estos posts? – No pero es muy muy recomendable. La idea de estos posts es que quienes los sigan dispongan de FCEUX. Para saber como compilar la última versión en GNU+Linux puedes visitar el primer post: FCEUX – 0x00 – Compilar la última versión
¿Necesito saber Lua para programar scripts para FCEUX? La verdad es que no. Lua es muy sencillo y los ejemplos de código que se ponen de ejemplo en estos posts son muy cortos.
Y bueno. Espero que eso ayude un poco a ponerse en situación a un posible lector para que sepa un poco de que va todo esto.
Descargar la ROM del Tetris
En esta ocasión vamos a necesitar descargar la rom del Tetris.
Descargar rom: Tetris.zip
Esa rom la cargaremos en el emulador para probar que funciona correctamente el juego. No es necesario descomprimir el zip.
Cargar la ROM del Tetris
Abres FCEUX y presionas Control + O . Seleccionas la rom y a disfrutar.
Otra opción es cargar también tanto la ROM como el script en LUA (Si es que quieres cargar uno) directamente así:
$ fceux --noframe --nogui --loadlua Tetris.lua Tetris.zip
Sacando la posición y el tipo de piezas
Cargando este pequeño script en LUA podemos determinar en que posición andan las piezas.
while true do
x = memory.readbyte("0x0060"); -- Posición x pieza actual
y = memory.readbyte("0x0061"); -- Posición y pieza actual
p = memory.readbyte("0x0062"); -- id pieza actual
gui.text(10,10,"x: " .. x .. " y: " .. y .. " p: " .. p);
emu.frameadvance();
end
Esto permite por ejemplo conocer los tipos de piezas que vamos a tener en el tetris. Son estos: imgs_tetris_nes_piezas.tar.gz
Podemos ir parando el juego (pulsando la tecla Pause de nuestro teclado) cada vez que sale una nueva ficha. Moverla con la tecla F para ver que la variable p va cambiando de número.
Esto al final nos permite sacar eso que he sacado yo. Y saber que en tetris disponemos de 7 tipos de piezas.
Lo que hace el juego es girar las piezas 90 grados. De esa forma en teoría todas las piezas tendrían que tener 4 posiciones pero si giras por el ejemplo la 10 cuatro veces en todas tendrás la misma forma.
Si giras la pieza 8,9 cuatro veces 90 grados tendrás solamente 2 formas.
Es por esto que al final disponemos solamente de 7 tipos de piezas que suponen 18 formas.
Examinar zonas de la memoria
Para ver que valores cambian en memoria es interesante crear una función que nos permita justo eso. Podemos imprimir los resultados por consola para ir mirando si cambian.
Un código de ejemplo para hacer esto puede ser este:
function from_Hex(str)
local converted = string.format( "0X%4.4X", str )
return converted
end
function show_memory(from,to)
for position = from,to -- Desde 00 a FF por ejemplo
do
valor = string.format('%02d',memory.readbyte(from_Hex(position)));
io.write("[" .. from_Hex(position) .. " : " .. string.format('%X',valor) .. "]\n");
end
end
while true do
x = memory.readbyte("0x0060"); -- Posición x pieza actual
y = memory.readbyte("0x0061"); -- Posición y pieza actual
p = memory.readbyte("0x0062"); -- id pieza actual
gui.text(10,10,"x: " .. x .. " y: " .. y .. " p: " .. p);
show_memory(96,98)
emu.frameadvance();
end
Al cargarlo junto a la rom vamos a poder ir viendo en pantalla la zona que indiquemos. En este caso le he pasado que muestre desde la 96 a 98.
Le paso los valores en decimal.
Eso me permite monitorizar los valores desde la consola y por tanto buscar novedad en esas posiciones de memoria.
El valor de la siguiente pieza
Gracias a la función show_memory() que hemos creado antes podemos ir monitorizando zonas de memoria.
En este caso mientras juego voy monitorizando y viendo que cosas cambian. Se puede por ejemplo sacar la zona de memoria en la que se almacena la siguiente pieza.
Por ejemplo en la siguiente captura se ve que la pieza «NEXT» es la 2.
Y si miramos en la consola se ve que está en la posición 0x00BF
Cambiando la siguiente pieza por la que queramos
Ahora simplemente podemos crear una variable llamada «next» que contenga la zona de memoria en la que se almacena la siguiente pieza.
Luego cambiamos el valor por el de la pieza que queramos que salga.
function from_Hex(str)
local converted = string.format( "0X%4.4X", str )
return converted
end
function show_memory(from,to)
for position = from,to -- Desde 00 a FF por ejemplo
do
valor = string.format('%02d',memory.readbyte(from_Hex(position)));
io.write("[" .. from_Hex(position) .. " : " .. string.format('%X',valor) .. "]\n");
end
end
while true do
x = memory.readbyte("0x0060"); -- Posición x pieza actual
y = memory.readbyte("0x0061"); -- Posición y pieza actual
p = memory.readbyte("0x0062"); -- id pieza actual
gui.text(10,10,"x: " .. x .. " y: " .. y .. " p: " .. p);
next="0x00BF"
memory.writebyte(next, "10")
show_memory(190,192)
emu.frameadvance();
end
Se puede ver como siempre sale la pieza 10 (el cuadrado). En la captura se ve que ha salido 43 veces seguidas :D.
Y bueno. Más o menos eso es todo por hoy.
Saludos cordiales.