Idioma

La Lista de Despliegue y el uso de las Interrupciones

EL CHIP ANTIC


En un aspecto muy importante, su computadora ATARI es única en comparación con la mayoría de las otras microcomputadoras disponibles. La mayoría de las microcomputadoras contienen un solo microprocesador: el 6502, el Z-80 o uno de los muchos otros disponibles. Su ATARI, sin embargo, tiene cuatro microprocesadores, tres de los cuales han sido diseñados específicamente por ATARI y son exclusivos de sus computadoras. En este Capítulo, analizaremos uno de ellos, el llamado ANTIC.


El chip ANTIC es responsable de la visualización de video, que es una característica muy importante de las computadoras ATARI. En la mayoría de las demás microcomputadoras, el microprocesador es responsable no sólo de los cálculos y el flujo del programa, sino también del mantenimiento de la visualización del video. ATARI diseñó el chip ANTIC para aliviar al 6502 de esta carga, permitiéndole manejar la pantalla de video y al 6502 manejar el programa que se está ejecutando.


MEMORIA DE PANTALLA


Un área específica de la RAM está reservada en su ATARI para albergar la información que su programa debe mostrar en la pantalla del televisor o monitor. A esta área de la RAM la llamaremos Memoria de Pantalla. Como ocurre con la mayoría de las partes de la RAM utilizadas para propósitos específicos en las computadoras ATARI, la Memoria de Pantalla tiene un puntero específico, que siempre puede indicarnos dónde está, incluso si la movemos. Dado que podemos tener hasta 48 K de RAM en un ATARI normal, necesitamos 2 bytes para contener la dirección de la Memoria de Pantalla: estos se encuentran en las ubicaciones 88 y 89. En general, siempre que utiliza un comando GRAPHICS X, el Sistema Operativo configura la Memoria de Pantalla para el modo gráfico X justo debajo de la parte superior de la memoria. Dado que la cantidad de RAM requerida para la Memoria de Pantalla puede variar mucho, dependiendo del modo gráfico que hayamos elegido, es muy importante poder saber en qué parte de la RAM comienza; y estas dos ubicaciones de memoria nos lo pueden decir. Para determinar el comienzo de la Memoria de Pantalla, todo lo que se requiere es una línea de BASIC:


10 BEGDM=PEEK(88)+256*PEEK(89)	

Esta línea convierte los bytes alto y bajo del puntero al comienzo de la Memoria de Pantalla en una sola dirección. Veamos cómo podemos utilizar esta información.


Sabemos que, si ejecutamos el comando GRAPHICS 0 en BASIC, la pantalla se borrará. Lo que realmente sucede es que el Sistema Operativo busca en la ubicación 106, que hemos usado antes, para determinar dónde está la parte superior de la memoria RAM. Luego determina qué tan grande debe ser la Memoria de Pantalla para ese modo gráfico en particular y borra automáticamente ese espacio en la memoria, de modo que cuando se establezca el modo gráfico, la pantalla estará limpia y no llena de basura aleatoria. Finalmente, se configura el Display List, que discutiremos en breve, y luego el control vuelve a BASIC.


Una vez que tenemos la pantalla GRAPHICS 0 configurada, sabemos que podemos hacer que aparezca la letra A en la esquina superior izquierda de la pantalla escribiendo


PRINT "A"	

Sin embargo, hay otra manera de lograr este mismo fin. Ahora que sabemos dónde está ubicada la Memoria de Pantalla en la RAM, simplemente podemos hacer POKE usando el valor correcto de la letra A en la parte apropiada de la Memoria de Pantalla, y la letra aparecerá en la pantalla, tal como aparece cuando le hacemos PRINT.


POKE BEGDM+2,33	

El +2 en este comando hace que el margen izquierdo sea de 2 espacios, que es el margen predeterminado en las computadoras ATARI. El 33 representa el carácter A en el código de visualización. Tenga en cuenta que su ATARI en realidad mantiene tres conjuntos separados de códigos para el significado de los 256 valores posibles de los códigos ASCII. El primero es ATASCII, o código ATARI ASCII, que se utiliza en BASIC. Por ejemplo:


PRINT CHR$(65)	

imprimirá la letra A en la pantalla. El segundo conjunto de códigos es el conjunto de visualización (Display Set), en el que la letra A corresponde al código 33, como vimos anteriormente. Este es el conjunto de códigos que se utiliza al almacenar información directamente en la memoria de la pantalla. El tercer conjunto se denomina Juego de Caracteres Interno; se utiliza cuando su ATARI lee las teclas de su teclado. El uso más común del Juego de Caracteres Interno es cuando desea saber qué tecla se presionó por última vez. La ubicación 764 es un buffer de 1 byte que contiene el Código Interno de la última tecla presionada. Si la ubicación 764 contiene un 255, no se ha presionado ninguna tecla. Para esperar a que se presione una tecla podemos escribir esto:


100 POKE 764,255
110 IF PEEK(764)=255 THEN 110	

Si queremos saber qué tecla se presionó, tenemos que consultar el Juego de Caracteres Interno. Por ejemplo, si PEEK(764) = 127, entonces la letra mayúscula A fue la última tecla presionada.


Los tres conjuntos de caracteres utilizados en su ATARI se enumeran como referencia en el Apéndice 2. Podríamos imprimir todo en la pantalla consultando esta lista e introduciendo los códigos de visualización apropiados en el lugar adecuado de la Memoria de Pantalla, tal como hicimos arriba con la letra A.


Intentemos un experimento. Introduciremos el mismo código, 33, en la Memoria de Pantalla, pero en lugar de usar una pantalla GRAPHICS 0, probaremos otros modos gráficos.


10 FOR MODE=0 TO 8:REM Los modos graficos
20 GRAPHICS MODE:REM Establezca el modo MODE
30 BEGDM=PEEK(88)+256*PEEK(89):REM ?Donde esta la Memoria de Pantalla?
40 POKE BEGDM+2,33:REM POKE mostrar el caracter A ahí
50 FOR DELAY=1 TO 700:NEXT DELAY:REM Da la oportunidad de ver la pantalla
60 NEXT MODE:REM Ahora pasa el siguiente modo	

Cuando ejecutamos este programa, vemos que sucede algo muy interesante. En primer lugar, en GRAPHICS 0, aparece la esperada letra A en la esquina superior izquierda de la pantalla. En GRAPHICS 1 y 2, las letras A amarillas de tamaño moderado y grande aparecen en esa posición, respectivamente. Sin embargo, en los otros modos gráficos, no aparece ninguna letra A, ¡Y solo vemos puntos de varios colores!


LA LISTA DE DESPLIEGUE (DISPLAY LIST)


La razón de estas diferencias entre los modos gráficos radica en la forma en que ANTIC interpreta la Memoria de Pantalla. Si ANTIC simplemente toma lo que hay en la Memoria de Pantalla y lo pone en la pantalla, no le ahorra mucho trabajo al 6502. El 6502 aún tendría que determinar cómo debería verse la pantalla y luego organizar adecuadamente la memoria de la pantalla, todo lo cual tomaría una gran cantidad de tiempo. Por lo tanto, en las computadoras ATARI, el chip ANTIC hace este trabajo para el 6502. Todo lo que el 6502 tiene que hacer es configurar un programa corto que el chip ANTIC pueda entender, diciéndole a ANTIC cómo el 6502 quiere que se interprete la Memoria de Pantalla, y ANTIC hace el resto. Este programa se llama Lista de Despliegue. Para comprender completamente las capacidades que esta lista nos brinda como programadores, necesitaremos aprender un nuevo lenguaje de programación. Afortunadamente, no hay muchas instrucciones en este lenguaje, por lo que es bastante fácil de aprender.


Enumeraremos las instrucciones aquí, tanto en notación decimal como hexadecimal para mayor versatilidad, y luego describiremos cada instrucción en detalle.


Hex.Decimal
Instrucción

0
0
Deje 1 línea de visualización en blanco
10
16
Deje 2 líneas de visualización en blanco
20
32
Deje 3 líneas de visualización en blanco
30
48
Deje 4 líneas de visualización en blanco
40
64
Deje 5 líneas de visualización en blanco
50
80
Deje 6 líneas de visualización en blanco
60
96
Deje 7 líneas de visualización en blanco
70
112
Deje 8 líneas de visualización en blanco
2
2
Mostrar como modo de texto GRAPHICS 0
3
3
Mostrar como modo de texto especial
4
4
Mostrar como modo de texto de 4 colores
5
5
Mostrar como modo de texto grande de 4 colores
6
6
Mostrar como modo de texto GRAPHICS 1
7
7
Mostrar como modo de texto GRAPHICS 2
8
8
Mostrar como modo gráfico GRAPHICS 3 de 4 colores
9
9
Mostrar como modo gráfico GRAPHICS 4 de 2 colores
A
10
Mostrar como modo gráfico GRAPHICS 5 de 4 colores
B
11
Mostrar como modo gráfico GRAPHICS 6 de 2 colores
C
12
Mostrar como modo gráfico especial 160x20, 2 colores
D
13
Mostrar como modo gráfico GRAPHICS 7 de 4 colores
E
14
Mostrar como modo gráfico especial 160x40, 4 colores
F
15
Mostrar como modo gráfico GRAPHICS 8 de 1 1/2 color
1
1
Saltar a la ubicación especificada por los dos bytes siguientes
41
65
Saltar a la ubicación especificada por los dos bytes siguientes y esperar el Blanqueo Vertical

Se pueden incluir cuatro instrucciones más poniendo en 1 uno de los 4 bits en el código de instrucción. Estos son:


Bit
Instrucción
4Habilitar el desplazamiento (scrolling) vertical fino
5Habilitar el desplazamiento horizontal fino
6Cargar el escaneo de memoria (Load Memory Scan - LMS) desde los dos bytes siguientes
7Establecer una interrupción de la Lista de Despliegue (DLI) para la siguiente línea

¡Uf! Parece mucho, todo a la vez, pero si vamos paso a paso, será bastante fácil. Comenzaremos mirando una Lista de Despliegue simple. Esto se puede hacer con bastante facilidad, ya que, al igual que la Memoria de Pantalla, la Lista de Despliegue tiene un puntero, que se encuentra en las ubicaciones de memoria 560 y 561, y que siempre puede indicarnos dónde está ubicada la Lista de Despliegue. Eso hace que sea fácil escribir un programa BASIC simple para imprimir la Lista de Despliegue en la pantalla para que podamos verla.


10 GRAPHICS 0:REM Lista de Despliegue simple
20 DL=PEEK(560)+256*PEEK(561):REM Direccion de la Lista de Despliegue
30 FOR I=DL TO DL+31:REM Longitud de la Lista de Despliegue
40 PRINT PEEK(I); " ";:REM Salta un espacio entre bytes
50 NEXT I:REM Termine de imprimirlo	

Si ejecutamos este programa, nuestra pantalla debe mostrar algo como lo siguiente:


112 112 112 66 64 156 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 65
32 156	

Como veremos, si tiene menos de 48 K de memoria en su computadora, los últimos 2 bytes y el quinto y sexto bytes pueden ser distintos. Analicemos un byte a la vez, recordando que esta Lista de Despliegue es un programa de computadora y que la computadora en este caso es ANTIC. Al observar nuestra lista de instrucciones anterior, vemos que 112 significa dejar 8 líneas de visualización en blanco. Dado que hay 3 ocurrencias de 112, eso parece significar que el comienzo de este programa le dice a ANTIC que deje 24 líneas en blanco en la pantalla. ¿Puede ser esto correcto?


La mayoría de los televisores están diseñados para sobreexplorar (overscan) la pantalla visible. Es posible que haya notado que, en algunos televisores, la imagen de su computadora parece comenzar más cerca de la parte superior o más cerca del lado izquierdo o derecho de la pantalla que en otros. Para tener en cuenta esta diferencia entre televisores, la mayoría de las Listas de Despliegue comienzan con estas 24 líneas de visualización en blanco. Por supuesto, debemos recordar que en GRAPHICS 0, cada carácter tiene 8 bytes de alto. Por lo tanto, 24 líneas de visualización en blanco es exactamente la cantidad de espacio que ocuparían tres líneas de texto GRAPHICS 0. De manera similar, la pantalla normal en GRAPHICS 0 contiene 192 líneas de visualización (8 veces 24). Usted es libre de agregar una o dos líneas de texto para personalizar una Lista de Despliegue pero, aunque puede funcionar bien en su propio televisor o monitor, es posible que no funcione tan bien en el televisor de otra persona.


Los siguientes 3 bytes de la Lista de Despliegue son 66, 64 y 156. Cuando miramos el conjunto de posibles instrucciones para ANTIC dado anteriormente, no vemos 66 en la lista. Este 66 es una suma de 64 y 2. El 64 se deriva de configurar el bit 6 de la instrucción 2 de ANTIC. Este byte le dice a ANTIC que queremos que se muestre aquí una línea de GRAPHICS 0 y, dado que el bit 6 está establecido, también queremos cargar el escaneo de memoria en este punto. El cargar el escaneo de memoria significa que los siguientes 2 bytes de la Lista de Despliegue son un puntero en donde ANTIC puede encontrar la Memoria de Pantalla para esa línea y todas las líneas siguientes, hasta que se encuentre una nueva instrucción de carga de escaneo de la memoria. Los bytes 64 y 156 están en el orden típico del 6502: byte menos significativo o LSB ("Least Significant Byte") seguido del byte más significativo o MSB ("Most Significant Byte"). Y, para traducirlos a una dirección, le sumamos a LSB 256 veces el MSB. Dado que 64 + 256 * 156 = 40000, sabemos, al igual que ANTIC ahora, que la Memoria de Pantalla se puede encontrar a partir de la dirección 40000. Los siguientes 23 bytes de la Lista de Despliegue son todos 2, y simplemente le dicen a ANTIC que queremos que todas las líneas sean del modo GRAPHICS 0, que constan de 40 bytes de texto por línea, cada byte con 8 líneas de visualización de alto. Con la línea especificada por la instrucción de carga de escaneo de memoria, da un total de 24 líneas de GRAPHICS 0, o una pantalla GRAPHICS 0 normal. La siguiente instrucción de la Lista de Despliegue es 65, que se traduce en saltar y esperar el Blanqueo Vertical.


EL BLANQUEO VERTICAL (VERTICAL BLANK)


Para comprender la instrucción de Blanqueo Vertical, primero debemos analizar el método mediante el cual se produce la imagen en la pantalla de su televisor. La superficie frontal interior del tubo de imagen está recubierta de fósforo y sustancias químicas que emiten luz cuando son impactadas por un haz de electrones. En la parte trasera del tubo de imagen hay un cañón de electrones, que dispara electrones hacia la superficie frontal para golpear la superficie recubierta de fósforo. La posición horizontal y vertical en la que este haz de electrones incide en el fósforo se controla desviándolo de forma precisa. Desde el punto de vista de la persona que mira la televisión, el haz comienza en la esquina superior izquierda de la pantalla y atraviesa una sola línea a lo largo de la pantalla hasta llegar a la esquina superior derecha. Luego regresa para comenzar la línea 2, y así sucesivamente. La intensidad del haz varía a medida que escanea, produciendo puntos más oscuros o más claros, creando una imagen. Los dispositivos de este tipo se denominan dispositivos de escaneo rasterizado y son, con diferencia, el sistema más común para producir imágenes electrónicas. El otro tipo importante de dispositivo es el dispositivo vectorial, en el que el haz de electrones dibuja una línea comenzando en el punto de origen y escaneando en cualquier dirección que tome la línea hasta llegar a su final. Los dispositivos de escaneo rasterizado dibujan toda la pantalla en la que se muestra la línea; los dispositivos vectoriales dibujan sólo la línea, nada más.


Cuando un dispositivo de escaneo rasterizado ha recorrido toda la pantalla con el haz de electrones, la posición de éste regresa a la esquina superior izquierda y el dispositivo luego espera una señal de sincronización, indicándole que comience la siguiente pantalla, o cuadro (frame). De hecho, podemos ver esta pausa ajustando el control vertical de un televisor hasta que la imagen comience a rodar. La amplia barra horizontal negra que parece moverse verticalmente a través de la pantalla es creada por el haz de electrones que espera la señal de sincronización vertical. Este intervalo, durante el cual el haz de electrones no recorre la pantalla, se denomina Blanqueo Vertical.


Su computadora ATARI produce 262 líneas de escaneo por cada imagen producida, y la pantalla se vuelve a dibujar por completo 60 veces por segundo. Esto parece muy rápido, pero en relación con la velocidad de la computadora, el dibujo de la pantalla en realidad avanza a paso de tortuga. El dibujo completo de una pantalla toma 16.684 microsegundos, y el Blanqueo Vertical es de aproximadamente 1.400 microsegundos. Si recordamos que 1 ciclo de máquina de la computadora dura menos de 1 microsegundo, las velocidades relativas de la computadora y la televisión se vuelven obvias.


La instrucción de saltar y esperar el Blanqueo Vertical, que encontramos anteriormente, es en realidad una instrucción de 3 bytes. Le dice a ANTIC que su siguiente instrucción se puede encontrar en el lugar de la memoria señalado por los siguientes 2 bytes, en este caso, 32 y 156. Esta es, de hecho, la dirección de la Lista de Despliegue: la misma dirección que analizamos anteriormente y que se encuentra en las ubicaciones de memoria 560 y 561. La instrucción de saltar y esperar el Blanqueo Vertical además le indica a ANTIC que no comience a ejecutar el programa encontrado en esa dirección hasta que finalice el Blanqueo Vertical. Esta espera logra dos cosas. Primero, sincroniza la computadora y el televisor, por lo que la imagen es estable. En segundo lugar, le da a la computadora aproximadamente 1400 microsegundos, 60 veces por segundo, para usar mientras no suceda nada más. El ATARI utiliza este tiempo para tareas internas, como actualizar todos los temporizadores internos y mucho más. Discutiremos algunos usos de este tiempo más adelante en este Capítulo.


RESOLUCIÓN DE LA IMAGEN


Una nota final sobre la imagen de TV: aunque se producen 262 líneas (scan lines) por fotograma, sólo 192 de ellas son visibles en la mayoría de los televisores debido al sobreescaneo (Overscan), por lo que la resolución vertical más alta del ATARI es de 192 píxeles (elementos de imagen) en la dimensión vertical. En la dimensión horizontal, la resolución más alta utilizable es de 160 píxeles, aunque la pantalla del modo GRAPHICS 8 en realidad utiliza 320 píxeles de resolución en la dirección horizontal. Sin embargo, en GRAPHICS 8, todos estamos familiarizados con los artefactos de color que resultan. Si dibujamos una línea diagonal en la pantalla en GRAPHICS 8, la línea parece ser de diferentes colores, dependiendo de su ubicación en la pantalla. Para producir un color verdadero en la pantalla, se deben activar dos píxeles horizontales adyacentes; de lo contrario, solo uno de los colores primarios utilizados para la transmisión de televisión puede aparecer cuando pretendemos que aparezca un color como el blanco. Cuando la reproducción del color es importante, nuestra resolución horizontal está limitada a 160 píxeles.


ACCESO DIRECTO A MEMORIA (DMA - DIRECT MEMORY ACCESS)


Ahora estamos empezando a comprender cómo produce la imagen una computadora ATARI. En resumen, una parte de la memoria se utiliza para almacenar la información que se va a mostrar (Memoria de Pantalla), y esto es interpretado por ANTIC utilizando el programa llamado Lista de Despliegue. Una nota más sobre este proceso: ANTIC y el 6502 en realidad comparten el área de RAM llamada Memoria de Pantalla. El 6502 produce y cambia la información allí almacenada, y ANTIC la lee, la interpreta y la pone en pantalla. Debería quedar claro que ambos microprocesadores no pueden acceder simultáneamente a la misma memoria. De hecho, cuando el 6502 la necesita, ANTIC no puede acceder a ella y cuando ANTIC lee la Memoria de Pantalla, el 6502 se apaga. ANTIC accede a la Memoria de Pantalla mediante un proceso llamado Acceso Directo a Memoria (Direct Memory Access o DMA). Al hacerlo, ANTIC en realidad le roba tiempo al 6502, y durante este tiempo no se realiza ningún procesamiento en el 6502. Cuando ANTIC termina de leer la Memoria de Pantalla, el 6502 comienza a procesar nuevamente. Este proceso de DMA en realidad ralentiza un poco la ejecución del programa: un programa en BASIC se puede acelerar en un 30 por ciento aproximadamente al desactivar el DMA. Para deshabilitar el DMA desde BASIC, todo lo que se necesita es hacer


POKE 559,0	

Para volver a habilitar el DMA, haga


POKE 559,34	

Un grave inconveniente compensa el aumento de velocidad obtenido: la pantalla de su televisor se apagará y permanecerá así hasta que se vuelva a habilitar el DMA. Sin embargo, todo lo que se imprime en la pantalla durante el tiempo que el DMA esté deshabilitado aparecerá cuando el DMA se vuelva a habilitar.


Ahora que sabemos cómo se produce la imagen en el televisor, podemos empezar a modificarla para nuestros propios fines. Han aparecido muchos artículos que describen cómo crear Listas de Despliegue personalizadas, como aquellas que combinan varios modos de texto diferentes y quizás incluso varias líneas de gráficos también. El resto de este Capítulo estará dedicado a programas que no se pueden escribir en BASIC, pero a los que se puede acceder desde BASIC utilizando subrutinas en Lenguaje de Máquina: realizarán algunas tareas bastante interesantes para nosotros.


PROCESAMIENTO DE LAS INTERRUPCIONES


Utilizada en el contexto de este libro, una Interrupción es un mensaje que le dice al microprocesador 6502 que detenga lo que estaba a punto de suceder en su ATARI y en su lugar haga algo definido por el programador. Cuando finaliza esa tarea, el 6502 puede continuar con lo que había planeado antes de la interrupción. Normalmente se utilizan dos tipos de interrupciones, las cuales se relacionan con la imagen de televisión: interrupciones de Lista de Despliegue (Display List Interrupt) e interrupciones del Blanqueo Vertical (Vertical Blank Interrupt). Ninguna de estas puede usarse sin subrutinas en Lenguaje de Máquina, ya que lenguajes como BASIC son demasiado lentos para estos propósitos.


INTERRUPCION DE LA LISTA DE DESPLIEGUE (DLI - DISPLAY LIST INTERRUPT)


Primero cubriremos las interrupciones de Lista de Despliegue. Cuando analizamos la Lista de Despliegue, notamos que si se establece (hacemos igual a 1) el bit 7 (el bit más significativo) de cualquier instrucción de la Lista de Despliegue, se habilita una interrupción de la Lista de Despliegue para la siguiente línea del televisor. ¿Qué quiere decir esto?


En la Página 2 de la RAM, en las ubicaciones $200 y $201 (decimal 512 y 513), se encuentra el vector de interrupción de la Lista de Despliegue. Un vector, como hemos comentado antes, es como una señal que apunta a alguna parte. Normalmente, la ubicación $200 contiene $B3 y la ubicación $201 contiene $E7, por lo que esta señal apunta a $E7B3. Esta ubicación contiene el byte $40, que es el código de Lenguaje de Máquina de la instrucción RTI (Return from Interrupt), o Regresar desde la Interrupción. Otra forma de decir esto es que el vector de interrupción de la Lista de Despliegue normalmente apunta al final de una rutina de interrupción. Esto es para evitar que establezca una interrupción en la Lista de Despliegue y que la computadora se dirija a una dirección aleatoria e intente ejecutar el código que se encuentra allí.


Las consideraciones de tiempo son importantes en este caso. Una interrupción de Lista de Despliegue normal consta de tres partes: La parte 1 ocurre durante el tiempo que le toma al haz de electrones terminar de escanear la línea que tiene el bit 7 configurado. La parte 2 ocurre entre el momento en que el haz comienza a escanear la línea en la que la interrupción tiene efecto y el momento en que el haz ingresa a la parte visible de la línea. La parte 3 comienza cuando el haz ingresa a la pantalla visible y concluye al final de la rutina de interrupción de la Lista de Despliegue.


El haz de electrones necesita 114 ciclos de máquina para recorrer cada línea horizontal. Aunque el bit 7 se establece al principio de la línea, el 6502 no es informado sobre la interrupción hasta el ciclo 36. Por lo tanto, es evidente que no se pueden implementar rutinas largas en Lenguaje de Máquina utilizando interrupciones de Lista de Despliegue; simplemente no hay suficiente tiempo para ello.


UN EJEMPLO SIMPLE


Las interrupciones de la Lista de Despliegue se usan comúnmente para cambiar el color de fondo de la pantalla mientras ésta se dibuja. Escribamos una rutina de este tipo y luego implementémosla. Dado que interrumpiremos el 6502 mientras ejecuta instrucciones, una cosa de la que debemos estar seguros es que, si planeamos usar un registro o el Acumulador, debemos guardar sus valores iniciales y restaurar esos valores antes de regresar de la interrupción. Veamos el programa y luego analicémoslo:


Listado 8.1


            0100 ; ******************************
            0110 ; Configuracion de una rutina DLI simple
            0120 ; ******************************
0000        0130        *=    $600    ; Lugar seguro para la rutina
D40A        0140 WSYNC  =     $D40A
D018        0150 COLPF2 =     $D018   ; Color de fondo
            0160 ; ******************************
            0170 ; Ahora la rutina DLI
            0180 ; ******************************
0600 48     0190        PHA           ; Guardar valor en el Acumulador
0601 A942   0200        LDA  #$42     ; Para un color rojo oscuro
0603 8D0AD4 0210        STA  WSYNC    ; Ver discusion
0606 8D18D0 0220        STA  COLPF2   ; Poner nuevo color
            0230 ; ******************************
            0240 ; Restablezcamos el Acumulador
            0250 ; ******************************
0609 68     0260        PLA           ; Restaurarlo
060A 40     0270        RTI           ; Y hemos terminado	

Lo primero que debemos notar de esta rutina es que no comienza con una instrucción PLA. De hecho, la única instrucción PLA en el programa se usa para restaurar desde la Pila el valor original que estaba en el Acumulador; este valor se colocó en la Pila en la línea 190 para su custodia durante la ejecución de esta rutina. Sin embargo, esta rutina está destinada a interactuar con BASIC, y sabemos que cualquier llamada USR desde el BASIC necesita la instrucción PLA para sacar la cantidad de parámetros en la Pila.


Este aparente error no nos causará problemas, ya que esta rutina no debe ser llamada mediante una llamada USR, sino que se accede a ella directamente mediante la rutina de interrupción que configuraremos en nuestro programa BASIC en breve. Las interrupciones no necesitan instrucción PLA, ya que no pasan información a la rutina del Lenguaje de Máquina y, por lo tanto, la Pila permanece ordenada.


Repasemos esta rutina en detalle. Primero cargamos el Acumulador con el número hexadecimal $42, que especifica un color rojo oscuro en el sistema de selección de color ATARI. Este número surge de la suma de 16 veces el color con la luminancia. Dado que el 4 en el número hexadecimal $42 está en la columna de los dieciséis y el 2 en la columna de las unidades, esto representa un color 4 con una luminancia 2. Almacenamos este número en el registro de hardware para el color de fondo usado en GRAPHICS 0, que se encuentra en la dirección $D018, y que se llama COLPF2 en el sistema de equivalencias del ATARI. Es importante entender por qué utilizamos el registro hardware y no el registro de color normal, que se encuentra en la dirección decimal 710.


Si almacenamos un número (como $42) que representa un color en el registro de color normal en la ubicación 710, la pantalla se pondrá rojo y permanecerá roja hasta que cambiemos el número almacenado en esa ubicación. Sin embargo, esto no es lo que pretendíamos hacer con esta rutina. Queríamos que sólo la parte inferior de la pantalla se vuelva roja mientras que la parte superior mantiene su color azul normal. Necesitamos saber que el registro de hardware $D018 se actualiza 60 veces por segundo desde su registro "sombra" (Shadow Register), 710. Durante cada Blanqueo Vertical, su ATARI lee el valor almacenado en la ubicación 710 y coloca este valor en el registro hardware $D018. Por lo tanto, 60 veces por segundo, se le dice a la pantalla que se vuelva azul, ya que el número almacenado en 710, que es 148, le dice a la computadora que desea un color azul. Ahora observe lo que está haciendo nuestra rutina.


Sesenta veces por segundo, entre los cuadros que componen la imagen de su televisor, se le dice a su ATARI que el color de fondo de la pantalla debe ser azul. Nuestra rutina le dice al mismo registro de hardware que después de que se muestran varias líneas del siguiente cuadro, el color de fondo ahora debe ser rojo, por lo que dibuja las líneas restantes de ese cuadro con un fondo rojo. Luego observe lo que sucede cuando se completa ese cuadro y comienza el siguiente Blanqueo Vertical. Su ATARI pone 148 en el registro de hardware, volviendo azul la parte superior del siguiente cuadro, y nuestra rutina vuelve a convertir la parte inferior de ese cuadro en rojo, y así sucesivamente. El resultado es que la parte superior de la imagen permanece azul y la parte inferior permanece roja. Si hubiéramos utilizado la ubicación 710 en la línea 220 en lugar de $D018, toda la pantalla habría permanecido en rojo.


Entre la carga del Acumulador con el valor del color deseado y el almacenamiento de este valor en el registro de color del hardware, vemos la línea 210, que hace referencia a una ubicación WSYNC en $D40A. Esta es una ubicación muy importante para las interrupciones de la Lista de Despliegue.


Imagine el haz de electrones escaneando la pantalla de su televisor de izquierda a derecha. Cada vez que llega al borde derecho, retrocede una línea hacia abajo y comienza de nuevo en el borde izquierdo con la siguiente línea. Si estamos haciendo algo como cambiar el color que se muestra en el fondo, queremos asegurarnos de que el cambio de color se produzca al principio de una línea y no en algún lugar en el medio. Si simplemente ponemos el nuevo valor de color en el registro hardware $D018, el color de fondo cambiará dondequiera que esté el haz de electrones. Para evitar esto, la línea 210 almacena un valor (cualquier valor: el color está disponible, así que lo usaremos) en la ubicación WSYNC. No importa qué valor se almacene aquí: es el acto de almacenar cualquier valor en esta ubicación lo que desencadena la acción resultante. Siempre que se haga POKE con un valor a WSYNC, la computadora simplemente espera la sincronización horizontal antes de continuar. Esta ocurre mientras el haz de electrones está fuera de la pantalla, esperando comenzar la siguiente línea. Después de la sincronización, la computadora ejecuta la línea 220, que almacena el color deseado en el registro de hardware. Este método garantiza que el cambio de color siempre se producirá al principio de una línea de escaneo y no en el medio.


El resto de este programa simplemente restaura el valor original que estaba en el Acumulador y luego regresa a lo que estaba sucediendo antes de la interrupción, por medio de la instrucción RTI (Return From Interrupt - Regresar desde la Interrupción) en la línea 270.


La configuración de una rutina de interrupción de Lista de Despliegue requiere algo de programación en BASIC, ya que ésta no puede, por sí sola, causar el cambio de color deseado. Veamos el programa BASIC utilizado para implementar esta rutina en particular:


10 GOSUB 20000:REM Configuracion de rutina DLI simple
20 HIBYTE=INT(ADR(SIMPDLI$)/256):REM ?Donde esta nuestra rutina DLI?
30 LOBYTE=ADR(SIMPDLI$)-256*HIBYTE:REM Su byte bajo
40 POKE 512,LOBYTE:REM Configura el byte bajo del nuevo vector
50 POKE 513,HIBYTE:REM Configura el byte alto
60 DL=PEEK(560)+ 256*PEEK(561):REM ?Donde esta la Lista de Despliegue?
70 POKE DL+12,PEEK(DL+12)+128:REM Establecer el bit 7 de la Lista de Despliegue
80 POKE 54286,192:REM Habilitar DLI
90 END:REM Pero el cambio de color permanece
20000 DIM SIMPDLI$(13):REM Codigo reubicable en la cadena
20010 FOR I=1 TO 13:REM Longitud de la rutina DLI simple
20020 READ A:REM Obtener un byte
20030 SIMPDLI$(I,I)=CHR$(A):REM Ponlo en la cadena
20040 NEXT I:RETURN : REM Terminado
20050 DATA 72,169,66,141,10,212,141,24,208,104
20060 DATA 64,246,243	

Como puede ver, primero configuramos la rutina que acabamos de escribir como una cadena; esto se logra en la subrutina en las líneas 20000 a 20060. A continuación, tenemos que calcular dónde almacenó BASIC esta cadena y dividir la dirección en sus bytes alto y bajo. Luego podemos decirle a la computadora dónde está ubicada la rutina, de modo que cuando encuentre la instrucción de interrupción de la Lista de Despliegue, sepa dónde acudir para encontrar el programa que debe ejecutar en ese momento. Esta información siempre se puede encontrar en el ATARI en las ubicaciones de memoria 512 y 513, almacenada en la forma habitual del 6502, es decir, byte bajo primero. Por lo tanto, en las líneas 40 y 50 colocamos los 2 bytes de nuestra dirección calculada en las ubicaciones de memoria 512 y 513.


La línea 60 encuentra la Lista de Despliegue por nosotros y, dado que hemos usado estas instrucciones antes, no las discutiremos aquí. La línea 70 establece el bit de interrupción de la Lista de Despliegue, el bit 7, en el duodécimo byte de la Lista de Despliegue. También podríamos haber configurado el cambio de color más abajo en la pantalla diciendo, por ejemplo, DL+20 en lugar de DL+12. Experimente y observe los resultados usted mismo. Solo recuerde que el bit de habilitación de interrupción de la Lista de Despliegue debe configurarse en una instrucción válida de la Lista de Despliegue. No intente configurarlo en uno de los 2 bytes de dirección que apuntan a la Memoria de la Pantalla (DL+4 o DL+5), o en uno de los 2 bytes de dirección que apuntan al comienzo de la Lista de Despliegue (los últimos 2 bytes de la Lista de Despliegue).


¡La línea 80 es crítica! Aunque hemos hecho todo lo necesario para habilitar las interrupciones de la Lista de Despliegue, todavía no le hemos dicho a nuestro ATARI que nos gustaría habilitarlas. Hacemos esto en la línea 80. Esta instrucción es necesaria antes de que funcionen las interrupciones de la Lista de Despliegue, y si tiene problemas para que funcionen, verifique esta línea antes de depurar su código de Lenguaje de Máquina buscando un error.


UN EJEMPLO MÁS COMPLICADO:
UNA RUTINA DE DLI BASADA EN TABLAS


Hay muchos usos que se les pueden dar a las interrupciones de la Lista de Despliegue. Algunos de estos son:


1. Cambiar el color del fondo.
2. Cambiar el color de los personajes.
3. Cambiar el conjunto de caracteres por completo (Insertando la dirección, en páginas, en el registro de hardware apropiado: $D409, no en 756).
4. Invertir el juego de caracteres: puede resultar útil para dibujar cartas en la pantalla: dibuja la mitad, luego invierte el juego de caracteres y dibuja la mitad inferior (registro de hardware = $D401).
5. Simular el movimiento del horizonte mediante DLI en movimiento.

Son posibles muchos otros usos, limitados únicamente por su imaginación. Daremos un ejemplo más aquí, simplemente para mostrar cómo implementar una rutina de interrupción de Lista de Despliegue más complicada. Sólo recuerde que el tiempo apremia, así que mantenga su código lo más conciso y rápido posible.


Este ejemplo presentará técnicas de búsqueda en tablas. Pondremos una interrupción de la Lista de Despliegue en cada línea de una pantalla de GRAPHICS 0 y cambiaremos el color del fondo detrás de cada línea producida. Para ello, construiremos una tabla de colores, cada uno de los cuales se utilizará para una sola línea de la pantalla. Por lo tanto, debemos leer cada valor de la tabla por turnos y almacenarlo en el registro hardware del color de fondo en el momento adecuado. A continuación, necesitamos obtener el siguiente valor de la tabla para la siguiente línea de la pantalla. Construiremos nuestra tabla en la Página 4, pero también podría haber sido colocada en la Página 6 o en cualquier otro lugar de la memoria protegida, como ya hemos comentado. La rutina de interrupción de la Lista de Despliegue en lenguaje Ensamblador se muestra a continuación:


Listado 8.2


            0100 ; ******************************
            0110 ; Configurar las condiciones iniciales
            0120 ; ******************************
0000        0130        *=   $600
D018        0140 COLPF2 =    $D018
D40A        0150 WSYNC  =    $D40A
0400        0160 OFFSET =    $0400
            0170 ; ******************************
            0180 ; !!Guardar registros!!
            0190 ; ******************************
0600 48     0200        PHA           ; Guarde el Acumulador
0601 98     0210        TYA           ; Y el registro Y
0602 48     0220        PHA           ; Manera facil de guardarlo
            0230 ; ******************************
            0240 ; La rutina propiamente tal
            0250 ; ******************************
0603 AC0004 0260        LDY OFFSET    ; Obtener desplazamiento inicial
0606 B90204 0270        LDA OFFSET+2,Y ; Obtener color desde la tabla
0609 8D0AD4 0280        STA WSYNC     ; Espera sincronizacion horizontal
060C 8D18D0 0290        STA COLPF2    ; Cambiar color
060F EE0004 0300        INC OFFSET    ; Para el siguiente color
0612 AD0004 0310        LDA OFFSET    ; ?Terminamos?
0615 CD0104 0320        CMP OFFSET+1  ; Almacenar # de colores
0618 9005   0330        BCC SKIP      ; No - salir de la rutina DLI
061A A900   0340        LDA #0        ; Si
061C 8D0004 0350        STA OFFSET    ; Restablecer el contador de desplazamiento
            0360 ; ******************************
            0370 ; !Recuerde restaurar los registros!
            0380 ; ******************************
061F 68     0390 SKIP   PLA           ; Configurado para restaurar Y
0620 A8     0400        TAY           ; Restaurar Y
0621 68     0410        PLA           ; Restaurar Acumulador
0622 40     0420        RTI           ; Salir de la rutina DLI	

Tenga en cuenta las diferencias entre esta rutina y la rutina de interrupción de la Lista de Despliegue anterior. Dado que este programa utiliza tanto el Acumulador como el registro Y, necesitaremos guardar ambos en la Pila. Esto se hace mediante PHA del valor del Acumulador, luego transfiriendo el registro Y al Acumulador y haciéndole PHA en la Pila.


La principal diferencia entre las dos rutinas de interrupción de la Lista de Despliegue radica en las líneas de la 260 a la 270 y de la 300 a la 350. Primero en la línea 260 cargamos el registro Y desde OFFSET. El número así cargado es un desplazamiento en la tabla de colores, que comienza en $402 y continúa hacia arriba en la memoria. Si OFFSET es igual a 5, entonces elegiremos el sexto color de la tabla (Recuerde: el primer color es el número cero). Este se convierte en el número almacenado en el registro hardware del color de fondo en ese momento. Las líneas 300 a 350 simplemente incrementan OFFSET y determinan si se han utilizado todos los colores. Si es así, restablecemos OFFSET a cero y salimos. Si no, simplemente salimos. Tenga en cuenta que la ubicación $401 (OFFSET + 1) almacena la cantidad de colores en la tabla para que podamos determinar cuándo terminamos.


Como guardamos tanto el registro Y como el Acumulador, necesitaremos restaurar ambos. Lo hacemos en las líneas 390 a 420 simplemente invirtiendo el proceso que las guardó.


Ahora veamos el programa BASIC que podemos usar para acceder a nuestra rutina de interrupción de Lista de Despliegue basada en tablas:


10 GOSUB 20000:REM Configurar la rutina DLI en una cadena
20 HI=INT(ADR(TABLEDLI$)/256):LO=ADR(TABLEDLI$)-HI*256:REM Obtener direcciones de la rutina DLI
30 GRAPHICS 0:SETCOLOR 1 ,0,0:REM Iniciar con fondo negro
40 RESTORE 270:REM Asegurese de que estamos leyendo los datos correctos
50 FOR I=0 TO 27:REM Numero de datos en la tabla
60 READ A:REM Obtener un byte
70 POKE 1026+ I,A:REM Poner el color en la tabla de la Pagina 4
80 NEXT I:REM Terminar de copiar la tabla
90 POKE 1024,0:REM Comenzar con desplazamiento cero en la tabla
100 POKE 1025,27:REM Poner número de colores aqui
140 DL=PEEK (560)+256*PEEK(561)+6:REM Las instrucciones DL normales comienzan con el septimo byte de la Lista de Despliegue
150 DLBEG=DL-6:REM El comienzo de la Lista de Despliegue
160 FOR I=0 TO 2:REM Los primeros 3 bytes omiten 8 lineas.
170 POKE DLBEG+I,240:REM Establezca DLI incluso en las lineas omitidas!!!
180 NEXT I:REM Termina estos tres
190 POKE DLBEG+I,194:REM Establece un DLI incluso en la instruccion "cargar escaneo de memoria"
200 FOR I=DL TO DL+22:REM Cambia todos los 2 a 130
210 POKE I ,130:REM Establecer DLIs
220 NEXT I:REM Terminado
230 POKE 512,LO:POKE 513,HI:REM Decirle a ATARI donde esta nuestra rutina
240 POKE 54286,192:REM Habilita las interrupciones
250 LIST :REM Nos da algo que mirar a traves de los colores
260 END :REM Todo terminado
270 DATA 6,22,38,54,70,86,102,118,134,150,166,182,198,214
280 DATA 230,246,246,230,214,198,182,166,150,134,118,102, 86,70
290 DATA 54,38,22,6
20000 DIM TABLEDLI$(35):REM Cadena de configuracion
20010 RESTORE 20060:REM Asegurese de que estamos leyendo los datos correctos
20020 FOR I=1 TO 35:REM Numero de bytes en la rutina
20030 READ A:REM Obtenga un byte
20040 TABLEDLI$(I,I)=CHR$(A): REM Colocar el byte en su lugar en la cadena
20050 NEXT I:RETURN :REM Finalizar la cadena
20060 DATA 72,152,72,172,0,4,185,2,4,141
20070 DATA 10,212,141,24,208,238,0,4,173,0
20080 DATA 4,205,1,4, 144,5,169,0,141,0
20090 DATA 4,104,168,104,64	

La subrutina en la línea 20000 configura nuestra rutina en una cadena. A continuación, averiguamos dónde está almacenada la cadena y descomponemos esa dirección en sus bytes alto y bajo. El comando GRAPHICS 0 garantiza que la Lista de Despliegue esté configurada como queremos y hacemos que el color de fondo inicialmente sea negro. Luego colocamos los valores de color que nos gustaría ver en la pantalla en su lugar en la tabla en la Página 4, un byte a la vez. Al alterar los datos en la línea 270, se puede obtener un patrón de colores diferente. Experimente con estos números: le resultará bastante fácil producir efectos espectaculares en sus programas. Hacemos POKE con un cero en la ubicación $400 (decimal 1024) ya que queremos que nuestra rutina comience con el primer color de la tabla. Si pusiéramos otro número aquí, digamos 10, todo el espectro de colores se desplazaría hacia arriba en la pantalla; Empezaríamos con el undécimo color y terminaríamos con el décimo.


A continuación, encontramos tanto el comienzo de la Lista de Despliegue como el comienzo de las instrucciones para GRAPHICS 0 (un 2 como instrucción de la Lista de Despliegue), y configuramos el bit alto en cada instrucción en la Lista de Despliegue, estableciendo así una interrupción de la Lista de Despliegue para cada línea. Tenga en cuenta que incluso podemos configurar interrupciones para las primeras tres instrucciones de la Lista de Despliegue, que solo le indican a ANTIC que deje 8 líneas en blanco. Al usar esta rutina, ¡Haremos que cada grupo de ocho líneas en blanco tenga un color diferente! En la línea 230, le decimos a la computadora dónde está nuestra rutina DLI y luego, en la línea siguiente, habilitamos las interrupciones de la Lista de Despliegue. El comando LIST en la línea 250 simplemente coloca algo de texto en la pantalla y lo desplaza a través de los colores creados por la rutina DLI, dando un efecto bastante agradable.


Una nota sobre las rutinas DLI: las computadoras ATARI usan WSYNC para crear el clic que acompaña a la pulsación de cada tecla del teclado. Por lo tanto, los programas que utilizan muchas interrupciones en la Lista de Despliegue, como este, pueden verse perturbados al presionar teclas. La solución más sencilla a este problema es no solicitar pulsaciones de teclas en su programa si utiliza DLI con frecuencia. Puede, por ejemplo, elegir de un menú usando el joystick o usar las teclas START, SELECT u OPTION para tomar decisiones. Otra nota a tener en cuenta es que la tecla SYSTEM RESET eliminará, por supuesto, cualquier interrupción de la Lista de Despliegue que se haya configurado, ya que este comando configura una nueva Lista de Despliegue de GRAPHICS 0.


INTERRUPCION DEL BLANQUEO VERTICAL (VBI - VERTICAL BLANK INTERRUPT)


Un segundo tipo común de interrupción utilizado en su ATARI es la interrupción del Blanqueo Vertical, comentada anteriormente. Usando este sistema, es posible realizar multiprocesamiento en una computadora ATARI. En el multiprocesamiento se procesan dos programas simultáneamente. Aunque el uso de la interrupción del Blanqueo Vertical no puede producir un verdadero multiprocesamiento, es posible configurar dos programas, de modo que uno se procese en el tiempo normal y el otro durante el Blanqueo Vertical. Parecerá que ambos se están ejecutando simultáneamente.


Un excelente ejemplo de un programa que utiliza este tipo de multiprocesamiento es EASTERN FRONT, escrito por Chris Crawford y disponible a través de ATARI. En este juego, usted toma el papel del ejército alemán durante la Operación Barbarroja, la invasión alemana de Rusia durante la Segunda Guerra Mundial, y la computadora toma el papel del ejército ruso. La computadora "piensa" en sus movimientos durante el Blanqueo Vertical y maneja sus movimientos en tiempo real. Cuanto más piense en su siguiente movimiento, más blanqueos verticales pasarán y, por lo tanto, más tiempo tendrá la computadora para determinar sus movimientos.


Un segundo uso común del Blanqueo Vertical para multiprocesamiento aparece en una amplia variedad de programas actualmente disponibles para ATARI. ¿Ha notado la música de fondo que suena mientras juega? Esta música no ralentiza el juego en absoluto, porque se reproduce sólo en el Blanqueo Vertical. Nuestro próximo programa mostrará cómo se hace esto, con un ejemplo bastante simple. Aunque esta rutina es reubicable, simplemente haremos POKE de la rutina en la Página 6 para acceder a ella. A estas alturas ya sabe cómo convertir una rutina en una cadena y puede hacerlo fácilmente con esta.


Se requieren dos partes en cualquier rutina VBI. Una, por supuesto, es la rutina misma. La otra, es una rutina corta para instalar la rutina de interrupción del Blanqueo Vertical.


Normalmente, a medida que ocurre cada Blanqueo Vertical, su ATARI se dirige a una rutina específica que se ejecuta en cada uno de estos intervalos. La rutina en realidad se compone de dos partes: La primera se llama rutina Inmediata y la segunda se llama rutina Diferida. El vector para la rutina Inmediata se encuentra en $0222. Esta es una dirección de 2 bytes a la que salta la computadora para ejecutar cada rutina VBI Inmediata; normalmente apunta a la rutina de servicio que comienza en $E45F. Esta rutina termina mediante la vectorización a través de las ubicaciones $0224 y $0225, que contienen la dirección de la rutina VBI Diferida, que normalmente se encuentra en $E462. Diagramáticamente:


VBI → $0222 → $E45F → $0224 → $E462 → RTI

Todo lo que tenemos que hacer para insertar nuestra propia rutina en lugar de la rutina normal de ATARI es dirigir el vector a nuestra rutina. Para ello, primero debemos decidir qué rutina queremos sustituir. Como veremos más adelante, las rutinas largas de interrupción del Blanqueo Vertical tienen que reemplazar las rutinas normales; no hay tiempo suficiente para ejecutar ambos durante un Blanqueo Vertical. Dado que la rutina inmediata señalada por el vector ubicado en $0222 es responsable de gran parte del mantenimiento de la computadora, como actualizar los relojes del sistema, copiar los registros "sombra", leer los joysticks y mucho más, es más seguro mantenerlo funcionando normalmente, y reemplazar la rutina de Blanqueo Vertical diferida; En resumen, para este ejemplo, usaremos la rutina diferida.


Cada vez que cambiamos un vector, tenemos un problema potencial. Con el vector de Blanqueo Vertical, que es invocada 60 veces por segundo y se puede utilizar en cualquier momento en relación con la ejecución de nuestro programa, se magnifica la posibilidad de encontrar este problema. Se puede describir mejor con un ejemplo sencillo. Sabemos que el byte almacenado en $0222 es $5F y el byte en $0223 es $E4. Supongamos que nos gustaría cambiar este vector para que apunte a $0620 en lugar de $E45F; primero cambiamos la ubicación $0222 a $20, y luego cambiamos $0223 a 6. Simple, ¿no? Pero supongamos que entre el momento en que cambiamos la ubicación $0222 a $20 y el momento en que comenzamos a cambiar la ubicación $0223, nuestra computadora sufre una interrupción del Blanqueo Vertical. Vectorizará la dirección almacenada en estas 2 ubicaciones, que ahora es $E420 porque hemos cambiado 1 byte, pero no el otro. La computadora se dirigirá a la tierra de Nunca Jamás, ya que no hay nada ejecutable en la dirección $E420. Para solucionar este problema, ATARI ha proporcionado su propia rutina para cambiar los vectores de Blanqueo Verticales y evitar que ocurra este problema. Para ver cómo funciona, veamos el código requerido:


LDY #$20 ; Byte bajo de rutina
LDX #$06; Byte alto
LDA #07; Para vector diferido
JSR SETVBV; Establecer el vector
RTS; Todo listo	

Si quisiéramos configurar nuestra rutina para la rutina de Blanqueo Vertical inmediata, cargaríamos el Acumulador con 6 antes de realizar el JSR a SETVBV ($E45C). Eso es todo al respecto. Recuerde que su rutina de interrupción del Blanqueo Vertical debe estar implementada antes de usar esta rutina de configuración. Si no es así, la computadora fallará dentro de un sexagésimo de segundo después de ejecutar esta rutina.


Por supuesto, existe una longitud finita para cada parte del Blanqueo Vertical. La rutina Diferida tiene una duración máxima de unos 20.000 ciclos de máquina y la rutina Inmediata no puede durar más de unos 2.000 ciclos de máquina. Si su rutina supera estos límites, la computadora fallará, ya que la pantalla del televisor y la computadora ya no podrán mantener la sincronización.


Ahora que hemos decidido usar el vector Diferido y sabemos cómo instalar nuestra rutina, veamos la rutina para reproducir música en el Blanqueo Vertical y luego la discutiremos en profundidad.


Listado 8.3


            0100 ; ******************************
            0110 ; Las equivalencias que usaremos
            0120 ; ******************************
0000        0130        *=   $0600
00C0        0140 COUNT1 =    $00C0
0224        0150 VVBLKD =    $0224
00C2        0160 COUNT2 =    $00C2
E45C        0170 SETVBV =    $E45C
0660        0180 MUSIC  =    $0660
E462        0190 RETURN =    $E462
D200        0200 SND    =    $D200
D201        0210 VOL    =    $D201
            0220 ; ******************************
            0230 ; Hacemos PLA para mantener limpia la Pila
            0240 ; ******************************
0600 68     0250        PLA
            0260 ; ******************************
            0270 ; Inicializar contadores en cero
            0280 ; ******************************
0601 A900   0290        LDA #0
0603 85C0   0300        STA COUNT1    ; Contador de tiempo para notas
0605 85C2   0310        STA COUNT2    ; Que nota suena
            0320 ; ******************************
            0330 ; Ahora reinicie el vector Diferido
            0340 ; ******************************
0607 A020   0350        LDY #$20      ; Byte bajo de la rutina
0609 A206   0360        LDX #$06      ; Byte alto de la rutina
060B A907   0370        LDA #07       ; Queremos el vector Diferido
060D 205CE4 0380        JSR SETVBV    ; Establecer vector
0610 60     0390        RTS           ; Inicializacion completa
            0400 ; ******************************
            0410 ; Rutina VBI propiamente tal
            0420 ; ******************************
0611        0430        *=   $0620
0620 E6C0   0440        INC  COUNT1    ; Para la nota de sincronizacion
0622 A6C0   0450        LDX  COUNT1    ; ?Termino la nota?
0624 E00C   0460        CPX  #12       ; Si >=12 entonces termino
0626 9005   0470        BCC  NO        ; Aun no termina
0628 A900   0480        LDA  #0        ; Si, entonces configure el volumen = 0
062A 8D01D2 0490        STA  VOL       ; Ahora nota apagada
062D E00F   0500 NO     CPX  #15       ; ?Han pasado 15/60 segundos?
062F B003   0510        BCS  PLAY      ; Si, reproduzca la siguiente nota
0631 4C62E4 0520        JMP  RETURN    ; No, dejelo continuar
0634 A900   0530 PLAY   LDA  #0        ; Restablecer contador
0636 85C0   0540        STA  COUNT1    ; Para sincronizar
0638 A6C2   0550        LDX  COUNT2    ; Obtener nota correcta
063A BD6006 0560        LDA  MUSIC,X   ; De la tabla
063D 8D00D2 0570        STA  SND       ; Establezca su frecuencia
0640 A9A6   0580        LDA  #$A6      ; Distorcion = 10 ($A)
0642 8D01D2 0590        STA  VOL       ; Volumen = 6
0645 E6C2   0600        INC  COUNT2    ; Configuracion para la siguiente nota
0647 A6C2   0610        LDX  COUNT2    ; ?Terminamos?
0649 E008   0620        CPX  #8        ; Si = 8, hemos terminado
064B 9004   0630        BCC  DONE      ; No
064D A900   0640        LDA  #0        ; Si, restablecer el contador para
064F 85C2   0650        STA  COUNT2    ; Empezar de nuevo
0651 4C62E4 0660 DONE   JMP  RETURN    ; Todo terminado
            0670 ; ******************************
            0680 ; Tabla de Notas Musicales
            0690 ; ******************************
0654        0700        *=    $0660
0660 F3     0710        .BYTE 243,243,217,243,204,243,217,243
0661 F3
0662 D9
0663 F3
0664 CC
0665 F3
0666 D9
0667 F3	

La rutina de inicialización pone dos contadores en cero: uno para el número de la nota que se va a tocar y el otro para determinar la duración de la misma. Luego modificamos el vector Diferido para que apunte a nuestra rutina, en lugar de la rutina normal. La rutina en sí comienza en $0620 (línea 430). Primero incrementamos el contador de duración. Si este es igual a 12, apagamos la nota; De lo contrario, la nota sigue sonando. La nota se puede desactivar almacenando un cero en el registro hardware que controla el volumen de esa voz, en la línea 490.


Para dejar una breve pausa entre notas, esperamos hasta que el contador llegue a 15 antes de comenzar la siguiente nota. Para tocar una nueva nota, almacenamos un cero en el contador de duración y obtenemos del contador de notas el número de la siguiente nota que se tocará. Luego usamos ese número como desplazamiento en la tabla de notas que se encuentra en $0660 (línea 710). Por lo tanto, si COUNT2 es igual a 2, se tocará la tercera nota. Las notas se buscan en la tabla de la línea 560 y se reproducen en las tres líneas siguientes. Luego incrementamos COUNT2 para la siguiente nota y determinamos si hemos terminado en las líneas 610 a 630; si es así, comenzamos las notas de nuevo asignando 0 a COUNT2.


Salimos de esta rutina saltando a RETURN, ubicación $E462, que finaliza nuestra rutina llamando a la rutina Diferida normal. Si hubiéramos usado el vector Inmediato para nuestra rutina, habríamos apuntado nuestra salida a $E45F, o, para una rutina realmente larga, a $E462, lo que habría eliminado todo el procesamiento normal del Blanqueo Vertical del ATARI pero habríamos ganado mucho tiempo en el Blanqueo Vertical para nuestro propio procesamiento.


Configurar una rutina de Blanqueo Vertical para nuestra rutina de reproducción de música en BASIC es bastante simple, tal como veremos ahora:


10 GOSUB 19000:REM POKEs para la rutina de inicialización
20 GOSUB 20000:REM POKEs para la rutina VBI
30 GOSUB 21000:REM POKEs para la tabla de notas a tocar
40 X=USR(1536):REM Encienda la musica!
50 END :REM Esto no apagara la música
19000 RESTORE 19050:REM Asegurese de obtener los datos correctos
19010 FOR I=1536 TO 1552:REM Longitud de la rutina de inicializacion
19020 READ A:REM Obtenga un byte
19030 POKE I,A:REM Pongalo en su lugar
19040 NEXT I:RETURN :REM Todo hecho
19050 DATA 104,169,0,133,192,133,194,160,32,162
19060 DATA 6,169,7,32,92,228,96
20000 RESTORE 20050:REM Asegurese de leer los datos correctos
20010 FOR I=1568 TO 1619 :REM Longitud de la rutina VBI
20020 READ A:REM Obtener un byte
20030 POKE I,A:REM Ponerlo en su lugar
20040 NEXT I:RETURN :REM Terminado
20050 DATA 230,192,166,192,224,12,144,5,169,0
20060 DATA 141,1,210,224,15,176, 3,76,98,228
20070 DATA 169,0,133,192,166,194,189,96,6,141
20080 DATA 0,210,169,166,141,1,210,230,194,166
20090 DATA 194,224,8,144,4,169,0,133,194,76,98,228
21000 RESTORE 21050:REM Leer los datos correctos
21010 FOR I=1632 TO 1639:REM Longitud de la tabla de musica
21020 READ A:REM Obtener un byte
21030 POKE I,A:REM Ponerlo en la tabla
21040 NEXT I:RETURN :REM Todo hecho
21050 DATA 243,243,217,243,204,243,217,243	

Este programa simplemente accede a las tres subrutinas y luego a los USR para inicializar la rutina e insertar el vector apropiadamente. La primera subrutina hace POKE de la rutina de inicialización en la Página 6, la segunda hace POKE de la rutina de interrupción del Blanqueo Vertical en la Página 6, y la tercera hace POKE de la tabla de notas musicales en su lugar apropiado en la Página 6. La línea 40 activa la rutina a través de su inicialización. ¡Voilá! Ya tiene música para ayudarle durante una sesión de programación larga. La música continuará reproduciéndose hasta que presione la tecla SYSTEM RESET, o hasta que restablezca el vector Diferido a su valor original.


La música que reproduce esta rutina es bastante limitada. Todas las notas deben tener la misma longitud: por ejemplo, son todas negras o son todas blancas. Además, sólo se utiliza una voz. Hay rutinas mucho más complicadas para el ATARI, que le permitirán incluir música compleja de múltiples voces en sus programas. Pero ahora puede escribir esa rutina usted mismo.


Una nota final sobre el Blanqueo Vertical: un uso extremadamente poderoso de esta función es leer los joysticks y mover los Players por la pantalla. Al poner esta rutina en el Blanqueo Vertical, podemos eliminar una de las partes que consume más tiempo de la mayoría de los programas BASIC y permitir que la computadora lea los joysticks y actualice las posiciones de los jugadores 60 veces por segundo, sin ralentizar la acción en tiempo real en absoluto. Quizás quiera intentar convertir la rutina del joystick que escribimos en el Capítulo 7 en una utilizada en el Blanqueo Vertical, como un ejercicio.


DESPLAZAMIENTO (SCROLLING) FINO


Aún tenemos que cubrir los dos últimos bits de las instrucciones de la Lista de Despliegue: los bits de habilitación de desplazamiento fino horizontal y vertical (bits 4 y 5, respectivamente). La función del desplazamiento fino les permite a los programadores producir algunos de los efectos más interesantes y emocionantes en el ATARI: programas que desplazan una pantalla aparentemente interminable más allá de donde se encuentra el jugador. De hecho, uno de los mejores ejemplos de desplazamiento fino se encuentra en EASTERN FRONT, ya mencionado por su uso de multiprocesamiento. Puede desplazar un mapa detallado de Europa del Este a través de muchas pantallas de tamaño normal. La acción tiene lugar en todo el mapa, lo que lo convierte en una experiencia emocionante y desafiante.


Ahora cubriremos un ejemplo de desplazamiento horizontal fino y analizaremos el desplazamiento vertical fino para permitirle escribir sus propias rutinas. Pero antes debemos abordar una dificultad que tiene el desplazamiento horizontal fino. Como ya sabe, una Lista de Despliegue normal de GRAPHICS 0 contiene el código ANTIC 2 para cada línea, lo que le indica a ANTIC que queremos que los siguientes 40 bytes de Memoria de Pantalla se interpreten como texto y en consecuencia se coloquen en la pantalla. Sin embargo, surge un problema cuando desplazamos la información de la pantalla hacia la izquierda. Veamos un ejemplo para ver el problema gráficamente:


Número de columna de la pantalla

                     111111111122222222223333333333
           0123456789012345678901234567890123456789
---------------------------------------------------
.          
.          
Línea 5    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Línea 6    bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
Línea 7    cccccccccccccccccccccccccccccccccccccccc
.
.	

Mientras solo tengamos 40 caracteres para mostrar, no hay problema. Sin embargo, ¿Cómo podemos desplazar la ventana de visualización sobre esta información? Por ejemplo, si intentamos desplazar la pantalla hacia la derecha (Es decir, desplazar la información hacia la izquierda)... ¿Cuál será el último carácter de cada línea? La línea 5 ahora terminará con ab, la línea 6 con ac, y así sucesivamente. Esto no es un verdadero desplazamiento horizontal, sino un desplazamiento mixto horizontal y vertical.


Para lograr un verdadero desplazamiento horizontal, necesitamos una forma especial de Lista de Despliegue. Necesitamos crear una Lista de Despliegue personalizada que tenga espacio para más de 40 caracteres por línea, de modo que cuando nos desplacemos, podamos ver la información que anteriormente estaba oculta, fuera de la pantalla. Afortunadamente, ya conocemos las técnicas necesarias para crear una Lista de Despliegue personalizada. Necesitaremos tener una opción de escaneo de carga de memoria separada en cada línea, y necesitaremos reservar suficiente memoria para que cada línea tenga más de 40 bytes de longitud. Diseñemos nuestra Lista de Despliegue con cada línea de 250 bytes de largo, de modo que nuestra Memoria de Pantalla sea más de 6 veces más amplia que una pantalla GRAPHICS 0 normal. Eso nos dará mucho espacio para desplazarnos. La pantalla se ve así:


Número de Columna de la Pantalla

                   111111111122222222223333333333
         0123456789012345678901234567890123456789
---------------------------------------------------
.
.
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
.
.	

En este diagrama, podemos ver que la Memoria de Pantalla para cada línea es más ancha que la pantalla misma. Esto ahora nos da espacio para mover la pantalla de un lado a otro sobre los datos, sin que se produzca el desplazamiento vertical artificial de las b en la línea a, y así sucesivamente.


La segunda característica de nuestra Lista de Despliegue que debemos considerar es que cada instrucción LMS también debe tener el bit 4 establecido en 1, por lo que debemos agregar 16 a la instrucción 64 del LMS. Por supuesto, también debemos sumar la instrucción ANTIC para la interpretación de los datos. En este caso, usaremos GRAPHICS 0 (modo ANTIC 2), por lo que necesitaremos sumar 2. La suma de 64 + 16 + 2 nos da 82, que son las instrucciones para cada línea de nuestra Lista de Despliegue personalizada.


Por supuesto, podríamos construir nuestra Lista de Despliegue modificada desde el BASIC, como vimos anteriormente, pero experimentemos y escribamos un programa en lenguaje Ensamblador para construir esta Lista de Despliegue. Ubicaremos la nueva Lista de Despliegue en la Página 6, donde estará segura. Recuerde: cada Lista de Despliegue comienza con 24 líneas en blanco y luego continúa con 24 líneas de códigos ANTIC antes de la instrucción JVB, la que finaliza la lista. Veamos un programa que puede construir dicha Lista de Despliegue para nosotros:


Listado 8.4


            0100 ; ******************************
            0110 ; Origen y equivalencias
            0120 ; ******************************
0000        0130        *=   $600    ; Debe estar en la cadena
0600        0140 DLIST  =    $0600   ; Donde estara DL
0058        0150 SAVMSC =    $58     ; Mostrar direccion de memoria
0230        0160 SDLSTL =    $230    ; Direccion de DL
E45C        0170 SETVBV =    $E45C   ; Para configurar el vector VB
            0180 ; ******************************
            0190 ; Rutina de inicializacion para configurar
            0200 ; una nueva Lista de Despliegue e
            0210 ; insertar la rutina de desplazamiento
            0220 ; en la Interrupción del Blanqueo
            0230 ; Vertical.
            0240 ; ******************************
0600 68     0250 INIT   PLA          ; Mantenga la Pila ordenada
0601 A970   0260        LDA #$70     ; 8 lineas de escaneo en blanco
0603 8D0006 0270        STA DLIST    ; En el primero
0606 8D0106 0280        STA DLIST+1  ; 3 lineas de la
0609 8D0206 0290        STA DLIST+2  ; Lista de Despliegue
060C A018   0300        LDY #24      ; # de lineas en DL
060E A203   0310        LDX #3       ; Establecer contador
0610 A952   0320        LDA #82      ; EMS + GRAPHICS 0 + desplazamiento
0612 9D0006 0330        STA DLIST,X  ; En la Lista de Despliegue
0615 E8     0340        INX          ; Mantenga el contador en funcionamiento
0616 A558   0350        LDA SAVMSC   ; Obtener la direccion de la Memoria de Pantalla
0618 9D0006 0360        STA DLIST,X  ; En la Lista de Despliegue
061B E8     0370        INX          ; Mantener el contador en marcha
061C A559   0380        LDA SAVMSC+1 ; Obtener byte alto
061E 38     0390        SEC          ; Configurar para restar
061F E918   0400        SBC #24      ; Hacer espacio para la visualizacion
0621 9D0006 0410        STA DLIST,X  ; En la Lista de Despliegue
0624 E8     0420        INX          ; Mantener el contador en marcha
0625 88     0430        DEY          ; Una linea terminada
0626 A952   0440 LOOP   LDA #82      ; LMS + desplazamiento horizonta
0628 9D0006 0450        STA DLIST,X  ; En la Lista de Despliegue
062B E8     0460        INX          ; Mantener el contador en marcha
062C BDFD05 0470        LDA DLIST-3,X ; Obtener la última memoria
062F 18     0480        CLC          ; Configurar para sumar
0630 69FA   0490        ADC #250     ; La linea es de 250 bytes
0632 9D0006 0500        STA DLIST,X  ; En la Lista de Despliegue
0635 E8     0510        INX          ; Mantener el contador en marcha
0636 BDFD05 0520        LDA DLIST-3,X ; Obtener byte alto
0639 6900   0530        ADC #0       ; Ver discusion
063B 9D0006 0540        STA DLIST,X  ; En la Lista de Despliegue
063E E8     0550        INX          ; Mantener el contador en marcha
063F 88     0560        DEY          ; Otra linea lista
0640 D0E4   0570        BNE LOOP     ; ?Finalizado? NO
0642 A941   0580        LDA #65      ; SI - Instruccion JVB 
0644 9D0006 0590        STA DLIST,X  ; En la Lista de Despliegue
0647 E8     0600        INX          ; Mantener el contador en marcha
0648 A900   0610        LDA #0       ; Byte bajo de la Pagina 6
064A 9D0006 0620        STA DLIST,X  ; En la Lista de Despliegue
064D 8D3002 0630        STA SDLSTL   ; Dile a Atari
0650 E8     0640        INX          ; Mantener el contador en marcha
0651 A906   0650        LDA #6       ; Byte alto de la Pagina 6
0653 9D0006 0660        STA DLIST,X  ; En la Lista de Despliegue
0656 8D3102 0670        STA SDLSTL+1 ; Dile a Atari
            0680 ; ******************************
            0690 ; Insertar rutina de desplazamiento en
            0700 ; el Blanqueo Vertical Diferido.
            0710 ; ******************************
0659 68     0720        PLA          ; Obtenga la direccion de la rutina
065A AA     0730        TAX          ; Al registro X
065B 68     0740        PLA          ; Direccion final
065C A8     0750        TAY          ; Al registro Y
065D A907   0760        LDA #$07     ; Vector Diferido
065F 205CE4 0770        JSR SETVBV   ; Establezca el vector
0662 60     0780        RTS          ; Todo terminado	

Comenzamos colocando en la parte superior de nuestra nueva Lista de Despliegue tres líneas $70, cada una de las cuales significa dejar 8 líneas en blanco. A continuación, cargamos el registro Y con 24. Usamos esto para realizar un seguimiento de cuántas líneas de la Lista de Despliegue hemos construido. El registro X se establece en 3, ya que queremos omitir las primeras tres instrucciones de $70. La siguiente instrucción que necesitamos en la Lista de Despliegue es 82, por lo que la almacenamos adecuadamente en las líneas 320 y 330. Luego incrementamos nuestro contador X, ya que hemos agregado un byte a la Lista de Despliegue. Necesitaremos incrementar este contador con cada byte agregado.


Dado que cada línea es una instrucción LMS, los siguientes 2 bytes de la línea deben ser la dirección de la Memoria de Pantalla desde la cual ANTIC obtendrá la información para mostrar. El comienzo de la Lista de Despliegue debe apuntar al comienzo de la Memoria de Pantalla, y este puntero siempre se encuentra en las ubicaciones $58 y $59 (SAVMSC). Sin embargo, nuestra Memoria de Pantalla enormemente ampliada, más de 6 veces más grande de lo normal, requiere un lugar donde residir. Por lo tanto, restaremos 24 páginas del byte alto de la ubicación normal de la Memoria de Pantalla, lo que nos dará el espacio que necesitamos. La transferencia de la información desde la ubicación $58 a la nueva Lista de Despliegue se realiza en las líneas 350 a 370, y la transferencia desde $59 y la ampliación de la Memoria de Pantalla, se realiza en las líneas 380 a 420. Ya que hemos completado una línea de la nueva Lista de Despliegue, que contiene una instrucción LMS y una dirección, en la línea 430 disminuimos nuestro contador de líneas, Y.


Ahora ingresaremos a un ciclo grande, desde la línea 440 a la línea 570. El ciclo se ejecutará 23 veces, y cada vez creará una línea más de nuestra nueva Lista de Despliegue. La primera instrucción colocada en él es 82, tal como se mencionó anteriormente. Luego recuperamos el byte bajo de la última dirección y le sumamos 250, en las líneas 470 a 510. ¡Recuerde usar la instrucción CLC antes de cualquier suma! Esto establece el byte bajo de la segunda línea de la Memoria de Pantalla 250 bytes más allá de la línea anterior, por lo que cada línea tendrá una longitud de 250 bytes en lugar de los 40 bytes normales.


Las líneas 520 a 540 no parecen hacer nada, ¿verdad? Suman cero a un número y lo reemplazan en la memoria. Pero recuerde, el bit de Acarreo se suma a cada instrucción ADC y no hemos borrado el Acarreo desde la última suma. Por lo tanto, si la suma anterior resultó en un número mayor que 255, la dirección baja colocada en la Lista de Despliegue en la línea 500 en realidad será la suma menos 256. Sin embargo, el Acarreo fue establecido en 1 y aumentará el byte alto de la dirección en 1 cuando sumamos cero. La dirección entonces apuntará al área correcta de la memoria. Hay otra forma de codificar esta operación:


LDA ADDR1
CLC
ADC #250
STA ADDR1
BCC PASS
INC ADDR2
PASS ....	

En este caso, si el acarreo no se establece en la primera suma, ADDR2 no se incrementa; pero si la primera suma es mayor que 255, ADDR2 será mayor de lo que era en 1.


Concluimos el ciclo disminuyendo nuevamente nuestro contador de líneas, Y. Si Y aún no ha llegado a cero, tenemos más trabajo por hacer y volvemos a hacerlo. Si Y ha llegado a cero, hemos terminado con esta parte y simplemente necesitamos configurar la instrucción JVB para que apunte a nuestra Lista de Despliegue en la Página 6. Hacemos esto en las líneas 580 a 670. Tenga en cuenta las líneas 630 y 670: Estas insertan la dirección de nuestra nueva Lista de Despliegue en las ubicaciones $230 y $231, que son los punteros internos a la Lista de Despliegue que utiliza ATARI (y ANTIC).


Para que el desplazamiento sea rápido y fluido, colocaremos nuestra rutina en la interrupción del Blanqueo Vertical. Nuestro programa BASIC pasará la dirección de la rutina de desplazamiento a la rutina de configuración, y las líneas 720 a 770 extraen esta dirección de la Pila y configuran la rutina de desplazamiento en el Blanqueo Vertical Diferido. Finalmente, regresamos a BASIC en la línea 780.


Ahora que tenemos nuestra Lista de Despliegue construida, todo lo que necesitamos hacer es escribir una breve rutina en Lenguaje de Máquina que manejará el desplazamiento en sí. Para comprender mejor esta rutina, primero analicemos el mecanismo del desplazamiento fino. Un carácter en GRAPHICS 0 tiene 8 bits de ancho. El desplazamiento aproximado se realiza un carácter a la vez: con cada movimiento, cada letra en la pantalla parece saltar una posición hacia la izquierda o hacia la derecha. Queremos un desplazamiento fino, en el que idealmente cada movimiento debería ser de solo un píxel o un bit en cualquier dirección. El ATARI nos permite lograr esto con bastante facilidad con un registro llamado HSCROL ($D404). El registro de desplazamiento vertical correspondiente, que funciona exactamente de la misma manera, se llama VSCROL y está ubicado en $D405.


HSCROL puede realizar un desplazamiento bit a bit de un carácter de 8 bits, pero luego debe restablecerse. Si se escribe un cero en HSCROL, la posición del carácter es normal. Si escribimos un 1 en HSCROL, el carácter se desplaza 1 píxel hacia la izquierda. Escribir un 2 desplaza la imagen 1 píxel más, y así sucesivamente, hasta 7. En este punto, escribimos otro 0 en HSCROL y desplazamos todo el carácter 1 posición completa hacia la izquierda en la pantalla cambiando la dirección en el Instrucción LMS en cada línea. Pictóricamente, los personajes cambian así:


Número escrito en HSCROL
    0           1            2
.......I    ......I.    .....I..
.......I    ......I.    .....I..
.......I    ......I.    .....I..
.......I    ......I.    .....I..
.......I    ......I.    .....I..
.......I    ......I.    .....I..
.......I    ......I.    .....I..
.......I    ......I.    .....I..	

Después de haber completado un ciclo completo del 0 al 7, desplazando el carácter 1 posición completa, podemos comenzar un nuevo ciclo de 0 a 7, y así sucesivamente. Al continuar con esto, podemos desplazarnos por todo el ancho de la Memoria de Pantalla. De hecho, la rutina que escribiremos A continuación, ni siquiera verificará el ancho de la memoria, por lo que continuará desplazándose hasta la parte superior de la memoria si la deja funcionar el tiempo suficiente. ¡Podrá ver el Sistema Operativo de tu ATARI de una manera nueva y completamente única!


Ahora que sabemos lo que haremos, veamos el programa:


Listado 8.5


            0100 ; ******************************
            0110 ; Configurar equivalencias y origen
            0120 ; ******************************
0000        0130        *=   $600
0600        0140 DLIST  =    $600
D404        0150 HSCROL =    $D404
E462        0160 XITVBV =    $E462
            0170 ; ******************************
            0180 ; Guardar Acumulador y registro X
            0190 ; ******************************
0600 48     0200        PHA          ; Guardar Acumulador
0601 8A     0210        TXA          ; Transferir registro X
0602 48     0220        PHA          ; Y guardarlo
            0230 ; ******************************
            0240 ; Haga primero el desplazamiento fino
            0250 ; ******************************
0603 A207   0260        LDX #7       ; 8 bits por caracter
0605 8E04D4 0270 LOOP   STX HSCROL   ; Desplacese por el 1ero
0608 CA     0280        DEX          ; Configurar para el siguiente desplazamiento
0609 10FA   0290        BPL LOOP     ; Haga un ciclo hasta completar 8
060B A207   0300        LDX #7       ; Restablecer el registro de desplazamiento
060D 8E04D4 0310        STX HSCROL   ; Al comienzo
            0320 ; ******************************
            0330 ; Ahora haremos un desplazamiento grueso
            0340 ; ******************************
0610 A200   0350        LDX #0       ; Contador
0612 BD0406 0360 LOOP2  LDA DLIST+4,X ; Obtener Memoria de Pantalla
0615 18     0370        CLC          ; Antes de la suma
0616 6901   0380        ADC #1       ; Subirlo en 1
0618 9D0406 0390        STA DLIST+4,X ; En la Lista de Despliegue
061B BD0506 0400        LDA DLIST+5,X ; Obtener byte alto
061E 6900   0410        ADC #0       ; Sumar acarreo
0620 9D0506 0420        STA DLIST+5,X ; En la Lista de Despliegue
0623 E8     0430        INX          ; Avanzar en
0624 E8     0440        INX          ; la Lista de Despliegue
0625 E8     0450        INX          ; 3 bytes
0626 E048   0460        CPX #72      ; 24 * 3 = 72
0628 90E8   0470        BCC LOOP2    ; No terminado
            0480 ; ******************************
            0490 ; Ahora restaure los registros
            0500 ; ******************************
062A 68     0510        PLA          ; Primero, registro X
062B AA     0520        TAX          ; Restaurado
062C 68     0530        PLA          ; Luego el Acumulador
062D 4C62E4 0540        JMP XITVBV   ; Salir de VB	

Dado que esto será en la interrupción del Blanqueo Vertical, en las líneas 200 a 220 guardaremos los dos registros que usaremos: el Acumulador y el registro X. A continuación, en las líneas 260 a 310 recorreremos rápidamente los 8 bits almacenados en HSCROL, reiniciando nuestro contador en 7 antes de salir. Luego, en las líneas 350 a 470 ingresamos a otro ciclo, que simplemente recorre la Lista de Despliegue y aumenta cada dirección 1 byte, logrando el desplazamiento horizontal aproximado. Si nos desplazamos verticalmente, tendremos que sumar 250 a cada dirección para poder desplazarnos aproximadamente 1 línea hacia arriba aquí (o sumar 40, si estuviéramos usando una memoria de pantalla de ancho normal). En este ciclo, utilizamos el registro X como contador de bytes en lugar de contador de líneas, por lo que debemos incrementar 3 veces el registro X en cada ciclo (Ya que hay 3 bytes por línea en la Lista de Despliegue).


Finalmente, en las líneas 510 a 530 restauramos los registros que guardamos al inicio del programa, y en la línea 540 salimos a la rutina de salida del Blanqueo Vertical Diferido.


Ahora podemos escribir un programa BASIC muy simple para usar las dos rutinas que hemos escrito:


10 GOSUB 20000:REM Configura una cadena para formar una Lista de Despliegue modificada
20 GOSUB 30000:REM Configura una cadena con una rutina de desplazamiento en ella
30 FOR I=34000 TO 40000 STEP 5:POKE I,86:NEXT I:REM Pone las lineas en la Memoria de Pantalla para que podamos ver el desplazamiento
40 DUMMY= USR(ADR(DLSCROLL$),ADR(SCROLL$))
50 GOTO 50
20000 DIM DLSCROLL$(99):REM Longitud de la rutina para configurar la Lista de Despliegue de desplazamiento
20010 FOR I=1 TO 99:REM Longitud de la cadena
20020 READ A:REM Obtener un byte
20030 DLSCROLL$(I,I)=CHR$(A):REM Insertarlo en la cadena
20040 NEXT I:RETURN :REM Todo terminado
20050 DATA 104,169,112,141,0,6,141,1,6,141
20060 DATA 2,6,160,24,162,3,169,82,157,0
20070 DATA 6,232,165,88,157,0,6,232,165,89
20080 DATA 56,233,24,157,0,6,232,136,169,82
20090 DATA 157,0,6,232,189,253,5,24,105,250
20100 DATA 157,0,6,232,189,253,5,105,0,157
20110 DATA 0,6,232,136,208,228,169,65,157,0
20120 DATA 6,232,169,0,157,0,6,141,48,20
20130 DATA 232,169,6,157,0,6,141,49,2,104
20140 DATA 170,104,168,169,7,32,92,228,96
30000 DIM SCROLL$(48):REM Longitud de la rutina
30010 FOR I=1 TO 48:REM Obtenerlo todo
30020 READ A:REM Obtener un byte
30030 SCROLL$(I)=CHR$(A):REM Pongalo en la cadena
30040 NEXT I:RETURN :REM Todo hecho
30050 DATA 72,138,72,162,7,142,4,212,202,16
30060 DATA 250,162,7,142,4,212,162,0,189,4
30070 DATA 6,24,105,1,157,4,6,189,5,6
30080 DATA 105,0,157,5,6,232,232,232,224,72
30090 DATA 144,232,104,170,104,76,98,228	

Este programa primero almacena en cadenas el programa de creación de la Lista de Despliegue y la rutina de desplazamiento, usando las subrutinas en las líneas 20000 y 30000, respectivamente. La línea 30 simplemente pone algunas líneas verticales en nuestra Memoria de Pantalla ampliada para que tengamos información para desplazarnos. La línea 40 configura la nueva Lista de Despliegue, usando DLSCROLL$, y pasa la dirección de SCROLL$ a esta rutina para que pueda insertarse en la del Blanqueo Vertical. Como no vamos a hacer nada más que observar el desplazamiento, la línea 50 simplemente mantiene el programa en tiempo real ejecutándose en un ciclo mientras el programa de interrupción del Blanqueo Vertical (Nuestra rutina de desplazamiento) continúa haciendo lo suyo. Si mira este programa durante demasiado tiempo, no podemos ser responsables de sus acciones: ¡Es hipnótico!


Con esto concluye nuestra revisión de la Lista de Despliegue, la Memoria de Pantalla, el manejo de interrupciones y el desplazamiento fino. Ahora debería poder escribir algunas rutinas bastante sofisticadas en lenguaje Ensamblador y utilizarlas en sus programas BASIC con facilidad.



Índice de Contenido | Capítulo anterior | Siguiente capítulo