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 09:02 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 11:02 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 11:02 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 01:02 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 20:02
       
      ... albo jak zrobił Mono - liczyć blitterem VBXE i wrzucać na Antic ;)
      • 6:
         
        CommentAuthorMaW
      • CommentTime21 Feb 2014 21:02
       
      Czy to coś Wam pomoże: ->link<- ?
      • 7:
         
        CommentAuthorxeen
      • CommentTime22 Feb 2014 07:02
       
      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 12:02
       
      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 13:02
       
      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 20:02
       
      Jestem spokojny, ale czuwam ;) hahahahhh