Atari Assembler – Jugando con el video

En el ejemplo anterior ocupamos la instrucción STA (STore Acum) para copiar el valor de A en memoria. Los que estaban atentos se deben haber fijado que al momento de indicar la posición de memoria a ocupar, usamos sólo un byte: 133 para el STA y 212 para indicar la posición de memoria.

1536 133 212     STA 212

Esto nos permitiría escribir en las primeras 255 posiciones de memoria, pero qué pasa si queremos ocupar las posiciones más allá de la 255? La respuesta es simple si se entendió la forma en que el ATARI representa números que requieren más de un byte.  Inocentemente podríamos pensar que para escribir en la posición 26628 (L=4, H=104) podriamos usar

1536 133   4 104 STA 260

Pero entonces cómo el 6502 discriminaría si usaremos uno o dos bytes para indicar la dirección?.  Lo cierto es que NO discrimina, para el 6502 el codigo de arriba sería interpretado como:

1536 133  4     STA 4
1538 104        PLA

Para resolver este problema, el 6502 tiene un set de instrucciones que ocupa direcciones de 8 bits, y otro set de instrucciones para ocupar direcciones de 16 bits.  En el caso del valor 133, se trata de la versión de STA que ocupa 8 bits como dirección

Nota: A estas instrucciones se le llama PAGE-ZERO porque acceden a la primera página de memoria, la página cero, en donde cada página corresponde a 256 bytes.  De lo anterior, se deduce que la memoria del atari tiene 256 páginas de 256 bytes cada una = 65536 bytes o 64KBytes.

Entonces, así como existe un STA para direcciones de 8 bits, existe también un STA para direcciones de 16 bits.  En este caso y siguiendo la tabla de códigos del 6502 vemos que el 141 corresponde al STA de 16 bits.

Por lo tanto, para escribir STA 26628 el código será

1536 141   4 104 STA 26628

Acceso simple al video

El sistema operativo del Atari mantiene los colores que estamos usando en una zona específica de memoria.  Recordemos que en una pantalla normal, se define que hay un color de borde, un color de fondo y distintos colores utilizados para trazar gráficos o texto.

Para este ejemplo usaremos la posición 710 que corresponde al color de fondo de la pantalla.  Desde BASIC podemos modificar el valor almacenado en esta posición y el color de la pantalla cambiará.

Por ejemplo, este POKE dejará el fondo en negro

POKE 710, 0

Este ejemplo dejará el fondo en gris

POKE 710, 4

Y este ejemplo dejará el fondo en verde

POKE 710, 214

El cálculo que usa el chip de video para saber de qué color estamos hablando es el siguiente:

Color*16 + Luminosidad

En donde luminosidad y color pueden tomar valores entre 0 y 15.  Los alumnos aplicados se darán cuenta de que los 8 bits de la posición 710 se agrupan en un par de valores de 4 bits, en donde los 4 bits menos significativos representan la luminosidad y los 4 bits más significativos representan el color.

bit
76543210
^^^^^^^^ 
||||||||
****|||| <-- color
    **** <-- luminosidad

Por lo tanto en los ejemplos anteriores el cero corresponde a GRIS con luminosidad CERO.  El 4 corresponde a GRIS con luminosidad 4 y el 214 corresponde a VERDE (13) con luminosidad 6 (13*16 + 6).

Un progama simple en Assembler que modifique el color de fondo sería el equivalente al POKE, por lo tanto recurrimos a nuestro amigo STA ahora aplicado a una dirección de 16 bit (710)

El programa equivalente a decir POKE 710, 214 quedaría así:

1536 104         PLA
1537 169 214     LDA #214
1539 141 198   2 STA 710
1542 96          RTS

Es muy similar a lo que ya hemos hecho con la diferencia que ahora usamos el STA de 16 bits para llegar a la dirección 710 (198 + 2*256), y la otra diferencia es que en termino de resultados, por fin vemos algo un poco más atractivo.

10 TRAP 20: FOR I=0 TO 255: READ D: POKE 1536+I, D: NEXT I
20 PRINT USR(1536)
30 DATA 104, 169, 214, 141, 198, 2, 96

Captura de pantalla 2013-04-13 a la(s) 19.06.34Jugando con el color

El programa anterior es bastante estático, porque sólo cambia una vez el color.  Podemos modificar un poco el programa para que sean distintos los colores que aparezcan en pantalla.

Para lograrlo podemos usar cualquier valor que vaya cambiando, uno que está a la mano es la posición de memoria 20 que es un contador de frames.  Este contador se incrementa una vez por cada frame (refresco) de pantalla.  Entonces lo que tendríamos que hacer es tomar el valor del contador y ponerlo en el registro que tiene el color de fondo de la pantalla

1536 104           PLA
1537 165  20       LDA 20
1539 141 192   2   STA 710
1542  71   1   6   JMP 1537
1545  96           RTS

Esta rutina usa una variante del LDA que ya conocemos. En este caso en vez de asignar el valor 20 al registro A, lo que hace es tomar el valor almacenado en la posición de memoria 20, que corresponde al contador de frames.

El LDA que estuvimos usando hasta ahora tenía un signo #, lo que significa que el valor a asignar es el que se indica a continuación, este modo se llama modo inmediato.  En cambio el LDA de ahora no tiene signo #, lo que indica que el valor se va a tomar de una dirección de memoria, en este caso corresponde a la dirección de memoria 20 que sólo require 1 byte (Page Zero).  El LDA inmediato se codifica como 169, mientras que el LDA que toma el valor de memoria desde la página cero corresponde al 165.

Otra forma de entender la diferencia entre el modo inmediato y el acceso a memoria es el siguiente código BASIC

10 A = 20: REM Modo inmediato
20 A = PEEK(20): REM Lectura de memoria en la posición 20.

En la posición 1542 encontramos una nueva instrucción.  Se trata de JMP (JuMP), que es nada más y nada menos que un GO TO.  El JMP hará que el 6502 salte a ejecutar la dirección indicada como parámetro.  Por lo tanto esta rutina quedará iterando entre la posición 1537 y la 1542 para siempre, o hasta que presionemos RESET o apagemos el computador.  La instrucción RTS en 1545 nunca se ejecutará.

Nuestro programa BASIC ahora será:

10 TRAP 20: FOR I=0 TO 255: READ D: POKE 1536+I, D: NEXT I
20 PRINT USR(1536)
30 DATA 104, 165, 20, 141, 198, 2, 76, 1, 6, 96

Ver video con resultado AtariAsmDemo01.

Como muestra el video, se ve una especie de «flash» de colores.  Lo que está sucediendo en realidad es que al ir incrementando el contador de frames, va aumentando la luminancia, y cada vez que se traspasa un múltiplo de 16, se va cambiando de color.   Por ejemplo entre el 0 y el 15 veremos 15 luminosidades de gris, desde el negro al blanco, luego comienzan las 16 luminosidades de café, etc.

Operaciones booleanas

La rutina que acabamos de hacer también nos puede servir para ver cómo funcionan las operaciones booleanas en el 6502.  Por ejemplo si quisieramos que el color siempre se mantuviera y sólo se cambiara la luminosidad, podriamos eliminar todos los bits en donde viene el color y dejar sólo los de la luminosidad.

Manos a la obra:

1536 104           PLA
1537 165  20       LDA 20
1539  41  15       AND #15
1541   9 208       ORA #208
1543 141 192   2   STA 710
1547  71   1   6   JMP 1537
1551  96           RTS

El programa es muy similar a lo que ya teníamos, pero en vez de copiar el valor que obtuvimos del contador de frames directamente en el registro de color, le hacemos un par de modificaciones:

1539  41  15       AND #15  ; En binario es 00001111. Esto elimina los bits del color y deja sólo los de luminancia
1541   8 208       ORA #208 ; Agregamos     11010000 que corresponde a los tonos verdes

Por ejemplo, si el valor leido es 33, que corresponde al color 2, luminosidad 1 (2*16 + 1), estas serían las modificaciones

A = 0010 0001
A = 0000 0001 ; por el AND #15 se eliminaran los 4 bits superiores
A = 1101 0001 ; por el ORA #208 se agregarán 4 nuevos bits superiores

Como pueden observar, todas las modificaciones se hicieron sobre el valor almacenado en el registro A, por algo se llama acumulador.  Finalmente el valor resultante que quedó en A se deja en el registro de color.

Programa BASIC modificado:

10 TRAP 20: FOR I=0 TO 255: READ D: POKE 1536+I, D: NEXT I
20 PRINT USR(1536)
30 DATA 104, 165, 20, 41, 15, 9, 208, 141, 198, 2, 76, 1, 6, 96

Ver video con resultado AtariAsmDemo02.
Como podrán ver en el video, después de ejecutarlo la primera vez con el color verde/amarillo, le cambio el valor del color en el ORA para que use otro color.