Odpovídáte na názor k článku Vývoj her a dem pro ZX Spectrum: vlastní vykreslovací subrutiny podruhé. Názory mohou přidávat pouze registrovaní uživatelé. Nově přidané názory se na webu objeví až po schválení redakcí.
Diky za clanek. Dnes to bylo pro me fakt prekvapeni cist... .)
Skoda jen ze u toho prikladu v kapitole 14. se to nedotahlo do konce.
Myslim tim ze pokud potrebuji nejak uklizet u fce tak osobne preferuji kdyz to dela primo ta funkce sama jednou a ne pokazde kdyz je volana. Takze kdyz uz to ma byt trochu prakticke tak bych uchovaval jak HL tak BC. A to zrovna u BC neni tak snadne a bude to stat instrukci navic. Uchranit AF by bylo jeste drazsi...
Mozna jeste dulezitejsi vec je si u kazde rutiny psat jaky to ma vstupy a jaky vystupy a i co to zmeni. Je to prace navic, ale pak kdyz neco pouzijeme tak si staci nastudovat tu prvni rutinu a ne hledat co to dela a co to vola a rekurzivne hledat dale...
Dale stoji za uvahu jak je to s tou funkci co prepocitava XY na adresu, zda ji nepouzivame nahodou jen kvuli prehlednosti a nedavame tam konstanty jako ted. Co to dat do makra. Neni to zrovna co bych preferoval, protoze se staneme trochu zavisly na preklaci (pasmu).
SCREEN_ADR equ $4000
CHAR_ADR equ $3c00
ENTRY_POINT equ $8000
org ENTRY_POINT
start:
ld b, 15 ; x-ová souřadnice
ld c, 12 ; y-ová souřadnice
call calc_char_address ; výpočet adresy
ld hl, TEXT ; adresa prvního znaku v řetězci
call print_string ; tisk celého řetězce
finish:
jr finish ; žádný návrat do systému
calc_char_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
print_string:
ld a, (hl) ; načíst kód znaku z řetězce
and a ; test na kód znak s kódem 0
ret Z ; ukončit podprogram na konci řetězce
call draw_char ; tisk jednoho znaku
inc hl ; přechod na další znak
jr print_string ; na další znak
; Input: A = char, DE = address
; Output: DE = adress next char, zero flag for x,y=0,8;0,16;0,24(overflow DE=0x5800)
; Poluttes: AF
draw_char:
push hl ; uschovat HL na zásobník
push bc ; uschovat BC na zásobník
ld bc, CHAR_ADR ; adresa, od níž začínají masky znaků
ld h, c ; C je nulové, protože CHAR_ADR=0x3c00
ld l, a ; kód znaku je nyní ve dvojici HL
add hl, hl ; 2x
add hl, hl ; 4x
add hl, hl ; 8x
add hl, bc ; přičíst bázovou adresu masek znaků
ld b, 8 ; počitadlo zapsaných bajtů
ld c, d
loop:
ld a,(hl) ; načtení jednoho bajtu z masky
ld (de),a ; zápis hodnoty na adresu (DE)
inc l ; posun na další bajt masky (nemusíme řešit přetečení do vyššího bajtu)
inc d ; posun na definici dalšího obrazového řádku
djnz loop ; vnitřní smyčka: blok s osmi zápisy
inc e
ld a, c
pop bc ; obnovit obsah BC ze zásobníku
pop hl ; obnovit obsah HL ze zásobníku
ret z ; D+=8,E=E+1=0
ld d, a
ret ; D=D,E=E+1
; nulou ukončený řetězec
TEXT: db "Hello, Speccy!", 0
end ENTRY_POINT
Makra se v pasmu delaji dvema zpusoby a jeden je:
; Input: x = 0..31
; y = 0..23
; Output:
; ld de, 0x4000 + ((0x18 & y) << 8) + ((0x07 & y ) << 5) + ( 0x1F & x )
XY_2_DE_addr MACRO _x, _y
ld de, 0x4000+((24&(_y))<<8)+((7&(_y))<<5)+(31&(_x))
ENDM
XY_2_DE_addr 15,12
Takze kod pak muze vypadat i takto:
kompilace pres:
sjasmplus input.asm --raw=output.bin
tady nic krome labelu (vcetne equ) nesmi zacinat na novem radku
nebo:
pasmo -d input.asm output.bin
SCREEN_ADR equ $4000
CHAR_ADR equ $3c00
ENTRY_POINT equ $8000
org ENTRY_POINT
; Input: x = 0..31
; y = 0..23
; Output:
; ld de, 0x4000 + ((0x18 & y) << 8) + ((0x07 & y ) << 5) + ( 0x1F & x )
XY_2_DE_addr MACRO _x, _y
ld de, 0x4000+((24&(_y))<<8)+((7&(_y))<<5)+(31&(_x))
ENDM
start:
XY_2_DE_addr 15, 12
ld hl, TEXT ; adresa prvního znaku v řetězci
; call print_string ; tisk celého řetězce
finish:
; jr finish ; žádný návrat do systému
if 0
calc_char_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
endif
print_string:
ld a, (hl) ; načíst kód znaku z řetězce
and a ; test na kód znak s kódem 0
ret Z ; ukončit podprogram na konci řetězce
call draw_char ; tisk jednoho znaku
inc hl ; přechod na další znak
jr print_string ; na další znak
; Input: A = char, DE = address
; Output: DE = adress next char, zero flag for x,y=0,8;0,16;0,24(overflow DE=0x5800)
; Poluttes: AF, BC
;draw_char_save_bc
draw_char:
push hl ; uschovat HL na zásobník
ifdef draw_char_save_bc
push bc ; uschovat BC na zásobník
endif
ld bc, CHAR_ADR ; adresa, od níž začínají masky znaků
ld h, c ; C je nulové, protože CHAR_ADR=0x3c00
ld l, a ; kód znaku je nyní ve dvojici HL
add hl, hl ; 2x
add hl, hl ; 4x
add hl, hl ; 8x
add hl, bc ; přičíst bázovou adresu masek znaků
ld b, 8 ; počitadlo zapsaných bajtů
ld c, d
loop:
ld a,(hl) ; načtení jednoho bajtu z masky
ld (de),a ; zápis hodnoty na adresu (DE)
inc l ; posun na další bajt masky (nemusíme řešit přetečení do vyššího bajtu)
inc d ; posun na definici dalšího obrazového řádku
djnz loop ; vnitřní smyčka: blok s osmi zápisy
inc e
ifdef draw_char_save_bc
ld a, c
pop bc ; obnovit obsah BC ze zásobníku
pop hl ; obnovit obsah HL ze zásobníku
ret z ; D+=8,E=E+1=0
ld d, a
else
pop hl ; obnovit obsah HL ze zásobníku
ret z ; D+=8,E=E+1=0
ld d, c
endif
ret ; D=D,E=E+1
; nulou ukončený řetězec
TEXT: db "Hello, Speccy!", 0
Vysledek ma pouze 54 bajtu z puvodnich 78.
Jeste jsem tam teda udelal zase nejake neciste triky s propadavanim do fci...