Programación #3: Mejorando el motor de plataformas BASIC y otras coserías.

Buenas. Tras el éxito demoledor de mi anterior entrada (de valor arqueológico demostrado, rescatando una parte perdida de la Historia de los Videojuegos como es una versión RC del Tomb Raider 2 para PSX y que prometí que investigaría pero que no he tenido tiempo ni de tocar), con ningún comentario, y una baja de visitas acojonante en la última semana (por mi culpa y no actualizar :P), me dispongo a seguir con el tema de la programación, que aunque también me resulte parco en cuanto a comentarios (y eso que se supone que se piden por vuestro bien), sé que al menos ayuda a algunos programadores anónimos. Como no he recibido ninguna indicación sobre el nivel, doy el empleado en el anterior artículo sobre BASIC como “bueno” y sigo en mi linea.

cat_licking.jpg

Como hablamos adelantamos el martes pasado, en el anterior artículo, hoy nos dedicaremos a pulir un poco el motor de plataformas BASIC símplemente añadiéndole soporte para pulsaciones simultáneas de teclas, lo que aumentará la jugabilidad muchísimos enteros. Sin más dilación, pasemos a hablar de los puertos de E/S.

Los puertos de E/S son la forma que tiene el procesador para comunicarse con los periféricos. Uno de estos periféricos, que es el que nos ocupa, es el teclado. El teclado está dividido en ocho semifilas (cada una cubriendo el estado, de forma binaria, de cinco teclas de las 40 que maneja el Spectrum) y cada una de esas semifilas está mapeada a una dirección de E/S. Esto significa que si queremos saber qué teclas de una semifila en concreto están pulsadas, tendremos que leer el valor de la dirección de E/S correspondiente. Esto se consigue con IN.

Para saber las direcciones correctas, podemos calcularlas sabiendo que cada semifila está numerada de 0 a 7 y que su dirección de E/S cumple la fórmula 254 + 256 * (255 – 2 ^ n), pero mejor miramos un poco de escaquilleo el manual del Spectrum 48 donde se nos muestra la siguiente información:

IN 65278 lee la semifila CAPS SHIFT a V
IN 65022 lee la semifila A a G
IN 64510 lee la semifila Q a T
IN 63486 lee la semifila 1 a 5
IN 61438 lee la semifila 0 a 6
IN 57342 lee la semifila P a Y
IN 49150 lee la semifila ENTER a H
IN 32766 lee la semifila SPACE a B

Esto de las semifilas y las 40 teclas nos puede confundir si no olvidamos que el teclado del ZX Spectrum original tenía precísamente 40 teclas y estaban ordenadas según el siguiente gráfico, donde vemos cláramente que hay 4 filas de 10 teclas. Llamamos, pues, semifilas, a cada una de las dos mitades de cada fila. Con un poco de matemáticas de segundo de EGB podremos darnos cuenta de que, en total, hay ocho semifilas:

spectkey.jpg

Por ejemplo, si queremos ver si se está pulsando la tecla O, habrá que ver primero en qué semifila está. Mirando el teclado, vemos que está en la semifila que va desde la Y hasta la P, cuya dirección es 57342. Haciendo un LET a=IN 57342 obtendremos en a un valor de 0 a 255 del que deberemos entender si “O” está pulsada o no.

Por lo general, esto se hace mirando los bits del valor leído del puerto. Los cinco bits menos significativos del byte leído nos indican el estado de las cinco teclas. El bit 0 indica siempre el estado de la tecla más externa de la semifila (la de más a la derecha en las semifilas de la derecha, y la de más a la izquierda en las de la izquierda). Este estado está en lógica inversa, esto es, el bit correspondiente a la tecla valdrá 1 si esta tecla está sin pulsarse, y 0 si está pulsada:

X X X 4 3 2 1 0
- - - Y U I O P

Sabiendo esto, para ver si la O está pulsada deberemos comprobar que el bit 1 del dato leído del puerto situado en 57342 valga 0.

Si el BASIC tuviera alguna herramienta eficaz para trabajar con el valor de los bits de un byte, esta tarea sería realmente trivial. Como no los tenemos, habrá que buscarse otra forma. La más sencilla es comparar con valores fijos. Como por lo general tendremos O, P, Q, A, nos damos cuenta de que todas están en diferentes semifilas excepto O y P, y nunca tendremos que detectar la pulsación de O y P a la vez (no se puede avanzar a la vez en direcciones opuestas). Sólo tendremos que ver qué valor decimal corresponde a los patrones binarios XXX11110 para la pulsación de P, Q o A (las tres están situadas en el extremo más externo de sus semifilas correspondientes) y XXX11101 para la pulsación de O.

Si eres un poco avispado ya te habrás dado cuenta del problema, llegando a este punto: ¿Qué valor tiene ese XXX? (no, porno no es un valor binario válido) ¡Ay, amigo! ¡Buena pregunta! Normalmente muchos programadores asumían que también estaba a 1 (con lo que usaríamos el valor 254 para comparar en el caso de P, Q o A y 253 en el caso de O, ya que 11111110 = 254 y 11111101 = 253), pero por desgracia eso no es cierto para todos los modelos de Spectrum ni para todas las configuraciones de hardware existentes (periféricos conectados al ordenador pueden poner valores diferentes en el bus de datos). Las placas de issue 2, por ejemplo, contienen otros valores en el bus de datos a la hora de acceder al teclado.

Hay muchas formas de resolver este problema, pero la más sencilla es símplemente comparar con dos valores: el que devuelve un teclado normal y el que devuelve un teclado de issue 2. Esto es un poco guarro, pero estamos programando en BASIC Spectrum (el cual, por definición, es bastante guarro) y, lo que es más importante: funciona y no quita muchos ciclos, lo cual es indispensable.

Una ligera prueba en Spectaculator, que puede configurarse para que use el teclado de issue 2, nos da los valores que buscamos para los bits que desconocemos. Sólo tenemos que teclear y ejecutar este pequeño programa, y fijarnos como normalmente obtenemos 253 y 254 (255 sin pulsar nada) para las pulsaciones de O y P, respectivamente, y otros valores diferentes si activamos el teclado issue 2 en las opciones del emu:

10 PRINT AT 0,0; IN 57342; " "
20 GOTO 10

Los valores que obtenemos para estas pulsaciones son 189 y 190 (con 191 sin pulsar), lo que significa que los bits desconocidos son nada más y nada menos que XXX = 101. Podremos garantizar que nuestro programa funcionará en todos los Spectrum si comparamos siempre con ambos valores (por ejemplo, para detectar O deberíamos mirar si IN 57342=253 OR IN 57342=189).

Lo que haremos con nuestro programa del otro día será quitar los INKEY$ y cambiarlos lecturas a los puertos. El programa así modificado quedaría, por tanto, tal que así:

100 LET fr=1-fr:
    IF sal=1 THEN GOTO 120
110 IF y<20 THEN
       IF ATTR(y+2,x)=7 AND ATTR(y+2,x+1)=7 THEN
          PRINT AT y,x;"  ";AT y+1,x;a$;AT y+2,x;b$:
          LET y=y+1
120 IF IN 57342=253 OR IN 57342=189 THEN
       IF x>0 THEN
          IF ATTR(y,x-1)=7 AND ATTR(y+1,x-1)=7 THEN
             LET a$="AB“:
             LET b$=”CD“:
             LET c$=”EF“:
             LET x=x-1:
             PRINT AT y,x;a$;” “;AT y+1,x;(b$ AND fr=0);(c$ AND fr=1);” ”
130 IF IN 57342=254 OR IN 57342=190 THEN
       IF x<30 THEN
          IF ATTR(y,x+2)=7 AND ATTR(y+1,x+2)=7 THEN
             LET a$=”GH“:
             LET b$=”IJ“:
             LET c$=”KL“:
             PRINT AT y,x;” “;a$;AT y+1,x;” “;(b$ AND fr=0);(c$ AND fr=1);:
             LET x=x+1
140 IF IN 64510=254 OR IN 64510=190 THEN
       IF sal=0 THEN
          IF ATTR(y+2,x)<>7 OR ATTR(y+2,x+1)<>7 THEN
             LET sal=1:
             LET nu=0
150 IF sal=0 THEN
       RETURN
160 IF ATTR(y-1,x)=7 AND ATTR(y-1,x+1)=7 THEN
       LET y=y-1:
       PRINT AT y,x;a$;AT y+1,x;b$;AT y+2,x;”  ”
170 LET nu=nu+1:
    IF nu=5 THEN
       LET sal=0
180 RETURN

En el zip que os he dejado aquí tenéis el programoncio. Probadlo y veréis como podéis saltar mientras estáis andando sin tener que dejar de pulsar la tecla de dirección como en la anterior versión.

Para el próximo capítulo de BASIC os enseñaré a programar unos cuantos tipos de enemigos sencillotes pero que dan mucho porculo. ¡Hasta entonces!

12 Responses to Programación #3: Mejorando el motor de plataformas BASIC y otras coserías.

  1. Juno dice:

    Estos artículos de programación de Spectrum son muy interesantes. No sé si llegaré a aplicarlos algún día, pero una cosa no quita a la otra.

    Espero los nuevos con impaciencia.😀

  2. sromero dice:

    “Si eres un poco avispado ya te habrás dado cuenta del problema, llegando a este punto: ¿Qué valor tiene ese XXX? (no, porno no es un valor binario válido) ¡Ay, amigo! ¡Buena pregunta!”

    X-D X-D X-D

  3. AugustoRuiz dice:

    Hmmm… El AND del BASIC Spectrum (creo que era &) no vale para hacer ANDs binarios??? (en Locomotive Basic – CPC – sí que vale…)… What a pufo… :S

  4. anjuel dice:

    Joder, ya me he liao!😛

  5. alt@ir dice:

    Están muy interesantes los artículos de tu blog, tanto los de programación como las revisiones de los juegos de Lokosoft😀

    La programación del Spectrum ya quedó muy atrás para mi, pero curiosamente hoy me ha regalado un compañero de trabajo un libraco bien gordo sobre programación del Z80 que tenía por ahi y por no tirarlo me lo ha dado… si hubiera caido en mis manos hace 20 años ese libro :-O

    Pues eso, que aunque no escriba muchos comentarios puedes estar seguro de que sigo tu blog con interés (de hecho estoy suscrito)

    Saludos!

  6. na_th_an dice:

    Gracias a todos por los comentarios. Se agradecen UN MONTÓN🙂

    @Augus: El BASIC del CPC está basado en el dialecto de Microsoft (empresa que ha hecho muchas cosas mal, algunas moderadamente bien y “3” cosas REALMENTE bien, a saber: la definición del dialecto de BASIC (super potente), las consolas y DirectX), pero el de Sinclair se lo inventaron más o menos y se les olvidó poner algo tan util como las operaciones a nivel de bit. De hecho, Sinclair BASIC tiene tres pegas: no tiene procedures, no tiene operaciones a nivel de bit, y tiene un intérprete lentísimo. Lo último se soluciona con un buen compilador, pero las otras dos quedarán como lacra eterna😦

  7. jessy dice:

    hola como estan , bueno la verdad es q no se que decir por que encontre esta pagina buscandro un trabajo y lo cual no puedo encontrar es una tarea y asi de casualidad encontre esto y x eso nose q comentar mas .bye q esten bien todos bye besos…

  8. gerardo dice:

    quiero hacerte una pregunta se puede programar una rom para colocarle a una expetrun de un sistema de alarma

  9. na_th_an dice:

    No. Hay que suicidarse comiendo boniatos: es la única solución.

  10. Pingback: Tutorial de ZX Basic + Fourspriter #15: Leyendo el teclado. « Tetas, Culos y Retroinformática.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: