Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa |
cursos:ensamblador:gfx5_mapeados [13-01-2024 11:06] – sromero | cursos:ensamblador:gfx5_mapeados [19-01-2024 08:27] (actual) – sromero |
---|
XTILE = X_INICIAL + X*ANCHO_TILE | XTILE = X_INICIAL + X*ANCHO_TILE |
YTILE = Y_INICIAL + Y*ALTO_TILE | YTILE = Y_INICIAL + Y*ALTO_TILE |
CALL Draw_Sprite | call Draw_Sprite |
</code> | </code> |
| |
TILE = [DIR_PANTALLA] | TILE = [DIR_PANTALLA] |
DIR_PANTALLA = DIR_PANTALLA + 1 | DIR_PANTALLA = DIR_PANTALLA + 1 |
PUSH DIR_MEM | push DIR_MEM |
DIR_SPRITE = BASE_TILESET + (TILE*ANCHO_TILE*ALTO_TILE) | DIR_SPRITE = BASE_TILESET + (TILE*ANCHO_TILE*ALTO_TILE) |
Dibujar Sprite desde DIR_SPRITE a DIR_MEM | Dibujar Sprite desde DIR_SPRITE a DIR_MEM |
POP DIR_MEM | pop DIR_MEM |
DIR_MEM = DIR_MEM + ANCHO_TILE | DIR_MEM = DIR_MEM + ANCHO_TILE |
</code> | </code> |
bucle_anchura: | bucle_anchura: |
A = (IX) | A = (IX) |
INC IX | inc ix |
| |
Si A == 255 : | Si A == 255 : |
JR saltar_bloque | jr saltar_bloque |
| |
PUSH HL | push hl |
DIR_SPRITE = BASE_TILESET + (A*ANCHO_TILE*ALTO_TILE) | DIR_SPRITE = BASE_TILESET + (A*ANCHO_TILE*ALTO_TILE) |
HL = BASE_TILESET + (A*8*TAMAÑO_BLOQUES_EN_CADA_TILE) | HL = BASE_TILESET + (A*8*TAMAÑO_BLOQUES_EN_CADA_TILE) |
PUSH HL | push hl |
Imprimir_Sprite_de_HL_a_DE | Imprimir_Sprite_de_HL_a_DE |
Convertir DIR HL imagen en DIR HL atributos | Convertir DIR HL imagen en DIR HL atributos |
Imprimir_Atributos_Sprite | Imprimir_Atributos_Sprite |
POP HL | pop hl |
| |
saltar_bloque: | saltar_bloque: |
HL = HL + ANCHO_TILE | HL = HL + ANCHO_TILE |
DJNZ bucle_anchura | djnz bucle_anchura |
| |
DJNZ bucle_altura | djnz bucle_altura |
</code> | </code> |
| |
| |
;;;;;; Impresion de la parte grafica de los tiles ;;;;;; | ;;;;;; Impresion de la parte grafica de los tiles ;;;;;; |
LD IX, (DM_MAP) ; IX apunta al mapa | ld ix, (DM_MAP) ; IX apunta al mapa |
LD A, (DM_HEIGHT) | ld a, (DM_HEIGHT) |
LD B, A ; B = ALTO_EN_TILES (para bucle altura) | ld b, a ; B = ALTO_EN_TILES (para bucle altura) |
| |
drawm16_yloop: | drawm16_yloop: |
PUSH BC ; Guardamos el valor de B | push bc ; Guardamos el valor de B |
| |
LD A, (DM_HEIGHT) ; A = ALTO_EN_TILES | ld a, (DM_HEIGHT) ; A = ALTO_EN_TILES |
SUB B ; A = ALTO - iteracion_bucle = Y actual | sub b ; A = ALTO - iteracion_bucle = Y actual |
RLCA ; A = Y * 2 | rlca ; A = Y * 2 |
| |
;;; Calculamos la direccion destino en pantalla como | ;;; Calculamos la direccion destino en pantalla como |
;;; DIR_PANT = DIRECCION(X_INICIAL, Y_INICIAL + Y*2) | ;;; DIR_PANT = DIRECCION(X_INICIAL, Y_INICIAL + Y*2) |
LD BC, (DM_COORD_X) ; B = DB_COORD_Y y C = DB_COORD_X | ld bc, (DM_COORD_X) ; B = DB_COORD_Y y C = DB_COORD_X |
ADD A, B | add a, b |
LD B, A | ld b, a |
LD A, B | ld a, b |
AND $18 | and $18 |
ADD A, $40 | add a, $40 |
LD H, A | ld h, a |
LD A, B | ld a, b |
AND 7 | and 7 |
RRCA | rrca |
RRCA | rrca |
RRCA | rrca |
ADD A, C | add a, c |
LD L, A ; HL = DIR_PANTALLA(X_INICIAL,Y_INICIAL+Y*2) | ld l, a ; HL = DIR_PANTALLA(X_INICIAL,Y_INICIAL+Y*2) |
| |
LD A, (DM_WIDTH) | ld a, (DM_WIDTH) |
LD B, A ; B = ANCHO_EN_TILES | ld b, a ; B = ANCHO_EN_TILES |
| |
drawm16_xloop: | drawm16_xloop: |
PUSH BC ; Nos guardamos el contador del bucle | push bc ; Nos guardamos el contador del bucle |
| |
LD A, (IX+0) ; Leemos un byte del mapa | ld a, (ix+0) ; Leemos un byte del mapa |
INC IX ; Apuntamos al siguiente byte del mapa | inc ix ; Apuntamos al siguiente byte del mapa |
| |
CP 255 ; Bloque especial a saltar: no se dibuja | cp 255 ; Bloque especial a saltar: no se dibuja |
JP Z, drawm16_next | jp z, drawm16_next |
| |
LD B, A | ld b, a |
EX AF, AF' ; Nos guardamos una copia del bloque en A' | ex af, af' ; Nos guardamos una copia del bloque en A' |
LD A, B | ld a, b |
| |
;;; Calcular posicion origen (array sprites) en HL como: | ;;; Calcular posicion origen (array sprites) en HL como: |
;;; direccion = base_sprites + (NUM_SPRITE*32) | ;;; direccion = base_sprites + (NUM_SPRITE*32) |
EX DE, HL ; Intercambiamos DE y HL (DE=destino) | ex de, hl ; Intercambiamos DE y HL (DE=destino) |
LD BC, (DM_SPRITES) | ld bc, (DM_SPRITES) |
LD L, 0 | ld l, 0 |
SRL A | srl a |
RR L | rr l |
RRA | rra |
RR L | rr l |
RRA | rra |
RR L | rr l |
LD H, A | ld h, a |
ADD HL, BC ; HL = BC + HL = DS_SPRITES + (DS_NUMSPR * 32) | add hl, bc ; HL = BC + HL = DS_SPRITES + (DS_NUMSPR * 32) |
EX DE, HL ; Intercambiamos DE y HL (DE=origen, HL=destino) | ex de, hl ; Intercambiamos DE y HL (DE=origen, HL=destino) |
| |
PUSH HL ; Guardamos el puntero a pantalla recien calculado | push hl ; Guardamos el puntero a pantalla recien calculado |
PUSH HL | push hl |
| |
;;; Impresion de los primeros 2 bloques horizontales del tile | ;;; Impresion de los primeros 2 bloques horizontales del tile |
| |
LD B, 8 | ld b, 8 |
drawm16_loop1: | drawm16_loop1: |
| |
LD A, (DE) ; Bloque 1: Leemos dato del sprite | ld a, (de) ; Bloque 1: Leemos dato del sprite |
LD (HL), A ; Copiamos dato a pantalla | ld (hl), a ; Copiamos dato a pantalla |
INC DE ; Incrementar puntero en sprite | inc de ; Incrementar puntero en sprite |
INC L ; Incrementar puntero en pantalla | inc l ; Incrementar puntero en pantalla |
LD A, (DE) ; Bloque 2: Leemos dato del sprite | ld a, (de) ; Bloque 2: Leemos dato del sprite |
LD (HL), A ; Copiamos dato a pantalla | ld (hl), a ; Copiamos dato a pantalla |
INC DE ; Incrementar puntero en sprite | inc de ; Incrementar puntero en sprite |
INC H ; Hay que sumar 256 para ir al siguiente scanline | inc h ; Hay que sumar 256 para ir al siguiente scanline |
DEC L ; pero hay que restar el INC L que hicimos. | dec l ; pero hay que restar el inc l que hicimos. |
DJNZ drawm16_loop1 | djnz drawm16_loop1 |
INC L ; Decrementar el ultimo incrementado en el bucle | inc l ; Decrementar el ultimo incrementado en el bucle |
| |
; Avanzamos HL 1 scanline (codigo de incremento de HL en 1 scanline) | ; 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 | ; desde el septimo scanline de la fila Y+1 al primero de la Y+2 |
LD A, L | ld a, l |
ADD A, 31 | add a, 31 |
LD L, A | ld l, a |
JR C, drawm16_nofix_abajop | jr c, drawm16_nofix_abajop |
LD A, H | ld a, h |
SUB 8 | sub 8 |
LD H, A | ld h, a |
drawm16_nofix_abajop: | drawm16_nofix_abajop: |
| |
;;; Impresion de los segundos 2 bloques horizontales: | ;;; Impresion de los segundos 2 bloques horizontales: |
LD B, 8 | ld b, 8 |
drawm16_loop2: | drawm16_loop2: |
LD A, (DE) ; Bloque 1: Leemos dato del sprite | ld a, (de) ; Bloque 1: Leemos dato del sprite |
LD (HL), A ; Copiamos dato a pantalla | ld (hl), a ; Copiamos dato a pantalla |
INC DE ; Incrementar puntero en sprite | inc de ; Incrementar puntero en sprite |
INC L ; Incrementar puntero en pantalla | inc l ; Incrementar puntero en pantalla |
LD A, (DE) ; Bloque 2: Leemos dato del sprite | ld a, (de) ; Bloque 2: Leemos dato del sprite |
LD (HL), A ; Copiamos dato a pantalla | ld (hl), a ; Copiamos dato a pantalla |
INC DE ; Incrementar puntero en sprite | inc de ; Incrementar puntero en sprite |
INC H ; Hay que sumar 256 para ir al siguiente scanline | inc h ; Hay que sumar 256 para ir al siguiente scanline |
DEC L ; pero hay que restar el INC L que hicimos. | dec l ; pero hay que restar el inc l que hicimos. |
DJNZ drawm16_loop2 | djnz drawm16_loop2 |
| |
| |
;;;;;; Impresion de la parte de atributos del tile ;;;;;; | ;;;;;; Impresion de la parte de atributos del tile ;;;;;; |
| |
POP HL ; Recuperar puntero a inicio de tile | pop hl ; Recuperar puntero a inicio de tile |
| |
;;; Calcular posicion destino en area de atributos en DE. | ;;; Calcular posicion destino en area de atributos en DE. |
LD A, H ; Codigo de Get_Attr_Offset_From_Image | ld a, h ; Codigo de Get_Attr_Offset_From_Image |
RRCA | rrca |
RRCA | rrca |
RRCA | rrca |
AND 3 | and 3 |
OR $58 | or $58 |
LD D, A | ld d, a |
LD E, L ; DE tiene el offset del attr de HL | ld e, l ; DE tiene el offset del attr de HL |
| |
LD HL, (DM_ATTRIBS) | ld hl, (DM_ATTRIBS) |
EX AF, AF' ; Recuperamos el bloque del mapa desde A' | ex af, af' ; Recuperamos el bloque del mapa desde A' |
LD C, A | ld c, a |
LD B, 0 | ld b, 0 |
ADD HL, BC | add hl, bc |
ADD HL, BC | add hl, bc |
ADD HL, BC | add hl, bc |
ADD HL, BC ; HL = HL+HL=(DS_NUMSPR*4) = Origen de atributo | add hl, bc ; HL = HL+HL=(DS_NUMSPR*4) = Origen de atributo |
| |
LDI | ldi |
LDI ; Imprimimos la primeras fila de atributos | ldi ; Imprimimos la primeras fila de atributos |
| |
;;; Avance diferencial a la siguiente linea de atributos | ;;; Avance diferencial a la siguiente linea de atributos |
LD A, E ; A = E | ld a, e ; A = E |
ADD A, 30 ; Sumamos A = A + 30 mas los 2 INCs de LDI. | 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) | ld e, a ; Guardamos en E (E = E+30 + 2 por ldi=E+32) |
JR NC, drawm16_att_noinc | jr nc, drawm16_att_noinc |
INC D | inc d |
drawm16_att_noinc: | drawm16_att_noinc: |
LDI | ldi |
LDI ; Imprimimos la segunda fila de atributos | ldi ; Imprimimos la segunda fila de atributos |
| |
POP HL ; Recuperamos el puntero al inicio | pop hl ; Recuperamos el puntero al inicio |
| |
drawm16_next: | drawm16_next: |
INC L ; Avanzamos al siguiente tile en pantalla | inc l ; Avanzamos al siguiente tile en pantalla |
INC L ; horizontalmente | inc l ; horizontalmente |
| |
POP BC ; Recuperamos el contador para el bucle | pop bc ; Recuperamos el contador para el bucle |
DEC B ; DJNZ se sale de rango, hay que usar DEC+JP | dec b ; djnz se sale de rango, hay que usar DEC+jp |
JP NZ, drawm16_xloop | jp nz, drawm16_xloop |
| |
;;; En este punto, hemos dibujado ANCHO tiles en pantalla (1 fila) | ;;; En este punto, hemos dibujado ANCHO tiles en pantalla (1 fila) |
POP BC | pop bc |
DEC B ; Bucle vertical | dec b ; Bucle vertical |
JP NZ, drawm16_yloop | jp nz, drawm16_yloop |
| |
RET | ret |
</code> | </code> |
| |
| |
\\ | \\ |
1.- Eliminar el ''INC L'' tras el ''DJNZ drawm16_loop1''. | 1.- Eliminar el ''inc l'' tras el ''djnz drawm16_loop1''. |
| |
2.- Eliminar los ''INC DE'', ''INC H'' y ''DEC L'' antes del ''DJNZ drawm16_loop2''. | 2.- Eliminar los ''inc de'', ''inc h'' y ''dec l'' antes del ''djnz drawm16_loop2''. |
\\ | \\ |
| |
ORG 35000 | ORG 35000 |
| |
CALL ClearScreen_Pattern ; Imprimimos patron de fondo | call ClearScreen_Pattern ; Imprimimos patron de fondo |
| |
LD HL, sokoban1_gfx | ld hl, sokoban1_gfx |
LD (DM_SPRITES), HL | ld (DM_SPRITES), hl |
LD HL, sokoban1_attr | ld hl, sokoban1_attr |
LD (DM_ATTRIBS), HL | ld (DM_ATTRIBS), hl |
LD HL, sokoban_LEVEL1 | ld hl, sokoban_LEVEL1 |
LD (DM_MAP), HL | ld (DM_MAP), hl |
LD A, 16 | ld a, 16 |
LD (DM_WIDTH), A ; ANCHO | ld (DM_WIDTH), a ; ANCHO |
LD A, 12 | ld a, 12 |
LD (DM_HEIGHT), A ; ALTO | ld (DM_HEIGHT), a ; ALTO |
XOR A | xor a |
LD (DM_COORD_X), A ; X = Y = 0 | ld (DM_COORD_X), a ; X = Y = 0 |
LD (DM_COORD_Y), A ; Establecemos valores llamada | ld (DM_COORD_Y), a ; Establecemos valores llamada |
| |
CALL DrawMap_16x16 ; Imprimir pantalla de mapa | call DrawMap_16x16 ; Imprimir pantalla de mapa |
| |
loop: | loop: |
JR loop | jr loop |
| |
;----------------------------------------------------------------------- | ;----------------------------------------------------------------------- |
ClearScreen_Pattern: ; Rutina para incluir: | ClearScreen_Pattern: ; Rutina para incluir: |
(...) ; Rellenado de fondo con un patron | (...) ; Rellenado de fondo con un patron |
RET ; (del capitulo de Sprites Lowres) | ret ; (del capitulo de Sprites Lowres) |
| |
;----------------------------------------------------------------------- | ;----------------------------------------------------------------------- |
| |
<code z80> | <code z80> |
LD HL, sokoban1_gfx | ld hl, sokoban1_gfx |
LD (DM_SPRITES), HL | ld (DM_SPRITES), hl |
LD HL, sokoban1_attr | ld hl, sokoban1_attr |
LD (DM_ATTRIBS), HL | ld (DM_ATTRIBS), hl |
LD HL, sokoban_LEVEL1 | ld hl, sokoban_LEVEL1 |
LD (DM_MAP), HL | ld (DM_MAP), hl |
LD A, 7 | ld a, 7 |
LD (DM_WIDTH), A ; ANCHO | ld (DM_WIDTH), a ; ANCHO |
LD A, 9 | ld a, 9 |
LD (DM_HEIGHT), A ; ALTO | ld (DM_HEIGHT), a ; ALTO |
LD A, 8 | ld a, 8 |
LD (DM_COORD_X), A ; X_INICIAL | ld (DM_COORD_X), a ; X_INICIaL |
LD A, 3 | ld a, 3 |
LD (DM_COORD_Y), A ; Y_INICIAL | ld (DM_COORD_Y), a ; Y_INICIaL |
CALL DrawMap_16x16 ; Imprimir pantalla de mapa | call DrawMap_16x16 ; Imprimir pantalla de mapa |
</code> | </code> |
| |
| |
;;;;;; Impresion de la parte grafica de los tiles ;;;;;; | ;;;;;; Impresion de la parte grafica de los tiles ;;;;;; |
LD IX, (DM_MAP) ; IX apunta al mapa | ld ix, (DM_MAP) ; IX apunta al mapa |
LD A, (DM_HEIGHT) | ld a, (DM_HEIGHT) |
LD B, A ; B = ALTO_EN_TILES (para bucle altura) | ld b, a ; B = ALTO_EN_TILES (para bucle altura) |
| |
drawm8_yloop: | drawm8_yloop: |
PUSH BC ; Guardamos el valor de B | push bc ; Guardamos el valor de B |
| |
LD A, (DM_HEIGHT) ; A = ALTO_EN_TILES | ld a, (DM_HEIGHT) ; A = ALTO_EN_TILES |
SUB B ; A = ALTO - iteracion_bucle = Y actual | sub b ; A = ALTO - iteracion_bucle = Y actual |
;;; NUEVO: Eliminamos RLCA (no multiplicar Y*2) | ;;; NUEVO: Eliminamos rlca (no multiplicar Y*2) |
| |
;;; Calculamos la direccion destino en pantalla como | ;;; Calculamos la direccion destino en pantalla como |
;;; DIR_PANT = DIRECCION(X_INICIAL, Y_INICIAL + Y) | ;;; DIR_PANT = DIRECCION(X_INICIAL, Y_INICIAL + Y) |
LD BC, (DM_COORD_X) ; B = DB_COORD_Y y C = DB_COORD_X | ld bc, (DM_COORD_X) ; B = DB_COORD_Y y C = DB_COORD_X |
ADD A, B | add a, b |
LD B, A | ld b, a |
LD A, B | ld a, b |
AND $18 | and $18 |
ADD A, $40 | add a, $40 |
LD H, A | ld h, a |
LD A, B | ld a, b |
AND 7 | and 7 |
RRCA | rrca |
RRCA | rrca |
RRCA | rrca |
ADD A, C | add a, c |
LD L, A ; HL = DIR_PANTALLA(X_INICIAL,Y_INICIAL+Y*2) | ld l, a ; HL = DIR_PANTALLA(X_INICIAL,Y_INICIAL+Y*2) |
| |
LD A, (DM_WIDTH) | ld a, (DM_WIDTH) |
LD B, A ; B = ANCHO_EN_TILES | ld b, a ; B = ANCHO_EN_TILES |
| |
drawm8_xloop: | drawm8_xloop: |
PUSH BC ; Nos guardamos el contador del bucle | push bc ; Nos guardamos el contador del bucle |
| |
LD A, (IX+0) ; Leemos un byte del mapa | ld a, (ix+0) ; Leemos un byte del mapa |
INC IX ; Apuntamos al siguiente byte del mapa | inc ix ; Apuntamos al siguiente byte del mapa |
| |
CP 255 ; Bloque especial a saltar: no se dibuja | cp 255 ; Bloque especial a saltar: no se dibuja |
JP Z, drawm8_next | jp z, drawm8_next |
| |
LD B, A | ld b, a |
EX AF, AF' ; Nos guardamos una copia del bloque en A' | ex af, af' ; Nos guardamos una copia del bloque en A' |
LD A, B | ld a, b |
| |
;;; Calcular posicion origen (array sprites) en HL como: | ;;; Calcular posicion origen (array sprites) en HL como: |
;;; direccion = base_sprites + (NUM_SPRITE*8) | ;;; direccion = base_sprites + (NUM_SPRITE*8) |
EX DE, HL ; Intercambiamos DE y HL (DE=destino) | ex de, hl ; Intercambiamos DE y HL (DE=destino) |
LD BC, (DM_SPRITES) | ld bc, (DM_SPRITES) |
LD L, A | ld l, a |
LD H, 0 | ld h, 0 |
ADD HL, HL | add hl, hl |
ADD HL, HL | add hl, hl |
ADD HL, HL ;;; NUEVO: NUM_SPRITE*8 en lugar de *32 | add hl, hl ;;; NUEVO: NUM_SPRITE*8 en lugar de *32 |
ADD HL, BC ; HL = BC + HL = DM_SPRITES + (DM_NUMSPR * 8) | add hl, bc ; HL = BC + HL = DM_SPRITES + (DM_NUMSPR * 8) |
EX DE, HL ; Intercambiamos DE y HL (DE=origen, HL=destino) | ex de, hl ; Intercambiamos DE y HL (DE=origen, HL=destino) |
| |
PUSH HL ; Guardamos el puntero a pantalla recien calculado | push hl ; Guardamos el puntero a pantalla recien calculado |
PUSH HL | push hl |
| |
;;; Impresion de los primeros 2 bloques horizontales del tile | ;;; Impresion de los primeros 2 bloques horizontales del tile |
LD B, 8 | ld b, 8 |
| |
drawm8_loop: ;;; NUEVO: Bucle de impresion de 1 solo bloque | drawm8_loop: ;;; NUEVO: Bucle de impresion de 1 solo bloque |
LD A, (DE) ; Bloque 1: Leemos dato del sprite | ld a, (de) ; Bloque 1: Leemos dato del sprite |
LD (HL), A ; Copiamos dato a pantalla | ld (hl), a ; Copiamos dato a pantalla |
INC DE ; Incrementar puntero en sprite | inc de ; Incrementar puntero en sprite |
INC H ; Hay que sumar 256 para ir al siguiente scanline | inc h ; Hay que sumar 256 para ir al siguiente scanline |
DJNZ drawm8_loop | djnz drawm8_loop |
| |
;;; En este punto, los 8 scanlines del tile estan dibujados. | ;;; En este punto, los 8 scanlines del tile estan dibujados. |
| |
;;;;;; Impresion de la parte de atributos del tile ;;;;;; | ;;;;;; Impresion de la parte de atributos del tile ;;;;;; |
POP HL ; Recuperar puntero a inicio de tile | pop hl ; Recuperar puntero a inicio de tile |
| |
;;; Calcular posicion destino en area de atributos en DE. | ;;; Calcular posicion destino en area de atributos en DE. |
LD A, H ; Codigo de Get_Attr_Offset_From_Image | ld a, h ; Codigo de Get_Attr_Offset_From_Image |
RRCA | rrca |
RRCA | rrca |
RRCA | rrca |
AND 3 | and 3 |
OR $58 | or $58 |
LD D, A | ld d, a |
LD E, L ; DE tiene el offset del attr de HL | ld e, l ; DE tiene el offset del attr de HL |
| |
LD HL, (DM_ATTRIBS) | ld hl, (DM_ATTRIBS) |
EX AF, AF' ; Recuperamos el bloque del mapa desde A' | ex af, af' ; Recuperamos el bloque del mapa desde A' |
LD C, A | ld c, a |
LD B, 0 ;;; NUEVO: HL = HL+DM_NUMSPR (NO *4) | ld b, 0 ;;; NUEVO: HL = HL+DM_NUMSPR (NO *4) |
ADD HL, BC ; HL = HL+DM_NUMSPR = Origen de atributo | add hl, bc ; HL = HL+DM_NUMSPR = Origen de atributo |
| |
LD A, (HL) | ld a, (hl) |
LD (DE), A ;;; NUEVO: Impresion de un unico atributo. | ld (de), a ;;; NUEVO: Impresion de un unico atributo. |
POP HL ; Recuperamos el puntero al inicio | pop hl ; Recuperamos el puntero al inicio |
| |
drawm8_next: | drawm8_next: |
INC L ; Avanzamos al siguiente tile en pantalla | inc l ; Avanzamos al siguiente tile en pantalla |
| |
POP BC ; Recuperamos el contador para el bucle | pop bc ; Recuperamos el contador para el bucle |
DEC B ; DJNZ se sale de rango, hay que usar DEC+JP | dec b ; djnz se sale de rango, hay que usar DEC+jp |
JP NZ, drawm8_xloop | jp nz, drawm8_xloop |
| |
;;; En este punto, hemos dibujado ANCHO tiles en pantalla (1 fila) | ;;; En este punto, hemos dibujado ANCHO tiles en pantalla (1 fila) |
POP BC | pop bc |
DEC B ; Bucle vertical | dec b ; Bucle vertical |
JP NZ, drawm8_yloop | jp nz, drawm8_yloop |
| |
RET | ret |
</code> | </code> |
| |
<code z80> | <code z80> |
;;; Calculamos la posicion de "pantalla_actual" en al tabla | ;;; Calculamos la posicion de "pantalla_actual" en al tabla |
LD BC, Mapa ; BC = Inicio de la tabla Mapa | ld bc, Mapa ; BC = Inicio de la tabla Mapa |
LD A, (pantalla_actual) ; A = Pantalla actual | ld a, (pantalla_actual) ; A = Pantalla actual |
LD L, A | ld l, a |
LD H, 0 ; HL = Pantalla actual | ld h, 0 ; HL = Pantalla actual |
SLA L | sla l |
RL H ; HL = Pantalla actual * 2 | rl h ; HL = Pantalla actual * 2 |
ADD HL, BC ; HL = Mapa + (Pantalla actual * 2) | add hl, bc ; HL = Mapa + (Pantalla actual * 2) |
| |
;;; Ahora leemos de (HL) la dirección de dibujado en el mismo HL | ;;; Ahora leemos de (HL) la dirección de dibujado en el mismo HL |
LD A, (HL) ; Leemos la parte baja de la direccion en A | ld a, (hl) ; Leemos la parte baja de la direccion en A |
INC HL ; ... para no corromper HL y poder leer ... | inc hl ; ... para no corromper HL y poder leer ... |
PUSH HL | push hl |
LD H, (HL) ; ... la parte alta sobre H ... | ld h, (hl) ; ... la parte alta sobre H ... |
LD L, A | ld l, a |
LD (DM_MAP), HL ; Almacenamos el mapa a imprimir | ld (DM_MAP), hl ; Almacenamos el mapa a imprimir |
CALL DrawMap_16x16 ; Imprimimos el mapa | call DrawMap_16x16 ; Imprimimos el mapa |
</code> | </code> |
| |
<code z80> | <code z80> |
BYTES_POR_PANTALLA EQU 4 | BYTES_POR_PANTALLA EQU 4 |
RUTINA_ROM_HL_POR_DE EQU $30A9 | RUTINA_ROM_HL_POR_DE EQU $30a9 |
| |
;------------------------------------------------------------ | ;------------------------------------------------------------ |
;------------------------------------------------------------ | ;------------------------------------------------------------ |
Get_Screen_Pointer: | Get_Screen_Pointer: |
LD H, 0 | ld h, 0 |
LD D, H ; HL = PANTALLA | ld d, h ; HL = PANTALLA |
LD E, BYTES_POR_PANTALLA ; DE = BYTES POR PANTALLA | ld e, BYTES_POR_PANTALLA ; DE = BYTES POR PANTALLA |
CALL RUTINA_ROM_HL_POR_DE ; HL = HL * DE | call RUTINA_ROM_HL_POR_DE ; HL = HL * DE |
ADD HL, BC ; Lo sumamos al inicio del MAPA | add hl, bc ; Lo sumamos al inicio del MAPA |
RET ; HL = MAPA + (PANTALLA*BYTES) | ret ; HL = MAPA + (PANTALLA*BYTES) |
</code> | </code> |
| |
<code z80> | <code z80> |
;;; En el inicio del programa... | ;;; En el inicio del programa... |
LD HL, sokoban1_gfx | ld hl, sokoban1_gfx |
LD (DM_SPRITES), HL | ld (DM_SPRITES), hl |
LD HL, sokoban1_attr | ld hl, sokoban1_attr |
LD (DM_ATTRIBS), HL | ld (DM_ATTRIBS), hl |
LD A, 16 | ld a, 16 |
LD (DM_WIDTH), A ; ANCHO | ld (DM_WIDTH), a ; ANCHO |
LD A, 12 | ld a, 12 |
LD (DM_HEIGHT), A ; ALTO | ld (DM_HEIGHT), a ; ALTO |
XOR A | xor a |
LD (DM_COORD_X), A ; X = Y = 0 | ld (DM_COORD_X), a ; X = Y = 0 |
LD (DM_COORD_Y), A ; Establecemos valores llamada | ld (DM_COORD_Y), a ; Establecemos valores llamada |
| |
(...) | (...) |
;;; En el bucle principal de nuestro programa: | ;;; En el bucle principal de nuestro programa: |
DibujarPantalla: | DibujarPantalla: |
LD BC, Mapa | ld bc, Mapa |
LD A, (pantalla_actual) | ld a, (pantalla_actual) |
LD L, A | ld l, a |
CALL Get_Screen_Pointer ; HL = Datos de la pantalla | call Get_Screen_Pointer ; HL = Datos de la pantalla |
LD A, (HL) ; Leemos la parte baja de la direccion en A | ld a, (hl) ; Leemos la parte baja de la direccion en A |
INC HL ; ... para no corromper HL y poder leer ... | inc hl ; ... para no corromper HL y poder leer ... |
PUSH HL | push hl |
LD H, (HL) ; ... la parte alta sobre H ... | ld h, (hl) ; ... la parte alta sobre H ... |
LD L, A | ld l, a |
LD (DM_MAP), HL ; Almacenamos el mapa a imprimir | ld (DM_MAP), hl ; Almacenamos el mapa a imprimir |
CALL DrawMap_16x16 ; Imprimimos el mapa | call DrawMap_16x16 ; Imprimimos el mapa |
| |
POP HL ; Recuperamos el puntero a datos de pantalla | pop hl ; Recuperamos el puntero a datos de pantalla |
INC HL ; Avanzamos hasta el primer ID de conexion | inc hl ; Avanzamos hasta el primer ID de conexion |
LD A, (HL) ; Leemos conexion izquierda | ld a, (hl) ; Leemos conexion izquierda |
LD (con_izquierda), A ; la almacenamos | ld (con_izquierda), a ; la almacenamos |
INC HL ; Avanzamos hasta el segundo ID de conexion | inc hl ; Avanzamos hasta el segundo ID de conexion |
LD A, (HL) ; Leemos conexion a derecha | ld a, (hl) ; Leemos conexion a derecha |
LD (con_derecha), A ; la almacenamos | ld (con_derecha), a ; la almacenamos |
</code> | </code> |
| |
DrawMap_16x16_Map: | DrawMap_16x16_Map: |
| |
LD IX, (DM_MAP) ; IX apunta al mapa | ld ix, (DM_MAP) ; IX apunta al mapa |
| |
;;; NUEVO: Posicionamos el puntero de mapa en posicion inicial. | ;;; NUEVO: Posicionamos el puntero de mapa en posicion inicial. |
LD HL, (DM_MAPY) | ld hl, (DM_MAPY) |
LD DE, ANCHO_MAPA_TILES | ld de, ANCHO_MAPA_TILES |
CALL MULT_HL_POR_DE ; HL = (ANCHO_MAPA * MAPA_Y) | call MULT_HL_POR_DE ; HL = (ANCHO_MAPA * MAPA_Y) |
LD BC, (DM_MAPX) | ld bc, (DM_MAPX) |
ADD HL, BC ; HL = MAPA_X + (ANCHO_MAPA * MAPA_Y) | add hl, bc ; HL = MAPA_X + (ANCHO_MAPA * MAPA_Y) |
EX DE, HL | ex de, hl |
ADD IX, DE ; IX = Inicio_Mapa + HL | add ix, de ; IX = Inicio_Mapa + HL |
;;; FIN NUEVO | ;;; FIN NUEVO |
</code> | </code> |
<code z80> | <code z80> |
;;; NUEVO: Incrementar puntero de mapa a siguiente linea | ;;; NUEVO: Incrementar puntero de mapa a siguiente linea |
LD BC, ANCHO_MAPA_TILES - ANCHO_PANTALLA | ld bc, ANCHO_MAPA_TILES - ANCHO_PANTALLA |
ADD IX, BC | add ix, bc |
;;; FIN NUEVO | ;;; FIN NUEVO |
| |
;;; En este punto, hemos dibujado ANCHO tiles en pantalla (1 fila) | ;;; En este punto, hemos dibujado ANCHO tiles en pantalla (1 fila) |
POP BC | pop bc |
DEC B ; Bucle vertical | dec b ; Bucle vertical |
JP NZ, drawmg16_yloop | jp nz, drawmg16_yloop |
| |
RET | ret |
</code> | </code> |
| |
;;; Rutina de la ROM del Spectrum, en otros sistemas | ;;; Rutina de la ROM del Spectrum, en otros sistemas |
;;; sustituir por una rutina especifica de multiplicacion | ;;; sustituir por una rutina especifica de multiplicacion |
MULT_HL_POR_DE EQU $30A9 | MULT_HL_POR_DE EQU $30a9 |
| |
;--------------------------------------------------------------- | ;--------------------------------------------------------------- |
DrawMap_16x16_Map: | DrawMap_16x16_Map: |
| |
LD IX, (DM_MAP) ; IX apunta al mapa | ld ix, (DM_MAP) ; IX apunta al mapa |
| |
;;; NUEVO: Posicionamos el puntero de mapa en posicion inicial. | ;;; NUEVO: Posicionamos el puntero de mapa en posicion inicial. |
LD HL, (DM_MAPY) | ld hl, (DM_MAPY) |
LD DE, ANCHO_MAPA_TILES | ld de, ANCHO_MAPA_TILES |
CALL MULT_HL_POR_DE ; HL = (ANCHO_MAPA * MAPA_Y) | call MULT_HL_POR_DE ; HL = (ANCHO_MAPA * MAPA_Y) |
LD BC, (DM_MAPX) | ld bc, (DM_MAPX) |
ADD HL, BC ; HL = MAPA_X + (ANCHO_MAPA * MAPA_Y) | add hl, bc ; HL = MAPA_X + (ANCHO_MAPA * MAPA_Y) |
EX DE, HL | ex de, hl |
ADD IX, DE ; IX = Inicio_Mapa + HL | add ix, de ; IX = Inicio_Mapa + HL |
;;; FIN NUEVO | ;;; FIN NUEVO |
| |
LD A, (DM_HEIGHT) | ld a, (DM_HEIGHT) |
LD B, A ; B = ALTO_EN_TILES (para bucle altura) | ld b, a ; B = ALTO_EN_TILES (para bucle altura) |
| |
drawmg16_yloop: | drawmg16_yloop: |
PUSH BC ; Guardamos el valor de B | push bc ; Guardamos el valor de B |
| |
LD A, (DM_HEIGHT) ; A = ALTO_EN_TILES | ld a, (DM_HEIGHT) ; A = ALTO_EN_TILES |
SUB B ; A = ALTO - iteracion_bucle = Y actual | sub b ; A = ALTO - iteracion_bucle = Y actual |
RLCA ; A = Y * 2 | rlca ; A = Y * 2 |
| |
;;; Calculamos la direccion destino en pantalla como | ;;; Calculamos la direccion destino en pantalla como |
;;; DIR_PANT = DIRECCION(X_INICIAL, Y_INICIAL + Y*2) | ;;; DIR_PANT = DIRECCION(X_INICIAL, Y_INICIAL + Y*2) |
LD BC, (DM_COORD_X) ; B = DB_COORD_Y y C = DB_COORD_X | ld bc, (DM_COORD_X) ; B = DB_COORD_Y y C = DB_COORD_X |
ADD A, B | add a, b |
LD B, A | ld b, a |
LD A, B | ld a, b |
AND $18 | and $18 |
ADD A, $40 | add a, $40 |
LD H, A | ld h, a |
LD A, B | ld a, b |
AND 7 | and 7 |
RRCA | rrca |
RRCA | rrca |
RRCA | rrca |
ADD A, C | add a, c |
LD L, A ; HL = DIR_PANTALLA(X_INICIAL,Y_INICIAL+Y*2) | ld l, a ; HL = DIR_PANTALLA(X_INICIAL,Y_INICIAL+Y*2) |
| |
LD A, (DM_WIDTH) | ld a, (DM_WIDTH) |
LD B, A ; B = ANCHO_EN_TILES | ld b, a ; B = ANCHO_EN_TILES |
| |
drawmg16_xloop: | drawmg16_xloop: |
PUSH BC ; Nos guardamos el contador del bucle | push bc ; Nos guardamos el contador del bucle |
| |
LD A, (IX+0) ; Leemos un byte del mapa | ld a, (ix+0) ; Leemos un byte del mapa |
INC IX ; Apuntamos al siguiente byte del mapa | inc ix ; Apuntamos al siguiente byte del mapa |
| |
CP 255 ; Bloque especial a saltar: no se dibuja | cp 255 ; Bloque especial a saltar: no se dibuja |
JP Z, drawmg16_next | jp z, drawmg16_next |
| |
LD B, A | ld b, a |
EX AF, AF' ; Nos guardamos una copia del bloque en A' | ex af, af' ; Nos guardamos una copia del bloque en A' |
LD A, B | ld a, b |
| |
;;; Calcular posicion origen (array sprites) en HL como: | ;;; Calcular posicion origen (array sprites) en HL como: |
;;; direccion = base_sprites + (NUM_SPRITE*32) | ;;; direccion = base_sprites + (NUM_SPRITE*32) |
EX DE, HL ; Intercambiamos DE y HL (DE=destino) | ex de, hl ; Intercambiamos DE y HL (DE=destino) |
LD BC, (DM_SPRITES) | ld bc, (DM_SPRITES) |
LD L, 0 | ld l, 0 |
SRL A | srl a |
RR L | rr l |
RRA | rra |
RR L | rr l |
RRA | rra |
RR L | rr l |
LD H, A | ld h, a |
ADD HL, BC ; HL = BC + HL = DM_SPRITES + (DM_NUMSPR * 32) | add hl, bc ; HL = BC + HL = DM_SPRITES + (DM_NUMSPR * 32) |
EX DE, HL ; Intercambiamos DE y HL (DE=origen, HL=destino) | ex de, hl ; Intercambiamos DE y HL (DE=origen, HL=destino) |
| |
PUSH HL ; Guardamos el puntero a pantalla recien calculado | push hl ; Guardamos el puntero a pantalla recien calculado |
PUSH HL | push hl |
| |
;;; Impresion de los primeros 2 bloques horizontales del tile | ;;; Impresion de los primeros 2 bloques horizontales del tile |
| |
LD B, 8 | ld b, 8 |
drawmg16_loop1: | drawmg16_loop1: |
| |
LD A, (DE) ; Bloque 1: Leemos dato del sprite | ld a, (de) ; Bloque 1: Leemos dato del sprite |
LD (HL), A ; Copiamos dato a pantalla | ld (hl), a ; Copiamos dato a pantalla |
INC DE ; Incrementar puntero en sprite | inc de ; Incrementar puntero en sprite |
INC L ; Incrementar puntero en pantalla | inc l ; Incrementar puntero en pantalla |
LD A, (DE) ; Bloque 2: Leemos dato del sprite | ld a, (de) ; Bloque 2: Leemos dato del sprite |
LD (HL), A ; Copiamos dato a pantalla | ld (hl), a ; Copiamos dato a pantalla |
INC DE ; Incrementar puntero en sprite | inc de ; Incrementar puntero en sprite |
INC H ; Hay que sumar 256 para ir al siguiente scanline | inc h ; Hay que sumar 256 para ir al siguiente scanline |
DEC L ; pero hay que restar el INC L que hicimos. | dec l ; pero hay que restar el inc l que hicimos. |
DJNZ drawmg16_loop1 | djnz drawmg16_loop1 |
INC L ; Decrementar el ultimo incrementado en el bucle | inc l ; Decrementar el ultimo incrementado en el bucle |
| |
; Avanzamos HL 1 scanline (codigo de incremento de HL en 1 scanline) | ; 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 | ; desde el septimo scanline de la fila Y+1 al primero de la Y+2 |
LD A, L | ld a, l |
ADD A, 31 | add a, 31 |
LD L, A | ld l, a |
JR C, drawmg16_nofix_abajop | jr c, drawmg16_nofix_abajop |
LD A, H | ld a, h |
SUB 8 | sub 8 |
LD H, A | ld h, a |
drawmg16_nofix_abajop: | drawmg16_nofix_abajop: |
| |
;;; Impresion de los segundos 2 bloques horizontales: | ;;; Impresion de los segundos 2 bloques horizontales: |
LD B, 8 | ld b, 8 |
drawmg16_loop2: | drawmg16_loop2: |
LD A, (DE) ; Bloque 1: Leemos dato del sprite | ld a, (de) ; Bloque 1: Leemos dato del sprite |
LD (HL), A ; Copiamos dato a pantalla | ld (hl), a ; Copiamos dato a pantalla |
INC DE ; Incrementar puntero en sprite | inc de ; Incrementar puntero en sprite |
INC L ; Incrementar puntero en pantalla | inc l ; Incrementar puntero en pantalla |
LD A, (DE) ; Bloque 2: Leemos dato del sprite | ld a, (de) ; Bloque 2: Leemos dato del sprite |
LD (HL), A ; Copiamos dato a pantalla | ld (hl), a ; Copiamos dato a pantalla |
INC DE ; Incrementar puntero en sprite | inc de ; Incrementar puntero en sprite |
INC H ; Hay que sumar 256 para ir al siguiente scanline | inc h ; Hay que sumar 256 para ir al siguiente scanline |
DEC L ; pero hay que restar el INC L que hicimos. | dec l ; pero hay que restar el inc l que hicimos. |
DJNZ drawmg16_loop2 | djnz drawmg16_loop2 |
| |
;;; En este punto, los 16 scanlines del tile estan dibujados. | ;;; En este punto, los 16 scanlines del tile estan dibujados. |
;;;;;; Impresion de la parte de atributos del tile ;;;;;; | ;;;;;; Impresion de la parte de atributos del tile ;;;;;; |
| |
POP HL ; Recuperar puntero a inicio de tile | pop hl ; Recuperar puntero a inicio de tile |
| |
;;; Calcular posicion destino en area de atributos en DE. | ;;; Calcular posicion destino en area de atributos en DE. |
LD A, H ; Codigo de Get_Attr_Offset_From_Image | ld a, h ; Codigo de Get_Attr_Offset_From_Image |
RRCA | rrca |
RRCA | rrca |
RRCA | rrca |
AND 3 | and 3 |
OR $58 | or $58 |
LD D, A | ld d, a |
LD E, L ; DE tiene el offset del attr de HL | ld e, l ; DE tiene el offset del attr de HL |
| |
LD HL, (DM_ATTRIBS) | ld hl, (DM_ATTRIBS) |
EX AF, AF' ; Recuperamos el bloque del mapa desde A' | ex af, af' ; Recuperamos el bloque del mapa desde A' |
LD C, A | ld c, a |
LD B, 0 | ld b, 0 |
ADD HL, BC | add hl, bc |
ADD HL, BC | add hl, bc |
ADD HL, BC | add hl, bc |
ADD HL, BC ; HL = HL+HL=(DM_NUMSPR*4) = Origen de atributo | add hl, bc ; HL = HL+HL=(DM_NUMSPR*4) = Origen de atributo |
| |
LDI | ldi |
LDI ; Imprimimos la primeras fila de atributos | ldi ; Imprimimos la primeras fila de atributos |
| |
;;; Avance diferencial a la siguiente linea de atributos | ;;; Avance diferencial a la siguiente linea de atributos |
LD A, E ; A = E | ld a, e ; A = E |
ADD A, 30 ; Sumamos A = A + 30 mas los 2 INCs de LDI. | 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) | ld e, a ; Guardamos en E (E = E+30 + 2 por ldi=E+32) |
JR NC, drawmg16_att_noinc | jr nc, drawmg16_att_noinc |
INC D | inc d |
drawmg16_att_noinc: | drawmg16_att_noinc: |
LDI | ldi |
LDI ; Imprimimos la segunda fila de atributos | ldi ; Imprimimos la segunda fila de atributos |
| |
POP HL ; Recuperamos el puntero al inicio | pop hl ; Recuperamos el puntero al inicio |
| |
drawmg16_next: | drawmg16_next: |
INC L ; Avanzamos al siguiente tile en pantalla | inc l ; Avanzamos al siguiente tile en pantalla |
INC L ; horizontalmente | inc l ; horizontalmente |
| |
POP BC ; Recuperamos el contador para el bucle | pop bc ; Recuperamos el contador para el bucle |
DEC B ; DJNZ se sale de rango, hay que usar DEC+JP | dec b ; djnz se sale de rango, hay que usar DEC+jp |
JP NZ, drawmg16_xloop | jp nz, drawmg16_xloop |
| |
;;; NUEVO: Incrementar puntero de mapa a siguiente linea | ;;; NUEVO: Incrementar puntero de mapa a siguiente linea |
LD BC, ANCHO_MAPA_TILES - ANCHO_PANTALLA | ld bc, ANCHO_MAPA_TILES - ANCHO_PANTALLA |
ADD IX, BC | add ix, bc |
;;; FIN NUEVO | ;;; FIN NUEVO |
| |
;;; En este punto, hemos dibujado ANCHO tiles en pantalla (1 fila) | ;;; En este punto, hemos dibujado ANCHO tiles en pantalla (1 fila) |
POP BC | pop bc |
DEC B ; Bucle vertical | dec b ; Bucle vertical |
JP NZ, drawmg16_yloop | jp nz, drawmg16_yloop |
| |
RET | ret |
</code> | </code> |
| |
;------------------------------------------------------------- | ;------------------------------------------------------------- |
Map_Inc_X: | Map_Inc_X: |
LD HL, (DM_MAPX) | ld hl, (DM_MAPX) |
| |
;;; Comparacion 16 bits de HL y (ANCHO_MAPA-ANCHO_PANTALLA) | ;;; Comparacion 16 bits de HL y (ANCHO_MAPA-ANCHO_PANTALLA) |
LD A, H | ld a, h |
CP (ANCHO_MAPA_TILES-ANCHO_PANTALLA) / 256 | CP (ANCHO_MAPA_TILES-ANCHO_PANTALLA) / 256 |
RET NZ | ret nz |
LD A, L | ld a, l |
CP (ANCHO_MAPA_TILES-ANCHO_PANTALLA) % 256 | CP (ANCHO_MAPA_TILES-ANCHO_PANTALLA) % 256 |
RET Z | ret z |
| |
INC HL ; No eran iguales, podemos incrementar. | inc hl ; No eran iguales, podemos incrementar. |
LD (DM_MAPX), HL | ld (DM_MAPX), hl |
RET | ret |
| |
;------------------------------------------------------------- | ;------------------------------------------------------------- |
;------------------------------------------------------------- | ;------------------------------------------------------------- |
Map_Inc_Y: | Map_Inc_Y: |
LD HL, (DM_MAPY) | ld hl, (DM_MAPY) |
| |
;;; Comparacion 16 bits de HL y (ALTO_MAPA-ALTO_PANTALLA) | ;;; Comparacion 16 bits de HL y (ALTO_MAPA-ALTO_PANTALLA) |
LD A, H | ld a, h |
CP (ALTO_MAPA_TILES-ALTO_PANTALLA) / 256 | CP (ALTO_MAPA_TILES-ALTO_PANTALLA) / 256 |
RET NZ | ret nz |
LD A, L | ld a, l |
CP (ALTO_MAPA_TILES-ALTO_PANTALLA) % 256 | CP (ALTO_MAPA_TILES-ALTO_PANTALLA) % 256 |
RET Z | ret z |
| |
INC HL ; No eran iguales, podemos incrementar. | inc hl ; No eran iguales, podemos incrementar. |
LD (DM_MAPY), HL | ld (DM_MAPY), hl |
RET | ret |
| |
;------------------------------------------------------------- | ;------------------------------------------------------------- |
;------------------------------------------------------------- | ;------------------------------------------------------------- |
Map_Dec_X: | Map_Dec_X: |
LD HL, (DM_MAPX) | ld hl, (DM_MAPX) |
LD A, H | ld a, h |
AND A | and a |
JR NZ, mapdecx_doit ; Verificamos que DM_MAPX no sea 0 | jr nz, mapdecx_doit ; Verificamos que DM_MAPX no sea 0 |
LD A, L | ld a, l |
AND A | and a |
RET Z | ret z |
mapdecx_doit: | mapdecx_doit: |
DEC HL | dec hl |
LD (DM_MAPX), HL ; No es cero, podemos decrementar | ld (DM_MAPX), hl ; No es cero, podemos decrementar |
RET | ret |
| |
;------------------------------------------------------------- | ;------------------------------------------------------------- |
;------------------------------------------------------------- | ;------------------------------------------------------------- |
Map_Dec_Y: | Map_Dec_Y: |
LD HL, (DM_MAPY) | ld hl, (DM_MAPY) |
LD A, H | ld a, h |
AND A | and a |
JR NZ, mapdecy_doit ; Verificamos que DM_MAPX no sea 0 | jr nz, mapdecy_doit ; Verificamos que DM_MAPX no sea 0 |
LD A, L | ld a, l |
AND A | and a |
RET Z | ret z |
mapdecy_doit: | mapdecy_doit: |
DEC HL | dec hl |
LD (DM_MAPY), HL ; No es cero, podemos decrementar | ld (DM_MAPY), hl ; No es cero, podemos decrementar |
RET | ret |
</code> | </code> |
| |
ORG 35000 | ORG 35000 |
| |
LD HL, sokoban1_gfx | ld hl, sokoban1_gfx |
LD (DM_SPRITES), HL | ld (DM_SPRITES), hl |
LD HL, sokoban1_attr | ld hl, sokoban1_attr |
LD (DM_ATTRIBS), HL | ld (DM_ATTRIBS), hl |
LD HL, mapa_ejemplo | ld hl, mapa_ejemplo |
LD (DM_MAP), HL | ld (DM_MAP), hl |
LD A, ANCHO_PANTALLA | ld a, ANCHO_PANTALLA |
LD (DM_WIDTH), A | ld (DM_WIDTH), a |
LD A, ALTO_PANTALLA | ld a, ALTO_PANTALLA |
LD (DM_HEIGHT), A | ld (DM_HEIGHT), a |
XOR A | xor a |
LD (DM_COORD_X), A | ld (DM_COORD_X), a |
LD (DM_COORD_Y), A | ld (DM_COORD_Y), a |
LD (DM_MAPX), A ; Establecemos MAPX, MAPY iniciales = 0 | ld (DM_MAPX), a ; Establecemos MaPX, MaPY iniciales = 0 |
LD (DM_MAPY), A | ld (DM_MAPY), a |
| |
redraw: | redraw: |
CALL DrawMap_16x16_Map ; Imprimir pantalla de mapa | call DrawMap_16x16_Map ; Imprimir pantalla de mapa |
| |
bucle: | bucle: |
CALL LEER_TECLADO ; Leemos el estado de O, P, Q, A | call LEER_TECLADO ; Leemos el estado de O, P, Q, A |
| |
BIT 0, A ; Modificamos MAPX y MAPY segun OPQA | bit 0, a ; Modificamos MAPX y MAPY segun OPQA |
JR Z, nopulsada_q | jr z, nopulsada_q |
CALL Map_Dec_Y | call Map_Dec_Y |
JR redraw | jr redraw |
nopulsada_q: | nopulsada_q: |
BIT 1, A | bit 1, a |
JR Z, nopulsada_a | jr z, nopulsada_a |
CALL Map_Inc_Y | call Map_Inc_Y |
JR redraw | jr redraw |
nopulsada_a: | nopulsada_a: |
BIT 2, A | bit 2, a |
JR Z, nopulsada_p | jr z, nopulsada_p |
CALL Map_Inc_X | call Map_Inc_X |
JR redraw | jr redraw |
nopulsada_p: | nopulsada_p: |
BIT 3, A | bit 3, a |
JR Z, nopulsada_o | jr z, nopulsada_o |
CALL Map_Dec_X | call Map_Dec_X |
JR redraw | jr redraw |
nopulsada_o: | nopulsada_o: |
JR bucle | jr bucle |
| |
loop: | loop: |
JR loop | jr loop |
| |
;------------------------------------------------------------- | ;------------------------------------------------------------- |
;------------------------------------------------------------- | ;------------------------------------------------------------- |
LEER_TECLADO: | LEER_TECLADO: |
LD D, 0 | ld d, 0 |
LD BC, $FBFE | ld bc, $fbfe |
IN A, (C) | in a, (c) |
BIT 0, A ; Leemos la tecla Q | bit 0, a ; Leemos la tecla Q |
JR NZ, Control_no_up ; No pulsada, no cambiamos nada en D | jr nz, Control_no_up ; No pulsada, no cambiamos nada en D |
SET 0, D ; Pulsada, ponemos a 1 el bit 0 | set 0, d ; Pulsada, ponemos a 1 el bit 0 |
Control_no_up: | Control_no_up: |
| |
LD BC, $FDFE | ld bc, $fdfe |
IN A, (C) | in a, (c) |
BIT 0, A ; Leemos la tecla A | bit 0, a ; Leemos la tecla A |
JR NZ, Control_no_down ; No pulsada, no cambianos nada en D | jr nz, Control_no_down ; No pulsada, no cambianos nada en D |
SET 1, D ; Pulsada, ponemos a 1 el bit 1 | set 1, d ; Pulsada, ponemos a 1 el bit 1 |
Control_no_down: | Control_no_down: |
| |
LD BC, $DFFE | ld bc, $dffe |
IN A, (C) | in a, (c) |
BIT 0, A ; Leemos la tecla P | bit 0, a ; Leemos la tecla P |
JR NZ, Control_no_right ; No pulsada | jr nz, Control_no_right ; No pulsada |
SET 2, D ; Pulsada, ponemos a 1 el bit 2 | set 2, d ; Pulsada, ponemos a 1 el bit 2 |
| |
Control_no_right: | Control_no_right: |
; BC ya vale $DFFE, (O y P en misma fila) | ; BC ya vale $dffe, (O y P en misma fila) |
BIT 1, A ; Tecla O | bit 1, a ; Tecla O |
JR NZ, Control_no_left | jr nz, Control_no_left |
SET 3, D | set 3, d |
Control_no_left: | Control_no_left: |
| |
LD A, D ; Devolvemos en A el estado de las teclas | ld a, d ; Devolvemos en A el estado de las teclas |
RET | ret |
| |
;------------------------------------------------------------- | ;------------------------------------------------------------- |
;;; Rutina de la ROM del Spectrum, en otros sistemas | ;;; Rutina de la ROM del Spectrum, en otros sistemas |
;;; sustituir por una rutina especifica de multiplicacion | ;;; sustituir por una rutina especifica de multiplicacion |
MULT_HL_POR_DE EQU $30A9 | MULT_HL_POR_DE EQU $30a9 |
| |
;----------------------------------------------------------------------- | ;----------------------------------------------------------------------- |
DrawMap_16x16_Cod_Basica: | DrawMap_16x16_Cod_Basica: |
| |
LD HL, (DM_SPRITES) | ld hl, (DM_SPRITES) |
LD (DS_SPRITES), HL ; Establecer tileset (graficos) | ld (DS_SPRITES), hl ; Establecer tileset (graficos) |
LD HL, (DM_ATTRIBS) | ld hl, (DM_ATTRIBS) |
LD (DS_ATTRIBS), HL ; Establecer tileset (atributos) | ld (DS_ATTRIBS), hl ; Establecer tileset (atributos) |
LD BC, (DM_COORD_X) ; B = Y_INICIO, C = X_INICIO | ld bc, (DM_COORD_X) ; B = Y_INICIO, C = X_INICIO |
LD DE, (DM_MAP) ; DE apunta al mapa | ld de, (DM_MAP) ; DE apunta al mapa |
| |
drawm16cb_loop: | drawm16cb_loop: |
LD A, (DE) ; Leemos el valor de COORD_X_TILE | ld a, (de) ; Leemos el valor de COORD_X_TILE |
INC DE ; Apuntamos al siguiente byte del mapa | inc de ; Apuntamos al siguiente byte del mapa |
| |
CP 255 ; Bloque especial fin de pantalla | cp 255 ; Bloque especial fin de pantalla |
RET Z ; En ese caso, salir | ret z ; En ese caso, salir |
| |
ADD A, C ; A = (X_INICIO + COORD_X_TILE) | add a, c ; A = (X_INICIO + COORD_X_TILE) |
RLCA ; A = (X_INICIO + COORD_X_TILE) * 2 | rlca ; A = (X_INICIO + COORD_X_TILE) * 2 |
LD (DS_COORD_X), A ; Establecemos COORD_X a imprimir tile | ld (DS_COORD_X), a ; Establecemos COORD_X a imprimir tile |
| |
LD A, (DE) ; Leemos el valor de COORD_Y_TILE | ld a, (de) ; Leemos el valor de COORD_Y_TILE |
INC DE | inc de |
ADD A, B ; A = (X_INICIO + COORD_X_TILE) | add a, b ; A = (X_INICIO + COORD_X_TILE) |
RLCA ; A = (Y_INICIO + COORD_Y_TILE) | rlca ; A = (Y_INICIO + COORD_Y_TILE) |
LD (DS_COORD_Y), A ; Establecemos COORD_Y a imprimir tile | ld (DS_COORD_Y), a ; Establecemos COORD_Y a imprimir tile |
| |
LD A, (DE) ; Leemos el valor del TILE | ld a, (de) ; Leemos el valor del TILE |
INC DE | inc de |
LD (DS_NUMSPR), A ; Establecemos el TILE | ld (DS_NUMSPR), a ; Establecemos el TILE |
| |
EXX ; Preservar todos los registros en shadows | exx ; Preservar todos los registros en shadows |
CALL DrawSprite_16x16_LD ; Imprimir el tile con los parametros | call DrawSprite_16x16_LD ; Imprimir el tile con los parametros |
EXX ; Recuperar valores de los registros | exx ; Recuperar valores de los registros |
| |
JR drawm16cb_loop ; Repetimos hasta encontrar el 255 | jr drawm16cb_loop ; Repetimos hasta encontrar el 255 |
</code> | </code> |
| |
Por otra parte, como ya no estamos dibujando los bloques 0, antes de llamar a la rutina de dibujado diferencial es necesario borrar el contenido del área donde vamos a dibujar con el color plano del bloque 0 para que el resultado de la impresión incluya los bloques vacíos en aquellas áreas en que no dibujamos. Es decir, vaciaremos los "bloques vacíos" borrando inicialmente la pantalla antes de realizar la impresión de los "bloques con datos". | Por otra parte, como ya no estamos dibujando los bloques 0, antes de llamar a la rutina de dibujado diferencial es necesario borrar el contenido del área donde vamos a dibujar con el color plano del bloque 0 para que el resultado de la impresión incluya los bloques vacíos en aquellas áreas en que no dibujamos. Es decir, vaciaremos los "bloques vacíos" borrando inicialmente la pantalla antes de realizar la impresión de los "bloques con datos". |
| |
Para borrar este área de pantalla podemos utilizar un simple borrado de atributos (establecer todos los atributos a cero) siempre y cuando los personajes del juego que se moverán sobre las áreas "vacías" se dibujen mediante transferencia y no mediante operaciones lógicas. Recordemos que si hemos borrado mediante atributos en negro estas áreas están vacías de color pero no de contenido gráfico y la impresión con OR haría aparecer el antiguo contenido gráfico de la pantalla. En el caso de impresión de sprites con OR sobre el área "vacía" del mapa sería necesario realizar el borrado previo a la impresión del mapa no como borrado de atributos sino como borrado de zona gráfica y de atributos. | Para borrar este área de pantalla podemos utilizar un simple borrado de atributos (establecer todos los atributos a cero) siempre y cuando los personajes del juego que se moverán sobre las áreas "vacías" se dibujen mediante transferencia y no mediante operaciones lógicas. Recordemos que si hemos borrado mediante atributos en negro estas áreas están vacías de color pero no de contenido gráfico y la impresión con or haría aparecer el antiguo contenido gráfico de la pantalla. En el caso de impresión de sprites con OR sobre el área "vacía" del mapa sería necesario realizar el borrado previo a la impresión del mapa no como borrado de atributos sino como borrado de zona gráfica y de atributos. |
| |
El siguiente programa ejemplo hace uso de la anterior rutina: | El siguiente programa ejemplo hace uso de la anterior rutina: |
| |
;;; Borramos la pantalla (graficos y atributos) | ;;; Borramos la pantalla (graficos y atributos) |
XOR A | xor a |
CALL ClearScreen | call ClearScreen |
XOR A | xor a |
CALL ClearAttributes | call ClearAttributes |
| |
;;; Establecer valores de llamada: | ;;; Establecer valores de llamada: |
LD HL, sokoban1_gfx | ld hl, sokoban1_gfx |
LD (DM_SPRITES), HL | ld (DM_SPRITES), hl |
LD HL, sokoban1_attr | ld hl, sokoban1_attr |
LD (DM_ATTRIBS), HL | ld (DM_ATTRIBS), hl |
LD HL, sokoban_LEVEL1_codif_basica | ld hl, sokoban_LEVEL1_codif_basica |
LD (DM_MAP), HL | ld (DM_MAP), hl |
LD A, 16 | ld a, 16 |
LD (DM_WIDTH), A | ld (DM_WIDTH), a |
LD A, 12 | ld a, 12 |
LD (DM_HEIGHT), A | ld (DM_HEIGHT), a |
XOR A | xor a |
LD (DM_COORD_X), A | ld (DM_COORD_X), a |
LD (DM_COORD_Y), A | ld (DM_COORD_Y), a |
| |
;;; Impresion de pantalla por codificacion basica | ;;; Impresion de pantalla por codificacion basica |
CALL DrawMap_16x16_Cod_Basica | call DrawMap_16x16_Cod_Basica |
| |
loop: | loop: |
JR loop | jr loop |
| |
DM_SPRITES DEFW 0 | DM_SPRITES DEFW 0 |
DrawMap_16x16_Cod_Horiz: | DrawMap_16x16_Cod_Horiz: |
| |
LD HL, (DM_SPRITES) | ld hl, (DM_SPRITES) |
LD (DS_SPRITES), HL ; Establecer tileset (graficos) | ld (DS_SPRITES), hl ; Establecer tileset (graficos) |
LD HL, (DM_ATTRIBS) | ld hl, (DM_ATTRIBS) |
LD (DS_ATTRIBS), HL ; Establecer tileset (atributos) | ld (DS_ATTRIBS), hl ; Establecer tileset (atributos) |
LD BC, (DM_COORD_X) ; B = Y_INICIO, C = X_INICIO | ld bc, (DM_COORD_X) ; B = Y_INICIO, C = X_INICIO |
LD DE, (DM_MAP) ; DE apunta al mapa | ld de, (DM_MAP) ; DE apunta al mapa |
| |
LD HL, DS_COORD_X | ld hl, DS_COORD_X |
| |
drawm16ch_read: | drawm16ch_read: |
LD A, (DE) ; Leemos el valor de COORD_X_TILE | ld a, (de) ; Leemos el valor de COORD_X_TILE |
INC DE ; Apuntamos al siguiente byte del mapa | inc de ; Apuntamos al siguiente byte del mapa |
| |
drawm16ch_loop: | drawm16ch_loop: |
CP 255 ; Bloque especial fin de pantalla | cp 255 ; Bloque especial fin de pantalla |
RET Z ; En ese caso, salir | ret z ; En ese caso, salir |
| |
ADD A, C ; A = (X_INICIO + COORD_X_TILE) | add a, c ; A = (X_INICIO + COORD_X_TILE) |
RLCA ; A = (X_INICIO + COORD_X_TILE) * 2 | rlca ; A = (X_INICIO + COORD_X_TILE) * 2 |
LD (HL), A ; Establecemos COORD_X a imprimir tile | ld (hl), a ; Establecemos COORD_X a imprimir tile |
| |
LD A, (DE) ; Leemos el valor de COORD_Y_TILE | ld a, (de) ; Leemos el valor de COORD_Y_TILE |
INC DE | inc de |
ADD A, B ; A = (Y_INICIO + COORD_Y_TILE) | add a, b ; A = (Y_INICIO + COORD_Y_TILE) |
RLCA ; A = (Y_INICIO + COORD_Y_TILE) | rlca ; A = (Y_INICIO + COORD_Y_TILE) |
LD (DS_COORD_Y), A ; Establecemos COORD_Y a imprimir tile | ld (DS_COORD_Y), a ; Establecemos COORD_Y a imprimir tile |
| |
;;; Bucle impresion de todos los tiles del scanline (aunque sea 1 solo) | ;;; Bucle impresion de todos los tiles del scanline (aunque sea 1 solo) |
| |
drawm16ch_tileloop: | drawm16ch_tileloop: |
LD A, (DE) ; Leemos el valor del TILE de pantalla | ld a, (de) ; Leemos el valor del TILE de pantalla |
INC DE ; Incrementamos puntero | inc de ; Incrementamos puntero |
| |
CP 255 | cp 255 |
JR Z, drawm16ch_read ; Si es fin de tile codificado, fin bucle | jr z, drawm16ch_read ; Si es fin de tile codificado, fin bucle |
| |
LD (DS_NUMSPR), A ; Establecemos el TILE | ld (DS_NUMSPR), a ; Establecemos el TILE |
| |
EXX ; Preservar todos los registros en shadows | exx ; Preservar todos los registros en shadows |
CALL DrawSprite_16x16_LD ; Imprimir el tile con los parametros | call DrawSprite_16x16_LD ; Imprimir el tile con los parametros |
EXX ; Recuperar valores de los registros | exx ; Recuperar valores de los registros |
| |
INC (HL) ; Avanzamos al siguiente tile | inc (hl) ; Avanzamos al siguiente tile |
INC (HL) ; COORD_X = COORD_X + 2 | inc (hl) ; COORD_X = COORD_X + 2 |
| |
JR drawm16ch_tileloop ; Repetimos hasta encontrar el 255 | jr drawm16ch_tileloop ; Repetimos hasta encontrar el 255 |
</code> | </code> |
| |
DrawMap_16x16_Cod_Vert: | DrawMap_16x16_Cod_Vert: |
| |
LD HL, (DM_SPRITES) | ld hl, (DM_SPRITES) |
LD (DS_SPRITES), HL ; Establecer tileset (graficos) | ld (DS_SPRITES), hl ; Establecer tileset (graficos) |
LD HL, (DM_ATTRIBS) | ld hl, (DM_ATTRIBS) |
LD (DS_ATTRIBS), HL ; Establecer tileset (atributos) | ld (DS_ATTRIBS), hl ; Establecer tileset (atributos) |
LD BC, (DM_COORD_X) ; B = Y_INICIO, C = X_INICIO | ld bc, (DM_COORD_X) ; B = Y_INICIO, C = X_INICIO |
LD DE, (DM_MAP) ; DE apunta al mapa | ld de, (DM_MAP) ; DE apunta al mapa |
| |
LD HL, DS_COORD_Y ; CAMBIO: Ahora HL apunta a la variable Y | ld hl, DS_COORD_Y ; CAMBIO: Ahora HL apunta a la variable Y |
| |
drawm16cv_read: | drawm16cv_read: |
LD A, (DE) ; Leemos el valor de COORD_X_TILE | ld a, (de) ; Leemos el valor de COORD_X_TILE |
INC DE ; Apuntamos al siguiente byte del mapa | inc de ; Apuntamos al siguiente byte del mapa |
| |
drawm16cv_loop: | drawm16cv_loop: |
CP 255 ; Bloque especial fin de pantalla | cp 255 ; Bloque especial fin de pantalla |
RET Z ; En ese caso, salir | ret z ; En ese caso, salir |
| |
ADD A, C ; A = (X_INICIO + COORD_X_TILE) | add a, c ; A = (X_INICIO + COORD_X_TILE) |
RLCA ; A = (X_INICIO + COORD_X_TILE) * 2 | rlca ; A = (X_INICIO + COORD_X_TILE) * 2 |
LD (DS_COORD_X), A ; CAMBIO: Establecemos COORD_X a imprimir tile | ld (DS_COORD_X), a ; CaMBIO: Establecemos COORD_X a imprimir tile |
| |
LD A, (DE) ; Leemos el valor de COORD_Y_TILE | ld a, (de) ; Leemos el valor de COORD_Y_TILE |
INC DE | inc de |
ADD A, B ; A = (Y_INICIO + COORD_Y_TILE) | add a, b ; A = (Y_INICIO + COORD_Y_TILE) |
RLCA ; A = (Y_INICIO + COORD_Y_TILE) | rlca ; A = (Y_INICIO + COORD_Y_TILE) |
LD (HL), A ; CAMBIO: Establecemos COORD_Y a imprimir tile | ld (hl), a ; CAMBIO: Establecemos COORD_Y a imprimir tile |
| |
;;; Bucle impresion de todos los tiles del scanline (aunque sea 1 solo) | ;;; Bucle impresion de todos los tiles del scanline (aunque sea 1 solo) |
drawm16cv_tileloop: | drawm16cv_tileloop: |
| |
LD A, (DE) ; Leemos el valor del TILE de pantalla | ld a, (de) ; Leemos el valor del TILE de pantalla |
INC DE ; Incrementamos puntero | inc de ; Incrementamos puntero |
| |
CP 255 | cp 255 |
JR Z, drawm16cv_read ; Si es fin de tile codificado, fin bucle | jr z, drawm16cv_read ; Si es fin de tile codificado, fin bucle |
| |
LD (DS_NUMSPR), A ; Establecemos el TILE | ld (DS_NUMSPR), a ; Establecemos el TILE |
| |
EXX ; Preservar todos los registros en shadows | exx ; Preservar todos los registros en shadows |
CALL DrawSprite_16x16_LD ; Imprimir el tile con los parametros | call DrawSprite_16x16_LD ; Imprimir el tile con los parametros |
EXX ; Recuperar valores de los registros | exx ; Recuperar valores de los registros |
| |
INC (HL) | inc (hl) |
INC (HL) ; COORD_Y = COORD_Y + 2 | inc (hl) ; COORD_Y = COORD_Y + 2 |
| |
JR drawm16cv_tileloop ; Repetimos hasta encontrar el 255 | jr drawm16cv_tileloop ; Repetimos hasta encontrar el 255 |
</code> | </code> |
| |
| |
<code z80> | <code z80> |
LD DE, DS_COORD_Y ; DE apunta a la coordenada Y | ld de, DS_COORD_Y ; DE apunta a la coordenada Y |
LD HL, DS_COORD_X ; HL apunta a la coordenada X | ld hl, DS_COORD_X ; HL apunta a la coordenada X |
</code> | </code> |
| |
Despues, incluímos 2 instrucciones ''NOP'' (de 1 byte, con opcode 0), antes y después de los ''INC (HL)'' que producen el incremento de la coordenada apuntada por HL (''COORD_X''). Además, establecemos 2 etiquetas del programa ensamblador en las posiciones de los 2 NOPs para poder referenciar la dirección de memoria donde se han ensamblado estos NOPs en el código: | Despues, incluímos 2 instrucciones ''NOP'' (de 1 byte, con opcode 0), antes y después de los ''inc (hl)'' que producen el incremento de la coordenada apuntada por HL (''COORD_X''). Además, establecemos 2 etiquetas del programa ensamblador en las posiciones de los 2 NOPs para poder referenciar la dirección de memoria donde se han ensamblado estos NOPs en el código: |
| |
<code z80> | <code z80> |
drawm16cm_dir1: | drawm16cm_dir1: |
NOP | nop |
INC (HL) | inc (hl) |
INC (HL) ; COORD = COORD + 2 | inc (hl) ; COORD = COORD + 2 |
drawm16cm_dir2: | drawm16cm_dir2: |
NOP | nop |
</code> | </code> |
| |
Cuando entramos por primera vez en la rutina, y comenzamos a procesar "scanlines", sabemos que son todos horizontales hasta que encontremos el valor "254" (cambio de horizontales a verticales), por lo que nuestra rutina de impresión de tiles en bucle horizontal funciona adecuadamente: se ejecuta un NOP (que no tiene ningún efecto salvo el consumo de 4 ciclos de reloj), después los 2 ''INC (HL)'' y luego otro ''NOP'', lo que produce el incremento de ''COORD_X'' en 2 unidades (HL apunta a ''COORD_X''). | Cuando entramos por primera vez en la rutina, y comenzamos a procesar "scanlines", sabemos que son todos horizontales hasta que encontremos el valor "254" (cambio de horizontales a verticales), por lo que nuestra rutina de impresión de tiles en bucle horizontal funciona adecuadamente: se ejecuta un nop (que no tiene ningún efecto salvo el consumo de 4 ciclos de reloj), después los 2 ''inc (hl)'' y luego otro ''NOP'', lo que produce el incremento de ''COORD_X'' en 2 unidades (HL apunta a ''COORD_X''). |
| |
Cuando la rutina encuentra un valor 254 como "fin de scanline" debe de cambiar al modo de impresión vertical, por lo que dentro del bucle de procesado del scanline añadimos el siguiente código: | Cuando la rutina encuentra un valor 254 como "fin de scanline" debe de cambiar al modo de impresión vertical, por lo que dentro del bucle de procesado del scanline añadimos el siguiente código: |
(...) | (...) |
| |
CP 254 | cp 254 |
JR Z, drawm16cm_switch ; Codigo 254 -> cambiar a codif. vertical | jr z, drawm16cm_switch ; Codigo 254 -> cambiar a codif. vertical |
| |
(...) | (...) |
drawm16cm_switch: | drawm16cm_switch: |
;;; Cambio de codificacion de horizontal a vertical: | ;;; Cambio de codificacion de horizontal a vertical: |
LD A, $EB ; Opcode de EX DE, HL | ld a, $eb ; Opcode de ex de, hl |
LD (drawm16cm_dir1), A ; Lo escribimos sobre los NOPs | ld (drawm16cm_dir1), a ; Lo escribimos sobre los NOPs |
LD (drawm16cm_dir2), A | ld (drawm16cm_dir2), a |
JR drawm16cm_read | jr drawm16cm_read |
</code> | </code> |
| |
Es decir, cuando se encuentra un valor 254 como fin de scanline saltamos a drawm16cm_switch, la cual escribe un valor **$EB** (''EX DE, HL'') en las posiciones de memoria donde antes había un NOP, cambiando la porción de código que habíamos visto antes por: | Es decir, cuando se encuentra un valor 254 como fin de scanline saltamos a drawm16cm_switch, la cual escribe un valor **$eb** (''ex de, hl'') en las posiciones de memoria donde antes había un nop, cambiando la porción de código que habíamos visto antes por: |
| |
<code z80> | <code z80> |
drawm16cm_dir1: | drawm16cm_dir1: |
EX DE, HL | ex de, hl |
INC (HL) | inc (hl) |
INC (HL) ; COORD = COORD + 2 | inc (hl) ; COORD = COORD + 2 |
drawm16cm_dir2: | drawm16cm_dir2: |
EX DE, HL | ex de, hl |
</code> | </code> |
| |
Esto provoca que, a partir de haber encontrado el 254 y hasta que finalice la rutina (código 255 de fin de pantalla), los INC (HL) incrementen ''COORD_Y'' (debido al ''EX DE, HL'') en lugar de ''COORD_X'', convirtiendo la rutina en un sistema de impresión de scanlines horizontales. | Esto provoca que, a partir de haber encontrado el 254 y hasta que finalice la rutina (código 255 de fin de pantalla), los inc (hl) incrementen ''COORD_Y'' (debido al ''ex de, hl'') en lugar de ''COORD_X'', convirtiendo la rutina en un sistema de impresión de scanlines horizontales. |
| |
Cuando salimos de la rutina, esta se queda con los valores de ''EX DE, HL'' en memoria, por lo que la siguiente vez que sea llamada tenemos que asegurarnos de que vuelven a estar los NOPs en su lugar, porque las pantallas siempre empiezan por scanlines horizontales. Para lograr esto, nuestra rutina debe empezar por la colocación del ''NOP'' en las direcciones apuntadas por las etiquetas: | Cuando salimos de la rutina, esta se queda con los valores de ''ex de, hl'' en memoria, por lo que la siguiente vez que sea llamada tenemos que asegurarnos de que vuelven a estar los NOPs en su lugar, porque las pantallas siempre empiezan por scanlines horizontales. Para lograr esto, nuestra rutina debe empezar por la colocación del ''NOP'' en las direcciones apuntadas por las etiquetas: |
| |
<code z80> | <code z80> |
DrawMap_16x16_Cod_Mixta: | DrawMap_16x16_Cod_Mixta: |
| |
XOR A ; Opcode de "NOP" | xor a ; Opcode de "nop" |
LD (drawm16cm_dir1), A ; Almacenar en la posicion de las labels | ld (drawm16cm_dir1), a ; almacenar en la posicion de las labels |
LD (drawm16cm_dir2), A | ld (drawm16cm_dir2), a |
</code> | </code> |
| |
DrawMap_16x16_Cod_Mixta: | DrawMap_16x16_Cod_Mixta: |
| |
XOR A ; Opcode de "NOP" | xor a ; Opcode de "nop" |
LD (drawm16cm_dir1), A ; Almacenar en la posicion de labels | ld (drawm16cm_dir1), a ; almacenar en la posicion de labels |
LD (drawm16cm_dir2), A | ld (drawm16cm_dir2), a |
| |
LD HL, (DM_SPRITES) | ld hl, (DM_SPRITES) |
LD (DS_SPRITES), HL ; Establecer tileset (graficos) | ld (DS_SPRITES), hl ; Establecer tileset (graficos) |
LD HL, (DM_ATTRIBS) | ld hl, (DM_ATTRIBS) |
LD (DS_ATTRIBS), HL ; Establecer tileset (atributos) | ld (DS_ATTRIBS), hl ; Establecer tileset (atributos) |
LD BC, (DM_COORD_X) ; B = Y_INICIO, C = X_INICIO | ld bc, (DM_COORD_X) ; B = Y_INICIO, C = X_INICIO |
LD IX, (DM_MAP) ; DE apunta al mapa | ld ix, (DM_MAP) ; DE apunta al mapa |
| |
LD DE, DS_COORD_Y ; DE apunta a la coordenada Y | ld de, DS_COORD_Y ; DE apunta a la coordenada Y |
LD HL, DS_COORD_X ; HL apunta a la coordenada X | ld hl, DS_COORD_X ; HL apunta a la coordenada X |
| |
drawm16cm_read: | drawm16cm_read: |
LD A, (IX+0) ; Leemos el valor de COORD_X_TILE | ld a, (ix+0) ; Leemos el valor de COORD_X_TILE |
INC IX ; Apuntamos al siguiente byte del mapa | inc ix ; Apuntamos al siguiente byte del mapa |
| |
drawm16cm_loop: | drawm16cm_loop: |
CP 255 ; Bloque especial fin de pantalla | cp 255 ; Bloque especial fin de pantalla |
RET Z ; En ese caso, salir | ret z ; En ese caso, salir |
| |
ADD A, C ; A = (X_INICIO + COORD_X_TILE) | add a, c ; A = (X_INICIO + COORD_X_TILE) |
RLCA ; A = (X_INICIO + COORD_X_TILE) * 2 | rlca ; A = (X_INICIO + COORD_X_TILE) * 2 |
LD (HL), A ; Establecemos COORD_X a imprimir tile | ld (hl), a ; Establecemos COORD_X a imprimir tile |
| |
LD A, (IX+0) ; Leemos el valor de COORD_Y_TILE | ld a, (ix+0) ; Leemos el valor de COORD_Y_TILE |
INC IX | inc ix |
ADD A, B ; A = (Y_INICIO + COORD_Y_TILE) | add a, b ; A = (Y_INICIO + COORD_Y_TILE) |
RLCA ; A = (Y_INICIO + COORD_Y_TILE) | rlca ; A = (Y_INICIO + COORD_Y_TILE) |
LD (DE), A ; Establecemos COORD_Y a imprimir tile | ld (de), a ; Establecemos COORD_Y a imprimir tile |
| |
;;; Bucle impresion vertical de los N tiles del scanline | ;;; Bucle impresion vertical de los N tiles del scanline |
drawm16cm_tileloop: | drawm16cm_tileloop: |
LD A, (IX+0) ; Leemos el valor del TILE de pantalla | ld a, (ix+0) ; Leemos el valor del TILE de pantalla |
INC IX ; Incrementamos puntero | inc ix ; Incrementamos puntero |
| |
CP 255 | cp 255 |
JR Z, drawm16cm_read ; Si es fin de tile codificado, fin bucle | jr z, drawm16cm_read ; Si es fin de tile codificado, fin bucle |
| |
CP 254 | cp 254 |
JR Z, drawm16cm_switch ; Codigo 254 -> cambiar a codif. vertical | jr z, drawm16cm_switch ; Codigo 254 -> cambiar a codif. vertical |
| |
LD (DS_NUMSPR), A ; Establecemos el TILE | ld (DS_NUMSPR), a ; Establecemos el TILE |
EXX ; Preservar todos los registros en shadows | exx ; Preservar todos los registros en shadows |
CALL DrawSprite_16x16_LD ; Imprimir el tile con los parametros | call DrawSprite_16x16_LD ; Imprimir el tile con los parametros |
EXX ; Recuperar valores de los registros | exx ; Recuperar valores de los registros |
| |
drawm16cm_dir1: ; Etiqueta con la direccion del NOP | drawm16cm_dir1: ; Etiqueta con la direccion del nop |
NOP ; NOP->INC COORD_X, EX DE,HL->INC COORD_Y | nop ; nop->inc cOORD_X, ex de,hl->inc cOORD_Y |
| |
INC (HL) | inc (hl) |
INC (HL) ; COORD = COORD + 2 | inc (hl) ; COORD = COORD + 2 |
| |
drawm16cm_dir2: ; Etiqueta con la direccion del NOP | drawm16cm_dir2: ; Etiqueta con la direccion del nop |
NOP ; NOP->INC COORD_X, EX DE,HL->INC COORD_Y | nop ; nop->inc cOORD_X, ex de,hl->inc cOORD_Y |
| |
JR drawm16cm_tileloop ; Repetimos hasta encontrar el 255 | jr drawm16cm_tileloop ; Repetimos hasta encontrar el 255 |
| |
drawm16cm_switch: | drawm16cm_switch: |
;;; Cambio de codificacion de horizontal a vertical: | ;;; Cambio de codificacion de horizontal a vertical: |
LD A, $EB ; Opcode de EX DE, HL | ld a, $eb ; Opcode de ex de, hl |
LD (drawm16cm_dir1), A ; Ahora se hace el EX DE, HL y por lo tanto | ld (drawm16cm_dir1), a ; ahora se hace el ex de, hl y por lo tanto |
LD (drawm16cm_dir2), A ; INC (HL) incrementa COORD_Y en vez de X | ld (drawm16cm_dir2), a ; inc (hl) incrementa COORD_Y en vez de X |
JR drawm16cm_read ; Volvemos al bucle de lectura | jr drawm16cm_read ; Volvemos al bucle de lectura |
</code> | </code> |
| |
</code> | </code> |
| |
Aunque hemos dicho que el tamaño máximo del mapa será de 16x16, la realidad es que puede ser como máximo de 16x14, ya que si ambas coordenadas X e Y valen 15 ($F), el byte resultante compuesto sería $FF que es el código de final de pantalla. De la misma forma, si X vale 15 e Y vale 14, el valor resultante, $FE, sería confundido por la rutina mixta con el código especial de cambio de scanlines horizontales a verticales. | Aunque hemos dicho que el tamaño máximo del mapa será de 16x16, la realidad es que puede ser como máximo de 16x14, ya que si ambas coordenadas X e Y valen 15 ($f), el byte resultante compuesto sería $fF que es el código de final de pantalla. De la misma forma, si X vale 15 e Y vale 14, el valor resultante, $fE, sería confundido por la rutina mixta con el código especial de cambio de scanlines horizontales a verticales. |
| |
Así, con un mapa de 16x14, el máximo tamaño de pantalla que podemos ocupar según las dimensiones de cada tile serían: | Así, con un mapa de 16x14, el máximo tamaño de pantalla que podemos ocupar según las dimensiones de cada tile serían: |
| |
<code z80> | <code z80> |
;;; (venimos del LD A, (IX+0) / INC IX de la coordenada X) | ;;; (venimos del ld a, (ix+0) / inc ix de la coordenada X) |
| |
;;; Sumamos la coordenada X recogida y obtenemos desde el mapa la Y: | ;;; Sumamos la coordenada X recogida y obtenemos desde el mapa la Y: |
ADD A, C ; A = (X_INICIO + COORD_X_TILE) | add a, c ; A = (X_INICIO + COORD_X_TILE) |
RLCA ; A = (X_INICIO + COORD_X_TILE) * 2 | rlca ; A = (X_INICIO + COORD_X_TILE) * 2 |
LD (HL), A ; Establecemos COORD_X a imprimir tile | ld (hl), a ; Establecemos COORD_X a imprimir tile |
| |
LD A, (IX+0) ; Leemos el valor de COORD_Y_TILE | ld a, (ix+0) ; Leemos el valor de COORD_Y_TILE |
INC IX | inc ix |
ADD A, B ; A = (Y_INICIO + COORD_Y_TILE) | add a, b ; A = (Y_INICIO + COORD_Y_TILE) |
RLCA ; A = (Y_INICIO + COORD_Y_TILE) | rlca ; A = (Y_INICIO + COORD_Y_TILE) |
LD (DE), A ; Establecemos COORD_Y a imprimir tile | ld (de), a ; Establecemos COORD_Y a imprimir tile |
</code> | </code> |
| |
| |
<code z80> | <code z80> |
PUSH AF | push af |
AND %11110000 ; Nos quedamos con la parte alta (COORD_X) | and %11110000 ; Nos quedamos con la parte alta (COORD_X) |
RRCA ; Pasamos parte alta a parte baja | rrca ; Pasamos parte alta a parte baja |
RRCA ; con 4 desplazamientos | rrca ; con 4 desplazamientos |
RRCA | rrca |
RRCA ; Ya podemos sumar: | rrca ; Ya podemos sumar: |
ADD A, C ; A = (X_INICIO + COORD_X_TILE) | add a, c ; A = (X_INICIO + COORD_X_TILE) |
RLCA ; A = (X_INICIO + COORD_X_TILE) * 2 | rlca ; A = (X_INICIO + COORD_X_TILE) * 2 |
LD (HL), A ; Establecemos COORD_X a imprimir tile | ld (hl), a ; Establecemos COORD_X a imprimir tile |
| |
POP AF | pop af |
AND %00001111 ; Nos quedamos con la parte baja (COORD_Y) | and %00001111 ; Nos quedamos con la parte baja (COORD_Y) |
| |
ADD A, B ; A = (Y_INICIO + COORD_Y_TILE) | add a, b ; A = (Y_INICIO + COORD_Y_TILE) |
RLCA ; A = (Y_INICIO + COORD_Y_TILE) | rlca ; A = (Y_INICIO + COORD_Y_TILE) |
LD (DE), A ; Establecemos COORD_Y a imprimir tile | ld (de), a ; Establecemos COORD_Y a imprimir tile |
</code> | </code> |
| |
De la rutina original hemos eliminado las instrucciones ''LD A, (IX+0)'' e ''INC IX'' (29 ciclos de reloj menos) y hemos añadido ''PUSH AF''/''POP AF'' e instrucciones ''AND'' y ''RLCA'' (51 ciclos de reloj más) resultando en una rutina que es 22 ciclos de reloj más lenta por scanline. Pero a cambio de estos 22 ciclos de reloj se pueden producir grandes ahorros en las pantallas resultantes. | De la rutina original hemos eliminado las instrucciones ''ld a, (ix+0)'' e ''inc ix'' (29 ciclos de reloj menos) y hemos añadido ''push af''/''pop af'' e instrucciones ''AND'' y ''RLCA'' (51 ciclos de reloj más) resultando en una rutina que es 22 ciclos de reloj más lenta por scanline. Pero a cambio de estos 22 ciclos de reloj se pueden producir grandes ahorros en las pantallas resultantes. |
| |
La rutina de impresión de 16x16 Mixta con coordenadas X e Y codificadas en un mismo byte quedaría como el código que sigue: | La rutina de impresión de 16x16 Mixta con coordenadas X e Y codificadas en un mismo byte quedaría como el código que sigue: |
DrawMap_16x16_Cod_Mixta_XY: | DrawMap_16x16_Cod_Mixta_XY: |
| |
XOR A ; Opcode de "NOP" | xor a ; Opcode de "nop" |
LD (drawm16cmxy_dir1), A ; Almacenar en la posicion de las labels | ld (drawm16cmxy_dir1), a ; almacenar en la posicion de las labels |
LD (drawm16cmxy_dir2), A | ld (drawm16cmxy_dir2), a |
LD HL, (DM_SPRITES) | ld hl, (DM_SPRITES) |
LD (DS_SPRITES), HL ; Establecer tileset (graficos) | ld (DS_SPRITES), hl ; Establecer tileset (graficos) |
LD HL, (DM_ATTRIBS) | ld hl, (DM_ATTRIBS) |
LD (DS_ATTRIBS), HL ; Establecer tileset (atributos) | ld (DS_ATTRIBS), hl ; Establecer tileset (atributos) |
LD BC, (DM_COORD_X) ; B = Y_INICIO, C = X_INICIO | ld bc, (DM_COORD_X) ; B = Y_INICIO, C = X_INICIO |
LD IX, (DM_MAP) ; DE apunta al mapa | ld ix, (DM_MAP) ; DE apunta al mapa |
| |
LD DE, DS_COORD_Y ; DE apunta a la coordenada Y | ld de, DS_COORD_Y ; DE apunta a la coordenada Y |
LD HL, DS_COORD_X ; HL apunta a la coordenada X | ld hl, DS_COORD_X ; HL apunta a la coordenada X |
| |
drawm16cmxy_read: | drawm16cmxy_read: |
LD A, (IX+0) ; Leemos el valor de COORDENADAS | ld a, (ix+0) ; Leemos el valor de COORDENADAS |
INC IX ; Apuntamos al siguiente byte del mapa | inc ix ; Apuntamos al siguiente byte del mapa |
| |
drawm16cmxy_loop: | drawm16cmxy_loop: |
CP 255 ; Bloque especial fin de pantalla | cp 255 ; Bloque especial fin de pantalla |
RET Z ; En ese caso, salir | ret z ; En ese caso, salir |
| |
PUSH AF ; Extraccion de coordenadas XY en X e Y | push af ; Extraccion de coordenadas XY en X e Y |
AND %11110000 ; Nos quedamos con la parte alta (COORD_X) | and %11110000 ; Nos quedamos con la parte alta (COORD_X) |
RRCA ; Pasamos parte alta a parte baja | rrca ; Pasamos parte alta a parte baja |
RRCA ; con 4 desplazamientos | rrca ; con 4 desplazamientos |
RRCA | rrca |
RRCA ; Ya podemos sumar | rrca ; Ya podemos sumar |
ADD A, C ; A = (X_INICIO + COORD_X_TILE) | add a, c ; A = (X_INICIO + COORD_X_TILE) |
RLCA ; A = (X_INICIO + COORD_X_TILE) * 2 | rlca ; A = (X_INICIO + COORD_X_TILE) * 2 |
LD (HL), A ; Establecemos COORD_X a imprimir tile | ld (hl), a ; Establecemos COORD_X a imprimir tile |
POP AF | pop af |
AND %00001111 ; Nos quedamos con la parte baja (COORD_Y) | and %00001111 ; Nos quedamos con la parte baja (COORD_Y) |
ADD A, B ; A = (Y_INICIO + COORD_Y_TILE) | add a, b ; A = (Y_INICIO + COORD_Y_TILE) |
RLCA ; A = (Y_INICIO + COORD_Y_TILE) | rlca ; A = (Y_INICIO + COORD_Y_TILE) |
LD (DE), A ; Establecemos COORD_Y a imprimir tile | ld (de), a ; Establecemos COORD_Y a imprimir tile |
| |
;;; Bucle impresion vertical de los N tiles del scanline | ;;; Bucle impresion vertical de los N tiles del scanline |
drawm16cmxy_tileloop: | drawm16cmxy_tileloop: |
LD A, (IX+0) ; Leemos el valor del TILE de pantalla | ld a, (ix+0) ; Leemos el valor del TILE de pantalla |
INC IX ; Incrementamos puntero | inc ix ; Incrementamos puntero |
| |
CP 255 | cp 255 |
JR Z, drawm16cmxy_read ; Si es fin de tile codificado, fin bucle | jr z, drawm16cmxy_read ; Si es fin de tile codificado, fin bucle |
CP 254 | cp 254 |
JR Z, drawm16cmxy_switch ; Codigo 254 -> cambiar a codif. vertical | jr z, drawm16cmxy_switch ; Codigo 254 -> cambiar a codif. vertical |
| |
LD (DS_NUMSPR), A ; Establecemos el TILE | ld (DS_NUMSPR), a ; Establecemos el TILE |
EXX ; Preservar todos los registros en shadows | exx ; Preservar todos los registros en shadows |
CALL DrawSprite_16x16_LD ; Imprimir el tile con los parametros | call DrawSprite_16x16_LD ; Imprimir el tile con los parametros |
EXX ; Recuperar valores de los registros | exx ; Recuperar valores de los registros |
| |
drawm16cmxy_dir1: ; Etiqueta con la direccion del NOP | drawm16cmxy_dir1: ; Etiqueta con la direccion del nop |
NOP ; NOP->INC COORD_X, EX DE,HL->INC COORD_Y | nop ; nop->inc cOORD_X, ex de,hl->inc cOORD_Y |
INC (HL) | inc (hl) |
INC (HL) ; COORD = COORD + 2 | inc (hl) ; COORD = COORD + 2 |
drawm16cmxy_dir2: ; Etiqueta con la direccion del NOP | drawm16cmxy_dir2: ; Etiqueta con la direccion del nop |
NOP ; NOP->INC COORD_X, EX DE,HL->INC COORD_Y | nop ; nop->inc cOORD_X, ex de,hl->inc cOORD_Y |
JR drawm16cmxy_tileloop ; Repetimos hasta encontrar el 255 | jr drawm16cmxy_tileloop ; Repetimos hasta encontrar el 255 |
| |
drawm16cmxy_switch: | drawm16cmxy_switch: |
;;; Cambio de codificacion de horizontal a vertical: | ;;; Cambio de codificacion de horizontal a vertical: |
LD A, $EB ; Opcode de EX DE, HL | 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_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 | ld (drawm16cmxy_dir2), a ; inc (hl) incrementa COORD_Y en vez de X |
JR drawm16cmxy_read | jr drawm16cmxy_read |
</code> | </code> |
| |
;--------------------------------------------------------------- | ;--------------------------------------------------------------- |
DrawMap_16x16_Codificada: | DrawMap_16x16_Codificada: |
LD HL, (DM_MAP) ; HL apunta al mapa | ld hl, (DM_MAP) ; HL apunta al mapa |
LD A, (HL) ; Leemos tipo de codificacion | ld a, (hl) ; Leemos tipo de codificacion |
INC HL ; Incrementamos puntero (a datos) | inc hl ; Incrementamos puntero (a datos) |
LD (DM_MAP), HL ; Guardamos el valor en DM_MAP | ld (DM_MAP), hl ; Guardamos el valor en DM_MAP |
| |
AND A ; Es A == 0? (MAP_CODIF_NONE) | and a ; Es A == 0? (MAP_CODIF_NONE) |
JR NZ, dm16c_nocero ; No | jr nz, dm16c_nocero ; No |
CALL DrawMap_16x16 | call DrawMap_16x16 |
RET | ret |
| |
dm16c_nocero: | dm16c_nocero: |
CP MAP_CODIF_HORIZ ; Es A == MAP_CODIF_HORIZ? | CP MAP_CODIF_HORIZ ; Es A == MAP_CODIF_HORIZ? |
JR NZ, dm16c_nohoriz ; No, saltar | jr nz, dm16c_nohoriz ; No, saltar |
CALL DrawMap_16x16_Cod_Horiz | call DrawMap_16x16_Cod_Horiz |
RET | ret |
| |
dm16c_nohoriz: | dm16c_nohoriz: |
CP MAP_CODIF_VERT ; Es A == MAP_CODIF_VERT? | CP MAP_CODIF_VERT ; Es A == MAP_CODIF_VERT? |
JR NZ, dm16c_novert ; No, saltar | jr nz, dm16c_novert ; No, saltar |
CALL DrawMap_16x16_Cod_Vert | call DrawMap_16x16_Cod_Vert |
RET | ret |
| |
dm16c_novert: | dm16c_novert: |
CP MAP_CODIF_MIXTA ; Es A == MAP_CODIF_MIXTA? | CP MAP_CODIF_MIXTA ; Es A == MAP_CODIF_MIXTA? |
JR NZ, dm16c_nomixta ; No, saltar | jr nz, dm16c_nomixta ; No, saltar |
CALL DrawMap_16x16_Cod_Mixta | call DrawMap_16x16_Cod_Mixta |
RET | ret |
| |
dm16c_nomixta: ; Entonces es basica. | dm16c_nomixta: ; Entonces es basica. |
CALL DrawMap_16x16_Cod_Basica | call DrawMap_16x16_Cod_Basica |
RET | ret |
</code> | </code> |
| |
DrawSprite_MxN_LD_extendida: | DrawSprite_MxN_LD_extendida: |
| |
LD A, (DS_HEIGHT) | ld a, (DS_HEIGHT) |
LD B, A | ld b, a |
LD A, (DS_WIDTH) | ld a, (DS_WIDTH) |
LD C, A ; Obtenemos datos del sprite | ld c, a ; Obtenemos datos del sprite |
| |
;;; B = ALTO de Sprite | ;;; B = ALTO de Sprite |
;;; C = ANCHO de Sprite | ;;; C = ANCHO de Sprite |
| |
LD A, C ; A = ANCHO | ld a, c ; A = ANCHO |
CP 16 ; Comparar ancho | cp 16 ; Comparar ancho |
JR NZ, dspMN_no16 ; ¿es 16? | jr nz, dspMN_no16 ; ¿es 16? |
| |
SUB B ; A = Ancho - alto | sub b ; A = Ancho - alto |
JR NZ, dspMN_generica ; Si no es cero, rutina generica | jr nz, dspMN_generica ; Si no es cero, rutina generica |
; Es cero, imprimir 16x16: | ; Es cero, imprimir 16x16: |
CALL DrawSprite16x16 ; Imprimir via especifica 16x16 | call DrawSprite16x16 ; Imprimir via especifica 16x16 |
RET | ret |
| |
dspMN_no16: | dspMN_no16: |
LD A, C ; Recuperamos ancho | ld a, c ; Recuperamos ancho |
CP 8 ; ¿es 8? | cp 8 ; ¿es 8? |
JR NZ, dspMN_generica ; Si no es 8, ni 16, generica | jr nz, dspMN_generica ; Si no es 8, ni 16, generica |
SUB B ; A = Ancho - alto | sub b ; A = Ancho - alto |
JR NZ, dspMN_generica ; Si no es cero, rutina generica | jr nz, dspMN_generica ; Si no es cero, rutina generica |
| |
CALL DrawSprite_8x8 ; Imprimir via especifica 8x8 | call DrawSprite_8x8 ; Imprimir via especifica 8x8 |
RET | ret |
| |
dspMN_generica: | dspMN_generica: |
;;; (resto rutina generica) | ;;; (resto rutina generica) |
RET | ret |
</code> | </code> |
| |
Esto implica la necesidad de 6912 bytes de memoria para evitar que el usuario vea la generación del mapa, por lo que no es normal utilizar esta técnica a menos que esté realmente justificado. | Esto implica la necesidad de 6912 bytes de memoria para evitar que el usuario vea la generación del mapa, por lo que no es normal utilizar esta técnica a menos que esté realmente justificado. |
| |
Si utilizamos pantallas virtuales necesitaremos modificar todas las rutinas de impresión para que trabajen con una dirección destino diferente en lugar de sobre $4000. Para que las rutinas sigan pudiendo utilizar los trucos de composición de dirección en base a desplazamientos de bits que vimos en capítulos anteriores lo normal es que busquemos una dirección de memoria libre cuyos 3 bits más altos ya no sean "010b" (caso de la videoram -> $4000 -> 0100000000000000b) sino, por ejemplo "110" ($C000). De esta forma se pueden alterar las rutinas fácilmente para trabajar sobre un área de 7KB equivalente a la videoram pero comenzando en $C000. | Si utilizamos pantallas virtuales necesitaremos modificar todas las rutinas de impresión para que trabajen con una dirección destino diferente en lugar de sobre $4000. Para que las rutinas sigan pudiendo utilizar los trucos de composición de dirección en base a desplazamientos de bits que vimos en capítulos anteriores lo normal es que busquemos una dirección de memoria libre cuyos 3 bits más altos ya no sean "010b" (caso de la videoram -> $4000 -> 0100000000000000b) sino, por ejemplo "110" ($c000). De esta forma se pueden alterar las rutinas fácilmente para trabajar sobre un área de 7KB equivalente a la videoram pero comenzando en $c000. |
| |
Por otra parte, si nos estamos planteando el usar una pantalla virtual simplemente para que no se vea el proceso de construcción de la pantalla, podemos ahorrarnos la pantalla virtual separando la rutina de impresión de pantalla en 2: una de impresión de gráficos y otra de impresión de atributos. Así, rellenamos el área de pantalla que aloja el mapa con atributos "cero" (negro), trazamos los datos gráficos (que no podrá ver el usuario) y después trazamos los atributos. Estos atributos podemos trazarlos directamente en pantalla tras un HALT, o en una "tabla de atributos virtual" de 768 que después copiaremos sobre el área de atributos. De esta forma utilizamos una pantalla virtual de 768 bytes en lugar de requerir 6912. | Por otra parte, si nos estamos planteando el usar una pantalla virtual simplemente para que no se vea el proceso de construcción de la pantalla, podemos ahorrarnos la pantalla virtual separando la rutina de impresión de pantalla en 2: una de impresión de gráficos y otra de impresión de atributos. Así, rellenamos el área de pantalla que aloja el mapa con atributos "cero" (negro), trazamos los datos gráficos (que no podrá ver el usuario) y después trazamos los atributos. Estos atributos podemos trazarlos directamente en pantalla tras un halt, o en una "tabla de atributos virtual" de 768 que después copiaremos sobre el área de atributos. De esta forma utilizamos una pantalla virtual de 768 bytes en lugar de requerir 6912. |
| |
| |