Odpověď na názor

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í.

  • Článek je starý, nové názory již nelze přidávat.
  • 9. 3. 2023 7:13

    _dw

    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...