1

Napisalem sobie chyba najbardziej prosta animacje jaka da sie zrobic czyli cykliczne przesuwanie pixela po osi x na ekrania i chce to zgrac z dwubuforwaniem. Oczywiscie cos poszlo nie tak... sama animacja zdaje sie dzialac, zmiana fizycznego i logiczengo ekranu tez, ale animacja i tak nie jest plynna i czasem przeskakuje. Tak jak by buforowanie zupelnie nie dzialalo. Jako, iz szukam juz pol weekendu bezskutecznie bledu to moze Wam sie cos nasunie co robie nie tak.

Moj prosty kod z komentarzami:

            ; wlaczenie trybu super user
            clr.l     -(a7) 
            move.w     #32,-(a7)
            trap     #1
            addq.l     #6,a7
            move.l     d0,_old_stack
_old_stack     dc.l     0
                
            ; wyliczenie adresu fizycznego ekranu                
            move.l  #screenbuffer+255,d0
            ; wyrownanie do rownych 256b            
            sub.b   d0,d0   
            ; ustawienie adres ekranu fizycznego do phyScr                                    
            move.l  d0,phyScr  
            ; znajdujemy obszar za fizycznym ekranem na ekran logiczny            
            addi.l  #160*200,d0  
            ; ustawiamy adres ekranu logicznego do logScr                               
            move.l  d0,logScr
            ; mowimy ST ze wyswetlany ekran zaczyna sie od phyScr            
            move.l  phyScr,d0
            lsr.w   #8,d0
            move.l  d0,$ffff8200.w 
            
            ; ustawienia koloru tla i animowanego pixela
            move.w     #$000,$ff8240
            move.w     #$777,$ff8244

; pozycja animowanego pixela                        
pos_x         dc.w     1
pos_y         dc.w     100                
        
drawStart            
            ; czekamy na vsync
            move.w     #37,-(a7)
            trap     #14 
            addq.l     #2,a7

            ; zamieniamy ekrany logiczny z fizycznym (stary logiczny staje sie fizycznym i odwrotnie)
            move.l    logScr,d0
            move.l    phyScr,logScr
            move.l    d0,phyScr
            ; mowimy ST ze wyswetlany ekran zaczyna sie od phyScr
            lsr.w   #8,d0
            move.l  d0,$ffff8200.w 
            ; adres logicznego ekranu wrzucamy do A0 - tam bedzie rysowac aplikacja
            move.l    logScr,a0
            
            ; ZAMIEN POWYZSZY BLOK NA PONIZSZY DLA WERSJI BEZ BUFFERINGU
            ;move.l    phyScr,d0
            ;lsr.w   #8,d0
            ;move.l  d0,$ffff8200.w 
            ;move.l    phyScr,a0
            
            ; prosta animacja pixela na osi X
            
            ; wyczyszczenie starej pozycji pixela na logicznym ekranie
            ; poniewaz rysujemy na 2 ekranam przemiennie
            ; to stara pozycja na ekranie logicznym to pos_x-1
            ; bo pos_x to aktualna pozycja pixela na ekranie fizycznym
            move.w    pos_x,d4
            ; ZAKOMENTUJ PONIZEJ DLA WERSJI BEZ BUFFERINGU
            subi.w    #1,d4
            cmp        #-1,d4
            ; jesli poprzenia pozycja to -1 to znaczy ze mamy wyczyscic ostatni pixel linii
            bne        notTooLess
            move.w    #319,d4
notTooLess
            
            move.w    d4,d0
            move.w    pos_y,d1
            ; wywolanie procedury czyszczacej pixel d0,d1
            ; ZAKOMENTUJ BY NIE CZYSCIC OBRAZU
            jsr        clrPixelD0D1
            
            ; postawienie pixela w nowej przesunietej w prawo pozycji
            addi    #1,pos_x
            cmp        #320,pos_x
            ; jesli nowa pozycja to 320 to stawiamy pixel na poczatku linii
            bne        notTooBig
            clr.w    pos_x
notTooBig            
            
            move.w    pos_x,d0
            move.w    pos_y,d1
            ; wywolanie procedury stawiajacej pixel d0,d1
            jsr        drawPixelD0D1

            ; petla nieskonczona
            jmp        drawStart

; procedura rysujaca pixel w do,d1 zakadajac ze pamiec ekranu zaczyna sie w A0
; rysowanie uzywa tylko pierwszego bit plane dla uproszczenia
drawPixelD0D1
            ; oblicznie adresu paczatku linii d1 w adresie a1
            move.l    a0,a1
            mulu    #160,d1
            adda.l    d1,a1
            clr.l    d3
            ; obliczamy offset poczatku Plane 1 zawierajacego pixel i przesuwamy o niego a1
            move.w    d0,d3
            lsr.w    #4,d3
            lsl.w    #3,d3
            adda.l    d3,a1
            ; obliczamy index pixela w bitplane
            and.w    #$f,d0
            ; zamieniamy index pixela na numer odpowiadajacego bitu (sa odwrocone) i umieszczamy do w d0
            neg.w    d0
            add        #$f,d0
            ; ustawiamy bit odpowiadajacy pixelowi w Plane 1
            move.l    (a1),d1
            bset    d0,d1
            move.l    d1,(a1)
            rts

; procedura czyszczaca pixel w do,d1 zakadajac ze pamiec ekranu zaczyna sie w A0
clrPixelD0D1
            ; analogicznie jak rysowanie powyzej
            move.l    a0,a1
            mulu    #160,d1
            adda.l    d1,a1
            clr.l    d3
            move.w    d0,d3
            lsr.w    #4,d3
            lsl.w    #3,d3
            adda.l    d3,a1
            and.w    #$f,d0
            neg.w    d0
            add        #$f,d0
            move.l    (a1),d1
            bclr    d0,d1
            move.l    d1,(a1)
            rts

; adres fizycznego ekranu
phyScr        ds.l    1
; adres logicznego ekranu
logScr        ds.l    1

; pamiec ekranu
screenbuffer        equ *        

Aplikacja jak widac jest trywialna. Przeuwam pixel o 1 w prawo, i czyszcze ostatnia pozycje na danym ekranie (jako iz mam 2 ekrany to na kazdym ekranie efektywnie animuje co 2 pixele). Manipulujac zakomentowanym kodem mozna wylaczyc buforowanie i w sumie efekt jest podobny. Mozna tez wylaczyc czyszczenie poprzedniej pozycji pixela i wtedy widac, ze samo rysowanie odbywa sie raczej prawidlowo i widac podmieniajace sie bardzo szybko ekrany z naprzemienna pozycja pixeli.

Macie jakis pomysl co robie nie tak? HELP!

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

Nie analizowałem kodu bo dopiero wstałem po ciężkiej sobocie %-) ale pierwsze co mi nachodzi do głowy, to czy synchronizujesz to z vbl'em?

3

maciekm napisał/a:

            move.l     d0,_old_stack
_old_stack     dc.l     0
               
            ; wyliczenie adresu fizycznego ekranu               
            move.l  #screenbuffer+255,d0

takie coś nie ma prawa działać,  nie możesz zaraz za instrukcją wstawiać danych, które będą wykonane przez cpu jak kod.

What can be asserted without proof can be dismissed without proof.

4 Ostatnio edytowany przez mkm (2013-03-10 14:43:51)

@jury tak mi sie wydaje:

Na poczatku petli rysowania mam
            move.w     #37,-(a7)
            trap     #14
            addq.l     #2,a7

Chwile pozniej zamieniam ekrany i czyszcze/rysuje tylko na niewidocznym.

@sqward dzieki za uwage :) rozumiem ze wszelkie deklaracje zmiennych powinny zjadowac sie poza kodem. poprawilem to u siebie... choc w tym przypadku nie poprawilo to mojego problemu.

Aha, dla informacji uzywam vasm i hatari. Choc na steem pod winda zachowuje sie to podobnie. Na real STE nie odpalalem, ale zakladam ze jesli na obu emulatorach jest zle to problemem jest moj kod;)

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

5

Odpalilem w koncu ten kod na STE i okazalo sie ze dziala w miare prawidlowo.
To znaczy animacja jest mniej wiecej plynna (moze nie idealnie), ale nie wystepuje ten efekt co mialem pod hatari, ze losowo raz na jakis czas cos przeskakuje itp. Dalo mi to do myslenia i stwierdzilem, ze moze problemem jest to ze pod emulatorem mam skonfigurowanego EmuTOS. No i faktycznie po zmianie na prawdziwy tos program zachowuje sie tak jak na prawdziwym sprzecie - animacja jest wolniejsza... ale nie ma tych losowych przeskokow/zwiech co na emutos.
Kurcze, skoro na takim banalnym kodzie jest taka duza roznica w dzialaniu to chyba z kompatybilnoscia emutos'a z tos'em jest gorzej niz zakladalem.

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

Spróbuj z wyłączonymi przerwaniami.

Atari: FireBee, (Falcon030 CT60e SuperVidel SvEthlana CTPCI), TT, (520ST Pak030 Frak PuPla Panther), (520ST 4MB ST RAM 8MB TT RAM CosmosEx SC1435), (1040STFM UltraSatan SM124), (1040STE 4MB ST RAM 8MB TT RAM CosmosEx NetUSBee SM144 SC1224), 260ST, 520 ST+, (MEGA ST SM125), (65XE Rapidus U1MB VBXE SIDE2 SIO2PC), (Jaguar SkunkBoard), Lynx II, 2x Portfolio

7

maciekm napisał/a:

Kurcze, skoro na takim banalnym kodzie jest taka duza roznica w dzialaniu to chyba z kompatybilnoscia emutos'a z tos'em jest gorzej niz zakladalem.

to nie jest kwestia kompatybilności, bo przecież program poprawnie działał. Tylko raczej z tego, że EmuTOS jest na razie w fazie beta i jak sami autorzy piszą, nie jest w ogóle zoptymalizowany. Na razie celem jest odtworzenie pełnej funkcjonalności wszystkich wersji TOSów.

Twój problem może wynikać właśnie z tego, że EmuTOS podkrada więcej cykli procesora niż TOS albo z tego że testowałeś pod emulatorem, gdzie występuje problem konwersji odświeżania PAL 50Hz do 60 albo i więcej hertzów.

Lynx I / Mega ST 1 / 7800 / Portfolio / Lynx II / Jaguar / TT030 / Mega STe / 800 XL / 1040 STe / Falcon030 / 65 XE / 520 STm / SM124 / SC1435
DDD HDD / AT Speed C16 / TF536 / SDrive / PAK68/3 / Lynx Multi Card / LDW Super 2000 / XCA12 / SkunkBoard / CosmosEx / SatanDisk / UltraSatan / USB Floppy Drive Emulator / Eiffel / SIO2PC / Crazy Dots / PAM Net
http://260ste.atari.org