Revistas en papel
 Commodore World Nº64
Anterior
Menú
Logotipo

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

Envía esta página web a un amigo:
Esta opción está desactivada temporalmente, rogamos disculpen las molestias

Volver a la página anterior

Al menú principal