Abych nebyl uplne mimo tema tak jsem udelal relativne rychlou rutinu pro vykresleni spritu s maskou a ohlidanim orezani vpravo a dole.
Orezani shora jde provest pouhou spravne zvolenenou hodnotou v DE (protoze calc_sprite_address rutina neumi spocitat zaporne souradnice).
Orezani zleva je vetsi problem ale staci proste zmensit velikost spritu a nastavit zacatek spritu na spravnou posunutou hodnotu. Pokud je to vlevo tak ze se nic nezobrazi tak je to problem, musel by se trosku zmenit kod a rutina umet osetrit i zapornou velikost sirky spritu.
Sprity mohou mit v podstate neomezenou velikost (255*255)
Sprity jsou ulozeny a vykreslovany postupne zhora dolu po sloupcich. Sloupce jsou vykresleny zleva doprava.
Na atributy jsem se vykaslal, ale taky by to slo provest.
SCREEN_ADR equ $4000
ENTRY_POINT equ $8000
org ENTRY_POINT
start:
ld hl, alien8 ; adresa zdrojového bloku
ld de, 0x4000 ; adresa cílového bloku
ld bc, 32*(192+24) ; velikost přenášených dat
ldir ; provést blokový přenos
ld bc, 0x0001 ; x-ová souřadnice a y-ová souřadnice
call calc_sprite_address ; výpočet adresy spritu
call draw_my_sprite
ld bc, 0x0505 ; x-ová souřadnice a y-ová souřadnice
call calc_sprite_address ; výpočet adresy spritu
call draw_my_sprite
ld bc, 0x1E06 ; x-ová souřadnice a y-ová souřadnice
call calc_sprite_address ; výpočet adresy spritu
call draw_my_sprite
ld bc, 0x100E ; x-ová souřadnice a y-ová souřadnice
call calc_sprite_address ; výpočet adresy spritu
call draw_my_sprite
ld bc, 0x1F16 ; x-ová souřadnice a y-ová souřadnice
call calc_sprite_address ; výpočet adresy
call draw_my_sprite
ld bc, 0*256+14 ; 3:10 x-ová souřadnice*256+y-ová souřadnice
call calc_sprite_address ; 3:17 výpočet adresy
ld hl, SPRITE_ADR+1*(3*16) ; 3:10
ld bc, 0x0203 ; 3:10 šířka a výška spritu
call draw_sprite ; 3:17
ld de, 0x38F8 ; 3:10 adresa
call draw_my_sprite ; 3:17
ld de, 0x38C8 ; 3:10 adresa
call draw_my_sprite ; 3:17
jr $ ; žádný návrat do systému
calc_sprite_address:
; parametry:
; B - x-ová souřadnice (ve znacích, ne pixelech)
; C - y-ová souřadnice (ve znacích, ne pixelech)
;
; návratové hodnoty:
; DE - adresa pro zápis bloku
;
; vzor adresy:
; 0 1 0 Y4 Y3 0 0 0 | Y2 Y1 Y0 X4 X3 X2 X1 X0
ld a, c
and %00000111 ; pouze spodní tři bity y-ové souřadnice (řádky 0..7)
rrca
rrca
rrca ; nyní jsou čísla řádků v horních třech bitech
or b ; připočítat x-ovou souřadnici
ld e, a ; máme spodní bajt adresy
; Y2 Y1 Y0 X4 X3 X2 X1 X0
ld a, c ; y-ová souřadnice
and %00011000 ; dva bity s indexem "bloku" 0..3 (dolní tři bity už máme zpracovány)
or %01000000 ; "posun" do obrazové paměti (na 0x4000)
ld d, a ; máme horní bajt adresy
; 0 1 0 Y5 Y4 0 0 0
ret ; návrat z podprogramu
draw_my_sprite:
ld hl, SPRITE_ADR ; 3:10
ld bc, 3*256+3 ; 3:10 výška spritu v řádcích
; input:
; hl = adresa dat spritu
; de = adresa nulteho pixelradku znaku
; bc = šířka a výška spritu ve znacích
draw_sprite:
ld a, c ; 1:4
ld (draw_sprite_c), a ; 3:13
draw_sprite_same_high:
di ; 1:4
ld (draw_sprite_exit+1), sp ; 4:20
ld sp, hl ; 1:6 adresa, od níž začíná data a maska spritu
jr draw_sprite_init ; 2:12
draw_sprite_column: ; další sloupec
dec b ; 1:4
jr z, draw_sprite_exit ; 2:7/12
draw_sprite_de equ $+1
ld de, 0x0000 ; 3:10 předchozí začátek sloupce (šlo by použít i ix nebo stínový registr)
inc e ; 1:4 další sloupec
ld a, 0x1F ; 2:7
and e ; 1:4
jr z, draw_sprite_exit ; 2:7/12
draw_sprite_c equ $+1
ld c, 0x00 ; 2:7 výška spritu ve znacích
draw_sprite_init:
ld (draw_sprite_de), de ; 4:20
; input:
; sp = adresa dat spritu
; de = adresa nulteho pixelradku znaku
; b = šířka spritu ve znacích
; c = výška spritu ve znacích
draw_sprite_third:
ld a, d ; 1:4
cp 0x58 ; 2:7
sbc a, a ; 1:4
and d ; 1:4
ld d, a ; 1:4
draw_sprite_row:
pop hl ; 1:10 nultý pixelřádek
ld a, (de) ; 1:7
and h ; 1:4
xor l ; 1:4
ld (de), a ; 1:7
inc d ; 1:4
pop hl ; 1:10 první pixelřádek
ld a, (de) ; 1:7
and h ; 1:4
xor l ; 1:4
ld (de), a ; 1:7
inc d ; 1:4
pop hl ; 1:10 druhý pixelřádek
ld a, (de) ; 1:7
and h ; 1:4
xor l ; 1:4
ld (de), a ; 1:7
inc d ; 1:4
pop hl ; 1:10 třetí pixelřádek
ld a, (de) ; 1:7
and h ; 1:4
xor l ; 1:4
ld (de), a ; 1:7
inc d ; 1:4
pop hl ; 1:10 čtvrtý pixelřádek
ld a, (de) ; 1:7
and h ; 1:4
xor l ; 1:4
ld (de), a ; 1:7
inc d ; 1:4
pop hl ; 1:10 patý pixelřádek
ld a, (de) ; 1:7
and h ; 1:4
xor l ; 1:4
ld (de), a ; 1:7
inc d ; 1:4
pop hl ; 1:10 šestý pixelřádek
ld a, (de) ; 1:7
and h ; 1:4
xor l ; 1:4
ld (de), a ; 1:7
inc d ; 1:4
pop hl ; 1:10 sedmý pixelřádek
ld a, (de) ; 1:7
and h ; 1:4
xor l ; 1:4
ld (de), a ; 1:7
inc d ; 1:4
dec c ; 1:4
jr z, draw_sprite_column ; 2:7/12 další řádek?
ld a, e ; 1:4
add a, 0x20 ; 2:7
ld e, a ; 1:4
jr c, draw_sprite_third ; 2:7/12 další třetina?
ld a, d ; 1:4
sub 0x08 ; 2:7
ld d, a ; 1:4
jr draw_sprite_row ; 2:12
draw_sprite_exit:
ld sp, 0x0000 ; 3:10
ei ; 1:4
ret ; 1:10 návrat z podprogramu
SPRITE_ADR
; column 0
db %00000000, %11111111 ; 1
db %00000000, %11111110
db %00000001, %11111100
db %00000011, %11111000
db %00000101, %11110000
db %00000101, %11110000
db %00000101, %11110000
db %00000100, %11110000
db %00000111, %11110000 ; 2
db %00001100, %11100000
db %00011111, %11000000
db %00000000, %11100000
db %00000011, %11111000
db %00000101, %11110000
db %00001110, %11100000
db %00011000, %11000000
db %00011000, %11000000 ; 3
db %00000001, %11100100
db %00000011, %11111000
db %00000001, %11111100
db %00000010, %11111000
db %00000111, %11100000
db %00011110, %11000000
db %00000000, %11100001
; column 1
db %00000000, %11111111 ; 1
db %00000000, %00001111
db %11110000, %00000111
db %00111000, %00000000
db %11010111, %00000000
db %11001100, %00000000
db %00110000, %00000001
db %11001000, %00000001
db %00110110, %00000000 ; 2
db %11111110, %00000000
db %11111000, %00000000
db %00000000, %00000000
db %11111111, %00000000
db %11111110, %00000000
db %11111101, %00000000
db %11111100, %00000000
db %00000000, %00000011 ; 3
db %11111000, %00000011
db %11111100, %00000001
db %10110000, %00000011
db %00001100, %00000001
db %00001110, %01100000
db %00000111, %11110000
db %00000000, %11111000
; column 2
db %00000000, %11111111 ; 1
db %00000000, %11101111
db %00010000, %11000111
db %00010000, %11000111
db %00010000, %00000111
db %00010000, %11000111
db %00010000, %11000111
db %00010000, %11000111
db %00010000, %11000111 ; 2
db %00111000, %00000011
db %00000000, %00000111
db %00110000, %00000111
db %10110000, %00000111
db %11100000, %00001111
db %11000000, %00011111
db %00000000, %00111111
db %00000000, %11111111 ; 3
db %00000000, %11111111
db %00000000, %11111111
db %00000000, %11111111
db %00000000, %11111111
db %00000000, %01111111
db %10000000, %00111111
db %00000000, %01111111
alien8:
incbin Alien8.scr
end ENTRY_POINT
Upravil jsem tu rutinu pro vypocet adresy, aby zvladl i zaporne Y. Staci jen poprehazet trosku instrukce, takze ve vysledku to ma stejnou velikost i rychlost.
calc_sprite_address:
; parametry:
; B - x-ová souřadnice (ve znacích, ne pixelech)
; C - y-ová souřadnice (ve znacích, ne pixelech)
;
; návratové hodnoty:
; DE - adresa pro zápis bloku
;
; vzor adresy:
; 0 1 0 Y4 Y3 0 0 0 | Y2 Y1 Y0 X4 X3 X2 X1 X0
ld a, c
and %00000111 ; pouze spodní tři bity y-ové souřadnice (řádky 0..7)
rrca
rrca
rrca ; nyní jsou čísla řádků v horních třech bitech
or b ; připočítat x-ovou souřadnici
ld e, a ; máme spodní bajt adresy
; Y2 Y1 Y0 X4 X3 X2 X1 X0
ld a, c ; y-ová souřadnice
add a, %01000000 ; + 0x4000
and %11111000 ; dva bity s indexem "bloku" 0..3 (dolní tři bity už máme zpracovány)
ld d, a ; máme horní bajt adresy
; 0 1 0 Y5 Y4 0 0 0
ret ; návrat z podprogramu
Aby to zvladlo i zaporne X jsem to uz musel upravit vic. Prvne jsem musel uvolnit jeden 16 bitovy registr takze jsem upravit tu rutinu vstupni registry byly zaroven vystupni registry. Aby to slo musel jsem prohodit co drzi X a co Y.
calc_sprite_address:
; parametry:
; D - y-ová souřadnice (ve znacích, ne pixelech)
; E - x-ová souřadnice (ve znacích, ne pixelech)
;
; návratové hodnoty:
; DE - adresa pro zápis bloku
;
; vzor adresy:
; 0 1 0 Y4 Y3 0 0 0 | Y2 Y1 Y0 X4 X3 X2 X1 X0
ld a, d
and %00000111 ; pouze spodní tři bity y-ové souřadnice (řádky 0..7)
rrca
rrca
rrca ; nyní jsou čísla řádků v horních třech bitech
or e ; připočítat x-ovou souřadnici
ld e, a ; máme spodní bajt adresy
; Y2 Y1 Y0 X4 X3 X2 X1 X0
ld a, d ; y-ová souřadnice
add a, %01000000 ; + 0x4000
and %11111000 ; dva bity s indexem "bloku" 0..3 (dolní tři bity už máme zpracovány)
ld d, a ; máme horní bajt adresy
; 0 1 0 Y5 Y4 0 0 0
ret ; návrat z podprogramu
Tim jsem si uvolnnil BC pro velikost spritu a HL pro jeho adresu a ta rutina mohlo zjistovat zda je X zaporne a pokud je tak misto toho X vynulovat a zmensit velikost sirky a dat spritu.
calc_sprite_address:
; parametry:
; D - y-ová souřadnice (ve znacích, ne pixelech)
; E - x-ová souřadnice (ve znacích, ne pixelech)
;
; návratové hodnoty:
; DE - adresa pro zápis bloku
;
; vzor adresy:
; 0 1 0 Y4 Y3 0 0 0 | Y2 Y1 Y0 X4 X3 X2 X1 X0
; hl = adresa spritu
; bc = šířka a výška spritu ve znacích
ld a, e ; 1:4
or a ; 1:4
jp p, calc_sprite_address_pls ; 3:10
push de ; 1:11
ex de, hl ; 1:4
ld h, 0x00 ; 2:7
ld l, c ; 1:4
add hl, hl ; 1:11 2 * sprite vyska
add hl, hl ; 1:11 4 * sprite vyska
add hl, hl ; 1:11 8 * sprite vyska
add hl, hl ; 1:11 16* sprite vyska
ex de, hl ; 1:4
add hl, de ; 1:11 hl + a*sprite vyska*16
dec b ; 1:4
jr z, $+5 ; 2:7/12 cely sprite je vlevo mimo screen
inc a ; 1:4
jr nz, $-5 ; 2:7/12
pop de ; 1:10
ld e, a ; 1:4
or a ; 1:4
ret nz ; 1:5/11
calc_sprite_address_pls:
ld a, d
and %00000111 ; pouze spodní tři bity y-ové souřadnice (řádky 0..7)
rrca
rrca
rrca ; nyní jsou čísla řádků v horních třech bitech
or e ; připočítat x-ovou souřadnici
ld e, a ; máme spodní bajt adresy
; Y2 Y1 Y0 X4 X3 X2 X1 X0
ld a, d ; y-ová souřadnice
add a, %01000000 ; + 0x4000
and %11111000 ; dva bity s indexem "bloku" 0..3 (dolní tři bity už máme zpracovány)
ld d, a ; máme horní bajt adresy
; 0 1 0 Y5 Y4 0 0 0
ret ; návrat z podprogramu
Cely program co kresli teoreticky az 255 x 255 znaku spritu na souradnice XY -128 az +127:
SCREEN_ADR equ $4000
ENTRY_POINT equ $8000
org ENTRY_POINT
start:
if 0
ld hl, alien8 ; adresa zdrojového bloku
ld de, 0x4000 ; adresa cílového bloku
ld bc, 32*(192+24) ; velikost přenášených dat
ldir ; provést blokový přenos
endif
ld hl, 0x4000 ; adresa cílového bloku
ld (hl), l ;
ld de, 0x4001 ; adresa cílového bloku
ld bc, 32*192 ; velikost přenášených dat
ldir ; provést blokový přenos
ld (hl), %00111000 ;
ld bc, 32*24-1 ; velikost přenášených dat
ldir ; provést blokový přenos
check:
ld de, 256*1 +((0-3) & 255) ; 3:10 y-ová souřadnice a x-ová souřadnice (uplne mimo screen)
call draw_my_sprite ; 3:17
ld de, 256*6 +((0-2) & 255) ; 3:10 y-ová souřadnice a x-ová souřadnice
call draw_my_sprite ; 3:17
ld de, 256*11+((0-1) & 255) ; 3:10 y-ová souřadnice a x-ová souřadnice
call draw_my_sprite ; 3:17
ld de, 256*16+0 ; 3:10 y-ová souřadnice a x-ová souřadnice
call draw_my_sprite ; 3:17
ld de, 256*21+1 ; 3:10 y-ová souřadnice a x-ová souřadnice
call draw_my_sprite ; 3:17
ld de, 0x0505 ; 3:10 y-ová souřadnice a x-ová souřadnice
call draw_my_sprite ; 3:17
ld de, 0x061E ; 3:10 y-ová souřadnice a x-ová souřadnice
call draw_my_sprite ; 3:17
ld de, 0x0E10 ; 3:10 y-ová souřadnice a x-ová souřadnice
call draw_my_sprite ; 3:17
ld de, 0x161F ; 3:10 y-ová souřadnice a x-ová souřadnice
call draw_my_sprite ; 3:17
ld de, 256*(0-2)+8 ; 3:10 y-ová souřadnice a x-ová souřadnice
call draw_my_sprite ; 3:17
ld de, 256*(0-1)+24 ; 3:10 y-ová souřadnice a x-ová souřadnice
call draw_my_sprite ; 3:17
jr $ ; žádný návrat do systému
calc_sprite_address:
; parametry:
; D - y-ová souřadnice (ve znacích, ne pixelech)
; E - x-ová souřadnice (ve znacích, ne pixelech)
;
; návratové hodnoty:
; DE - adresa pro zápis bloku
;
; vzor adresy:
; 0 1 0 Y4 Y3 0 0 0 | Y2 Y1 Y0 X4 X3 X2 X1 X0
; hl = adresa spritu
; bc = šířka a výška spritu ve znacích
ld a, e ; 1:4
or a ; 1:4
jp p, calc_sprite_address_pls ; 3:10
push de ; 1:11
ex de, hl ; 1:4
ld h, 0x00 ; 2:7
ld l, c ; 1:4
add hl, hl ; 1:11 2 * sprite vyska
add hl, hl ; 1:11 4 * sprite vyska
add hl, hl ; 1:11 8 * sprite vyska
add hl, hl ; 1:11 16* sprite vyska
ex de, hl ; 1:4
add hl, de ; 1:11 hl + a*sprite vyska*16
dec b ; 1:4
jr z, $+5 ; 2:7/12 cely sprite je vlevo mimo screen
inc a ; 1:4
jr nz, $-5 ; 2:7/12
pop de ; 1:10
ld e, a ; 1:4
or a ; 1:4
ret nz ; 1:5/11
calc_sprite_address_pls:
ld a, d
and %00000111 ; pouze spodní tři bity y-ové souřadnice (řádky 0..7)
rrca
rrca
rrca ; nyní jsou čísla řádků v horních třech bitech
or e ; připočítat x-ovou souřadnici
ld e, a ; máme spodní bajt adresy
; Y2 Y1 Y0 X4 X3 X2 X1 X0
ld a, d ; y-ová souřadnice
add a, %01000000 ; + 0x4000
and %11111000 ; dva bity s indexem "bloku" 0..3 (dolní tři bity už máme zpracovány)
ld d, a ; máme horní bajt adresy
; 0 1 0 Y5 Y4 0 0 0
ret ; návrat z podprogramu
draw_my_sprite:
ld hl, SPRITE_ADR ; 3:10
ld bc, 3*256+3 ; 3:10 výška spritu v řádcích
call calc_sprite_address ; 3:17 výpočet adresy
; input:
; hl = adresa dat spritu
; de = adresa nulteho pixelradku znaku
; bc = šířka a výška spritu ve znacích
draw_sprite:
ld a, c ; 1:4
ld (draw_sprite_c), a ; 3:13
draw_sprite_same_high:
di ; 1:4
ld (draw_sprite_exit+1), sp ; 4:20
ld sp, hl ; 1:6 adresa, od níž začíná data a maska spritu
jr draw_sprite_init ; 2:12
draw_sprite_column: ; další sloupec
dec b ; 1:4
jr z, draw_sprite_exit ; 2:7/12
draw_sprite_de equ $+1
ld de, 0x0000 ; 3:10 předchozí začátek sloupce (šlo by použít i ix nebo stínový registr)
inc e ; 1:4 další sloupec
ld a, 0x1F ; 2:7
and e ; 1:4
jr z, draw_sprite_exit ; 2:7/12
draw_sprite_c equ $+1
ld c, 0x00 ; 2:7 výška spritu ve znacích
draw_sprite_init:
ld (draw_sprite_de), de ; 4:20
; input:
; sp = adresa dat spritu
; de = adresa nulteho pixelradku znaku
; b = šířka spritu ve znacích
; c = výška spritu ve znacích
draw_sprite_third:
ld a, d ; 1:4
cp 0x58 ; 2:7
sbc a, a ; 1:4
and d ; 1:4
ld d, a ; 1:4
draw_sprite_row:
pop hl ; 1:10 nultý pixelřádek
ld a, (de) ; 1:7
and h ; 1:4
xor l ; 1:4
ld (de), a ; 1:7
inc d ; 1:4
pop hl ; 1:10 první pixelřádek
ld a, (de) ; 1:7
and h ; 1:4
xor l ; 1:4
ld (de), a ; 1:7
inc d ; 1:4
pop hl ; 1:10 druhý pixelřádek
ld a, (de) ; 1:7
and h ; 1:4
xor l ; 1:4
ld (de), a ; 1:7
inc d ; 1:4
pop hl ; 1:10 třetí pixelřádek
ld a, (de) ; 1:7
and h ; 1:4
xor l ; 1:4
ld (de), a ; 1:7
inc d ; 1:4
pop hl ; 1:10 čtvrtý pixelřádek
ld a, (de) ; 1:7
and h ; 1:4
xor l ; 1:4
ld (de), a ; 1:7
inc d ; 1:4
pop hl ; 1:10 patý pixelřádek
ld a, (de) ; 1:7
and h ; 1:4
xor l ; 1:4
ld (de), a ; 1:7
inc d ; 1:4
pop hl ; 1:10 šestý pixelřádek
ld a, (de) ; 1:7
and h ; 1:4
xor l ; 1:4
ld (de), a ; 1:7
inc d ; 1:4
pop hl ; 1:10 sedmý pixelřádek
ld a, (de) ; 1:7
and h ; 1:4
xor l ; 1:4
ld (de), a ; 1:7
inc d ; 1:4
dec c ; 1:4
jr z, draw_sprite_column ; 2:7/12 další řádek?
ld a, e ; 1:4
add a, 0x20 ; 2:7
ld e, a ; 1:4
jr c, draw_sprite_third ; 2:7/12 další třetina?
ld a, d ; 1:4
sub 0x08 ; 2:7
ld d, a ; 1:4
jr draw_sprite_row ; 2:12
draw_sprite_exit:
ld sp, 0x0000 ; 3:10
ei ; 1:4
ret ; 1:10 návrat z podprogramu
SPRITE_ADR
; column 0
db %00000000, %11111111 ; 1
db %00000000, %11111110
db %00000001, %11111100
db %00000011, %11111000
db %00000101, %11110000
db %00000101, %11110000
db %00000101, %11110000
db %00000100, %11110000
db %00000111, %11110000 ; 2
db %00001100, %11100000
db %00011111, %11000000
db %00000000, %11100000
db %00000011, %11111000
db %00000101, %11110000
db %00001110, %11100000
db %00011000, %11000000
db %00011000, %11000000 ; 3
db %00000001, %11100100
db %00000011, %11111000
db %00000001, %11111100
db %00000010, %11111000
db %00000111, %11100000
db %00011110, %11000000
db %00000000, %11100001
; column 1
db %00000000, %11111111 ; 1
db %00000000, %00001111
db %11110000, %00000111
db %00111000, %00000000
db %11010111, %00000000
db %11001100, %00000000
db %00110000, %00000001
db %11001000, %00000001
db %00110110, %00000000 ; 2
db %11111110, %00000000
db %11111000, %00000000
db %00000000, %00000000
db %11111111, %00000000
db %11111110, %00000000
db %11111101, %00000000
db %11111100, %00000000
db %00000000, %00000011 ; 3
db %11111000, %00000011
db %11111100, %00000001
db %10110000, %00000011
db %00001100, %00000001
db %00001110, %01100000
db %00000111, %11110000
db %00000000, %11111000
; column 2
db %00000000, %11111111 ; 1
db %00000000, %11101111
db %00010000, %11000111
db %00010000, %11000111
db %00010000, %00000111
db %00010000, %11000111
db %00010000, %11000111
db %00010000, %11000111
db %00010000, %11000111 ; 2
db %00111000, %00000011
db %00000000, %00000111
db %00110000, %00000111
db %10110000, %00000111
db %11100000, %00001111
db %11000000, %00011111
db %00000000, %00111111
db %00000000, %11111111 ; 3
db %00000000, %11111111
db %00000000, %11111111
db %00000000, %11111111
db %00000000, %11111111
db %00000000, %01111111
db %10000000, %00111111
db %00000000, %01111111
alien8:
incbin Alien8.scr
end ENTRY_POINT
PS: Ten Alien8 screen ma bohuzel 20 radek nastaven jak paper tak ink na nulu. Takze to testuji na bile plose.