ProgramaciónTaller de Juan AntonioZX Spectrum

El taller de Juanan: 0x08 Efectos de barrido de pantalla

27/04/2025

En esta nueva entrega de El taller de Juanan voy a mostraros cinco rutinas que limpian la pantalla de distinta manera, aunque en realidad solo cambio los atributos de la misma. Todas las rutinas reciben en la dirección de memoria $5CB0 (23728) los colores a aplicar en la pantalla y son reubicables, por lo que las podréis cargarlas en cualquier posición de memoria.

Efectos de barrido de pantalla

Antes de comenzar voy a explicar brevemente como es el área de atributos del ZX Spectrum. El área de atributos empieza en la posición de memoria $5800 (22528) y tiene una longitud de $300 bytes (768) que es el resultado de multiplicar 32 columnas por 24 líneas, siendo la última posición la $5AFF (23295).

En este caso las rutinas son compatibles con modelos de 16, 48 y 128K.

Vamos a ello.

Por defecto

Esta es la forma por defecto y la más rápida, consiste en cambiar todos los atributos de la pantalla sin aplicar ningún tipo de efecto, cambia los atributos de la primera posición y luego copia este atributo al resto.

El código ensamblador es el siguiente:

; -----------------------------------------------------------------------------
; Barrido por defecto. Limpia todos los atributos de la pantalla sin aplicar
; ningún efecto.
;
; Entrada: $5CB0 atributos para el barrido.
;
; Altera el valor de los registros AF, BC, DE y HL.
;
; 16 bytes.
; -----------------------------------------------------------------------------
Default:
ld   a, ($5CB0)         ; A = atributos para el barrido
ld   hl, $5800          ; HL = Inicio de área de atributos
ld   de, $5801          ; DE = segundo byte del área de atributos
ld   bc, $2ff           ; BC = longitud del área de atributos - 1
ld   (hl), a            ; Pone el atributo en la primera posición
ldir                    ; Vuelca el atributo al resto del área
ret

Esta rutina toma los atributos desde la posición de memoria 23728 y los aplica a toda el área de atributos.

De izquierda a derecha y de arriba abajo

En realidad esta rutina hace lo mismo que la anterior, pero da tiempo a que el ojo humano perciba parte del proceso.

; -----------------------------------------------------------------------------
; Barrido de izquierda a derecha y de arriba a abajo.
;
; Entrada: $5CB0 atributos para el barrido.
;
; Altera el valor de los registros AF, BC y HL.
;
; 20 bytes.
; -----------------------------------------------------------------------------
Left2Right:
ld   a, ($5CB0)         ; A = atributos para el barrido
ld   hl, $5800          ; HL = inicio del área de atributos
ld   c, $18             ; C = 24 líneas
left2Right_lpC:
ld   b, $20             ; B = 32 columnas
left2Right_lpR:
ld   (hl), a            ; Carga el atributo
inc  hl                 ; HL = siguiente columna
djnz left2Right_lpR     ; Bucle hasta que recorra las 32 columnas
halt
halt                    ; Pausa para que se aprecie el efecto
dec  c
jr   nz, left2Right_lpC ; Bucle hasta que recorra 24 líneas
ret

Esta rutina recorre las 24 líneas de la pantalla y por cada una de ellas aplica el atributo pasado a las 32 columnas de la línea. Antes de pasar a la línea siguiente hace una pausa para que se pueda ver el efecto.

De derecha a izquierda y de abaja a arriba

Esta rutina limpia la pantalla de manera inversa a la anterior.

; -----------------------------------------------------------------------------
; Barrido de derecha a izquierda y de abajo a arriba.
;
; Entrada: $5CB0 atributos para el barrido.
;
; Altera el valor de los registros AF, BC, y HL.
;
; 20 bytes.
; -----------------------------------------------------------------------------
Right2Left:
ld   a, ($5CB0)         ; A = atributos para el barrido
ld   hl, $5AFF          ; HL = fin del área de atributos
ld   c, $18             ; C = 24 líneas
right2Left_lpC:
ld   b, $20             ; B = 32 columnas
right2Left_lpR:
ld   (hl), a            ; Carga el atributo
dec  hl                 ; HL = columna anterior
djnz right2Left_lpR     ; Bucle hasta recorrer las 32 columnas
halt
halt                    ; Pausa para que se aprecie el efecto
dec  c
jr   nz, right2Left_lpC ; Bucle hasta recorrer 24 líneas
ret

En este caso empieza por la última posición del área de atributos, la columna 32 de la línea 24, limpia todas las columnas de la línea hacia la derecha y hace una pausa antes de pasar a la línea anterior.

De arriba a abajo y de izquierda a derecha

En este caso la rutina aplica los atributos a la primera columna de arriba a abajo, luego a la segunda y así hasta limpiar las 32 columnas.

; -----------------------------------------------------------------------------
; Barrido de arriba a abajo y de izquierda a derecha.
;
; Entrada: $5CB0 atributos para el barrido.
;
; Altera el valor de los registros AF, BC, D y HL.
;
; 30 bytes.
; -----------------------------------------------------------------------------
Up2Down:
ld   a, ($5CB0)         ; A = atributos para el barrido
ld   d, a               ; D = atributos para el barrido
ld   hl, $5800          ; HL = inicio del área de atributos
ld   c, $20             ; C = 32 columnas
up2Down_lpC:
push hl                 ; Preserva HL
ld   b, $18             ; B = 24 líneas
up2Down_lpR:
ld   (hl), d            ; Carga el atributo
ld   a, l
add  a, $20             ; Suma 32 para pasar a la línea siguiente
ld   l, a               ; HL = línea siguiente
jr   nc, up2Down_lpRend ; Si no hay acarreo salta
inc  h                  ; Si hay acarreo se lo aplica a H
up2Down_lpRend:
djnz up2Down_lpR        ; Bucle hasta recorrer 24 líneas
pop  hl                 ; Recupera HL
inc  l                  ; HL = siguiente columna
halt
halt                    ; Pausa para que se aprecie el efecto
dec  c
jr   nz, up2Down_lpC    ; Bucle hasta recorrer 32 columnas
ret

En el caso de esta rutina, primero limpia el atributo de la columna 1 y las 24 filas y hace una pausa antes de pasar a la siguiente columna para que se observe el efecto.

De abajo a arriba y de derecha a izquierda

Esta rutina limpia la pantalla de manera inversa a la anterior, empieza por la columna 32 de la línea 24 y termina en la columna 1 de la fila 1.

; -----------------------------------------------------------------------------
; Barrido de abajo a arriba y de derecha a izquierda.
;
; Entrada: $5CB0 atributos para el barrido.
;
; Altera el valor de los registros AF, BC, D y HL.
;
; 30 bytes.
; -----------------------------------------------------------------------------
Down2Up:
ld   a, ($5CB0)         ; A = atributos para el barrido
ld   d, a               ; D = atributos para el barrido
ld   hl, $5AFF          ; HL = fin del área de atributos
ld   c, $20             ; C = 32 columnas
down2Up_lpC:
push hl                 ; Preserva HL
ld   b, $18             ; B = 24 líneas
down2Up_lpR:
ld   (hl), d            ; Carga el atributo
ld   a, l
sub  $20
ld   l, a               ; HL = linea anterior
jr   nc, down2Up_lpRend ; Si no hay acarreo salta
dec  h                  ; Si hay acarreo se lo aplica a H
down2Up_lpRend:
djnz down2Up_lpR        ; Bucle hasta recorrer 24 líneas
pop  hl                 ; Recupera HL
dec  hl                 ; HL = columna anterior
halt
halt                    ; Pausa para que se aprecie el efecto
dec  c
jr   nz, down2Up_lpC    ; Bucle hasta recorrer 32 columnas
ret

Rutinas auxiliares

En este caso voy a usar unas rutinas auxiliares para el programa BASIC, que si bien no son necesarias, nos van a venir bien para probar todas las rutinas de golpe sin necesidad de recargar el programa.

Save y Restore

Con estas rutinas voy a cargar los atributos de la pantalla a la posición de memoria $7000 (28672) y luego los voy a recuperar desde allí.

; -----------------------------------------------------------------------------
; Graba los atributos de la pantalla a partir de la posición $7000
;
; Altera el valor de los registros BC, DE y HL.
;
; 12 bytes
; -----------------------------------------------------------------------------
SaveAttr:
ld   hl, $5800          ; HL = dirección de inicio de los atributos
ld   de, $7000          ; DE = dirección dónde se cargan los atributos
ld   bc, $0300          ; BC = longitud de los atributos
ldir                    ; Vuelca los atribtos desde $5800 a $7000
ret

; -----------------------------------------------------------------------------
; Recupera los atributos de la pantalla desde la posición $7000
;
; Altera el valor de los registros BC, DE y HL.
;
; 12 bytes
; -----------------------------------------------------------------------------
RestoreAttr:
ld   hl, $7000          ; HL = dirección desde la que se vuelca
ld   de, $5800          ; DE = dirección de inicio de los atributos
ld   bc, $0300          ; BC = longitud de los atributos
ldir                    ; Vuelca los atributos desde $7000 a $5800
ret

Entrada el programa

Para poder probar el programa voy a implementar una rutina de entrada. Esta rutina recibirá en la dirección de memoria $5CB1 (23729) el tipo de barrido a hacer, del 1 al 5.

; -----------------------------------------------------------------------------
; Inicio del programa
;
; Entrada: $5CB1 tipo de barrido.
;          $5CB0 atributos para el barrido.
;
; Altera el valor de los registros AF.
; -----------------------------------------------------------------------------
Start:
ld   a, ($5CB1)         ; A = tipo de barrido

dec  a
jr   z, Default         ; Barrido por defecto
dec  a
jr   z, Left2Right      ; Barrido de izquierda a derecha y de arriba a abajo
dec  a
jr   z, Right2Left      ; Barrido de derecha a izquierda y de abajo a arriba
dec  a
jr   z, Up2Down         ; Barrido de arriba a abajo de de izquierda a derecha
dec  a
jr   z, Down2Up         ; Barrido de abajo a arriba y de derecha a izquierda
ret

Uso desde BASIC

Y ahora toca ver cómo usar estas rutinas desde BASIC.

Aunque cada rutina es independiente, en este caso las voy incluir todas en un mismo programa con el único fin de que veáis el resultado de una sola vez.

  10 LOAD""SCREEN$
  20 RESTORE 1000:FOR I=0 TO 134:READ D:POKE 26500+I,D:NEXT I
  30 RESTORE 2000:FOR I=0 TO 23:READ D:POKE 29696+I,D:NEXT I
  40 LET T=23729:LET C=23728:RANDOMIZE USR 29696:REM Tipo de barrido, Color
  50 POKE T,1:POKE C,41:RANDOMIZE USR 26500:PAUSE 50:RANDOMIZE USR 29708:
     PAUSE 50: REM MODE 1 Default
  60 POKE T,2:RANDOMIZE USR 26500:PAUSE 50:RANDOMIZE USR 29708:PAUSE 50:
     REM MODE 2 Left2Right
  70 POKE T,3:RANDOMIZE USR 26500:PAUSE 50:RANDOMIZE USR 29708:PAUSE 50:
     REM MODE 3 Right2Left
  80 POKE T,4:RANDOMIZE USR 26500:PAUSE 50:RANDOMIZE USR 29708:PAUSE 50:
     REM MODE 4 Up2Down
  90 POKE T,5:RANDOMIZE USR 26500:PAUSE 50:RANDOMIZE USR 29708:PAUSE 50:
     REM MODE 5 Down2Up
 100 STOP
1000 DATA 58,177,92,61,40,13,61,40,26,61,40,43,61,40,60,61,40,87,201:
     REM Start, 19 bytes
1010 DATA 58,176,92,33,0,88,17,1,88,1,255,2,119,237,176,201:
     REM Default, 16 bytes
1020 DATA 58,176,92,33,0,88,14,24,6,32,119,35,16,252,118,118,13,32,245,201:
     REM Izquierda-Derecha, Arriba-Abajo, 20 bytes
1030 DATA 58,176,92,33,255,90,14,24,6,32,119,43,16,252,118,118,13,32,245,201:
     REM Derecha-Izquierda, Abajo-Arriba, 20 bytes
1040 DATA 58,176,92,87,33,0,88,14,32,229,6,24,114,125,198,32,111,48,1,36,16,
     246,225,44,118,118,13,32,236,201:
     REM Arriba-Abajo, Izquierda-Derecha, 30 bytes
1050 DATA 58,176,92,87,33,255,90,14,32,229,6,24,114,125,214,32,111,48,1,37,16,
     246,225,43,118,118,13,32,236,201:
     REM Abajo-Arriba, Derecha-Izquierda, 30 bytes
2000 DATA 33,0,88,17,0,112,1,0,3,237,176,201:
     REM SaveAttr, 12 bytes
2010 DATA 33,0,112,17,0,88,1,0,3,237,176,201:
     REM RestoreAttr, 12 bytes

En las línea 1000 están los bytes de la rutina de entrada. De las líneas 1010 a la 1050 están los bytes, por separado, de cada una de las rutinas de barrido, para que podáis incluir fácilmente en vuestros programas sólo la/las que os interesen. En las líneas 2000 y 2010 están las rutinas que guardan y restauran los atributos de la pantalla.

En la línea 20 cargo las rutinas de entrada y las de barrido a partir de la dirección de memoria 26500. En la línea 30 algo lo propio con las rutinas de salvado y restauración de atributos, en este caso a partir de la dirección de memoria 29696.

En la línea 40 declaro una variables para las direcciones de memoria en la cuales paso los datos y llamo a la rutina de guardado de los atributos.

En la línea 50 especifico que el tipo de barrido es 1 y los atributos a aplicar, en mi caso tinta azul y papel cielo. Llamo a la rutina de entrada, hago una pausa, llamo a la rutina de restauración de los atributos y hago otra pausa.

Las líneas de la 60 a la 90 son similares a la 50, pero en este caso solo especifico el tipo de barrido a hacer; el resto de la línea no cambia.

En la línea 100 finalizo el programa.

Como en ocasiones anteriores, he usado la pantalla de carga de Sir Fred para hacer la demo. Para saber cómo convertirla a .tap y cómo crear el .tap final podéis revisar el método en este capítulo.

Podéis ver el resultado final en este vídeo.

Espero que os pueda ser utilidad. Podéis bajar todos los archivos que he usado desde aquí.

BASICEnsambladorZX Spectrum

Deja una respuesta