; Ejemplo impresion mapa de 16x16 codificacion mixta y ; XY agrupados en el mismo byte (nibble alto=X, bajo=Y) 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_mixta_XY 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 mixta XY call DrawMap_16x16_Cod_Mixta_XY 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_Mixta_XY: (X e Y codificados en mismo byte) ; Imprime una pantalla de tiles de 16x16 pixeles. ; ; Entrada (paso por parametros en memoria): ; Direccion Parametro ; -------------------------------------------------------------- ; DM_* = Variables de MAPA ; DS_* = Variables de SPRITE ;--------------------------------------------------------------- DrawMap_16x16_Cod_Mixta_XY: xor a ; Opcode de "nop" ld (drawm16cmxy_dir1), a ; almacenar en la posicion de las labels ld (drawm16cmxy_dir2), a 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 ix, (DM_MAP) ; DE apunta al mapa ld de, DS_COORD_Y ; DE apunta a la coordenada Y ld hl, DS_COORD_X ; HL apunta a la coordenada X drawm16cmxy_read: ld a, (ix+0) ; Leemos el valor de COORDENADAS inc ix ; Apuntamos al siguiente byte del mapa drawm16cmxy_loop: cp 255 ; Bloque especial fin de pantalla ret z ; En ese caso, salir push af and %11110000 ; Nos quedamos con la parte alta (COORD_X) rrca ; Pasamos parte alta a parte baja rrca ; con 4 desplazamientos rrca rrca ; Ya podemos sumar add a, c ; A = (X_INICIO + COORD_X_TILE) rlca ; A = (X_INICIO + COORD_X_TILE) * 2 ld (hl), a ; Establecemos COORD_X a imprimir tile pop af and %00001111 ; Nos quedamos con la parte baja (COORD_Y) add a, b ; A = (Y_INICIO + COORD_Y_TILE) rlca ; A = (Y_INICIO + COORD_Y_TILE) ld (de), a ; Establecemos COORD_Y a imprimir tile ;;; Bucle impresion vertical de los N tiles del scanline drawm16cmxy_tileloop: ld a, (ix+0) ; Leemos el valor del TILE de pantalla inc ix ; Incrementamos puntero cp 255 jr z, drawm16cmxy_read ; Si es fin de tile codificado, fin bucle cp 254 jr z, drawm16cmxy_switch ; Codigo 254 -> cambiar a codif. vertical 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 drawm16cmxy_dir1: ; Etiqueta con la direccion del nop nop ; nop->inc cOORD_X, ex de,hl->inc cOORD_Y inc (hl) inc (hl) ; COORD = COORD + 2 drawm16cmxy_dir2: ; Etiqueta con la direccion del nop nop ; nop->inc cOORD_X, ex de,hl->inc cOORD_Y jr drawm16cmxy_tileloop ; Repetimos hasta encontrar el 255 drawm16cmxy_switch: ;;; Cambio de codificacion de horizontal a vertical: ld a, $eb ; Opcode de ex de, hl ld (drawm16cmxy_dir1), a ; ahora se hace el ex de, hl y por lo tanto ld (drawm16cmxy_dir2), a ; inc (hl) incrementa COORD_Y en vez de X jr drawm16cmxy_read ;----------------------------------------------------------------------- ; Level 1 from Sokoban: ;----------------------------------------------------------------------- sokoban_LEVEL1_codif_mixta_XY: ; Flag codificacion: -m ; Resultado: 60 Bytes DB 97 , 2 , 3 , 1 , 4 , 255 , 104 , 4 , 7 , 7 , 7 , 255 DB 105 , 5 , 2 , 3 , 2 , 255 , 82 , 2 , 3 , 255 , 99 , 6 DB 6 , 255 , 86 , 2 , 3 , 255 , 146 , 5 , 255 , 116 , 6 , 255 DB 150 , 2 , 255 , 103 , 1 , 254 , 162 , 4 , 5 , 4 , 5 , 3 DB 4 , 5 , 3 , 255 , 66 , 1 , 4 , 5 , 4 , 5 , 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