Názory k článku Vývoj her a dem pro ZX Spectrum: vlastní vykreslovací subrutiny podruhé

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

    Ratbatcat

    Jak vidim u clanku autor Pavel Tisnovsky tak vim, ze pujde znova o kvalitni cteni. Obsah, zpracovani, odkazy, proste na vybornou! Dekuji!

  • 9. 3. 2023 22:52

    Calculon

    Svatá pravda. Navíc u tohoto tématu článek vylepšuje ještě nostalgie (aspoň u mé generace, která vyrůstala na osmibitech).

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

  • 9. 3. 2023 12:40

    Korporátní lopata

    Je to možné řešení, ale v tomhle případě se předává obsah registrů A, DE a přepnutím do alternativní sady příjdeme o obsah DE.

  • 9. 3. 2023 8:08

    _dw

    Mozna se to makro mohlo jmenovat spis LD_DE_XYAddr...

    A jen pro srandu si vyzkouset malou upravu tisku

    loop:
        ld    a,(hl)             ; načtení jednoho bajtu z masky
    bolt
      ifdef bolt
        add  A,A
        or  (hl)
      endif
        ld  (de),a               ; zápis hodnoty na adresu (DE)

    9. 3. 2023, 08:09 editováno autorem komentáře

  • 9. 3. 2023 16:52

    Pavel Tišnovský
    Zlatý podporovatel

    Jojo, od příště už je nutný popisovat parametry, návratové hodnoty a "zničené" registry. Jinak s tím, kdo bude uchovávat hodnoty registrů mám pořád "ideovou" potíž :) Někdy prostě ta rutina bude dělat push/pop naprosto zbytečně, ale obecně je samozřejmě lepší, když registry uchovává (a potom je otázka, co s příznaky). Na MOS 6502 takové problémy nejsou...

  • 9. 3. 2023 18:58

    _dw

    Je to slozitejsi nez to na prvni pohled vypada... .)

    Doslo me, ze uz FORTHu si mohu dovolit vetsi volnost jen diky tomu ze v kodu nikde nejsou fce co vraceji priznaky, nebo fce co vraceji 8 bitovou hodnotu v A.
    Proste FORTH kdyz porovna neco, tak si ulozi hodnotu TRUE (-1) nebo FALSE (0) do 16 bitoveho registru (TOS) a pak se s tim dale pracuje. Nastesti to neni tak strasne, jak to vypada, protoze prekladac je schopen odchytit vetsinu techto slov a spojit je do nejakeho celku.

    Misto

    EQ IF

    vygeneruje spojene slovo

    EQ_IF, ktery vnitrne pouzije ten priznak co ma procesor na kterem ten forth pobezi. EQ ktery ulozi TRUE/FALSE na TOS a IF ktery ho teprve vyzvedne je virtualni zpusob jak je FORTH navrzen a to neni nic proti FORTHu. A ani to neni nic proti Z80, jen to jen problem prekladace, ze musi najit spravny zpusob jak to prevest do instrukci Z80.

    Slova (spojeni slov ) jsou pak neco jako inline fce a ja pak nemusim nic resit. Jen si uhlidat HL (TOS), DE (NOS) a HL' (RAS).

    V beznem asembleru mit tohle bude uz horsi, bude fakt zalezet jak si definujes v cem se ti budou slova vracet a dokonce jestli budes kombinovat 1, 8 a 16 bitove vstupy/vystupy.

    Ani mit A pouzity pro 8 bitovy vstup/vystup neni zadna slava pokud musis ochranovat F.

    A ani neplati vzdy ze je vhodnejsi mit PUSH + POP reseny v ramci fce (skoro neco jako pascalova konvence.. .) )

    Kdyz bude ta fce typu SWITCH... a ty v kazde vetvi budes muset delat POP POP POP... Tak se to vyplati delat v tom volani. Pripadne to obalit v dalsi fci a teprve tu volat.

    Je to cele uplna dzungle i kdyz muzou existovat nejaka optimalni pravidla, tak ne vzdy se vyplati. Neco jako je v sachu pozicni a kombinacni hra. Nektere pozice jsou nebezpecne na ne na prvni pohled viditelne kombinace, kde nic neplati vsechno si musis spocitat. Takze se nemuzeme drzet jen pozicnich pravidel i kdyz ty nam mohou hodne pomoct.
    Nebo je to asi stejny chaos jako formalni a kontextove gramatiky. To by musel rici nekdo kdo informatiku studoval. .)

    PS: Nastesti vetsinou plati, ze problem je na ZX skoro vzdy velikost kodu/grafiky a ne rychlost procesoru. Ja bych treba rutinu pro tisk znaku nerozbaloval. A kdybych musel tak prvne zkusil misto 8 cyklu mit 4 cykly. Proto preferuji mit mene PUSH POPu ve funkci nez mit vice, jen okolo volani kde je to nutne.

    Pak jsou tu nektere veci co za me resi proste makro (M4)

    Potrebuji nahrat do osmibitoveho registru nejakou konstantu? Ok. necham si to vygenerovat makrem, do ktereho jsou vstupy jake hodnoty/konstanty maji ostatni registry. A on najde tu spravnou variantu. Zmeni se nekde konstanta? Nevadi, nic nemusim menit, vygeneruje se jiny kod.

    9. 3. 2023, 18:59 editováno autorem komentáře

  • 9. 3. 2023 18:16

    _dw

    Ted jsem si teprve uvedomil, ze v te rutine draw_char je skryta vada. Protoze adresa fontu je zapsana pres promennou CHAR_ADR, aby tam nebyla magic cisla... .)

    Pak tam nemuzeme natvrdo prirazovat do registru H registr C s tim, ze je tam nula. Protoze to tak uz nemusi byt. Kdybych potreboval zmenit fonty a videl na zacatku ze staci zmenit CHAR_ADR a je hotovo, tak bych mozna ani neprochazel kod a nehledal vyskyty, protoze kdyz to vytknu tak to mohu menit.

    Spravne by to melo bys nejak takto:

    ;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ů
      if CHAR_ADR & 255
          .warning Pouzivas adresu fontu nezarovnanou na segment, to neni nejlepsi napad.
        ld    h, 0x00            ; C je nulové, protože CHAR_ADR=0x3c00
      else
        ld    h, c               ; C je nulové, protože CHAR_ADR=0x..00
      endif
        ld    l, a               ; kód znaku je nyní ve dvojici HL

    K Atarist, muzes to mit ve stinovych registrech, ale taky to neco bude stat. Nejhorsi na tomhle je, ze dopredu nevis co vsechno budes jeste potrebovat. Muzes to delat i tak, ze to budes neustale prepisovat v prubehu jak se budou pozadavky menit a dokud te to bude bavit. (nastesti retroprogramovani je jen hobby programovani).

    Kdyz se kouknes co to dela ted, a jestli je to uzitecne... tak to zatim neni lepsi nez pouzit ROM rutinu pro me. Tam budes mit jen problem s poslednim radkem (predposledni se da osetrit zmenou jedne ROM promenne).

    Tiskneme font v matici 8x8 a nemenime atributy, takze je jasne kam by se to vyvijelo dal. A pokud chceme tisknout atributy, ma smysl to na zacatku pozicovat jako XY? Neni to lepsi pozicovat rovnou jako adresu atributu?

    Pak potrebuji jinou rutinu calc_char_address. To uz nekdo musel resit... .)

    0x5800..0x5AFF
    -->
    0x4000..0x57FF

    00 01 00 11 11 00 Y5 Y4 Y3 Y2 Y1 X5 X4 X3 X2 X1
    -->
    00 01 00 Y5 Y4 00 00 00 Y3 Y2 Y1 X5 X4 X3 X2 X1

    Vypada to, ze to staci segment vynasobit osmi a invertovat 7.bit/vynulovat 7. bit/pricist 0x80.

                   ;[7:27]
    ld    A, ?     ; 1:4
    add   A, A     ; 1:4    2x
    add   A, A     ; 1:4    4x
    add   A, A     ; 1:4    8x
    xor  0x80      ; 2:7
    ld    ?, A     ; 1:4
    
    Varianta pokud neni volne A
                   ;[8:32]
    sla   D        ; 2:8    2x
    sla   D        ; 2:8    4x
    sla   D        ; 2:8    8x
    res   7, D     ; 2:8

    Kod upraveny tak, aby dekodoval v retezci nektere specialni znaky "\n", AT, ink, paper, flash, bright.

    SCREEN_ADR      equ $4000
    CHAR_ADR        equ $3c00
    ENTRY_POINT     equ $8000
    ATTR_T          equ $5C8F
    
    ZX_EOL          equ 0x0D     ; zx_constant   end of line
    
    ZX_INK          equ 0x10     ; zx_constant   colour
    ZX_PAPER        equ 0x11     ; zx_constant   colour
    ZX_FLASH        equ 0x12     ; zx_constant   0 or 1
    ZX_BRIGHT       equ 0x13     ; zx_constant   0 or 1
    ZX_AT           equ 0x16     ; zx_constant   Y,X
    
    ZX_BLUE              EQU %001     ; zx_constant
    ZX_YELLOW            EQU %110     ; zx_constant
    
    
             org ENTRY_POINT
    
    ; Input: x = 0..31
    ;        y = 0..23
    ; Output:
    ;     ld de, 0x4000 + ((0x1F & y ) << 5) + ( 0x1F & x )
    LD_R_XY2addr MACRO _r, _x, _y
        ld _r, 0x5800+((31&(_y))<<5)+(31&(_x))
    ENDM
    
    start:
        LD_R_XY2addr DE,15,12
        ld   HL, TEXT           ; 3:10    adresa prvního znaku v řetězci
    ;    call print_string       ; 3:17    tisk celého řetězce
    
    finish:
    ;    jr finish               ; 2:12    žádný návrat do systému
    
    
    print_string:
        ld    A,(ATTR_T)        ; 3:13
        ld    C, A              ; 1:4
    print_string_l:
        ld    A, (HL)           ; 1:7     načíst kód znaku z řetězce
        inc   HL                ; 1:6     přechod na další znak
    
        cp  0x20                ; 2:7
        call nc, draw_char      ; 3:10/17
        jr   nc, print_string_l ; 2:12    na další znak
    
        or    A                 ; 1:4     test na kód znak s kódem 0
        ret   z                 ; 1:5/11  ukončit podprogram na konci řetězce
    
        call print_set          ; 3:17
        jr   print_string_l     ; 2:12    na další znak
    
    ; Input: A = spec char
    print_set:
        sub  ZX_EOL             ; 2:7
        ret   c                 ; 1:5/11
        jr  nz, print_set_ink   ; 2:7/12
    
        ld    A, 0x1F           ; 2:7
        or    E                 ; 1:4
        ld    E, A              ; 1:4     nastaveni X na 31
        inc  DE                 ; 1:6     prechod na dalsi radek
        ret                     ; 1:10
    print_set_ink:
        sub  ZX_INK-ZX_EOL      ; 2:7
        jr   nz, print_set_paper; 2:7/12
    
        ld    A, C              ; 1:4
        and 0xF8                ; 2:7
        or  (HL)                ; 1:7
        inc  HL                 ; 1:6     přechod na další znak
        ld    C, A              ; 1:4     save new ink
    
        ret                     ; 1:10
    print_set_paper:
        dec   A                 ; 1:4
        jr   nz, print_set_flash; 2:7/12
    
        ld    A,(HL)            ; 1:7
        inc  HL                 ; 1:6     přechod na další znak
        add   A, A              ; 1:4     2x
        add   A, A              ; 1:4     4x
        add   A, A              ; 1:4     8x
        xor   C                 ; 1:4
        and 0x38                ; 2:7
        xor   C                 ; 1:4
        ld    C, A              ; 1:4     save new paper
    
        ret                     ; 1:10
    print_set_flash:
        dec   A                 ; 1:4
        jr   nz, print_set_brig ; 2:7/12
    
        ld    A, C              ; 1:4
        add   A, A              ; 1:4
        or   (HL)               ; 1:7
        inc  HL                 ; 1:6     přechod na další znak
        rrca                    ; 1:4
        ld    C, A              ; 1:4     save new flash
    
        ret                     ; 1:10
    print_set_brig:
        dec   A                 ; 1:4
        jr   nz, print_set_at   ; 2:7/12
    
        ld    A,(HL)            ; 1:7
        inc  HL                 ; 1:6     přechod na další znak
        rrca                    ; 1:4
        rrca                    ; 1:4
        xor   C                 ; 1:4
        and 0x40                ; 2:7
        xor   C                 ; 1:7
        ld    C, A              ; 1:4     save new bright
    
        ret                     ; 1:10
    print_set_at:
        sub  ZX_AT-ZX_BRIGHT    ; 1:4
        ret  nz                 ; 1:5/11
    
        ld    A,(HL)            ; 1:7     new y
        inc  HL                 ; 1:6     přechod na další znak
        ld    D, 0x16           ; 2:7
        add   A, A              ; 1:4
        add   A, A              ; 1:4
        add   A, A              ; 1:4
        add   A, A              ; 1:4
        rl    D                 ; 2:8
        add   A, A              ; 1:4
        rl    D                 ; 2:8
        xor (HL)                ; 1:7     new x
        inc  HL                 ; 1:6     přechod na další znak
        ld    E, A              ; 1:4
    
        ret                     ; 1:10
    
    
    ;  Input: A = char, DE = address, C = attr
    ; Output: DE = adress next char (overflow DE=0x5800)
    ; Poluttes: none
    draw_char:
    
        push AF                 ; 1:11    uschovat AF na zásobník
        push BC                 ; 1:11    uschovat BC na zásobník
        push HL                 ; 1:11    uschovat HL na zásobník
    
        ld    L, A              ; 1:4     kód znaku do L
        ld    A, C              ; 1:4
        ld  (DE),A              ; 1:7     uložení atributu znaku
    
        ld    BC, CHAR_ADR      ; 3:10    adresa, od níž začínají masky znaků
      if CHAR_ADR & 255
          .warning Pouzivas adresu fontu nezarovnanou na segment, to neni nejlepsi napad.
        ld    H, 0x00           ; 1:4     C je nenulové
      else
        ld    H, C              ; 1:4     C je nulové, protože CHAR_ADR=0x..00
      endif
    
        add  HL, HL             ; 1:11    2x
        add  HL, HL             ; 1:11    4x
        add  HL, HL             ; 1:11    8x
        add  HL, BC             ; 1:11    přičíst bázovou adresu masek znaků
    
        ld    B, 8              ; 2:7     počitadlo zapsaných bajtů
    
        ld    C, D              ; 1:4     uschovat D
        sla   D                 ; 2:8     2x
        sla   D                 ; 2:8     4x
        sla   D                 ; 2:8     8x
        res   7, D              ; 2:8
    loop:
        ld    A,(HL)            ; 1:7     načtení jednoho bajtu z masky
        ld  (DE),A              ; 1:7     zápis hodnoty na adresu (DE)
        inc   L                 ; 1:4     posun na další bajt masky (nemusíme řešit přetečení do vyššího bajtu)
        inc   D                 ; 1:4     posun na definici dalšího obrazového řádku
        djnz loop               ; 2:8/13  vnitřní smyčka: blok s osmi zápisy
        ld    D, C              ; 1:4     obnovit obsah D
        inc  DE                 ; 1:6
        pop  HL                 ; 1:10    obnovit obsah HL ze zásobníku
        pop  BC                 ; 1:10    obnovit obsah BC ze zásobníku
        pop  AF                 ; 1:10    obnovit obsah AF ze zásobníku
        ret                     ; 1:10    DE+=1
    
    ; nulou ukončený řetězec
    TEXT:   db "Hello, Speccy!", 0x0D,"dalsi radek na ",ZX_PAPER, ZX_YELLOW, "zlute...", ZX_AT,0,0,"pocatek", ZX_INK, ZX_BLUE," modrou!",ZX_AT,7,13,"ZX_AT 7,13 bright: ",ZX_BRIGHT,1,"ON",ZX_BRIGHT,0," OFF",ZX_AT,23,3,"ZX_AT 23,3 FLASH: ",ZX_FLASH,1,"ON",ZX_FLASH,0,"OFF",0

    Stoji tam za povsimnuti jak je udelana ta SWITCH..CASE cast. Je to vnoreno do funkce aby se vyskakovalo pres RET. Hodnota podle ktere se to rozhoduje je v A a pokud mezi sebou vetve jsou vzdaleny jen o 1 tak staci "DEC A".

    9. 3. 2023, 18:19 editováno autorem komentáře

  • 11. 3. 2023 0:54

    _dw

    Pridal jsem pro srandu nejakych devet fontu vypocitavanych z fontu romky a udelal jeste podporu pro OVER a INVERSE (to nema ale parametr, proste jen prohodi ink a paper).

    obrazek jsem hodil na https://imgbox.com/tAUffQw9
    zdrojak na https://pastebin.com/f6zCPL37

    Neni to zrovna optimalizovano na rychlost... Protoze se pro kazdy bajt z osmi znaku vola podrutina... Asi by bylo lepsi jen omezit pocet fontu na nejake rozumne a tu smycku mit v podrutine.

    Jinak treba ten font pod Hello,Speccy se pocita proste tak ze se najde posledni jednickovy bit a ten se zkopituje doprava. Hleda se trikem

    dec A
    xor Original
    and Original

    11. 3. 2023, 00:59 editováno autorem komentáře