Por Francisco Javier Rodríguez |
TRABAJANDO EN
DUAL PLAY FIELD |
Muchas veces habrán podido observar
cómo, sobre todo en juegos, un fino scroll
de la pantalla situado en primer término,
se desplazaba sobre otro scroll de fondo.
Para aquel que, si todavía no está muy
introducido en el mundo del Amiga o que
provenga del mundo del C-64, le resultará
algo más que asombroso. |
 |
Por todos son conocidas las posibilidades que el Amiga ofrece en diversos campos; todo ello debido a la cuidada estructura hardware con la que fue diseñado. Lo cierto del caso es que el Amiga es un ordenador que, entre sus modos gráficos, soporta sin una difícil programación, el trabajo con dos pantallas al mismo tiempo.
En este artículo se incluyen un pequeño programa en ensamblador, con el cual podrán observar los extraordinarios resultados obtenidos mediante este modo. Pero, antes de adentrarse en el programa propiamente dicho, empezaremos por conocer los registros implicados, así como las características e inconvenientes de su uso.
Descripción
Se puede describir el Dual PlayField (DPF), como la superposición en un mismo monitor de dos pantallas diferentes; conteniendo cada una de estas pantallas hasta un máximo de tres planos de información. Ya se verá el porqué más adelante.
El DPF se desarrolló, como principal motivo, para aprovechar de una forma más concreta y sin un esfuerzo excesivo de programación, el campo gráfico con el Amiga; ya que de esta forma se amplía el abanico de posibilidades en nuevos efectos, perspectivas o simplemente 'mezclas de imágenes'. De otra forma este método requeriría una gran dosis de programación, sin conseguir la misma calidad de resultados.
Actualmente este modo resulta más aprovechado por las empresas dedicadas a la creación de videojuegos, ya que es en este tipo de programas donde más cabida, o posibilidades prácticas, puede tener el trabajo en esta modalidad. También se puede observar este método en gran número de 'intros' las cuales se encuentran llenas de efectos.
Características
La construcción de una imagen en pantalla, desde el modo normal de trabajo, se consigue mediante la superoposición de varios puntos en planos continuos; de esta forma, a partir de la cantidad de puntos situados en una misma posición pero en planos diferentes, se obtendrá la información sobre el color que recibirá dicho punto.
El color de un punto es obtenido mediante un sencillo método; el valor resultante de los bits acumulados en los distintos planos, encontrará su valor real en la tabla de color; ésta se encuentra situada desde la dirección $DFF180 hasta la dirección $DFF1BE. Por tanto si la suma obtenida, en una pantalla compuesta por cinco planos, es en binario de #%00000, el color se correspondería con el valor almacenado en la dirección $DFF180, es decir el color de fondo ($DFF000 dirección inicial Custom Chips, $180 offset tabla de color). Como aclaración comentar que la información sobre el color de un registro determinado se encuentra representada por una palabra. La palabra se descompone en los siguientes datos:
| BIT 0-3 |
Intensidad de azul |
| BIT 4-7 |
Intensidad de verde |
| BIT 8-12 |
Intensidad de rojo |
En el modo DPF, el asunto varía un poco, ya que al dividirse un 'Screen' en dos pantallas individuales y al poseer éstas varios planos, la adquisición de la información para el color se obtiene de una forma diferente.
La división de los planos en este modo, para cada una de las dos pantallas, se realiza de la siguiente forma:
Los planos impares, es decir 1, 3 y 5, serán los planos contenidos en el primero de los campos; quedando los planos pares para el campo restante. De esta forma la información referente al color de cada uno de los campos se obtendrá como resultado de la suma de los bits contenidos en los planos de cada pantalla.
La máxima suma que se puede obtener en este modo, para cada uno de los campos, es de ocho; por lo que la división de color se realiza mediante el método que se expone a continuación:
La pantalla compuesta por la formación de los planos impares, tomará los valores de color desde la dirección $DFF180 hasta la dirección $DFF19C (ambas inclusive). Por tanto la otra pantalla tomará los valores de color desde la posición $DFF19D hasta el final de la tabla.
Otro detalle a tener en cuenta es que cuando se activa el modo DPF en alta resolución, la cantidad de colores por cada uno de los campos, se ve reducida a cuatro; quedando sin uso en la tabla de color, los cuatro registros superiores utilizados para cada uno de los campos. Por tanto para el primer campo no se utilizarían los registros desde $DFF184 hasta $DFF187 (ambos inclusive).
Los valores iniciales de cada tabla se corresponden con el color de fondo para cada uno de los campos, por consiguiente, tanto $DFF180, como $DFF19D, serán los colores de fondo; los cuales pueden tener valores distintos o iguales (todo depende del valor indicado por el usuario).
Prioridad en modo Dual Playfield
Una particular característica, en modo Dual Playfield, es la definición de prioridad de un campo sobre otro. Es decir, cuál de los campos aparecerá en primer término y cuál en segundo (fondo). Normalmente, el primer campo (constituido por los planos impares) tendrá prioridad sobre el segundo.
Para realizar este control ha de accederse el Bit denominado PF2PR1 (Bit 6), situado éste en el registro BPLCON2. Cuando PF2PR1 es igual a uno, el segundo campo ejercerá prioridad sobre el primero y en el caso contrario (PF2PR1 = 0) es cuando el primero de los campos predomina sobre el segundo. De igual forma también es posible el control de prioridades entre los diferentes planos y los Sprites.
Para activar el modo Dual PlayField, ha de escribirse a uno el bit 10 (denominado DBLPF) en el registro de control de bitplanos BPCON0.
Por último se indicarán los pasos a seguir para la construcción del Dual PlayField.
— Cargar los registros de color en memoria, sin olvidar que los registros del cero al siete pertenecerán al primer campo, y que los registros comprendidos del ocho al quince se corresponden con el segundo de los campos.
— Construir los campos mediante la correcta elección de Bitplanos.
— Activar los registros de módulo (BPL1MOD, BPL2MOD), así como los de elección de resolución, etc.
Comentarios del programa
-
Primero se ha efectuado una reserva de memoria chip, con la longitud del Copper deseado. Como consecuencia de la función AllocMem, se nos devuelve la dirección en la cual se ha reservado dicha memoria.
-
Conociendo la dirección a la que se han de trasladar los datos para el CopperList, sólo es necesario ir 'pokeando' dichos datos en el orden adecuado. Para ello es de gran utilidad la instrucción SWAP; por ejemplo:
DIR =$8000 (palabra)
MOVE.b DIR,A1 (valor de A1=00)
SWAP DIR (valor de DIR=0080)
MOVE.B DIR,A1 (valor de A1=80)
-
La operación de 'pokeado' de datos ha de repetirse N veces, es decir tantas como datos haya que transferir. En la rutina incluida en este programa, el control de cantidad de datos a mover viene determinado por un bucle.
La rutina utilizada para rellenar la palabra de dato en la dirección indicada (ésta se encuentra contenida en un registro indexado).
|
PROGRAMA DUAL PLAYFIELD
intena equ $9A
integr equ $1e
dmacon equ $96
color00 equ $180
vpoar equ $4
cop1lc equ $80
cop2lc equ $84
copjmp1 equ $88
copjmp2 equ $8a
bplcon0 equ $100
bplcon1 equ $102
bplcon2 equ $104
bpl1pth equ $0e0
bpl1ptl equ $0e2
bpl1mod equ $108
bpl2mod equ $10a
diwstrt equ $08e
diwstop equ $090
ddfatrt equ $092
ddfstop equ $094
openlibrary equ -552
forbid equ -132
permit equ -138
allocmem equ -190
freemem equ -210
startlist equ 38
chip equ 2
clsize equ 5*4
clear equ chip+$10000
exebase equ 4
planesize equ 52*345
planewidth equ 52
start:
move.l execbase,a6
move.l #planesize*2,d0
move.l #clear,d1
jsr allocmem(a6) ;aloja memoria para planos
move.l d0,planeadr ;salva direcci�n asignada
beq Salir ;si no ha podido reservar
;memoria, sale del programa
moveq #clsize,d0 ;tama�o del Copper List
moveq #chip,d1 ;a crear en memoria Chip
jsr allocmem(a6) ;reserva memoria.
move.l d0,cladr ;salva direcci�n asignada
beq freeplane ;si no ha podido reservar
;memoria, sale de programa
moveq #1,d4 ;contador en D4
move.l d0,a0 ;direcci�n para CopperList
move.l planeadr,d1 ;direcci�n de plano inicial
move.w #bpl1pth,d3 ;
Hazcl:
move.w d3,(a0)+ ;Aqui empieza a autocrearse
addq.w #2,d3 ;el Copper List
swap d1 ;mediante una sencilla rutina
move.w d1,(a0)+ ;de asignaci�n de datos
move.w d3,(a0)+
addq.w #2,d3
swap d1
move.w d1,(a0)+
add.l #planesize,d1
dbf d4,Hazcl
move.l #$fffffffe,(a0) ;marca final para CopperList
jsr forbid(a6) ;anula interrupciones
lea $dff000,a5 ;Direcci�n inicial de los
move.w #$01e0,dmacon(a5) ;Custom Chips
move.l cladr.cop1lc(a5)
clr.w copjmp1(a5)
move.w #0,color00(a5) ;Se ajustan varios par�metros
move.w #$0f00,color00+2(a5);de inicializaci�n, como color
move.w #$000f,color00+18(a5);e inicio/final de ventana
move.w #$1a64,diwstrt(a5)
move.w #$39d1,diwstop(a5)
move.w #$0020,ddfstrt(a5)
move.w #$00d8,ddfstop(a5)
move.w #%0010011000000000,bplcon0(a5)
clr.w bplcon1(a5)
clr.w bplcon2(a5)
move.w #4,bpl1mod(a5)
move.w #4,bpl2mod(a5)
move.w #$8180,dmacon(a5)
move.l planeadr,a0 ;Aqui empiezan a asignarse los
move.w #planesize/2-1,d0 ;valores iniciales para
move.w #13*16,d1 ;rellenar la pantalla con el
move.l #$ff0000ff,d2 ;gr�fico. En esta l�nea
move.w d1,d3 ;est� el byte que se
;reproducir� en pantalla
Rellena:
move.l d2,(a0)+ ;Aqu� se encuentra la rutina
subq.w #1,d3 ;encargada de rellenar la
bne.s continua ;pantalla con el byte
swap d2 ;descrito.
move.w d1,d3
continua:
dbf d9,Rellena
clr.l d0
clr.l d1
move.l cladr,a1
move.l planeadr,a0
Espera:
move.l vposr(a5),d2 ;antes de realizar el scroll
and.l #$0001ff00,d2 ;se espera por una determinada
cmp.l #$00001000,d2 ;l�nea de barrido.
bne.s Espera
addq.b #2,d0 ;se realizan las operaciones
cmp.w #$80,d0 ;de scroll, comprobando si se
bne,s novover ;ha alcanzado el limite.
clr,1 d0
novover:
move.l d0,d2 ;en caso de que el l�mite
lsr.w #2,d2 ;haya sido alcanzado.
mulu #52,d2 ;se inicializar� la funci�n
add.l a0,d2
add.l #planesize,d2
move.w d2,14(a1)
swap d2
move.w d2,10(a1)
addq.b #1,d1 ;las mismas operaciones que
cmp.w #$80,d1 ;antes, pero con el otro campo
bne.s nohover
clr.l d1
nohover:
move.l d1,d2
lsr.w #2,d2
move.l d2,d3
and.w #$fff0,d2
sub.w d2,d3
move.w d4,bplcon1(a5)
move.w d3,d4
lsr.w #3,d2
add.l a0,d2
move.w d2,6(a1)
swap d2
move.w d2,2(a1)
btst #6,$bde001 ;aqu� est� la t�pica compro-
bne.s Espera ;baci�n del bot�n del rat�n
move.l #grname,a1 ;Aqui se abre la librer�a
clr.l d0 ;gr�fica.
jsr openlibrary(a6)
move.l d0,a4
move.l startlist(a4),cop1lc(a5)
clr.w copjmp1(a5) ;Se habilita canal DMA y
move.w #$83e0,dmacon(a5) ;se inicia el proceso
jsr permit(a6) ;del Copper.
move.l cladr,a1 ;direcci�n de CopperList
moveq #clasize,d0 ;a A1, as� como su tama�o
jsr feeemem(a6) ; y se libera memoria.
freeplane:
move.l planeadr,a1 ;Direcci�n de plano en A1
move.l #planesize*2,d0 ;tambi�n el tama�o de los
jsr freemem(a6) ;mismos y se librera memoria.
Salir:
clr.l d0 ;En este punto se sale del
rts ;programa.
cladr: dc.l 0 ;Buffer para dir. CopperList
planeadr: dc.l 0 ;BUffer para dir. Bitplanos
test: dc.l 0
grname: dc.b 'graphics.library',0 ;Nombre de librer�a gr�fica.
end |
|
 |
 |
 |
 |
| ASIGNACIÓN DE BITPLANOS POR CAMPO |
 |
 |
 |
| N.º Bit Planos |
Planos Campo-1 |
Planos Campo-2 |
 |
 |
 |
| 1 |
1 |
Ninguno |
| 2 |
1 |
2 |
| 3 |
1, 3 |
2 |
| 4 |
1, 3 |
2, 4 |
| 5 |
1, 3, 5 |
2, 4 |
| 6 |
1, 3, 5 |
2, 4, 6 |
 |
|
|
 |
 |
 |
|