atarionline.pl Blitter na Atari :) - Forum Atarum

Jeśli chcesz wziąć udział w dyskusjach na forum - zaloguj się. Jeżeli nie masz loginu - poproś o członkostwo.

  • :
  • :

Vanilla 1.1.4 jest produktem Lussumo. Więcej informacji: Dokumentacja, Forum.

    • 1:
       
      CommentAuthorxeen
    • CommentTime20 Feb 2014 zmieniony
     
    Pytanie teoretycznie banalne, i być może banalne jest praktycznie. Ale postanowiłem zasięgnąć porady ekspertów :)

    Chodzi mi o to, jak najefektywniej pod względem szybkości działania (przy wykorzystanie jakiś tricków itp.) kopiować prostokątne obszary pamięci w asmie na Atari. Z moich przemyśleń i prób (być może błędnych)wynika, że mogą być różnice przy operacjach na grafice w zależności czy mamy do czynienia z ekranem docelowym wąskim, normalnym i szerokim.

    Czy zawsze najbardziej opłaca się trzymać dane źródłowe liniowo, czy niekoniecznie?

    Oczywiście teoretycznie jestem w stanie zrobić sobie prakalkulację i wygenerować serię lda <-> sta, ale chodzi mi o elastyczność na poziomie : na wejściu jest podane adres danych źródłowych o adres danych docelowych - dedykowane procedury dla obszarów o stałym rozmiarze (szerokość wysokość) - jeżeli to coś pomoże. Opcjonalnie dodatkowo jeszcze szerokość i wysokość - czyli rozmiar.

    Potrzebna mi informacja zależnie od konfiguracji Antic (czyli konkretni tryb graficzny, nie znakowy)

    oczywiście szukam porad nie tylko jeżeli chodzi o prockę kopiującą, ale także preshifting danych źródłowych i inne dowolne prekalki. Upraszczam do kopiowania na ekran.


    pomożecie? bo nie mieszczę się w ramce ;)
    • 2: CommentAuthormono
    • CommentTime20 Feb 2014 zmieniony
     
    Może nie jest to nic szczególnie specjalnego, ale:

    1. Tablicowanie adresów linii skaraca ci kod z (ekran wąski):
    ;.A=Y,.Y=X
    ldx #0
    stx scrad
    lsr
    ror scrad
    lsr
    ror scrad
    lsr
    ror scrad
    sta scrad+1
    lda #<scr
    adc scrad
    sta scrad
    lda #>scr
    adc scrad+1
    sta scrad+1
    lda (scrad),y

    do
    ;.X=Y,.Y=X
    lda lntablo,x
    sta scrad
    lda lntabhi,x
    sta scrad+1
    lda (scrad),y

    Przy ekranie normalnym dochodzi zsumowanie przesunięcia o 8 a przy szerokim o 16 (w pierwszej procedurze).

    2. Przy operacjach blokowych warto modyfikować kod:
    ;.X=Y,.A=X, .Y=width-1
    clc
    adc lntablo,x
    sta scrad
    lda #0
    adc lntabhi,x
    sta scrad+1
    loop:
    scrad = *+1
    lda $ffff,y
    dey
    bpl loop


    3. Ekran ZX Spectrum zorganizowany jest tak, że linie oddzielone są od siebie co stronę, dzięki temu przejście do następnej linii to inc scrad+1 a nie 2x lda:adc:sta (czy tam adc:sta:sxx:inc).

    4. Korzystaj z ujemnego indeksowania przy przesunięciach bloków (przykład ldir był na forum).

    5. Jeśli przesuwasz bloki danych zajmujące kilka stron to opłaca się więcej policzyć przed przesłaniem, niż liczyć w trakcie działania pętli - generalnie im mniej warunków w pętli tym lepiej. Przykładowo kopiując generator znaków:
    ldx #<src
    ldy #>src
    stx src0
    sty src0+1
    iny
    stx src1
    sty src1+1
    iny
    stx src2
    sty src2+1
    iny
    stx src3
    sty src3+1
    ldx #<dst
    ldy #>dst
    stx dst0
    sty dst0+1
    iny
    stx dst1
    sty dst1+1
    iny
    stx dst2
    sty dst2+1
    iny
    stx dst3
    sty dst3+1
    ldx #0
    ?copy:
    src0 = *+1
    lda $ffff,x
    dst0 = *+1
    sta $ffff,x
    src1 = *+1
    lda $ffff,x
    dst1 = *+1
    sta $ffff,x
    src2 = *+1
    lda $ffff,x
    dst2 = *+1
    sta $ffff,x
    src3 = *+1
    lda $ffff,x
    dst3 = *+1
    sta $ffff,x
    inx
    bne ?copy


    6. Używaj trybów abs,x/abs,y raczej niż (ind,x)/(ind),y - są o cykl/dwa krótsze.

    7. Używaj dex:bxx niż dex:cpx:bxx - oszczędzasz 2 cykle.
    Unikaj arytmetyki ze znakiem - skróci ci to testy warunków brzegowych.

    8. Generalnie warto mieć pod ręką tabelkę z Ruszczyca i ciągle liczyć.

    9. Układać w pamięci tak, żeby sprawdzić warunek brzegowy za pomocą inc:beq/bne/bmi/bpl (ewentualnie do tego bit:bvx).

    10. Obliczenia tablicować chociażby cząstkowo.

    Edit: ad.1. Jeśli adres ekranu masz od pełnej strony, to procedura skraca się do
    ;.A=Y,.Y=X
    ldx #0
    stx scrad
    lsr
    ror scrad
    lsr
    ror scrad
    lsr
    ror scrad
    adc #>scr
    sta scrad+1
    lda (scrad),y
    • 3: CommentAuthormono
    • CommentTime20 Feb 2014 zmieniony
     
    Możesz niezależnie od rozmiaru ekranu pokazywanego przez ANTIC trzymać w pamięci szerszy ekran - 48 bajtów lub 64 jeśli Ci na to pamięć pozwala. Jeśli nie tablicujesz adresów początków linii, to oszczędzisz na obliczeniu adresu linii.

    Edit: Unikaj skoków bxx i adresowania indeksowego przekraczających granicę stron (wydłuża o cykl).

    Edit 2: Jeśli chodzi o przesuwanie, to sprawdzaj różnicę i rób rol lub ror korygując ewentualnie potem adres obszaru do skopiowania o 1.
    • 4:
       
      CommentAuthorjhusak
    • CommentTime21 Feb 2014 zmieniony
     
    Najszybciej jest dla wąskiego trybu i organizacji znakowej (jak w C64).

    Pętla wówczas ma 8 razy więcej do przepisania bajt po bajcie, zanim zacznie korygować współrzędną y. Możemy tak przepisać cały blok 8x256 piksli w 13-14 cykli na bajt, czyli 3500 cykli (teraz już wiadomo, dlaczego gry na Spectrum tak szybko chodzą :)
    ldx #0
    t:
    lda src,x
    sta dst,x
    dex
    bne t
    ;korekta wsp. y: src i dst, dla dst wystarczy zwiększyć starszy bajt...
    ;jeszcze raz


    Nie ma szybszej metody (można jeszcze trochę pętlę rozwinąć i zaoszczędzić na skoku lub nawet na dexach, ale wtedy jest kłopot z aktualizacją wskaźników src i dst.

    Troszkę gorzej jest dla mniejszych przedziałów; dla połowy ekranu można zamast bne stosować bpl (chodzi o przepisanie bajtu spod indeksu 0); można też zmniejszyć adresy o 1 i przepisywać normalnie jak w przykładzie.

    Niestety dla normalnego i szerokiego trybu to nie zadziała, chyba, że zastosujemy 64-bajtowy ekran; wówczas jednak tracimy sporo pamięci na takie zabawy.

    W ramce i tak się nie zmieścisz ze zwykłym przepisywaniem. Prekalki są fajne do ograniczonych zastosowań - uniwersalność i prekalk są do siebie w sprzeczności.

    Co innego, jeśli chcesz osiągnąć efekt "jak przy przepisywaniu" - wtedy doublebuffer lub prekalk i multbuffer (animacja, hehe)
    • 5: CommentAuthorpin
    • CommentTime21 Feb 2014
     
    ... albo jak zrobił Mono - liczyć blitterem VBXE i wrzucać na Antic ;)
    • 6:
       
      CommentAuthorMaW
    • CommentTime21 Feb 2014
     
    Czy to coś Wam pomoże: ->link<- ?
    • 7:
       
      CommentAuthorxeen
    • CommentTime22 Feb 2014
     
    dziękuję za sugestie. kombinuję.

    W ramce i tak się nie zmieścisz ze zwykłym przepisywaniem.


    No to zależy od rozmiaru prostokąta i ilości kopiowań :)

    Prekalki są fajne do ograniczonych zastosowań

    Tak, i takie ograniczone zastosowania właśnie wchodzą w grę.
    • 8: CommentAuthorwieczor
    • CommentTime22 Feb 2014
     
    Doublebuffer jest dobrym rozwiązaniem (nie animacja, animacja jest jak masz gotowe klatki :) ). Większość rzeczy będzie wyglądać dobrze jeśli się zmieści w 2 ramkach a nie w jednej (i to na vblanku, wysoko postawiona poprzeczka, zwłaszcza jeśli tam chodzi jeszcze np. player RMT :) ). Z doublebufferem jest jeden plus - nie trzeba się mieścić między ekranami - przełączenie musi nastąpić między nimi. Wada - dwa razy tyle pamięci na ekran. No cóż - coś za coś.
    • 9:
       
      CommentAuthorxeen
    • CommentTime22 Feb 2014
     
    W moim przypadku DB nie wchodzi w grę (pamięć) i też z pewnych względów nie jest potrzebny, będę miał parę elementów i po prostu nie wszystkie będę rysował co klatkę tylko po prostu naprzemiennie - tak czy siak się nie wyrobię, a chciałbym.

    Kiedyś XXL mi mówił, że w zajawce Cybernoida bardzo pomógł mu "nielegalny" rozkaz SBX właśnie przy takim "blitterze" - albo źle zrozumiałem;) Zastanawiam się nad tym obecnie (Pin - spokojnie :)
    • 10: CommentAuthorpin
    • CommentTime22 Feb 2014
     
    Jestem spokojny, ale czuwam ;) hahahahhh