; Ejemplo impresion mapa de 16x16 codificacion scanlines verticales ORG 35000 ;;; Borramos la pantalla (graficos y atributos) xor a call ClearScreen xor a call ClearAttributes ;;; Establecer valores de llamada: ld hl, sokoban1_gfx ld (DM_SPRITES), hl ld hl, sokoban1_attr ld (DM_ATTRIBS), hl ld hl, sokoban_LEVEL1_codif_vert ld (DM_MAP), hl ld a, 16 ld (DM_WIDTH), a ld a, 12 ld (DM_HEIGHT), a xor a ld (DM_COORD_X), a ld (DM_COORD_Y), a ;;; Impresion de pantalla por codificacion scanlines verticales call DrawMap_16x16_Cod_Vert loop: jr loop ;------------------------------------------------------------- ; Variables que usaremos como parĂ¡metros ;------------------------------------------------------------- DM_SPRITES DEFW 0 DM_ATTRIBS DEFW 0 DM_MAP DEFW 0 DM_COORD_X DEFB 0 DM_COORD_Y DEFB 0 DM_WIDTH DEFB 0 DM_HEIGHT DEFB 0 DS_SPRITES DEFW 0 DS_ATTRIBS DEFW 0 DS_COORD_X DEFB 0 DS_COORD_Y DEFB 0 DS_NUMSPR DEFB 0 ;--------------------------------------------------------------- ; DrawMap_16x16_Cod_Vert: ; Imprime una pantalla de tiles de 16x16 pixeles. ; ; Entrada (paso por parametros en memoria): ; Direccion Parametro ; -------------------------------------------------------------- ; DM_SPRITES (2 bytes) Direccion de la tabla de tiles. ; DM_ATTRIBS (2 bytes) Direccion de la tabla de atributos. ; DM_MAP (2 bytes) Direccion de la pantalla en memoria. ; DM_COORD_X (1 byte) Coordenada X-Inicial en baja resolucion. ; DM_COORD_Y (1 byte) Coordenada Y-Inicial en baja resolucion. ; DM_WIDTH (1 byte) Ancho del mapa en tiles ; DM_HEIGHT (1 byte) Alto del mapa en tiles ;--------------------------------------------------------------- DrawMap_16x16_Cod_Vert: ld hl, (DM_SPRITES) ld (DS_SPRITES), hl ; Establecer tileset (graficos) ld hl, (DM_ATTRIBS) ld (DS_ATTRIBS), hl ; Establecer tileset (atributos) ld bc, (DM_COORD_X) ; B = Y_INICIO, C = X_INICIO ld de, (DM_MAP) ; DE apunta al mapa ld hl, DS_COORD_Y ; Ahora HL apunta a la variable Y drawm16cv_read: ld a, (de) ; Leemos el valor de COORD_X_TILE inc de ; Apuntamos al siguiente byte del mapa drawm16cv_loop: cp 255 ; Bloque especial fin de pantalla ret z ; En ese caso, salir add a, c ; A = (X_INICIO + COORD_X_TILE) rlca ; A = (X_INICIO + COORD_X_TILE) * 2 ld (DS_COORD_X), a ; Establecemos COORD_X a imprimir tile ld a, (de) ; Leemos el valor de COORD_Y_TILE inc de add a, b ; A = (Y_INICIO + COORD_Y_TILE) rlca ; A = (Y_INICIO + COORD_Y_TILE) ld (hl), a ; Establecemos COORD_Y a imprimir tile ;;; Bucle impresion de todos los tiles del scanline (aunque sea 1 solo) drawm16cv_tileloop: ld a, (de) ; Leemos el valor del TILE de pantalla inc de ; Incrementamos puntero cp 255 jr z, drawm16cv_read ; Si es fin de tile codificado, fin bucle ld (DS_NUMSPR), a ; Establecemos el TILE exx ; Preservar todos los registros en shadows call DrawSprite_16x16_LD ; Imprimir el tile con los parametros exx ; Recuperar valores de los registros inc (hl) inc (hl) ; COORD_Y = COORD_Y + 2 jr drawm16cv_tileloop ; Repetimos hasta encontrar el 255 ;----------------------------------------------------------------------- ; Level 1 from Sokoban: ;----------------------------------------------------------------------- sokoban_LEVEL1_codif_vert: ; Flag codificacion: -v DB 6 , 1 , 2 , 3 , 6 , 255 , 7 , 1 , 3 , 255 , 8 , 1 DB 1 , 255 , 9 , 1 , 4 , 5 , 255 , 4 , 2 , 1 , 4 , 5 DB 4 , 5 , 255 , 5 , 2 , 2 , 255 , 10 , 2 , 4 , 5 , 4 DB 5 , 3 , 4 , 5 , 3 , 255 , 7 , 3 , 6 , 6 , 255 , 5 DB 6 , 2 , 255 , 6 , 6 , 3 , 1 , 4 , 5 , 255 , 9 , 6 DB 2 , 255 , 7 , 8 , 7 , 2 , 255 , 8 , 8 , 7 , 3 , 255 DB 9 , 8 , 7 , 2 , 255 , 255 ;----------------------------------------------------------------------- ; ASM source file created by SevenuP v1.20 ; SevenuP (C) Copyright 2002-2006 by Jaime Tejedor Gomez, aka Metalbrain ; Pixel Size: ( 16, 128) - Char Size: ( 2, 16) ; Sort Priorities: X char, Char line, Y char ; Data Outputted: Gfx / Attr ;----------------------------------------------------------------------- sokoban1_gfx: DEFB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 DEFB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 DEFB 127,252,193, 86,152, 2,180,170, 173, 86,153,254,194,170,255,254 DEFB 0, 0,102,102, 51, 50,153,152, 204,204,102,102, 51, 50, 0, 0 DEFB 127,102,205, 76,151, 24,205, 50, 151,102,205, 76,151, 24,205, 50 DEFB 131,102,153, 76,173, 24,181, 50, 153,102,195, 76,127, 24, 0, 0 DEFB 255,252,255,134,255, 50,255, 90, 255,106,255, 50,255,134,255,254 DEFB 255,254,255,254,255,254,255,250, 255,242,253,166,255,252, 0, 0 DEFB 127,252,205,134,151, 50,205,106, 151, 90,205, 50,151,134,205,254 DEFB 195,254,153,254,173,254,181,250, 153,242,195,166,127,252, 0, 0 DEFB 255,254,255,254,255,254,255,254, 255,254,255,254,191,254,255,254 DEFB 255,134,191, 50,255,106,191, 90, 159, 50,207,134,127,252, 0, 0 DEFB 0, 0,127,254, 95,250, 96, 6, 111,182,111,118, 96,230,109,214 DEFB 107,182,103, 6,110,246,109,246, 96, 6, 95,250,127,254, 0, 0 DEFB 0, 0,123,222,123,222, 96, 6, 96, 6, 0, 0, 96, 6, 96, 6 DEFB 96, 6, 96, 6, 0, 0, 96, 6, 96, 6,123,222,123,222, 0, 0 sokoban1_attr: DEFB 0, 0, 0, 0, 5, 5, 70, 70, 5, 70, 5, 70, 69, 71, 69, 71 DEFB 5, 69, 69, 71, 69, 69, 71, 71, 2, 66, 66, 67, 6, 70, 70, 71 ;----------------------------------------------------------------------- ; Limpiar la pantalla con el patron de pixeles indicado. ; Entrada: A = patron a utilizar ;----------------------------------------------------------------------- ClearScreen: ld hl, 16384 ; HL = Inicio del area de imagen ld (hl), a ; Escribimos el valor de A en (HL) ld de, 16385 ; Apuntamos DE a 16385 ld bc, 192*32-1 ; Copiamos 6142 veces (HL) en (DE) ldir ret ;------------------------------------------------------------------------- ; Establecer los colores de la pantalla con el byte de atributos indicado. ; Entrada: A = atributo a utilizar ;------------------------------------------------------------------------- ClearAttributes: ld hl, 22528 ; HL = Inicio del area de atributos ld (hl), a ; Escribimos el patron A en (HL) ld de, 22529 ; Apuntamos DE a 22529 ld bc, 24*32-1 ; Copiamos 767 veces (HL) en (DE) ldir ; e incrementamos HL y DL. Restamos 1 ; porque ya hemos escrito en 22528. ret ;------------------------------------------------------------- ; DrawSprite_16x16_LD: ; Imprime un sprite de 16x16 pixeles con o sin atributos. ; ; Entrada (paso por parametros en memoria): ; Direccion Parametro ; (DS_SPRITES) Direccion de la tabla de Sprites ; (DS_ATTRIBS) Direccion de la tabla de Atribs (0=no atributos) ; (DS_COORD_X) Coordenada X en baja resolucion ; (DS_COORD_Y) Coordenada Y en baja resolucion ; (DS_NUMSPR) Numero de sprite a dibujar (0-N) ;------------------------------------------------------------- DrawSprite_16x16_LD: ; Guardamos en BC la pareja (x,y) -> B=COORD_Y y C=COORD_X ld bc, (DS_COORD_X) ;;; Calculamos las coordenadas destino de pantalla en DE: ld a, b and $18 add a, $40 ld d, a ld a, b and 7 rrca rrca rrca add a, c ld e, a push de ; Lo guardamos para luego, lo usaremos para ; calcular la direccion del atributo ;;; Calcular posicion origen (array sprites) en HL como: ;;; direccion = base_sprites + (NUM_SPRITE*32) ;;; Multiplicamos con desplazamientos, ver los comentarios. ld bc, (DS_SPRITES) ld a, (DS_NUMSPR) ld l, 0 ; AL = DS_NUMSPR*256 srl a ; Desplazamos a la derecha para dividir por dos rr l ; AL = DS_NUMSPR*128 rra ; Rotamos, ya que el bit que salio de L al CF fue 0 rr l ; AL = DS_NUMSPR*64 rra ; Rotamos, ya que el bit que salio de L al CF fue 0 rr l ; AL = DS_NUMSPR*32 ld h, a ; HL = DS_NUMSPR*32 add hl, bc ; HL = BC + HL = DS_SPRITES + (DS_NUMSPR * 32) ; HL contiene la direccion de inicio en el sprite ex de, hl ; Intercambiamos DE y HL (DE=origen, HL=destino) ;;; Repetir 8 veces (primeros 2 bloques horizontales): ld b, 8 drawsp16x16_loop1: ld a, (de) ; Bloque 1: Leemos dato del sprite ld (hl), a ; Copiamos dato a pantalla inc de ; Incrementar puntero en sprite inc l ; Incrementar puntero en pantalla ld a, (de) ; Bloque 2: Leemos dato del sprite ld (hl), a ; Copiamos dato a pantalla inc de ; Incrementar puntero en sprite inc h ; Hay que sumar 256 para ir al siguiente scanline dec l ; pero hay que restar el inc l que hicimos. djnz drawsp16x16_loop1 ; Avanzamos HL 1 scanline (codigo de incremento de HL en 1 scanline) ; desde el septimo scanline de la fila Y+1 al primero de la Y+2 ;;;inc h ; No hay que hacer inc h, lo hizo en el bucle ;;;ld a, h ; No hay que hacer esta prueba, sabemos que ;;;and 7 ; no hay salto (es un cambio de bloque) ;;;jr nz, drawsp16_nofix_abajop ld a, l add a, 32 ld l, a jr c, drawsp16_nofix_abajop ld a, h sub 8 ld h, a drawsp16_nofix_abajop: ;;; Repetir 8 veces (segundos 2 bloques horizontales): ld b, 8 drawsp16x16_loop2: ld a, (de) ; Bloque 1: Leemos dato del sprite ld (hl), a ; Copiamos dato a pantalla inc de ; Incrementar puntero en sprite inc l ; Incrementar puntero en pantalla ld a, (de) ; Bloque 2: Leemos dato del sprite ld (hl), a ; Copiamos dato a pantalla inc de ; Incrementar puntero en sprite inc h ; Hay que sumar 256 para ir al siguiente scanline dec l ; pero hay que restar el inc l que hicimos. djnz drawsp16x16_loop2 ;;; En este punto, los 16 scanlines del sprite estan dibujados. pop bc ; Recuperamos el offset del primer scanline ;;; Considerar el dibujado de los atributos (Si DS_ATTRIBS=0 -> ret) ld hl, (DS_ATTRIBS) xor a ; A = 0 add a, h ; A = 0 + H = H ret z ; Si H = 0, volver (no dibujar atributos) ;;; Calcular posicion destino en area de atributos en DE. ld a, b ; Codigo de Get_Attr_Offset_From_Image rrca ; Obtenemos dir de atributo a partir de rrca ; dir de zona de imagen. rrca ; Nos evita volver a obtener X e Y and 3 ; y hacer el calculo completo de la or $58 ; direccion en zona de atributos ld d, a ld e, c ; DE tiene el offset del attr de HL ld a, (DS_NUMSPR) ; Cogemos el numero de sprite a dibujar ld c, a ld b, 0 add hl, bc ; HL = HL+DS_NUMSPR add hl, bc ; HL = HL+DS_NUMSPR*2 add hl, bc ; HL = HL+DS_NUMSPR*3 add hl, bc ; HL = HL+HL=(DS_NUMSPR*4) = Origen de atributo ldi ldi ; Imprimimos las 2 primeras filas de atributo ;;; Avance diferencial a la siguiente linea de atributos ld a, e ; A = L add a, 30 ; Sumamos A = A + 30 mas los 2 INCs de ldi. ld e, a ; Guardamos en L (L = L+30 + 2 por ldi=L+32) jr nc, drawsp16x16_attrab_noinc inc d drawsp16x16_attrab_noinc: ldi ldi ret ; porque no necesitamos incrementar HL y DE END 35000