| INICIACIÓN AL LENGUAJE |
| ENSAMBLADOR |
GRÁFICOS (1) 6.ª Parte
Por Fernando G. Terradillos
Vamos a comenzar una serie de tres capítulos dedicados exclusivamente a los gráficos, pero no como anteriores capítulos, sino dirigiéndose a un sector de usuarios que deseen hacer sus propias introducciones o intros (llamadas así comúnmente).
Estas las habrás visto numerosas veces, en muchos juegos de procedencia extraña y habrás sentido mucha curiosidad de cómo funcionan. Pues bien con un poco de imaginación puedes hacerlas no tan buenas como las que se ven, pero sí saber cómo funcionan.
En esta primera parte veremos el funcionamiento de una de las partes más importantes de la capacidad gráfica del Amiga, nos referimos al Copper. Sí te habrás dado cuenta en muchos juegos que la pantalla de repente se divide en degradados de colores para darle más vistosidad, pues bien, es un cambio constante de un registro de color de los 32 posibles (no los confundas con los 4096 posibles, pues eso es cuestión de bitplanes).
Antes de nada para poder ejecutar los siguientes ejemplos necesitamos una rutina estándar que nos inicialice varios BitPlanes, es decir, una pantalla gráfica para su posterior uso. Paso a explicar la rutina 1.
Esta rutina simplemente lo que hace es inicializar los bitplanes de que va a constar nuestra pantalla. Para ello abre la librería graphics.library, sitúa nuestra memoria de trabajo a partir de la $70000 (muy poco utilizada normalmente) para insertar los dos bitplanes y las estructuras necesarias de InitRasport (inicializa el rasport o totalidad de pantalla) e InitBitmap (inicializa los dos bitplanes anteriores). A continuación relaciona o junta estas dos estructuras para su posterior visualización. Ya sólo falta poner las instrucciones del Copper que ahora veremos y el programa principal a instalar. Esta rutina es totalmente común a todos los programas que utilicen pantallas gráficas, lo que varía puede ser la forma de programarla. Recomiendo, después de haberla comprendido, instalar para cada bitplane y para cada estructura una memoria reservada previamente con la librería exec que se vio en los primeros capítulos. Ahora veremos las características del Copper. A grosso modo el Copper puede cambiar cualquier valor entre las posiciones de memoria $DFF000 y $DFF200 de una manera continua, es decir, sin depender de alguna manera del microprocesador. Estas posiciones de memoria controlan casi la totalidad de los gráficos del Amiga, desde los sprites, pasando por el sonido hasta llegar al Blitter.
El funcionamiento es el siguiente: la imagen que estás viendo actualmente en tu monitor es un volcado de una parte de la memoria a una velocidad de 50 imágenes por segundo (60 para los americanos). Cada una de éstas es en realidad un barrido continuo de una raya, línea de barrido o raster, en dirección izquierda a derecha y de arriba hacia abajo, así constantemente hasta producir la totalidad de la imagen para luego empezar de nuevo. Pensarás que estamos dando un curso de electrónica, pues no, ahora es donde entra el Amiga. El Copper permite tener total control sobre ésta, es decir saber en todo momento donde es´ta o detenernos hasta llegar a una posición prefijada. Como vimos al principio que en algunos juegos se cambiaba los colores de la pantalla en un degradado, pues esto quiere decir que el Copper está variando el color progresivamente en el color cero de la paleta cada vez que se produce una imagen. Una de las delimitaciones del Copper es que sólo actúa en los primeros 512 Kbytes de la memoria, pero los resultados son muy espectaculares, característico del Amiga y no de otros ordenadores cercanos.
Veamos ahora el funcionamiento exacto del Copper. Este se maneja mediante unas instrucciones, exactamente tres, que son WAIT, MOVE y SKIP. Antes de pasar a explicar las damos, unas generalidades. Estas permiten el control total del raster y se componen de 32 bits, es decir 2 grupos de 2 bytes, para que lo comprendas, y aunque sólo puede manejar registros de gráficos puede manejar memoria mediante el Blitter. Ahora pasemos a explicar cada una de ellas:
MOVE:
Esta instrucción permite mover un datos de 2 bytes a cualquier registro de los vistos anteriormente ($DFF000 - $DFF200). El dato a ser transferido está en la segunda palabra y el registro destino es la primera palabra.
PRIMERA PALABRA
Bit 0:
Siempre a 0 (bit caracterizador de la instrucción).
Bits 1-8:
Registro destino (8 bits = 255 posiciones posibles).
Bit 9-15:
Siempre debe ser 0.
SEGUNDA PALABRA
Bit 0-15:
16 bits (2bytes) a ser transferidos al registro previo.
Ver la rutina de ejemplo 2.
WAIT:
Esta instrucción causa al Copper una parada del raster cuando éste haya llegado a unas coordenadas específicadas en la instrucción. La primera palabra contiene las posiciones horizontales del raster, y la segunda contiene una máscara o filtro en el cual hace la comparación con el raster (siempre utilizaremos un mismo valor: $FFFE).
PRIMERA PALABRA
Bit 0:
Siempre a 1 (Bit caracterizador de la instrucción).
Bits 1-7:
Posición horizontal.
Bits 8-15:
Posición vertical.
SEGUNDA PALABRA
Bit 0:
Siempre a 0 (2.º Bit caracterizador).
Bits 1-7:
Bits de comparación posición horizontal.
Bits 8-14:
Bis de comparación posición vertial.
Bit 15:
Bit de terminado de Blitter (normalmente en 1).
Por ejemplo para esperar a que el raster haya llegado a la línea 100 esta sería la instrucción:
DC.W $6401,$FFFE
SKIP:
La instrucción provoca al Copper un salto a la siguiente instrucción si el valor del raster es igual o mayor que el valor en la instrucción, lo contrario que en el WAIT, el cual hubiera esperado hasta que el raster hubiera tenido el mismo valor que el dado.
PRIMERA PALABRA
Bit 0:
Siempre a 0 (Bit caracterizador).
Bits 1-7:
Posición horizontal.
Bits 8-15:
Posición vertical.
SEGUNDA PALABRA
Bit 0:
Siempre a 0 (2.º Bit caracterizador).
Bits 1-7:
Bits de comparación posición horizontal.
Bits 8-14:
Bits de comparación posición vertical.
Bit 15:
Bit de terminado de Blitter (normalmente en 1).
Aparte de estas tres instrucciones, debemos indicarle al Copper el momento en que acaba la lista, pues si no continuaría chequeando posiciones de memoria. Esto se hace mediante las dos palabras $FFFF, $FFFE, ya que es una situación imposible para cualquier instrucción.
La lista completa de instrucciones la llamaremos lista del Copper (Copper-list en inglés). En ella irán insertadas estos tres tipos de instrucciones de forma que el Copper las pueda realizar correctamente, finalizándola con $FFFF, $FFFE.
El ejemplo más sencillo es el clásico WAIT-MOVE para hacer cambiar los colores del fondo. Ver rutina 3.
Como programa principal a instalar pondremos una rutina para chequear si se ha pulsado el botón izquierdo del ratón. Si es así, reestablecerá los registros, cerrará librería, liberará el Copper y saldrá al CLI. Ver rutina 4.
El programa completo constaría de la rutina vista al principio en el cual tiene que insertar la lista del Copper con el resto de la lista en el final del programa y la rutina principal que chequea el botón del ratón para poder salir.
Como habrás podido observar hay más lista del Copper en el programa, éste activa los registros necesarios para que se visualice constantemente nuestra pantalla. Estos registros son muy numerosos, aproximadamente 200; para que puedas saber cómo son hemos preparado un resumen de ellos y los relacionaremos con los de la lista del Copper de nuestro programa, en la tabla 1.
La relación de los datos de la lista del Copper del programa, con los de la tabla 1 están en la tabla 2.
Como podrás observar algunos valores tienen fácil reconocimiento, pero la mayoría de ellos mantienen el mismo valor para todos los programas que se hagan de aquí. Exactamente todos menos los cuatro últimos, ya que son los punteros alto y bajo de cada bitplane (alto = 7, bajo = $8000, puntero = $7800).
Esto es todo por ahora. En el siguiente capítulo trataremos más cuestiones gráficas como el scroll de frases y el blitter.
RUTINA 1
BEGIN MOVEM.L D0-D7/A0-A6,-(A7)
MOVEA.L 4,A6
LEA GFXNAME,A1
JSR -$198(A6)
MOVE.L D0,GFXBASE
BSR.S MAIN
MOVEM.L (A7)+,D0-D7/A0-A6
RTS
MAIN CLR.L 0
MOVE.W #$20,$DFF09A
MOVE.W #-$7CB0,$DFF096
LEA COPPER+4,A1 ; APUNTA A COPPER
MOVE.L A1,$DFF084 ;SALVA EN CUSTOM
CHIP(COP2LCH)
CLR.W $DFF08A ;BORRA SEGUNDA Posici�n
COPPER
LEA $70000,A0 ;$70000=COMIENZO
MOVE.W #-$1801,D0 ;BORRA
LOOP2 CLR.B (A0)+ ;MEMORIA
DBF D0,LOOP2
MOVEA.L GFXBASE,A6 ;APUNTA BASE LIBRERIA
LEA $7D800,A5 ;ESTRUCTURA BITMAP
LEA $7D900,A4 ;ESTRUCTURA RASPORT
MOVEA.L A5,A0
MOVEQ #2,D0 ;2 BITPLANES
MOVE.W #$2C0,D1 ;704 ALTO
MOVE.W #$100,D2 ;256 ANCHO
JSR -$186(A6) ;INICIALIZA BITMAP=$7D800
MOVE.L #$78000,8(A5) ;BITPLANE 1
MOVE.L #$7AC00,$C(A5) ;BITPLANE 2
MOVEA.L A4,A1 ;ESTRUCTURA RASPORT=$7D900
JSR -$C6(A6) ;INICIALIZA RASPORT
MOVE.L A5,4(A4) ;JUNTA RASPORT Y BITMAP
MOVE.B #1,$19(A4)
;
; ;AQUI IRA EL PROGRAMA PRINCIPAL
;
CNOP 0,2
COPPER DC.W $0100,$4600,$0102,$0000
DC.W $0104,$0064,$0108,$010a,$0000,$0014,$008E,$2C81
DC.W $0090,$2CF4,$0092,$0030,$0094,$00D8,$00E4,$0007
DC.W $00E6,$8000,$00E0,$0007
DC.W $00E2,$0000
; LUGAR PARA INSERCION DE LA LISTA DEL COPPER
DC.W $0182,$0AAA
DC.W $0184,$0777,$0186,$0555,$0192,$0FFF,$0194,$0CCC
DC.W $AC01,$FFFE,$0108,$FF94,$FFFF,$FFFE
GFXNAME DC.B 'graphics.library',0
GFXBASE DC.L 0
END |
|
 |
 |
 |
RUTINA 2
DC.W $0180,$0FFF ;mueve valor $0FFF al registro $DFF180 (color 00)
DC.W $0182,$0222 ;mueve valor $0222 al registro $DFF182 (color 02)
DC.W $0094,$0100 ;mueve valor $0100 al registro $DFF094 (DDFSTOP) |
|
 |
 |
 |
RUTINA 3
DC.W $6401,$FFFE ;espera al raster en l�nea 100 (=$64)
DC.W $0180,$00F0 ;mueve valor $0111 al registro $DFF180 (color 00)
DC.W $6901,$FFFE ;espera al raster en l�nea 105 (=$69)
DC.W $0180,$0FF0 ;mueve valor $0333 al registro $DFF180 (color 00)
DC.W $7001,$FFFE ;espera al raster en l�nea 112 (=$70)
DC.W $0180,$00F0 ;mueve valor $0555 al registro $DFF180 (color 00)
DC.W $7701,$FFFE ;espera al raster en l�nea 119 (=$77)
DC.W $0180,$0FF0 ;mueve valor $0777 al registro $DFF180 (color 00) |
|
 |
 |
 |
RUTINA 4
LOOP BTST #6,$BFE001 ;ESPERA BOTON DEL RATON
BNE.S LOOP ;LOOP5
MOVE.W #-$7FE0,$DFF09A ;RESTABLECE CUSTOM CHIP
MOVE.W #$8000,$DFF096 ;
RTS |
|
 |
 |
 |
TABLA 1
NOMBRE DEL REGISTRO / NUMERO / COMENTARIO
-----------------------------------------
BLTCON0 040 Blitter control registro 0
BLTCON1 042 Blitter control registro 1
BLTAFWM 044 Blitter mascara primera palabra fuente A
BLTALWM 046 Blitter mascara ultima palabra para fuente A
BLTCPTH 048 Blitter puntero para fuente C (high 3 bits)
BLTCPTL 04A Blitter puntero para fuente C (low 15 bits)
BLTBPTH 04C Blitter puntero para fuente B (high 3 bits)
BLTBPTL 04E Blitter puntero para fuente B (low 15 bits)
BLTAPTH 050 Blitter puntero para fuente A (high 3 bits)
BTTARTL 052 Blitter puntero para fuente A (low 15 bits)
BLTDPTH 054 Blitter puntero para destino D (high 3 bits)
BLTDPTL 056 Blitter puntero para destino D (low 15 bits)
BLTSIZE 058 Blitter comienzo/tama�o (ancho, alto)
BLTCMOD 060 Blitter m�dulo para fuente C
BLTBMOD 062 Blitter m�dulo para fuente B
BLTAMOD 064 Blitter m�dulo para fuente A
BLTDMOD 066 Blitter m�dulo para destino D
BLTCDAT 070 Blitter fuente C para registro de datos
BLTBDAT 072 Blitter fuente B para registro de datos
BLTADAT 074 Blitter fuente A para registro de datos
DIWSTRT 08E Pantalla comienzo ventana (superior izq. v/h pos.)
DIWSTOP 090 Pantalla window stop (inferior derecho v/h pos.)
DDFSTRT 092 Pantalla bit plane data fetch comienzo (horiz. pos.)
DDFSTOP 094 Pantalla bit plane data fetch final (horiz. pos.)
DMACON 096 DMA control de escritura (puesto o borrado)
CLXCON 098 Control de colisi�n
INTENA 09A bits permiso interrupci�n (puesto o borrado bits)
INTREQ 09C bits respuesta interrupci�n (puesto o borrado bits)
ADKCON 09E Audio, disco, UART control
AUD0LCH 0A0 canal de audio 0 lugar (high 3 bits)
AUD0LCL 0A2 canal de audio 0 lugar (low 15 bits)
AUD0LEN 0A4 canal de audio 0 longitud
AUD0PER 0A6 canal de audio 0 periodo
AUD0VOL 0A8 canal de audio 0 volumen
AUD0DAT 0AA canal de audio 0 datos
AUD1LCH 0B0 canal de audio 1 lugar (high 3 bits)
AUD1LCL 0B2 canal de audio 1 lugar (low 15 bits)
AUD1LEN 0B4 canal de audio 1 longitud
AUD1PER 0B6 canal de audio 1 periodo
AUD1VOL 0B8 canal de audio 1 volumen
AUD1DAT 0BA canal de audio 1 datos
AUD2LCH 0C0 canal de audio 2 lugar (high 3 bits)
AUD2LCL 0C2 canal de audio 2 lugar (low 15 bits)
AUD2LEN 0C4 canal de audio 2 longitud
AUD2PER 0C6 canal de audio 2 periodo
AUD2VOL 0C8 canal de audio 2 volumen
AUD2DAT 0CA canal de audio 2 datos
AUD2LCH 0D0 canal de audio 3 lugar (high 3 bits)
AUD3LCL 0D2 canal de audio 3 lugar (low 15 bits)
AUD3LEN 0D4 canal de audio 3 longitud
AUD3PER 0D6 canal de audio 3 periodo
AUD3VOL 0D8 canal de audio 3 volumen
AUD3DAT 0DA canal de audio 3 datos
BPL1PTH 0E0 Bit plane 1 puntero (high 3 bits)
BPL1PTH 0E2 Bit plane 1 puntero (low 15 bits)
BPL2PTH 0E4 Bit plane 2 puntero (high 3 bits)
BPL2PTH 0E6 Bit plane 2 puntero (low 15 bits)
BPL3PTH 0E8 Bit plane 3 puntero (high 3 bits)
BPL3PTH 0EA Bit plane 3 puntero (low 15 bits)
BPL4PTH 0EC Bit plane 4 punteri (high 3 bits)
BPL4PTH 0EE Bit plane 4 puntero (low 15 bits)
BPL5PTH 0F0 Bit plane 5 puntero (high 3 bits)
BPL5PTH 0F2 Bit plane 5 puntero (low 15 bits)
BPL6PTH 0F4 Bit plane 6 puntero (high 3 bits)
BPL6PTH 0F6 Bit plane 6 puntero (low 15 bits)
BLPCON0 100 Bit plane registro de control (varios. control bits)
BLPCON1 102 Bit plane registro control (valor scroll PF1, PF2)
BLPCON2 104 Bit plane registro control (control de prioridad)
BPL1MOD 108 Bit plane m�dulo (planos impares)
BPL2MOD 10A Bit plane m�dulo (planos pares)
BPL1DAT 110 Bit plane 1 data (convertidor serial paralelo)
BPL2DAT 112 Bit plane 2 data (convertidor serial paralelo)
BPL3DAT 114 Bit plane 3 data (convertidor serial paralelo)
BPL4DAT 116 Bit plane 4 data (convertidor serial paralelo)
BPL5DAT 118 Bit plane 5 data (convertidor serial paralelo)
BPL6DAT 11A Bit plane 6 data (convertidor serial paralelo)
SPR0PTH 120 Sprite 0 puntero (high 3 bits)
SPR0PTH 122 Sprite 0 puntero (low 15 bits)
SPR1PTH 124 Sprite 1 puntero (high 3 bits)
SPR1PTH 126 Sprite 1 puntero (low 15 bits)
SPR2PTH 128 Sprite 2 puntero (high 3 bits)
SPR2PTH 12A Sprite 2 puntero (low 15 bits)
SPR3PTH 12C Sprite 3 puntero (high 3 bits)
SPR3PTH 12E Sprite 3 puntero (low 15 bits)
SPR4PTH 130 SPrite 4 puntero (high 3 bits)
SPR4PTH 132 Sprite 4 puntero (low 15 bits)
SPR5PTH 134 Sprite 5 puntero (high 3 bits)
SPR5PTH 136 Sprite 5 puntero (low 15 bits)
SPT6PTH 138 Sprite 6 puntero (high 3 bits)
SPR6PTH 13A Sprite 6 puntero (low 15 bits)
SPR7PTH 13C Sprite 7 puntero (high 3 bits)
SPR7PTH 13E Sprite 7 puntero (low 15 bits)
SPR0POS 140 Sprite 0 vert.-horiz. comienzo posici�n datos
SPR0CTL 142 Sprite 0 vert. final posici�n y datos de control
SPR0DATA 144 Sprite 0 imagen registro de datos A
SPR0DATB 146 Sprite 0 imagen registro de datos B
SPR1POS 148 Sprite 1 vert.-horiz. comienzo posici�n datos
SPR1CTL 14A Sprite 1 vert. final posici�n y datos de control
SPR1DATA 14C Sprite 1 imagen registro de datos A
SPR1DATB 14E Sprite 1 imagen registro de datos B
SPR2POS 150 Sprite 2 vert.-horiz. comienzo posici�n datos
SPR2CTL 152 Sprite 2 vert. final posici�n y datos de control
SPR2DATA 152 Sprite 2 imagen registro de datos A
SPR2DATB 156 Sprite 2 imagen registro de datos B
SPR3POS 158 Sprite 3 vert.-horiz. comienzo posici�n datos
SPR3CTL 15A Sprite 3 vert. final posici�n y datos de control
SPR3DATA 15C Sprite 3 imagen registro de datos A
SPR3DATB 15E Sprite 3 imagen registro de datos B
SPR4POS 160 Sprite 4 vert.-horiz. comienzo posici�n datos
SPR4CTL 162 Sprite 4 vert. final posici�n y datos de control
SPR4DATA 164 Sprite 4 imagen registro de datos A
SPR4DATB 166 Sprite 4 imagen registro de datos B
SPR5POS 168 Sprite 5 vert.-horiz. comienzo posici�n datos
SPR5CTL 16A Sprite 5 vert. final posici�n y datos de control
SPR5DATA 16C Sprite 5 imagen registro de datos A
SPR5DATB 16E Sprite 5 imagen registro de datos B
SPR6POS 170 Sprite 6 vert.-horiz. comienzo posici�n datos
SPR5CTL 172 Sprite 6 vert. final posici�n y datos de control
SPR6DATA 174 Sprite 6 imagen registro de datos A
SPR6DATB 176 Sprite 6 imagen registro de datos B
SPR7POS 178 Sprite 7 vert.-horiz. comienzo posici�n de datos
SPR7CTL 17A Sprite 7 vert. final posici�n y datos de control
SPR7DATA 17C Sprite 7 imagen registro de datos A
SPR7DATB 17E Sprite 7 imagen registro de datos B
COLOR00 - 31 180 - 1BE Color de tabla 00 - 31 |
|
 |
 |
 |
TABLA 2
DC.W $0100,$4600 MOVE: #$4600 A $DFF100, VARIOS BITS DE CONTROL
DC.W $0102,$0000 CONTROL SCROLL HORIZONTAL BITPLANE
DC.W $0104,$0064 REGISTROS MODO CONTROL BITPLANE (HIRES,DOBLE PANT.)
DC.W $010A,$0000 M�dulo BIT PLANE PAR
DC.w $0108,$0014 M�dulo BIT PLANE IMPAR
DC.W $00BE,$2C81 COMIENZO VENTANA, COORDENADAS
DC.W $0090,$2CF4 FINAL VENTANA, COORDENADAS
DC.W $009C,$0030 CONTROL DATA FETCH COMIENZO
DC.W $0094,$00D8 CONTROL DATA FETCH FINAL
DC.W $00E4,$0007 PUNTERO BITPLANE 2 (VALOR ALTO)= 7
DC.W $00E6,$8000 PUNTERO BITPLANE 2 (VALOR BAJO)= 8000
DC.W $00E0,$0007 PUNTERO BITPLANE 1 (VALOR ALTO)= 7
DC.W $00E2,$0000 PUNTERO BITPLANE 2 (VALOR ALTO)= 0000 |
|
 |
 |
 |
|
|