LOG - Obijuan/Learn-zx-spectrum-asm GitHub Wiki

LOG

Experimentos y log de aprendizaje del ensamblador del Z80 para el ZX-Spectrum

2023-07-12

En el ejemplo 01-test1.asm estoy desarrollando mi propia rutina para mover una bala hacia la derecha píxel a pixel. Ya tengo una que funciona bien, aunque he detectado un bug. La bala se mueve con un pequeño salto (me falta algún fotograma). Me he dado cuenta que necesito crear rutinas para depurar los programas, así como Macros y definiciones para hacer más fáciles los programas en asm

Voy a empezar creando una interfaz gráfica para visualizar información. Empiezo creando un LED, para visualizar los bits...

En este ejemplo se dibujan dos LEDs, uno encendido y otro apagado: 02-debug1-dark.asm

include "zxspectrum.h"  

  org $8000
  
  ;-- Entrar en el Dark Mode
  BORDER BLACK
  CLS BLACK, GREEN

  ;-- Led apagado
  ld a, $00
  ld ($4000),a
  ld a, $3C
  ld ($4100),a
  ld a, $42
  ld ($4200),a
  ld a, $42
  ld ($4300),a
  ld a, $42
  ld ($4400),a
  ld a, $42
  ld ($4500),a
  ld a, $3C
  ld ($4600),a
  ld a, $00
  ld ($4700),a
  
  ;-- Led encendido
  ld a, $00
  ld ($4001),a
  ld a, $3C
  ld ($4101),a
  ld a, $7E
  ld ($4201),a
  ld a, $7E
  ld ($4301),a
  ld a, $7A
  ld ($4401),a
  ld a, $76
  ld ($4501),a
  ld a, $3C
  ld ($4601),a
  ld a, $00
  ld ($4701),a
    

inf: jr inf

    include "Video.asm"

    end $8000

En el fichero zxspectrum.h estoy metiendo las macros y definiciones:

;-- Colores del ZX Spectrum
;-- Para tinta, papel y borde
BLACK:    EQU 0
BLUE:     EQU 1
RED:      EQU 2
MAGENTA:  EQU 3
GREEN:    EQU 4
CYAN:     EQU 5
YELLOW:   EQU 6
WHITE:    EQU 7

;-- Puerto de salida para establecer el color del borde
BORDER_PORT: EQU $FE

;-------------------------------------------
;-- BORDER: Establecer el color del borde 
;-------------------------------------------
MACRO BORDER ,color
  ld a, color
  out (BORDER_PORT), a
ENDM

;------------------------------------------------------------------------
;-- CLS(paper, ink): Borrar la pantalla con los attributos indicados 
;------------------------------------------------------------------------
MACRO CLS ,paper,ink
  ld a, paper << 3 | ink
  call cls
ENDM

Este es el resultado:

2023-07-13

Para depurar con facilidad voy a usar el teclado. Estoy leyendo la información del teclado de la wiki de speccy, que está muy bien:

https://wiki.speccy.org/cursos/ensamblador/teclado

Ahí hay una rutina para leer cualquier tecla. Hay que poner a 0 el byte alto de las direcciones para activar todas las semifilas

Las rutinas del teclado las estoy poniendo en Keyboard.asm:

;----------------------------------------------------------------------------
;-- RUTINAS DE TECLADO
;----------------------------------------------------------------------------

;-----------------------------------------------------------------------
; Wait_key_pressed: Esperar hasta que se pulse una tecla cualquiera
;-----------------------------------------------------------------------
Wait_Key_Pressed:
    xor a             ; A = 0
    in a, (KEY_PORT)  ;-- Leer teclado
    or $E0            ;-- 1110 0000  ;-- Activar resto de bits
    inc a             ;-- Si no pulsado, inc a --> A=0
    jr z, Wait_Key_Pressed  ;-- No hay tecla pulsada. Esperar...

    ;-- Fin: No se devuelve la tecla pulsada...
    ret
 

;-----------------------------------------------------------------------
; Esta rutina espera a que no haya ninguna tecla pulsada para volver,
; consultando las diferentes filas del teclado en un bucle.
;-----------------------------------------------------------------------
Wait_Key_Released:
 XOR A
 IN A, ($FE)
 OR 224
 INC A
 JR NZ, Wait_Key_Released
 RET

;----------------------------------------------------------------------
;-- Esperar a que una tecla se pulse y luego se libere
;----------------------------------------------------------------------
Wait_Key:
    call Wait_Key_Pressed
    call Wait_Key_Released
    ret

En este ejemplo: 03-debug-key-pressed.asm se imprime el carácter 'A' y se espera a que se pulse una tecla. Luego se imprime 'B' y al apretar otra tecla se imprime 'C'

  include "zxspectrum.h"  

;------------------------------------
;--- VARIABLES DEL SISTEMA
;------------------------------------

;-- Atributos permanentes del sistema. Es lo que se usa cuando se llama 
;-- a CLS
;-- Formato:  Flash, Bright, paper (3-bits), ink (3-bits)
ATTR_S: EQU $5C8D

;-------------------------------------------------
;-- Rutina de CLS en ROM
;-- Altera el valor de los registros AF, BC, DE Y HL
;----------------------------------------------------
ROM_CLS: EQU $0DAF

  org $8000
  
  ;------------- Pasar a Dark Mode ------------
  BORDER BLACK
  
  ;-- Establecer los atributos permanentes
  SET_ATTR_S BLACK, GREEN

  ;-- Borrar la pantalla
  CALL ROM_CLS
  ;--------------------------------------------

  ;-- Imprimir un caracter
  ld a, 'A'
  rst $10

  ;-- Esperar a que se pulse una tecla cualquiera
  call Wait_Key

  ;-- Imprimir otro caracter
  ld a, 'B'
  rst $10
    
  ;-- Esperar a que se pulse otra tecla
  call Wait_Key

  ;-- Imprimir otro caracter
  ld a, 'C'
  rst $10

  ;-- Terminar
inf: jr inf


    include "Video.asm"
    include "Keyboard.asm"

    end $8000

En esta animación se muestra se muestra el funcionamiento:

Tras apretar dos teclas aparece "ABC" en la pantalla:

Led parpadeante

En este ejemplo 04-led-blink-key.asm se cambia de estado el LED con cada pulsación de una tecla

 include "zxspectrum.h"  

  org $8000
  
  ;------------- Pasar a Dark Mode ------------
  BORDER BLACK
  
  ;-- Establecer los atributos permanentes
  SET_ATTR_S BLACK, GREEN

  ;-- Borrar la pantalla
  CALL ROM_CLS
  ;--------------------------------------------

  loop:
    
    ;-- Apagar led
    call led_off

    ;-- Esperar a que se pulse una tecla
    call Wait_Key

    ;-- Encender led
    call led_on

    ;-- Esperar a que se pulse una tecla
    call Wait_Key

    jr loop


led_off:
  ;-- Led apagado
  ld a, $00
  ld ($4000),a
  ld a, $3C
  ld ($4100),a
  ld a, $42
  ld ($4200),a
  ld a, $42
  ld ($4300),a
  ld a, $42
  ld ($4400),a
  ld a, $42
  ld ($4500),a
  ld a, $3C
  ld ($4600),a
  ld a, $00
  ld ($4700),a
  ret
  

led_on:
  ;-- Led encendido
  ld a, $00
  ld ($4000),a
  ld a, $3C
  ld ($4100),a
  ld a, $7E
  ld ($4200),a
  ld a, $7E
  ld ($4300),a
  ld a, $7A
  ld ($4400),a
  ld a, $76
  ld ($4500),a
  ld a, $3C
  ld ($4600),a
  ld a, $00
  ld ($4700),a
  ret


  ;-- Terminar
inf: jr inf


    include "Video.asm"
    include "Keyboard.asm"

    end $8000

En esta animación se muestra el funcionamiento

Esta es la versión del led parpadeante, que parpadea con periodo de 1 segundo: 05-led-blink.asm

 include "zxspectrum.h"  

  org $8000
  
  ;------------- Pasar a Dark Mode ------------
  BORDER BLACK
  
  ;-- Establecer los atributos permanentes
  SET_ATTR_S BLACK, GREEN

  ;-- Borrar la pantalla
  CALL ROM_CLS
  ;--------------------------------------------

loop:
    
    ;-- Dibujar led apagado
    ld hl, $4000
    ld de, sprite_led_off
    call draw_sprite8

    ;-- Esperar
    call wait_500ms

    ;-- Dibujar led encendido
    ld hl, $4000
    ld de, sprite_led_on
    call draw_sprite8

    ;-- Esperar
    call wait_500ms

    jr loop

;-------------------
;-- SPRITES
;-------------------  
;-- Led apagado
sprite_led_off: DEFB $00, $3C, $42, $42, $42, $42, $3C, $00

;-- Led encendido
sprite_led_on:  DEFB $00, $3C, $7E, $7E, $7A, $76, $3C, $00


    include "Video.asm"
    include "Keyboard.asm"
    include "Delay.asm"

    end $8000

Esta es la rutina draw_sprite8 para dibujar un sprite de 8 líneas (y bytes)

;-----------------------------------------------------------------------------
;-- draw_sprite: Dibujar un sprite (de 8 lineas) en la pantalla (de 8 lineas)
;-- 
;-- ENTRADAS:
;--   * HL: Direccion de la memoria de video
;--   * DE: Direccion del sprite a pintar
;-----------------------------------------------------------------------------
draw_sprite8:
  
  ld b, 8  ;-- El sprite tiene 8 lineas

sprite_loop:
  ld a, (de)  ;-- Leer byte del sprite
  ld (hl), a  ;-- Mostrar byte en pantalla
  inc h       ;-- Siguiente linea
  inc de      ;-- Siguiente byte
  djnz sprite_loop

  ret

Esta es la animación:

LED: 3 sprites

  • Ejemplo: 06-led-3-sprites.z80

He creado un sprite intermedio entre apagado y encendido... no es demasiado bueno, pero hay que probarlo

 include "zxspectrum.h"  

  org $8000
  
  ;------------- Pasar a Dark Mode ------------
  BORDER BLACK
  
  ;-- Establecer los atributos permanentes
  SET_ATTR_S BLACK, GREEN

  ;-- Borrar la pantalla
  CALL ROM_CLS
  ;--------------------------------------------

  ;-- Mostrar los 3 sprites
  ld hl, $4000
  ld de, sprite_led_off
  call draw_sprite8

  ld hl, $4001
  ld de, sprite_led_half
  call draw_sprite8

  ld hl, $4002
  ld de, sprite_led_on
  call draw_sprite8

inf:
  jr inf

;-------------------
;-- SPRITES
;-------------------  
;-- Led apagado
sprite_led_off: DEFB $00, $3C, $42, $42, $42, $42, $3C, $00

;-- Led medio-encendido
sprite_led_half: DEFB $00, $3C, $56, $4A, $52, $66, $3C, $00

;-- Led encendido
sprite_led_on:  DEFB $00, $3C, $7E, $7E, $7A, $76, $3C, $00


    include "Video.z80"
    include "Keyboard.z80"
    include "Delay.z80"

    end $8000

Este es el resultado:

Nuevo LED parpadeante

Se hace parpear el led usando los 3 sprites

  • Ejemplo: 07-led-3-sprites-blink.z80
 include "zxspectrum.h"  

  org $8000
  
  ;------------- Pasar a Dark Mode ------------
  BORDER BLACK
  
  ;-- Establecer los atributos permanentes
  SET_ATTR_S BLACK, GREEN

  ;-- Borrar la pantalla
  CALL ROM_CLS
  ;--------------------------------------------

loop:
    
    ;-- Dibujar led apagado
    ld hl, $4000
    ld de, sprite_led_off
    call draw_sprite8

    ;-- Esperar
    call wait_500ms

    ;-- Sprite2
    ld hl, $4000
    ld de, sprite_led_half
    call draw_sprite8

    ;-- Esperar
    call wait_60ms

    ;-- Dibujar led encendido
    ld hl, $4000
    ld de, sprite_led_on
    call draw_sprite8

    ;-- Esperar
    call wait_500ms

    ;-- Sprite2
    ld hl, $4000
    ld de, sprite_led_half
    call draw_sprite8

    ;-- Esperar
    call wait_60ms

    jr loop

;-------------------
;-- SPRITES
;-------------------  
;-- Led apagado
sprite_led_off: DEFB $00, $3C, $42, $42, $42, $42, $3C, $00

;-- Led medio-encendido
sprite_led_half: DEFB $00, $3C, $56, $4A, $52, $66, $3C, $00

;-- Led encendido
sprite_led_on:  DEFB $00, $3C, $7E, $7E, $7A, $76, $3C, $00


    include "Video.z80"
    include "Keyboard.z80"
    include "Delay.z80"

    end $8000

Este es el resultado:

2023-07-14

Sprites: Manic Miner!

Voy a hacer los sprites del Manic Miner! Este fue uno de los primeros juegos de Spectrum que tuve, y me pareció increible!

  • Ejemplo: 08-Manic-miner.z80
 include "zxspectrum.h"  

  org $8000
  
  ;------------- Pasar a Dark Mode ------------
  BORDER BLACK
  
  ;-- Establecer los atributos permanentes
  SET_ATTR_S BLACK, WHITE

  ;-- Borrar la pantalla
  CALL ROM_CLS
  ;--------------------------------------------

loop:
    
    ld hl, $4000
    ld de, sprite_Manic_miner0
    call draw_sprite18

    ld hl, $4002
    ld de, sprite_Manic_miner1
    call draw_sprite18

    ld hl, $4004
    ld de, sprite_Manic_miner2
    call draw_sprite18

    ld hl, $4005
    ld de, sprite_Manic_miner2_2
    call draw_sprite18

    ;-- Esperar
    call wait_500ms

    jr loop

;-------------------
;-- SPRITES
;-------------------  
;-- Manic Miner 0
sprite_Manic_miner0: 
  DEFB $00, $06, $3E, $7C, $34, $3E, $3C, $18 
  DEFB $3C, $6E, $6E, $6E, $76, $3C, $18, $18
  DEFB $1C, $00

;-- Manic Miner 1
sprite_Manic_miner1:
  DEFB $00, $06, $3E, $7C, $34, $3E, $3C, $18 
  DEFB $3C, $7E, $7E, $57, $FB, $3C, $36, $6E
  DEFB $77, $00

;-- Manic Miner 2-1
sprite_Manic_miner2:
  DEFB $00, $06, $3E, $7C, $34, $3E, $3C, $18 
  DEFB $3C, $3F, $7F, $FF, $DE, $1F, $3B, $61
  DEFB $71, $00

;-- Manic Miner 2-2
sprite_Manic_miner2_2:
  DEFB $00, $00, $00, $00, $00, $00, $00, $00 
  DEFB $00, $00, $80, $C0, $C0, $00, $40, $C0
  DEFB $80, $00


    include "Video.z80"
    include "Keyboard.z80"
    include "Delay.z80"

    end $8000

Este es el resultado:

Animación Manic Miner!

En este ejemplo se animan los sprites, dejándolos en las posición inicial (esquina superior izquierda)

  • Ejemplo: 09-Manic-miner.z80
  include "zxspectrum.h"  

  org $8000
  
  ;------------- Pasar a Dark Mode ------------
  BORDER BLACK
  
  ;-- Establecer los atributos permanentes
  SET_ATTR_S BLACK, WHITE

  ;-- Borrar la pantalla
  CALL ROM_CLS
  ;--------------------------------------------

loop:
    
    ;-- Fotograma 1
    ld hl, $4000
    ld de, sprite_Manic_miner0
    call draw_sprite18

    ld hl, $4001
    call blank_sprite18

    ;-- Esperar
    call wait_500ms

    ;-- Fotograma 2
    ld hl, $4000
    ld de, sprite_Manic_miner1
    call draw_sprite18

    ld hl, $4001
    call blank_sprite18

    ;-- Esperar
    call wait_500ms

    ;-- Fotograma 3
    ld hl, $4000
    ld de, sprite_Manic_miner2
    call draw_sprite18

    ld hl, $4001
    ld de, sprite_Manic_miner2_2
    call draw_sprite18

    ;-- Esperar
    call wait_500ms

    ;-- Fotograma 4
    ld hl, $4000
    ld de, sprite_Manic_miner1
    call draw_sprite18

    ld hl, $4001
    call blank_sprite18

    ;-- Esperar
    call wait_500ms

    jr loop

;-------------------
;-- SPRITES
;-------------------  
;-- Manic Miner 0
sprite_Manic_miner0: 
  DEFB $00, $06, $3E, $7C, $34, $3E, $3C, $18 
  DEFB $3C, $6E, $6E, $6E, $76, $3C, $18, $18
  DEFB $1C, $00

;-- Manic Miner 1
sprite_Manic_miner1:
  DEFB $00, $06, $3E, $7C, $34, $3E, $3C, $18 
  DEFB $3C, $7E, $7E, $57, $FB, $3C, $36, $6E
  DEFB $77, $00

;-- Manic Miner 2-1
sprite_Manic_miner2:
  DEFB $00, $06, $3E, $7C, $34, $3E, $3C, $18 
  DEFB $3C, $3F, $7F, $FF, $DE, $1F, $3B, $61
  DEFB $71, $00

;-- Manic Miner 2-2
sprite_Manic_miner2_2:
  DEFB $00, $00, $00, $00, $00, $00, $00, $00 
  DEFB $00, $00, $80, $C0, $C0, $00, $40, $C0
  DEFB $80, $00


    include "Video.z80"
    include "Keyboard.z80"
    include "Delay.z80"

    end $8000

Más Sprites del Manic Miner!

Voy a hacer más sprites del Manic miner: el muro de ladrillos y el suelo de la cueva. Los hago en Inkscape:

Este es el programa que los implementa: 10-Manic-miner-sprites.z80

  include "zxspectrum.h"  

  org $8000
  
  ;------------- Pasar a Dark Mode ------------
  BORDER BLACK
  
  ;-- Establecer los atributos permanentes
  SET_ATTR_S BLACK, WHITE

  ;-- Borrar la pantalla
  CALL ROM_CLS
  ;--------------------------------------------

    ;-- Pintar la parte estática
    ld hl, $4000
    ld de, sprite_ladrillos
    call draw_sprite8

    ld hl, $4020
    ld de, sprite_ladrillos
    call draw_sprite8

    ld hl, $4040
    ld de, sprite_ladrillos
    call draw_sprite8

    ;-- Atributos de los ladrillos
    ld hl, $5800
    ld a, YELLOW << PAPER | RED
    ld (hl), a
    ld ($5820), a
    ld ($5840), a

    ;-- Suelo
    ld hl, $4041
    ld de, sprite_suelo
    call draw_sprite8

    ld hl, $4042
    ld de, sprite_suelo
    call draw_sprite8

    ld hl, $4043
    ld de, sprite_suelo
    call draw_sprite8

    ;-- Atributo del suelo
    ld a, RED
    LD ($5841), a
    LD ($5842), a
    ld ($5843), a

loop:
    
    ;-- Fotograma 1
    ld hl, $4002
    ld de, sprite_Manic_miner0
    call draw_sprite16

    ld hl, $4003
    call blank_sprite16

    ;-- Esperar
    call wait_500ms

    ;-- Fotograma 2
    ld hl, $4002
    ld de, sprite_Manic_miner1
    call draw_sprite16

    ld hl, $4003
    call blank_sprite16

    ;-- Esperar
    call wait_500ms

    ;-- Fotograma 3
    ld hl, $4002
    ld de, sprite_Manic_miner2
    call draw_sprite16

    ld hl, $4003
    ld de, sprite_Manic_miner2_2
    call draw_sprite16

    ;-- Esperar
    call wait_500ms

    ;-- Fotograma 4
    ld hl, $4002
    ld de, sprite_Manic_miner1
    call draw_sprite16

    ld hl, $4003
    call blank_sprite16

    ;-- Esperar
    call wait_500ms

    jr loop

;-------------------
;-- SPRITES
;-------------------  
;-- Manic Miner 0
sprite_Manic_miner0: 
  DEFB $06, $3E, $7C, $34, $3E, $3C, $18, $3C 
  DEFB $6E, $6E, $6E, $76, $3C, $18, $18, $1C

;-- Manic Miner 1
sprite_Manic_miner1:
  DEFB $06, $3E, $7C, $34, $3E, $3C, $18, $3C
  DEFB $7E, $7E, $57, $FB, $3C, $36, $6E, $77

;-- Manic Miner 2-1
sprite_Manic_miner2:
  DEFB $06, $3E, $7C, $34, $3E, $3C, $18, $3C 
  DEFB $3F, $7F, $FF, $DE, $1F, $3B, $61, $71

;-- Manic Miner 2-2
sprite_Manic_miner2_2:
  DEFB $00, $00, $00, $00, $00, $00, $00, $00 
  DEFB $00, $80, $C0, $C0, $00, $40, $C0, $80
  
;--- Ladrillos
sprite_ladrillos:
  DEFB $DD, $00, $77, $00, $DD, $00, $77, $00

;--- Suelo
sprite_suelo:
  DEFB $FF, $FF, $DD, $6E, $C5, $40, $00, $00



    include "Video.z80"
    include "Keyboard.z80"
    include "Delay.z80"

    end $8000

Este es el resultado:

2023-07-15

Sigo creando Sprites... Ahora toca la llave y las estalacticas que están en la parte superior de la cueva

2023-07-16

  • 11-Manic-miner-sprites.z80
 include "zxspectrum.h"  

  org $8000
  
  ;------------- Pasar a Dark Mode ------------
  BORDER RED
  
  ;-- Establecer los atributos permanentes
  SET_ATTR_S BLACK, WHITE

  ;-- Borrar la pantalla
  CALL ROM_CLS
  ;--------------------------------------------

    ;-- Pintar la parte estática
    ld hl, $4000
    ld de, sprite_ladrillos
    call draw_sprite8

    ld hl, $4020
    ld de, sprite_ladrillos
    call draw_sprite8

    ld hl, $4040
    ld de, sprite_ladrillos
    call draw_sprite8

    ;-- Atributos de los ladrillos
    ld hl, $5800
    ld a, YELLOW << PAPER | RED
    ld (hl), a
    ld ($5820), a
    ld ($5840), a

    ;-- Suelo
    ld hl, $4041
    ld de, sprite_suelo
    call draw_sprite8

    ld hl, $4042
    ld de, sprite_suelo
    call draw_sprite8

    ld hl, $4043
    ld de, sprite_suelo
    call draw_sprite8

    ;-- Atributo del suelo
    ld a, BRIGHT | RED
    LD ($5841), a
    LD ($5842), a
    ld ($5843), a

    ;-- Estalactita
    ld hl, $4010
    ld de, sprite_stalactica
    call draw_sprite8

    ld a, CYAN
    ld ($5810), a

    ;-- Llave
    ld hl, $4012
    ld de, sprite_llave
    call draw_sprite8

    ld a, GREEN
    ld ($5812),a
    
    ;-- Fotograma 1
    ld hl, $4002
    ld de, sprite_Manic_miner0
    call draw_sprite16

    ;-- Fotograma 2
    ld hl, $4004
    ld de, sprite_Manic_miner1
    call draw_sprite16

    ;-- Fotograma 3
    ld hl, $4006
    ld de, sprite_Manic_miner2
    call draw_sprite16

    ld hl, $4007
    ld de, sprite_Manic_miner2_2
    call draw_sprite16

    ;-- Fotograma 4
    ld hl, $4008
    ld de, sprite_Manic_miner1
    call draw_sprite16

inf: jr inf



;-------------------
;-- SPRITES
;-------------------  
;-- Manic Miner 0
sprite_Manic_miner0: 
  DEFB $06, $3E, $7C, $34, $3E, $3C, $18, $3C 
  DEFB $6E, $6E, $6E, $76, $3C, $18, $18, $1C

;-- Manic Miner 1
sprite_Manic_miner1:
  DEFB $06, $3E, $7C, $34, $3E, $3C, $18, $3C
  DEFB $7E, $7E, $F7, $FB, $3C, $36, $6E, $77

;-- Manic Miner 2-1
sprite_Manic_miner2:
  DEFB $06, $3E, $7C, $34, $3E, $3C, $18, $3C 
  DEFB $3F, $7F, $FF, $DE, $1F, $3B, $61, $71

;-- Manic Miner 2-2
sprite_Manic_miner2_2:
  DEFB $00, $00, $00, $00, $00, $00, $00, $00 
  DEFB $00, $80, $C0, $C0, $00, $40, $C0, $80
  
;--- Ladrillos
sprite_ladrillos:
  DEFB $DD, $00, $77, $00, $DD, $00, $77, $00

;--- Suelo
sprite_suelo:
  DEFB $FF, $FF, $DD, $6E, $C5, $40, $00, $00

;--- Estalactita
sprite_stalactica:
  DEFB $FF, $FE, $7E, $7C, $4C, $4C, $08, $08

;--- Llave
sprite_llave:
  DEFB $30, $48, $88, $90, $68, $04, $0A, $04



    include "Video.z80"
    include "Keyboard.z80"
    include "Delay.z80"

    end $8000

2023-07-18

  • Fichero: 12-Manic-miner-sprites.z80

Reconstrucción inicial del nivel 1 del Manic Miner: barreras laterales, suelo, estalacticas y llaves. Falta el suelo movedizo, la cinta transportadora, los arbustos venenosos y todas las letras

include "zxspectrum.h"  

  org $8000
  
  ;------------- Pasar a Dark Mode ------------
  BORDER RED
  
  ;-- Establecer los atributos permanentes
  SET_ATTR_S BLACK, WHITE

  ;-- Borrar la pantalla
  CALL ROM_CLS
  ;--------------------------------------------

  call draw_left_border
  call draw_right_border

  call draw_suelo1

  ;-- Dibujar suelo
  ld b,5
  ld c,1
  ld a, 13
  ld de, sprite_suelo
  call lineah_sprite

  ;-- Atributos suelo
  ld b,5
  ld c,1
  ld a,13
  ld d, BRIGHT | RED
  call lineah_attr

  ;-- Dibujar suelo
  ld b,7
  ld c,1
  ld a, 3
  ld de, sprite_suelo
  call lineah_sprite

  ;-- Atributos suelo
  ld b,7
  ld c,1
  ld a,3
  ld d, BRIGHT | RED
  call lineah_attr

  ;-- Dibujar suelo
  ld b,9
  ld c,1
  ld a, 4
  ld de, sprite_suelo
  call lineah_sprite

  ;-- Atributos suelo
  ld b,9
  ld c,1
  ld a,4
  ld d, BRIGHT | RED
  call lineah_attr



  ;-- Dibujar suelo
  ld b,13
  ld c,5
  ld a, 19
  ld de, sprite_suelo
  call lineah_sprite

  ;-- Atributos suelo
  ld b,13
  ld c,5
  ld a,19
  ld d, BRIGHT | RED
  call lineah_attr


  

  ;-- Dibujar suelo
  ld b,12
  ld c,28
  ld a, 30
  ld de, sprite_suelo
  call lineah_sprite

  ;-- Atributos suelo
  ld b,12
  ld c,28
  ld a,30
  ld d, BRIGHT | RED
  call lineah_attr

  ;-- Dibujar suelo
  ld b,10
  ld c,29
  ld a, 30
  ld de, sprite_suelo
  call lineah_sprite

  ;-- Atributos suelo
  ld b,10
  ld c,29
  ld a,30
  ld d, BRIGHT | RED
  call lineah_attr

  
  ;-- Dibujar suelo
  ld b,5
  ld c,23
  ld a,30
  ld de, sprite_suelo
  call lineah_sprite

  ;-- Atributos suelo
  ld b,5
  ld c,23
  ld a,30
  ld d, BRIGHT | RED
  call lineah_attr


  ;-- Dibujar suelo
  ld b,5
  ld c,18
  ld a,18
  ld de, sprite_suelo
  call lineah_sprite

  ;-- Atributos suelo
  ld b,5
  ld c,18
  ld a,18
  ld d, BRIGHT | RED
  call lineah_attr


    ;-- Estalactita 2
    ld b,0
    ld c,16
    call DF_LOC
    ld de, sprite_stalactica
    call draw_sprite8

    ld b,0
    ld c,16
    call ATTLOC
    ld a, CYAN
    ld (hl), a

   ;-- Estalactita 1
    ld b,0
    ld c,11
    call DF_LOC
    ld de, sprite_stalactica
    call draw_sprite8

    ld b,0
    ld c,11
    call ATTLOC
    ld a, CYAN
    ld (hl), a


    ;-- Llave 1
    ld b,0
    ld c,9
    call DF_LOC
    ld de, sprite_llave
    call draw_sprite8

    ld b,0
    ld c,9
    call ATTLOC
    ld a, CYAN
    ld (hl),a

    ;-- Llave 2
    ld b,1
    ld c,16
    call DF_LOC
    ld de, sprite_llave
    call draw_sprite8

    ld b,1
    ld c,16
    call ATTLOC
    ld a, MAGENTA
    ld (hl),a

    ;-- Llave 3
    ld b,0
    ld c,29
    call DF_LOC
    ld de, sprite_llave
    call draw_sprite8

    ld b,0
    ld c,29
    call ATTLOC
    ld a, YELLOW
    ld (hl),a

     ;-- Llave 4
    ld b,4
    ld c,24
    call DF_LOC
    ld de, sprite_llave
    call draw_sprite8

    ld b,4
    ld c,24
    call ATTLOC
    ld a, GREEN
    ld (hl),a

     ;-- Llave 5
    ld b,6
    ld c,30
    call DF_LOC
    ld de, sprite_llave
    call draw_sprite8

    ld b,6
    ld c,30
    call ATTLOC
    ld a, CYAN
    ld (hl),a
    
    ;-- Fotograma 1
    ld hl, $48A2  ;1010 0010
    ld de, sprite_Manic_miner1
    call draw_sprite16

inf: jr inf

;-------------------
;-- SPRITES
;-------------------  
;-- Manic Miner 0
sprite_Manic_miner0: 
  DEFB $06, $3E, $7C, $34, $3E, $3C, $18, $3C 
  DEFB $6E, $6E, $6E, $76, $3C, $18, $18, $1C

;-- Manic Miner 1
sprite_Manic_miner1:
  DEFB $06, $3E, $7C, $34, $3E, $3C, $18, $3C
  DEFB $7E, $7E, $F7, $FB, $3C, $36, $6E, $77

;-- Manic Miner 2-1
sprite_Manic_miner2:
  DEFB $03, $1F, $3E, $1A, $1F, $1E, $0C, $1E 
  DEFB $3F, $7F, $FF, $DE, $1F, $3B, $61, $71

;-- Manic Miner 2-2
sprite_Manic_miner2_2:
  DEFB $00, $00, $00, $00, $00, $00, $00, $00 
  DEFB $00, $80, $C0, $C0, $00, $40, $C0, $80
  
;--- Ladrillos
sprite_ladrillos:
  DEFB $DD, $00, $77, $00, $DD, $00, $77, $00

;--- Suelo
sprite_suelo:
  DEFB $FF, $FF, $DD, $6E, $C5, $40, $00, $00

;--- Estalactita
sprite_stalactica:
  DEFB $FF, $FE, $7E, $7C, $4C, $4C, $08, $08

;--- Llave
sprite_llave:
  DEFB $30, $48, $88, $90, $68, $04, $0A, $04


;----------------------------------------------------------------------------
;--  draw_left_border: Dibujar el muro izquierdo de la pantalla 1
;----------------------------------------------------------------------------
draw_left_border:

  ;-- Posicion final en A
  ld a, 15

  ;--- Asignar atributos a una linea vertical
  ld b, 0  ;-- Linea
  ld c, 0   ;-- Columna

  ld d, YELLOW << PAPER | RED
  call lineav_attr

  ;-- Meter en A la posicion final
  ld a, 15

  ;-- Pintar muro de ladrillos izquierdo
  ld b, 0       ;--- Linea 0
  ld c, 0       ;--- Col   0
  ld de, sprite_ladrillos
  call lineav_sprite

  ret

;----------------------------------------------------------------------------
;--  draw_right_border: Dibujar el muro derecho de la pantalla 1
;----------------------------------------------------------------------------
draw_right_border:

;-- Posicion final en A
  ld a, 15

  ;--- Asignar atributos a una linea vertical
  ld b, 0  ;-- Linea
  ld c, 31   ;-- Columna

  ld d, YELLOW << PAPER | RED
  call lineav_attr

  ;-- Meter en A la posicion final
  ld a, 15

  ;-- Pintar muro de ladrillos izquierdo
  ld b, 0       ;--- Linea 0
  ld c, 31       ;--- Col   0
  ld de, sprite_ladrillos
  call lineav_sprite

  ret


;----------------------------------------------------------------------------
;-- lineav_attr:  Establecer una linea vertical de atributos
;--
;-- ENTRADAS:
;--   * B: linea inicial (0-23)
;--   * C: Columna (0-31)
;--   * A: Linea final (0-23)
;--   * D: Atributos a escribir
;----------------------------------------------------------------------------
lineav_attr:
linev_attr_loop:


  ;-- Preservar linea final
  push af

  ;-- Preservar posicion inicial
  push bc

  ;-- HL: Direccion de la memoria de atributos de la posicion actual
  call ATTLOC

  ;-- Recuperar posicion actual
  pop bc

  ;-- Guardar el atributo
  ld a, d
  ld (hl), a

  ;-- Recuperar la linea final
  pop af

  ;-- Incrementar la fila actual
  inc b

  ;-  Linea actual > linea final?
  cp b
  jr nc, linev_attr_loop  ;-- Linea actual < linea final: Repetir
  jr z, linev_attr_loop   ;-- Linea actual = linea final: Repetir (ultima vez)

  ;-- Se ha sobrepasado la linea final. Terminar
  ret


;----------------------------------------------------------------------------
;-- lineah_attr:  Establecer una linea horizontal de atributos
;--
;-- ENTRADAS:
;--   * B: linea inicial (0-23)
;--   * C: Columna (0-31)
;--   * A: Columna final (0-23)
;--   * D: Atributos a escribir
;----------------------------------------------------------------------------
lineah_attr:
lineh_attr_loop:


  ;-- Preservar linea final
  push af

  ;-- Preservar posicion inicial
  push bc

  ;-- HL: Direccion de la memoria de atributos de la posicion actual
  call ATTLOC

  ;-- Recuperar posicion actual
  pop bc

  ;-- Guardar el atributo
  ld a, d
  ld (hl), a

  ;-- Recuperar la linea final
  pop af

  ;-- Incrementar la columna actual
  inc c

  ;-  Col actual > Col final?
  cp c
  jr nc, lineh_attr_loop  ;-- Col actual < col final: Repetir
  jr z, lineh_attr_loop   ;-- Col actual = col final: Repetir (ultima vez)

  ;-- Se ha sobrepasado la linea final. Terminar
  ret





;----------------------------------------------------------------------------
;-- lineav_sprite:  Establecer una linea vertical de sprites
;--
;-- ENTRADAS:
;--   * B: linea inicial (0-23)
;--   * C: Columna (0-31)
;--   * A: Linea final (0-23)
;--   * DE: Direccion del sprite
;----------------------------------------------------------------------------
lineav_sprite:
linev_sprite_loop:

  push af
  push bc
  push de

  call DF_LOC
  call draw_sprite8

  pop de
  pop bc
  pop af
  inc b
  
  cp b
  jr nc, linev_sprite_loop
  jr z, linev_sprite_loop

  ret
  

;----------------------------------------------------------------------------
;-- lineah_sprite:  Establecer una linea horizontal de sprites
;--
;-- ENTRADAS:
;--   * B: linea inicial (0-23)
;--   * C: Columna (0-31)
;--   * A: Columna final (0-23)
;--   * DE: Direccion del sprite
;----------------------------------------------------------------------------
lineah_sprite:
lineh_sprite_loop:

  push af
  push bc
  push de

  call DF_LOC
  call draw_sprite8

  pop de
  pop bc
  pop af
  inc c
  
  cp c
  jr nc, lineh_sprite_loop
  jr z, lineh_sprite_loop

  ret

draw_suelo1:
  ;-- Dibujar suelo
  ld b,15
  ld c,1
  ld a, 30
  ld de, sprite_suelo
  call lineah_sprite

  ;-- Atributos suelo
  ld b,15
  ld c,1
  ld a,30
  ld d, BRIGHT | RED
  call lineah_attr
  ret


    include "Video.z80"
    include "Keyboard.z80"
    include "Delay.z80"

    end $8000

Este es el resultado: