Vlákno názorů k článku Vykreslování spritů a animací na ZX Spectru od _dw - Z kapitoly 7: Poznámka2: dokážete přijít na to, za...

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

    _dw

    Z kapitoly 7:
    Poznámka2: dokážete přijít na to, za jakých podmínek a zda vůbec NEbude vykreslovací rutina korektní?

    Moje reseni: Emork ohot ez es ejurtesoen yndaz z ujarko ykvozarbo, kat ot etsej ezles v udohcerp nitert a ot zu ej aklev teslob, ezotorp yt ejarko es ijad tiser i mit ez es ilserkyv avon akvozarbo. Ela aretkolam arh am ukvozarbo nej rtinvu ynitert.

    Jinak ten kod:

    draw_sprite:
            ld hl, SPRITE_ADR        ; 3:10 adresa, od níž začíná maska spritu
            push de                  ; 1:11
            call draw_8_lines        ; 3:17 vykreslit prvních 8 řádků spritu
    
            pop  de                  ; 1:10
            add_e 32                 ; 3:15 zvýšit E o hodnotu 32
            push de                  ; 1:11
            call draw_8_lines        ; 3:17 vykreslit druhých 8 řádků spritu
    
            pop  de                  ; 1:10
            add_e 32                 ; 3:15 zvýšit E o hodnotu 32
            call draw_8_lines        ; 3:17 vykreslit třetích 8 řádků spritu
    
            ret                      ; 1:10 návrat z podprogramu
                                    ;[23:143]
    
    draw_8_lines:
            ld b, 8                  ; 2:7          počitadlo zapsaných řádků
    
    loop:
            ld  a,(hl)               ; 1:7          načtení jednoho bajtu z masky
            ld  (de),a               ; 1:7          zápis hodnoty na adresu (DE)
            inc hl                   ; 1:6          posun na další bajt masky
            inc e                    ; 1:4
    
            ld  a,(hl)               ; 1:7          načtení jednoho bajtu z masky
            ld  (de),a               ; 1:7          zápis hodnoty na adresu (DE)
            inc hl                   ; 1:6          posun na další bajt masky
            inc e                    ; 1:4
    
            ld  a,(hl)               ; 1:7          načtení jednoho bajtu z masky
            ld  (de),a               ; 1:7          zápis hodnoty na adresu (DE)
            inc hl                   ; 1:6          posun na další bajt masky
    
            inc d                    ; 1:4          posun na definici dalšího obrazového řádku
            dec e                    ; 1:4          korekce - posun zpět pod první osmici pixelů
            dec e                    ; 1:4          dtto
            djnz loop                ; 2:13/8       vnitřní smyčka: blok s 3x osmi zápisy
            ret                      ; 1:10         návrat z podprogramu
                                    ;[19:756=7+8*93-5+10]

    By sel napsat rychleji a mensi:

    draw_sprite:
       ...
                                    ;[23:143]
    
    draw_8_lines:
            ld  bc, 8*(256+2)        ; 3:10         počitadlo zapsaných řádků
    loop:
            ldi                      ; 2:16         [DE++] = [HL++]; BC--
            ldi                      ; 2:16         [DE++] = [HL++]; BC--
            ld  a,(hl)               ; 1:7          načtení jednoho bajtu z masky
            ld  (de),a               ; 1:7          zápis hodnoty na adresu (DE)
            inc hl                   ; 1:6          posun na další bajt masky
            dec e                    ; 1:4          korekce
            dec e                    ; 1:4          korekce
            inc d                    ; 1:4          posun na definici dalšího obrazového řádku
            djnz loop                ; 2:13/8       vnitřní smyčka: blok s 3x osmi zápisy
            ret                      ; 1:10         návrat z podprogramu
                                    ;[16:631=10+8*77-5+10]

    A pokud by me restit i ten zasadni problem s korektnosti tak by sel udelat jeste mensi, pokud bude automaticky vracet spravne nastavene DE.

    draw_sprite:
            ld hl, SPRITE_ADR        ; 3:10         adresa, od níž začíná maska spritu
            call draw_8_lines        ; 3:17         vykreslit prvních 8 řádků spritu
            call draw_8_lines        ; 3:17         vykreslit druhých 8 řádků spritu
            call draw_8_lines        ; 3:17         vykreslit třetích 8 řádků spritu
            ret                      ; 1:10         návrat z podprogramu
                                    ;[13:71]
    
    draw_8_lines:
            ld  bc, 8*(256+2)        ; 3:10         počitadlo zapsaných řádků
    loop:
            ldi                      ; 2:16         [DE++] = [HL++]; BC--
            ldi                      ; 2:16         [DE++] = [HL++]; BC--
            ld  a,(hl)               ; 1:7          načtení jednoho bajtu z masky
            ld  (de),a               ; 1:7          zápis hodnoty na adresu (DE)
            inc hl                   ; 1:6          posun na další bajt masky
            dec e                    ; 1:4          korekce
            dec e                    ; 1:4          korekce
            inc d                    ; 1:4          posun na definici dalšího obrazového řádku
            djnz loop                ; 2:13/8       vnitřní smyčka: blok s 3x osmi zápisy
            ld  a, e                 ; 1:4
            add a, 32                ; 2:7
            ld  e, a                 ; 1:4
            ret c                    ; 1:5/11
            ld  a, d                 ; 1:4
            sub 8                    ; 2:7
            ld  d, a                 ; 1:4
            ret                      ; 1:10         návrat z podprogramu
                                    ;[25:647/666 =10+8*77-5+26/10+8*77-5+45]

    A kdyz uz spamuji tak rovnou pridam muj skript nakompilaci asm zdrojaku a rovnou spusteni v emulatoru. S tim ze jde parametrem i menit adresa na jakou se to zkompiluje. Staci mit v kodu neco jako:

    ifdef __ORG
      org __ORG
    else
      org 0x8000
    endif

    kde 0x8000 je default ale skript nastavuje __ORG kdyz mu ho zadate. Tim mu i reknete ze to ma spustit v emulatoru a nejen kompilovat binarku.

    Neni ani potreba definovat nejaky entry point. Protoze se to zkompiluje jako binarka a pres zmakebas to vytvari z basic loaderu tapku. Loader je nastaven na testovani rychlosti programu.

    https://github.com/DW0RKiN/M4_FORTH/blob/master/from_asm.sh

  • 25. 7. 2023 23:24

    _dw

    V emulatoru se to otevre v basicu, takze se jeste musi spustit ten basic loader pomoci klavesy R (run) a pak enter.

  • 26. 7. 2023 8:40

    atarist

    Fuse to spusti primo.
    Tedy - to je zvlastni - v modu s originalni ROM 48k to spusti primo, jinak ne. Divne...

  • 25. 7. 2023 14:33

    Pavel Tišnovský
    Zlatý podporovatel

    Diky za doplneni.

    Ten fix, co tam naznacujes, planuju na priste (ted by bylo dobre, aby si to lidi vyzkouseli a zjistili, proc to nejede dobre a hlavne kdy). A ten trik s LDI*, to jsem uplne zapomel - si s dovolenim a diky zase vezmu :)

    * porad to pisu dost mechanicky jako na stare dobre 6502

  • 26. 7. 2023 0:46

    _dw

    No ja pri tom narazil na to ze inc/dec reg_8bit nastavuje vlajku p/v! Myslel jsem, ze podteceni nemam jak pomoci inc/dec zjistit a ono to jde... (preteceni je jasne, to se nastavi zero)

    A to ani pokud je to v A. Takze jsem celou dobu delal SUB 0x01 misto DEC A... lol. Musim vyzkouset.

    Jinak jsem ten kod jeste vylepsil kdyz jsem se na nej ted kouknul. Protoze to pricitani 32 se da udelat pres registr C kdyz je volny.

    draw_8_lines:
            ld  bc, 8*(256+3)+32-3   ; 3:10         počitadlo zapsaných řádků
            ld  a, e                 ; 1:4          save E
    loop:
            ldi                      ; 2:16         [DE++] = [HL++]; BC--
            ldi                      ; 2:16         [DE++] = [HL++]; BC--
            ld  a,(hl)               ; 1:7          načtení jednoho bajtu z masky
            ld  (de),a               ; 1:7          zápis hodnoty na adresu (DE)
            inc hl                   ; 1:6          posun na další bajt masky
            dec e                    ; 1:4          korekce
            dec e                    ; 1:4          korekce
            inc d                    ; 1:4          posun na definici dalšího obrazového řádku
            djnz loop                ; 2:13/8       vnitřní smyčka: blok s 3x osmi zápisy
            ld  a, e                 ; 1:4
            add a, c                 ; 1:4
            ld  e, a                 ; 1:4
            ret c                    ; 1:5/11
            ld  a, d                 ; 1:4
            sub 8                    ; 2:7
            ld  d, a                 ; 1:4
            ret                      ; 1:10         návrat z podprogramu
                                    ;[24:644/663 =10+8*77-5+26/10+8*77-5+45]

    ...a pak vyzkousel 3x ldi a vysla uplne nejlepsi rutina jenze... mela drobnou chybku na krase...
    Ale i pres opravu te chybky je to nejlepsi reseni. A pokud mas ramecek okolo obrazovky tak muzes ten fix zrusit.

    draw_sprite:
            ld hl, SPRITE_ADR        ; 3:10         adresa, od níž začíná maska spritu
            call draw_8_lines        ; 3:17         vykreslit prvních 8 řádků spritu
            call draw_8_lines        ; 3:17         vykreslit druhých 8 řádků spritu
            call draw_8_lines        ; 3:17         vykreslit třetích 8 řádků spritu
            ret                      ; 1:10         návrat z podprogramu
                                    ;[13:71]
    
    draw_8_lines:
            ld  bc, 8*(256+3)+32-2   ; 3:10         počitadlo zapsaných řádků
            ld  a, e                 ; 1:4          save E
    loop:
            ld  e, a                 ; 1:4          load E
            ldi                      ; 2:16         [DE++] = [HL++]; BC--
            ldi                      ; 2:16         [DE++] = [HL++]; BC--
            ldi                      ; 2:16         [DE++] = [HL++]; BC--
            dec de                   ; 1:6          fix fail pri tisku posledniho znaku v tretine! ldi zvedne D pro kazdy radek...
            inc d                    ; 1:4          posun na definici dalšího obrazového řádku
    
            djnz loop                ; 2:13/8       vnitřní smyčka: blok s 3x osmi zápisy
            ld  a, e                 ; 1:4
            add a, c                 ; 1:4
            ld  e, a                 ; 1:4
            ret c                    ; 1:5/11
            ld  a, d                 ; 1:4
            sub 8                    ; 2:7
            ld  d, a                 ; 1:4
            ret                      ; 1:10         návrat z podprogramu
                                    ;[24:632/651 =10+8*75-5+26/10+8*75-5+45]

    ...ale ldi je ti stejne k nicemu pokud budes delat nejake xor .)))

    26. 7. 2023, 00:47 editováno autorem komentáře

  • 26. 7. 2023 1:44

    _dw

    Vsechno jinak! .) Tak z "detects overflow" z https://clrhome.org/table/ se v originalnim manualu k Z80 vyklubalo ze pokud pred odectenim obsahuje registr hodnotu 0x80, tak se ten priznak nastavi, v ostatnich 255 pripadech se vynuluje.

    Takze to dela neco jineho... ale zase existuje dalsi zpusob jak rychle testovat hodnoty 0x80 (dec) nebo 0x7F (inc).

    Pridava dalsi slozitost pro hledani optimalnich reseni...

    Existuje testovani bitu... 2:8 pokud nas zajima jen 7. bit

    Rotace 2:8 pokud nas zajima 0. nebo 7. bit

    "sla reg" by u 0x80 nastavila ZERO a CARRY, ale to nejde testovat najednou takze bez pouziti A snad:

    rlc reg 2:8
    dec reg 1:4

    nastavi ZERO jen pri puvodni hodnote 0x80

    ld A,reg 1:4
    xor 0x80 2:7 nastavi ZERO

    atd. atd.