; Ejemplo impresion mapa de 16x16 desde array global ORG 35000 ld hl, sokoban1_gfx ld (DM_SPRITES), hl ld hl, sokoban1_attr ld (DM_ATTRIBS), hl ld hl, mapa_ejemplo ld (DM_MAP), hl ld a, ANCHO_PANTALLA ld (DM_WIDTH), a ld a, ALTO_PANTALLA ld (DM_HEIGHT), a xor a ld (DM_COORD_X), a ld (DM_COORD_Y), a ld (DM_MAPX), a ; Establecemos MaPX, MaPY iniciales ld (DM_MAPY), a redraw: call DrawMap_16x16_Map ; Imprimir pantalla de mapa bucle: call LEER_TECLADO ; Leemos el estado de O, P, Q, A bit 0, a ; Modificamos MAPX y MAPY segun OPQA jr z, nopulsada_q call Map_Dec_Y jr redraw nopulsada_q: bit 1, a jr z, nopulsada_a call Map_Inc_Y jr redraw nopulsada_a: bit 2, a jr z, nopulsada_p call Map_Inc_X jr redraw nopulsada_p: bit 3, a jr z, nopulsada_o call Map_Dec_X jr redraw nopulsada_o: jr bucle loop: jr loop ;------------------------------------------------------------- ; LEER_TECLADO: Lee el estado de O, P, Q, A, y devuelve ; en A el estado de las teclas (1=pulsada, 0=no pulsada). ; El byte está codificado tal que: ; ; BITS 3 2 1 0 ; SIGNIFICADO LEFT RIGHT DOWN UP ;------------------------------------------------------------- LEER_TECLADO: ld d, 0 ld bc, $fbfe in a, (c) bit 0, a ; Leemos la tecla Q jr nz, Control_no_up ; No pulsada, no cambiamos nada en D set 0, d ; Pulsada, ponemos a 1 el bit 0 Control_no_up: ld bc, $fdfe in a, (c) bit 0, a ; Leemos la tecla A jr nz, Control_no_down ; No pulsada, no cambianos nada en D set 1, d ; Pulsada, ponemos a 1 el bit 1 Control_no_down: ld bc, $dffe in a, (c) bit 0, a ; Leemos la tecla P jr nz, Control_no_right ; No pulsada set 2, d ; Pulsada, ponemos a 1 el bit 2 Control_no_right: ; BC ya vale $dffe, (O y P en misma fila) bit 1, a ; Tecla O jr nz, Control_no_left set 3, d Control_no_left: ld a, d ; Devolvemos en A el estado de las teclas ret ;------------------------------------------------------------- ; 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 DM_MAPX DEFW 0 DM_MAPY DEFW 0 ;------------------------------------------------------------- ; Algunos valores hardcodeados para el ejemplo, en la rutina ; final se puede utilizar DM_WIDTH y DM_HEIGHT. ;------------------------------------------------------------- ANCHO_MAPA_TILES EQU 32 ALTO_MAPA_TILES EQU 24 ANCHO_PANTALLA EQU 14 ALTO_PANTALLA EQU 11 ;;; Rutina de la ROM del Spectrum, en otros sistemas ;;; sustituir por una rutina especifica de multiplicacion MULT_HL_POR_DE EQU $30a9 ;--------------------------------------------------------------- ; DrawMap_16x16_Map: ; 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 ; DM_MAPX (2 bytes) Coordenada X en mapa. ; DM_MAPY (2 bytes) Coordenada Y en mapa. ;--------------------------------------------------------------- DrawMap_16x16_Map: ld ix, (DM_MAP) ; IX apunta al mapa ;;; NUEVO: Posicionamos el puntero de mapa en posicion inicial. ld hl, (DM_MAPY) ld de, ANCHO_MAPA_TILES call MULT_HL_POR_DE ; HL = (ANCHO_MAPA * MAPA_Y) ld bc, (DM_MAPX) add hl, bc ; HL = MAPA_X + (ANCHO_MAPA * MAPA_Y) ex de, hl add ix, de ; IX = Inicio_Mapa + HL ;;; FIN NUEVO ld a, (DM_HEIGHT) ld b, a ; B = ALTO_EN_TILES (para bucle altura) drawmg16_yloop: push bc ; Guardamos el valor de B ld a, (DM_HEIGHT) ; A = ALTO_EN_TILES sub b ; A = ALTO - iteracion_bucle = Y actual rlca ; A = Y * 2 ;;; Calculamos la direccion destino en pantalla como ;;; DIR_PANT = DIRECCION(X_INICIAL, Y_INICIAL + Y*2) ld bc, (DM_COORD_X) ; B = DB_COORD_Y y C = DB_COORD_X add a, b ld b, a ld a, b and $18 add a, $40 ld h, a ld a, b and 7 rrca rrca rrca add a, c ld l, a ; HL = DIR_PANTALLA(X_INICIAL,Y_INICIAL+Y*2) ld a, (DM_WIDTH) ld b, a ; B = ANCHO_EN_TILES drawmg16_xloop: push bc ; Nos guardamos el contador del bucle ld a, (ix+0) ; Leemos un byte del mapa inc ix ; Apuntamos al siguiente byte del mapa cp 255 ; Bloque especial a saltar: no se dibuja jp z, drawmg16_next ld b, a ex af, af' ; Nos guardamos una copia del bloque en A' ld a, b ;;; Calcular posicion origen (array sprites) en HL como: ;;; direccion = base_sprites + (NUM_SPRITE*32) ex de, hl ; Intercambiamos DE y HL (DE=destino) ld bc, (DM_SPRITES) ld l, 0 srl a rr l rra rr l rra rr l ld h, a add hl, bc ; HL = BC + HL = DM_SPRITES + (DM_NUMSPR * 32) ex de, hl ; Intercambiamos DE y HL (DE=origen, HL=destino) push hl ; Guardamos el puntero a pantalla recien calculado push hl ;;; Impresion de los primeros 2 bloques horizontales del tile ld b, 8 drawmg16_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 drawmg16_loop1 inc l ; Decrementar el ultimo incrementado en el bucle ; 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 ld a, l add a, 31 ld l, a jr c, drawmg16_nofix_abajop ld a, h sub 8 ld h, a drawmg16_nofix_abajop: ;;; Impresion de los segundos 2 bloques horizontales: ld b, 8 drawmg16_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 drawmg16_loop2 ;;; En este punto, los 16 scanlines del tile estan dibujados. ;;;;;; Impresion de la parte de atributos del tile ;;;;;; pop hl ; Recuperar puntero a inicio de tile ;;; Calcular posicion destino en area de atributos en DE. ld a, h ; Codigo de Get_Attr_Offset_From_Image rrca rrca rrca and 3 or $58 ld d, a ld e, l ; DE tiene el offset del attr de HL ld hl, (DM_ATTRIBS) ex af, af' ; Recuperamos el bloque del mapa desde A' ld c, a ld b, 0 add hl, bc add hl, bc add hl, bc add hl, bc ; HL = HL+HL=(DM_NUMSPR*4) = Origen de atributo ldi ldi ; Imprimimos la primeras fila de atributos ;;; Avance diferencial a la siguiente linea de atributos ld a, e ; A = E add a, 30 ; Sumamos A = A + 30 mas los 2 INCs de ldi. ld e, a ; Guardamos en E (E = E+30 + 2 por ldi=E+32) jr nc, drawmg16_att_noinc inc d drawmg16_att_noinc: ldi ldi ; Imprimimos la segunda fila de atributos pop hl ; Recuperamos el puntero al inicio drawmg16_next: inc l ; Avanzamos al siguiente tile en pantalla inc l ; horizontalmente pop bc ; Recuperamos el contador para el bucle dec b ; djnz se sale de rango, hay que usar DEC+jp jp nz, drawmg16_xloop ;;; NUEVO: Incrementar puntero de mapa a siguiente linea ld bc, ANCHO_MAPA_TILES - ANCHO_PANTALLA add ix, bc ;;; FIN NUEVO ;;; En este punto, hemos dibujado ANCHO tiles en pantalla (1 fila) pop bc dec b ; Bucle vertical jp nz, drawmg16_yloop ret ;------------------------------------------------------------- ; Incrementar la variable DM_MAPX para scrollear a la derecha. ;------------------------------------------------------------- Map_Inc_X: ld hl, (DM_MAPX) ;;; Comparacion 16 bits de HL y (ANCHO_MAPA-ANCHO_PANTALLA) ld a, h CP (ANCHO_MAPA_TILES-ANCHO_PANTALLA) / 256 ret nz ld a, l CP (ANCHO_MAPA_TILES-ANCHO_PANTALLA) % 256 ret z inc hl ; No eran iguales, podemos incrementar. ld (DM_MAPX), hl ret ;------------------------------------------------------------- ; Incrementar la variable DM_MAPY para scrollear hacia abajo. ;------------------------------------------------------------- Map_Inc_Y: ld hl, (DM_MAPY) ;;; Comparacion 16 bits de HL y (ALTO_MAPA-ALTO_PANTALLA) ld a, h CP (ALTO_MAPA_TILES-ALTO_PANTALLA) / 256 ret nz ld a, l CP (ALTO_MAPA_TILES-ALTO_PANTALLA) % 256 ret z inc hl ; No eran iguales, podemos incrementar. ld (DM_MAPY), hl ret ;------------------------------------------------------------- ; Decrementar la variable DM_MAPX para scrollear a la izq. ;------------------------------------------------------------- Map_Dec_X: ld hl, (DM_MAPX) ld a, h and a jr nz, mapdecx_doit ; Verificamos que DM_MAPX no sea 0 ld a, l and a ret z mapdecx_doit: dec hl ld (DM_MAPX), hl ; No es cero, podemos decrementar ret ;------------------------------------------------------------- ; Decrementar la variable DM_MAPY para scrollear hacia arriba. ;------------------------------------------------------------- Map_Dec_Y: ld hl, (DM_MAPY) ld a, h and a jr nz, mapdecy_doit ; Verificamos que DM_MAPX no sea 0 ld a, l and a ret z mapdecy_doit: dec hl ld (DM_MAPY), hl ; No es cero, podemos decrementar ret ;----------------------------------------------------------------------- mapa_ejemplo: DEFB 1,2,1,1,2,1,2,1,2,1,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 DEFB 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DEFB 1,0,0,0,0,0,0,0,0,0,7,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DEFB 1,0,0,0,0,0,0,0,0,2,3,2,3,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,1 DEFB 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,1 DEFB 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,7,7,0,0,0,1 DEFB 1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,7,7,7,0,0,1 DEFB 1,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,5,0,0,0,0,0,0,2,3,2,3,2,0,1 DEFB 1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,4,0,0,0,0,0,0,0,0,0,0,0,0,1 DEFB 1,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,6,5,0,0,0,0,0,0,0,0,0,0,0,0,1 DEFB 1,4,2,3,2,3,0,0,0,0,2,3,2,3,2,3,2,3,4,2,3,2,0,0,0,0,0,0,0,0,0,1 DEFB 1,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DEFB 1,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DEFB 1,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DEFB 1,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,2,3,2,3,0,0,0,0,0,0,0,0,0,0,1 DEFB 1,0,0,0,6,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DEFB 1,0,0,6,6,6,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DEFB 1,0,2,3,2,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,1 DEFB 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,6,0,0,0,0,0,1 DEFB 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,6,6,6,0,0,0,0,1 DEFB 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,6,6,6,6,6,0,0,0,1 DEFB 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,2,3,2,3,2,3,2,3,0,0,1 DEFB 1,0,2,3,2,2,2,3,2,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DEFB 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ;----------------------------------------------------------------------- ; 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 END 35000