4. Vodorovne a zvisle ciary

   Minule sme si ukazali, ako sa da nakreslit nejaka vseobecna ciara. V praxi sa velmi casto vyskytuju aplikacie, v ktorych potrebujeme prave vodorovne a zvisle ciary. Linearny interpolator by sa sice v pohode dal pouzit aj na tento ucel (pretoze zvlada akekolvek ciary), ale bolo by to asi ako ist s kanonom na vrabca. Urcite sami uznate ze zdrzovat sa vypoctom kde bude lezat nasledujuci bod ked to uz v podstate vopred vieme, by sa nam urcite nepacilo. Preto by sme si mohli napisat dve rutinky, z ktorych jedna by kreslila len vodorovne a druha len zvisle ciary. Rutinky by boli vysoko optimalizovane na tento specialny ucel a nevedeli by nic ine. Tym by sme dosiahli ovela vyssiu rychlost kreslenia ako keby sme vsetky ciary kreslili klasickym linearnym interpolatorom.
   Lenze, to sa lahko povie (napise), ale ako to spravit ? Uz samotny interpolator je velmi efektivny, ved priamo s adresou a maskou pocita posunutie pre nasledujuci bod. Da sa to este vobec nejak zefektivnit ?
   Spravne tusite, ze keby sa nedalo, tak by som tuto otazku nekladol. Pametate si este na tu sialenu najrychlejsiu rutinku pre nakreslenie bodu ktora pozostava z jedinej instrukcie "ld (hl),a" ? Tak teraz vam ukazem, ze tento sposob kreslenia bodov nie je ani zdaleka najrychlejsi !
   Predstavte si, ze chceme nakreslit niekolko bodov vedla seba, ktorych bity dajme tomu lezia vsetky v jednom bajte vo videoramke. (Uz tusite kam mierim ?) Potom nam staci spravit logicky sucet masiek tychto bodov, vlozit ho do registra A, do HL este dame adresu tohto bajtu a zavolame tu nasu sedemtaktovu rutinku. Maximalny pocet bodov, ktore takto za sedem taktov mozeme nakreslit, je osem, co vychadza 0.875 taktu na nakreslenie jedneho bodu ! Nie je to uzasne ?
   Pravda, musi ale platit, ze tie body su v jednom bajte a tym vzhladom na usporiadanie videoramky lezia vodorovne vedla seba. Co keby sme to skusili nejak vyuzit pri kresleni vodorovnej ciary ?
   Tak teda skusme. Nasa rutinka "rovno" na kreslenie vodorovnych ciar najprv otestuje, ci sa obidva krajne body ciary nachadzaju v jednom bajte videoramky. Ak ano, vypocita masku pre vsetky body medzi nimi, a rovno vsetky tieto body jedinou instrukciou nakresli. Adresu tohto bajtu urci pomocou tabulky "tabbod". V pripade, ze sa krajne body nenachadzaju v tom istom bajte, vyrobi dve masky pre zakoncenia ciary, tie aplikuje na bajty s krajnymi bodmi ciary, a na vsetky bajty, ktore sa nachadzaju medzi bajtami s krajnymi bodmi, aplikuje masku 255.
   Pri kresleni zvislej ciary az tolko moznosti na optimalizaciu nemame. Na zaciatku musime pomocou tabulky "tabbod" urcit adresu a masku pre prvy bod ciary, potom v slucke kreslime jednotlive body pricom posun na dalsi bod urobime pomocou uz klasickej rutinky "dole". Este mozeme preskupit instrukcie a rutinku "dole" priamo vlozit do slucky (usetrime cas na call a ret).

tabbod #6000 
hitbod >tabbod 
   
run call mkbod 
 ld a,#01 
 call over 
 ld bc,#00 
 ld d,#ff 
 call rovno 
 ld bc,#1f00 
 ld d,#ff 
 call rovno 
 ld bc,#0100 
 ld d,#1e 
 call zvislo 
 ld bc,#01ff 
 ld d,#1e 
 call zvislo 
 ld bc,#0303 
 ld d,#fc 
 call rovno 
 ld bc,#1c03 
 ld d,#fc 
 call rovno 
 ld bc,#0403 
 ld d,#1b 
 call zvislo 
 ld bc,#04fc 
 ld d,#1b 
 jp zvislo 
   
over rrca  
 sbc a,a 
 and #18 
 xor #b6 
 ld (ooset1),a 
 ld (ooset2),a 
 ld (ooset3),a 
 ld (ooset4),a 
 ld (bodset),a 
 ret  
   
rovno ld a,d 
 cp 
 jr nc,rov01 
 ld d,c 
 ld c,a 
rov01 ld h,hitbod+2 
 ld l,c 
 ld a,(hl) 
 dec 
 ld l,b 
 or (hl) 
 dec 
 ld h,(hl) 
 ld l,a 
 ld a,c 
 and #f8 
 ld e,a 
 ld a,d 
 and #f8 
 cp 
 jr nz,r2byte 
 ld a,c 
 and #07 
 ld b,a 
 ld a,#ff 
 jr z,rov02 
rov03 srl 
 djnz rov03 
rov02 ld c,a 
rov99 ld a,d 
 and #07 
 ld b,a 
 ld a,#80 
 jr z,rov04 
rov05 scf  
 rra  
 djnz rov05 
rov04 and 
ooset1 xor (hl) 
 ld (hl),a 
 ret  
r2byte sub 
 rrca  
 rrca  
 rrca  
 ld e,a 
 ld a,c 
 and #07 
 ld b,a 
 ld a,#ff 
 jr z,ooset2 
rov06 srl 
 djnz rov06 
ooset2 xor (hl) 
 ld (hl),a 
 ld b,c 
 ld c,#ff 
rov40 inc 
 dec 
 jr z,rov99 
 ld a,c 
ooset3 xor (hl) 
 ld (hl),a 
 jr rov40 
   
zvislo ld a,d 
 cp 
 jr nc,zv2 
 ld d,b 
 ld b,a 
zv2 ld a,d 
 sub 
 ret 
 inc 
 ld d,a 
 ld h,hitbod+3 
 ld l,c 
 ld e,(hl) 
 dec 
 ld a,(hl) 
 dec 
 ld l,b 
 or (hl) 
 dec 
 ld h,(hl) 
 ld l,a 
 ld a,b 
zvis cpl  
 and #07 
 inc 
 ld b,a 
zv1 ld a,e 
ooset4 xor (hl) 
 ld (hl),a 
 inc 
 dec 
 ret 
 djnz zv1 
 ld b,#08 
 ld a,#20 
 add a,l 
 ld l,a 
 jr c,zv1 
 ld a,#f8 
 add a,h 
 ld h,a 
 jr zv1 

   Vstupne parametre do rutiniek "rovno" a "zvislo" su taketo: V registri BC sa vzdy nachadzaju suradnice jedneho krajneho bodu ciary (B=Y,C=X) a register D obsahuje suradnicu druheho bodu. V pripade "rovno" je to X suradnica a pri "zvislo" je to Y. Ako uz tradicne, rutinka "over" nastavuje sposob vykreslovania ciary a rutinka "run" je malicky priklad pouzitia tychto rutiniek.
   Skuseni optimalizatori urcite zbadaju dalsie moznosti ako este viac urychlit kreslenie vodorovnych a zvislych ciar. Napriklad rozvinutie slucky, rozvetvenie jednej univerzalnej casti na viacero specializovanejsich... Skuste nad tym pouvazovat.
   A co vas caka a menimie nabuduce ? Rotacny zemiakoid... Ale nie, nabuduce si budeme kreslit kruznice.

Vas Busy.

Nazad / back , predchadzajuca a dalsia lekcia