1 Ostatnio edytowany przez mkm (2014-05-21 21:54:06)

Mam dziwny problem z blitter'em, gdy chce wykonać po sobie 2 długie operacje w trybie BLiT. Czyli "wpuszczam" CPU dla przerwań, ale stosuję trick z szybszym restart'em blitter'a.
Mam taki test case:
1) rysuje sobie pół ekranu (cpu) na 4 bitplanach -> mam ekran wypełniony kolor'em 15
2) czyszczę blitter'em bitplan 1
3) czyszczę blitter'em bitplan 2

jako efekt powinienem mieć więć ekran wypełniony kolorem 12 (przecięcie planów 3 i 4).
i teraz jeśli zmodyfikuje kod do tylko jednej z wywołań blitter'a to wszystko jest ok.
mam wtedy ekrany wypełniony odpowiednio kolor'em 13 lub 14 (przecięcia odpowiednich 3 bitplanów) - czyli każda procka używająca blitter z osobna działa ok. Jeśli mam je obie oczywiście coś się wali...

Sam kod wzorowałem na http://s390174849.online.de/ray.tscc.de/blitter.htm

i wygląda on:

blitCleanPlane1:
            ; *** plane 1 clr ***
            ; end masks
            lea.l   BLT_ENDMASK1.w,a0
            moveq.l    #-1,d0
            move.l  d0,(a0)+
            move.w  d0,(a0)+

            ; dest xInc & dest yInc
            move.l  #$00080000,(a0)+

            movea.l    scr1,a1
            ; dest address
            move.l  a1,(a0)+

            ; xCount+1 & yCount
            move.l  #$00290064,(a0)+
            ; HOP & OP
            move.w  #$0200,(a0)+

            ; no HOG
            clr.w   (a0)

            ; set blitter active
            moveq.l    #7,d0
_blit1        bset.b  d0,(a0)
            nop
            bne.s   _blit1            
            ; wait blitter done

            rts

blitCleanPlane2:
            ; *** plane 2 clr ***
            ; end masks
            lea.l   BLT_ENDMASK1.w,a0
            moveq.l    #-1,d0
            move.l  d0,(a0)+
            move.w  d0,(a0)+

            ; dest xInc & dest yInc
            move.l  #$00080000,(a0)+

            movea.l    scr1,a1
            ; plane 2 shift
            add.l    #2,a1
            ; dest address
            move.l  a1,(a0)+

            ; xCount+1 & yCount
            move.l  #$00290064,(a0)+
            ; HOP & OP
            move.w  #$0200,(a0)+

            ; no HOG
            clr.w   (a0)

            ; set blitter active
            moveq.l    #7,d0
_blit2        bset.b  d0,(a0)
            nop
            bne.s   _blit2            

            rts


BLT_SRC_X_INC    equ    $ffff8a20
BLT_ENDMASK1    equ $ffff8a28
BLT_DEST_X_INC    equ $ffff8a2e

Mam wrażenie, że mimo wszystko pętla restartująca blitter do końca zadania coś wariuje w takich sytuacjach, albo coś zle robie. Efekt przynajmniej jest taki, ze mam kilka wierszy faktycznie wyczyszczone oba bitplany, a pózniej tylko bitplan 2 - który teoretycznie czyszcze później wiec jakby druga procedura przerwała działanie pierwszej zanim ona skończy (mimo pętli czekającej na jej koniec)

Efekt podobny i na Steem i Hatari (na STE mogę dopiero sprawdzić w weekend). Jakieś pomysły?


PS. ustawinia endmask sa zbedne, ale nevermind to nie ma znaczenia...

Maciek
--------
Atari 65XE + Ultimate 1MB + Stereo + SIO2SD | Atari 520STE + 4MB + UltraSatan | Atari Falcon 030 + CT60e + 14MB ST + 256MB TT + 68882  + CF + Netusbee | Amiga 500 + 1MB + Gotek | Amiga 600 + 2MB Chip + 8MB Fast + CF

2

Problem rozwiązany.
Nie wiem czy kogoś to zainteresuje... ale może komuś się kiedyś przyda więc wyjaśnienie poniżej:

Procedura startu i szybszego restartu blitter'a na podanej przeze mnie stronie zdaje się nie być prawidłowa. Po przejściu przez "bliblię blitter'a" by Paradox (http://paradox.atari.org/files/BLIT_FAQ.TXT) doszedłem do wniosku, że aby poprawnie ubsługiwać tryb BLiT pętla zamiast:

            ; set blitter active
            moveq.l    #7,d0
_blit1  bset.b  d0,(a0)
            nop
            bne.s   _blit1            
            ; wait blitter done

musi wyglądać

            ; set blitter active
            moveq.l    #7,d0
            bset.b  d0,(a0)
_blit1  bset.b  d0,(a0)
            nop
            bne.s   _blit1            
            ; wait blitter done

Pierwszy bset startuje blitter i w przypadku trybu BLiT po 64 cyklach dostęp do szyny wraca do CPU i zaczyna ono wykonywać kolejne instrukcje. Wtedy drugi bset będzie probować ustawić wartość jeszcze raz. Jeśli blitter ma jeszcze coś do zrobienia to wartość pola nie zmieni się i flaga Z będzie wyzerowana, więc pętla wykona się wracając do bset'a powodując szybszy restart blitter'a niż pełne 64 cykli. Jeśli jednak w tym czasie trafi się przerwanie to przejmie ono CPU i szyne w miejscu nop'a.
Przed poprawką bset był wykonywany jednokrotnie, więc wartość startowa bitu 7 zawszę wynosiła w pierwszej iteracji 0 (blitter inactive) czyli flaga Z była zawsze ustawiana. Przez co pętla nigdy się nie wykonywała. Oczywiście operacje wykonywane przez blitter były wykonywane - ale na przemian z kolejnymi instrukcjami kodu, więc jeśli dalej następował kod cpu rekonfigurujący blitter to efekt był taki jak w pierwszym poście. Takie przynajmniej jest moje zrozumiene. Na emulatorach zaczęło to działać poprawnie, na testy na real STE nie miałem czasu.

PS. Oczywiście w trybie HOG wszystko działało, ale wtedy to można zapomnieć o pogodzeniu tego z muzyką używającą timer'ów.

Maciek
--------
Atari 65XE + Ultimate 1MB + Stereo + SIO2SD | Atari 520STE + 4MB + UltraSatan | Atari Falcon 030 + CT60e + 14MB ST + 256MB TT + 68882  + CF + Netusbee | Amiga 500 + 1MB + Gotek | Amiga 600 + 2MB Chip + 8MB Fast + CF

3

Dzięki przydało się.
Może nie mi, ale koderowi, który wraca zzaświatów. Coś tam pamięta, ale pamieć w wieku lat 40 bywa mocno wybiórcza;D

bzzzz...bzzzzz..... o wgrało się !!!!