El taller de Juanan: 0x03 Clear attributes
24/11/2024Seguimos con rutinas en ensamblador para usar desde Basic en El taller de Juanan.
Esta pequeña rutina sirve para cambiar los colores de la pantalla de manera inmediata. Los atributos los voy a pasar desde Basic en la dirección de memoria 0x5CB0 (23728), que ya conocemos de entregas anteriores, y cargaré la rutina en la dirección 0x7530 (30000) para que sea compatible con todos los modelos de ZX Spectrum. No obstante, la rutina es reubicable y la podréis cargar dónde queráis.
Clear attributes
El área de atributos empieza en la dirección 0x5800 (22528) y tiene una longitud de 0x0300 bytes (768), 24 líneas * 32 columnas. En cada byte se especifica parpadeo, brillo, fondo y tinta, con el siguiente formato:
FBPPPIII
Siendo FLASH (0/1), BRIGHT (0/1), PAPER (0 a 7) e INK (0 a 7). La forma de pasar el atributo es FLASH * 128 + BRIGHT * 64 + PAPER * 8 + INK. Si quiero poner FLASH a 0, BRIGHT a 1, PAPER a 1 e INK a 7, debo pasar 0 * 128 + 1 * 64 + 1 * 8 + 7 = 79.
Los atributos, en memoria, van correlativos: la primera posición se corresponde con el carácter 0,0, la segunda con el carácter 0,1 y así sucesivamente.
Una vez explicado esto, muestro la rutina.
ATTR: equ 0x5cb0 ; Dirección del atributo Main: ld a, (ATTR) ; A = atributos (FBPPPIII) ld hl, 0x5800 ; HL = inicio área atributos ld de, 0x5001 ; DE = segundo byte área atributos ld bc, 0x02ff-0x40 ; BC = longitud área de atributos – 1 – 64 (2 líneas) ld (hl), a ; Pone los atributos en el primer byte del área ldir ; Pone los atributos en el resto del área ret ; Sale a Basic
La rutina es pequeña, tan solo ocupa dieciséis bytes.
Cargo en A los atributos, en HL la dirección de inicio del área de atributos, en DE la dirección del segundo byte del área de atributos, en BC la longitud del área de atributos – 1 (0x02ff) ya que al primer byte le asigno el atributo a continuación, y menos 64 (0x40) para no cambiar los atributos de la parte de la línea de comandos. Asigno el atributo al byte al que apunta HL, asigno el atributo al resto del área y salgo al Basic. No cambio las dos últimas líneas porque los atributos de éstas se cambian con el borde.
Uso desde BASIC
Para usarlo desde Basic voy a partir del programa que usé para el scroll a izquierda carácter a carácter.
1 DATA 0,3,15,63,127,123,125,62 2 DATA 0,128,193,243,255,255,187,253 3 DATA 48,120,254,255,249,246,239,255 4 DATA 0,24,124,252,254,254,124,120 5 DATA 31,7,3,1,0,0,0,0 6 DATA 254,255,247,231,3,1,0,0 7 DATA 255,47,223,255,249,240,224,0 8 DATA 224,240,248,240,192,0,0,0 9 DATA 63,127,239,247,238,127,63,0 10 DATA 255,255,190,119,251,255,255,0 11 DATA 248,252,238,222,190,252,248,0 20 DATA 58,176,92,33,0,88,17,1 21 DATA 88,1,191,2,119,237,176,201 40 BORDER 0: PAPER 0: INK 7: CLS: PRINT FLASH 1;AT 10,8;"CARGANDO DATOS" 50 FOR i=0 TO 87: READ a: POKE USR "A"+i,a: NEXT i 60 FOR i=0 TO 15: READ a: POKE 30000+i,a: NEXT i 100 BORDER 1: PAPER 5: INK 7: CLS 110 PRINT AT 1,5;CHR$(144)+CHR$(145)+CHR$(146)+CHR$(147): PRINT AT 2,5;CHR$(148)+CHR$(149)+CHR$(150)+CHR$(151) 120 PRINT AT 2,15;CHR$(144)+CHR$(145)+CHR$(146)+CHR$(147): PRINT AT 3,15;CHR$(148)+CHR$(149)+CHR$(150)+CHR$(151) 130 PRINT AT 1,25;CHR$(144)+CHR$(145)+CHR$(146)+CHR$(147): PRINT AT 2,25;CHR$(148)+CHR$(149)+CHR$(150)+CHR$(151) 140 INK 1:PRINT AT 5,10;CHR$(144)+CHR$(145)+CHR$(146)+CHR$(147): PRINT AT 6,10;CHR$(148)+CHR$(149)+CHR$(150)+CHR$(151) 150 PRINT AT 9,0;INK 3;CHR$(152)+CHR$(153)+CHR$(154): PRINT AT 10,10;INK 2;CHR$(152)+CHR$(153)+CHR$(154): PRINT AT 9,20;INK 1;CHR$(152)+CHR$(153)+CHR$(154) 160 INK 2:PAPER 6: FOR f=18 TO 20 STEP 2: PRINT AT f,0;CHR$(152)+CHR$(153)+CHR$(153)+CHR$(154);: FOR c=0 TO 6: PRINT CHR$(152)+CHR$(153)+CHR$(153)+CHR$(154);: NEXT c: NEXT f 170 FOR f=19 TO 21 STEP 2: PRINT AT f,0;CHR$(153)+CHR$(154)+CHR$(152)+CHR$(153);: FOR c=0 TO 6: PRINT CHR$(153)+CHR$(154)+CHR$(152)+CHR$(153);: NEXT c: NEXT f 180 INK 1:PAPER 5:PRINT AT 13,5;"Play On Retro Magazine": PRINT AT 15,8;"Pulse una tecla" 200 PAUSE 0 210 POKE 23728,79 220 RANDOMIZE USR 30000 230 PAUSE 0 240 POKE 23728,0 250 RANDOMIZE USR 30000 260 FOR F=0 TO 7: POKE 23728,F+64:RANDOMIZE USR 30000:PAUSE 10: NEXT F 270 PAUSE 0 280 POKE 23728,0 290 RANDOMIZE USR 30000 300 FOR F=0 TO 7: POKE 23728,F*8+64:RANDOMIZE USR 30000:PAUSE 10: NEXT F 310 PAUSE 0: CLS
En las líneas de la 1 a la 11 está la definición de los gráficos, de la 20 a la 21 la rutina, de la 40 a la 60 cargo los gráficos y la rutina y de la 100 a la 180 relleno la pantalla. En las líneas de la 200 a la 220 espero la pulsación de una tecla, le paso a la rutina FLASH 0, BRIGHT 1, PAPER 1 e INK 7 y la llamo. En las líneas de la 230 a la 260 vuelvo a esperar la pulsación de una tecla, le paso a la rutina FLASH 0, BRIGHT 0, PAPER 0 e INK 0 y la llamo. Hago un bucle de 1 a 7 para ir cambiando el color de la tinta, le sumo 64 para activar el brillo, llamo a la rutina y hago una pequeña pausa para que se aprecie el cambio. En las líneas de la 270 a la 300 hago lo mismo que en las anteriores, pero en esta ocasión cambiando el fondo. Finalmente, espero la pulsación de una tecla y limpio la pantalla.
Esta rutina no cambia los atributos de las dos últimas líneas. Si queréis que los cambie, en la línea 21 tenéis que cambiar 191 (tercer byte) por 255.
La rutina cambia los colores de la pantalla, pero no actualiza las variables de sistema donde se guardan los atributos y que usan CLS, PLOT, PRINT, etc.
En la próxima entrega usaré esta rutina y una variación de las rutinas de scroll para hacer efectos de barrido de pantalla.
Podéis ver el resultado final en este vídeo.
Todo el código fuente y los programas resultantes los podéis descargar desde aquí.
BASICEnsambladorZX Spectrum