atarionline.pl Przerwania DLI - 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:
         
        CommentAuthorshanti77
      • CommentTime10 Mar 2016 21:03
       
      Może ktoś mógłby mi wytłumaczyć dlaczego w tym programie dopisanie jednego rozkazu NOP w przerwaniu DLI powoduj,że zmiana koloru tła następuje dopiero przed końcem ekranu, a bez tego rozkazu kolor linii zmienia się już na samym jej początku. Używam XASM i emulator Altirra. Przy okazji mam jeszcze jedno pytanie , jak wpływa na przerwania DLI włączenie pionowego scrolla w programie ANTICA?
      • 2: CommentAuthormono
      • CommentTime10 Mar 2016 21:03 zmieniony
       
      Prawdopodobnie winny jest badline trybu 4 (konieczność zbuforowania treści pamięci ekranu w trybie tekstowym żeby nie marnować cykli w następnych liniach). WSYNC blokuje CPU do 110 cyklu w linii (jest ich 114). Polecam Altirra Reference Manual - tam jest wyjaśniona praca DMA ANTIC-a.

      Edit: VSCROL - DLI wywoływane jest zawsze w ostatniej linii skanningowej wiersza trybu. Jeśli włączony jest VSCROLL to linia skanningowa będzie wędrować w górę lub w dół odpowiednio do ustawień VSCROL ($D405).
      • 3:
         
        CommentAuthorxeen
      • CommentTime10 Mar 2016 23:03
       
      zawsze 110 niezależnie od szerokości?
      • 4: CommentAuthormono
      • CommentTime10 Mar 2016 23:03 zmieniony
       
      Z moich obserwacji wynika że tak.
      Phaeron pisze: "A write to WSYNC causes the CPU to halt execution until the start of horizontal blank. One more cycle passes before the CPU is halted until cycle 105 on the current scan line. If the next cycle is free, the CPU executes the first cycle of the next instruction; otherwise, the next instruction starts at cycle 105. DMA contention at cycles 105 and 106 may cause the CPU restart to be delayed until as late as cycle 107."
      Jednak 105 cykl a nie 110.
      • 5:
         
        CommentAuthorshanti77
      • CommentTime11 Mar 2016 07:03
       
      Czyli z tego wynika,że po zapisie do WSYNC zdąże wykonać 3 rozkazy zapisu (sta,stx,sty) poźniej jest przerwa i dopiero mogę coś zrobić w ostatniej ćwiartce ekranu.
      • 6: CommentAuthormono
      • CommentTime11 Mar 2016 09:03
       
      Tylko w pierwszej linii skanningowej trybu tekstowego, bo tam CPU jest haltowany przez ANTIC-a. Kolejne 7 linii już pobiera dane tak, jak w trybie graficznym - masz tam znacznie więcej czasu dla CPU.
      • 7: CommentAuthortebe
      • CommentTime11 Mar 2016 10:03
       
      o wyłączaniu badlines

      ->link<-
      • 8:
         
        CommentAuthorshanti77
      • CommentTime11 Mar 2016 10:03
       
      Jeszcze w sprawie VSCROLL'a z przerwaniami DLI, czy przerwanie w linii zawsze jest tam wywoływane, czy też jeśli linia się schowa to już nie? Pytam bo gdy wlączam w 1 linii VSCROLL pionowy to program automatycznie "idzie w maliny". Używam trybu 4 antica i w kilku liniach mam włączone przerwania DLI(również w 1 z VSCROLL), zmieniam adresy przerwania co wywołanie. W samych procedurach przerwań zmieniam tylko pozycję i kolor duszków. Czy po włączeniu VSCROLL'a przerwania mogą nałożyć się na siebie?
      • 9: CommentAuthormono
      • CommentTime11 Mar 2016 11:03 zmieniony
       
      Nałożyć się nie nałożą, ale jedno może przerwać drugie (jeśli procedura jest za długa) ponieważ DLI to NMI.
      Weźmy taki przykład:
      dlist:
      .byte $70+$80 ;8 pustych, w ostatniej DLI
      .byte $04+$20+$80 ;tryb 4 + VSCROLL + DLI w ostatniej linii

      Jeśli ustawisz rejestr VSCROL ($D405) na wartość 7 wiersz trybu 4 zostanie przesunięty o 7 linii skanningowych i będziesz miał wywołane DLI linia po linii (pierwsze z pustych linii, drugie z trybu 4). Jeśli pierwsza procedura obsługi DLI będzie się zbyt długo wykonywać, wtedy zostanie przerwana przez drugie DLI. Ilość cykli, które masz do dyspozycji zależy od:
      - tego co ANTIC potrzebuje zrobić w danej linii skanningowej trybu,
      - włączonych sprajtów (a konkretnie DMA - 4 cykle dla włączonych playerów, 1 cykl dla włączonych missiles),
      - odświeżania pamięci (zawsze 9 cykli).
      Ponieważ ANTIC blokuje CPU przy dostępie do magistrali.
      A co ANTIC może robić:
      - pobrać kolejny rozkaz i dane z dlisty (1 do 3 cykli),
      - pobrać dane z pamięci ekranu w trybie tekstowym, które to dane będą potem służyły do wyświetlania treści obrazu na podstawie generatora znaków (32, 40 lub 48 cykli zależnie od szerokości ekranu),
      - pobrać treść obrazu a) z pamięci ekranu w trybie graficznym, b) z generatora znaków w trybie tekstowym (32, 40 lub 48 cykli zależnie od szerokości ekranu).
      Dokładne diagramy kiedy ANTIC kradnie cykle przy włączonych lub wyłączonych HSCROLL/VSCROLL masz w Altirra Reference Manual.
      Kontrola DMA w DMACTL ($D400) odpowiada wyłącznie za:
      - pobieranie dlisty
      - pobieranie danych dla sprajtów.
      Odczyt danych z generatora i/lub pamięci ekranu odbywa się zawsze kiedy ANTIC rysuje linię trybu.

      Edit: Może istotne jeszcze będzie do liczenia cykli jak wygląda obsługa DLI przez OS:
      ; -- obsługa sekwencji NMI przez CPU (odłożenie F + adres powrotu z przerwania na stos + skok pośredni przez NMIVEC $FFFA) - 7 cykli
      bit NMIST ;$D40F - 4 cykle
      bpl ?nodli ;- skok nie wykonany - 2 cykle
      jmp (DLIV) ;$0200 - 5 cykli
      ?nodli:
      ... ;obsługa wejścia w VBLK lub RESET

      Zanim więc Twój kod zacznie być wykonywany mija 18 cykli.
      Można podnieść ROM i ustawić bezpośrednio wektor NMIVEC, wtedy zwłoka będzie 7 cykli potrzebnych na obsługę sekwencji NMI przez CPU. Procedura mogłaby wyglądać np tak:
      nmiservice:
      bit NMIST
      bpl ?nodli
      ;i tu zaczyna się Twój kod obsługujący DLI

      - zwłoka 13 cykli.
      A jak nie potrzebujesz VBLK i generalnie systemu to możesz bezpośrednio zacząć swój kod od nmiservice (zablokuj tylko VBLK w NMIEN $D40E) - zwłoka 7 cykli.
      DLI zgłaszane jest zdaje się w 10 cyklu linii skanningowej.

      Edit 2: Dużą pomocą może okazać się debugger Altirra lub atari800, który pokazuje w której linii i cyklu w linii aktualnie się znajdujesz.
      • 10:
         
        CommentAuthorshanti77
      • CommentTime11 Mar 2016 12:03
       
      Dzięki za pomoc, myślę że teraz sobie z tym poradzę nawet bez ruszania ROM'u.
      • 11:
         
        CommentAuthorCOR/ira4
      • CommentTime11 Mar 2016 21:03
       
      mnie zastanawia ile przerwań można sensownie zrobić w jednym cyklu i jaki one mają wpływ na wydajność .
      • 12:
         
        CommentAuthorshanti77
      • CommentTime11 Mar 2016 21:03
       
      Niestety przy używaniu scrolla pionowego korzystanie z przerwań dli jest praktycznie niemożliwe bo wszystko przesuwa się wraz z wartością w vscrol, dlatego postanowilem użyć licznika vcount i nie korzystać z przerwań dli.
      • 13:
         
        CommentAuthorjhusak
      • CommentTime11 Mar 2016 22:03 zmieniony
       
      Co? Dlaczego? Ale Jakto?
      • 14:
         
        CommentAuthorshanti77
      • CommentTime11 Mar 2016 23:03
       
      Przesow pionowy powoduje ze przerwania dli wykonuja sie w innych liniach ekranu po kazdym przesunieciu, musialbym zaleznie od przesuniecia odczekac odpowiednia ilosc linii zeby to wyrownac.
      • 15:
         
        CommentAuthorjhusak
      • CommentTime11 Mar 2016 23:03 zmieniony
       
      Nie widzę za bardzo zastosowania dla stosowania takich sztuczek.

      W przypadku scrolla pionowego dli ma się trzymać wraz ze scrollem, a w przypadku końca widoczności planszy wyłączamy scroll i już nic się nie przesuwa włącznie z przerwaniami.

      Jeśli znalazłeś taki przypadek, że jest trudno stosować dli, to trudno, ale w znakomitej większości przypadków to bułka z masłem.
      • 16:
         
        CommentAuthorshanti77
      • CommentTime12 Mar 2016 09:03
       
      Scroluje caly ekran a chce wyswietlac wyniki na duszkach, musze zmieniac i przesowac duszki zawsze w tej samej linii ekranu, a korzystajac z przerwan dli wszystko zaczyna sie ruszac.
      • 17: CommentAuthormono
      • CommentTime12 Mar 2016 10:03 zmieniony
       
      Jak wyświetlasz duchy?:
      1. Zapisujesz bezpośrednio do GRAFP/M?
      2. Włączasz DMA dla duchów (DMACTL) i rezerwujesz pamięć (PMGBASE)?
      W pierwszym przypadku możesz wywołać przerwanie DLI i robić odpowiednią ilość sta WSYNC:
      lda #lines
      sta VSCROL
      eor #%111
      tax
      ?loop:
      sta WSYNC
      dex
      bpl ?loop

      W drugim przypadku możesz w dowolnej chwili zmienić zawartość pamięci - nie potrzebujesz się synchronizować z linią.

      Edit: Możesz też użyć TIMER-a POKEY-owego z dzielnikiem 114 startowanego np na VBLK (248 linia ekranu).
      • 18:
         
        CommentAuthorxeen
      • CommentTime13 Mar 2016 17:03
       
      Lamerskie pytanie: czy robiąc co linie przerwanie będę w tym samym momencie je obsługiwał w każdej linii co STA WSYNC i jedno "duże" DLI?

      Innymi słowy czy jeżeli szybko zrobię RTI w danej linii i wygeneruję przerwanie w następnej to zaoszczędzę, czy też stracę, czy też nie ma to znaczenia.

      dziękuję
      • 19: CommentAuthormono
      • CommentTime14 Mar 2016 14:03 zmieniony
       
      Stracisz na cyklach obsługi przerwania (7 cykli sekwencji wejścia w przerwanie, 6 cykli RTI, no i wszystkie cykle zachowywania/odtwarzania rejestrów, no i jeśli używasz systemu/obsługujesz kilka rodzajów NMI/IRQ to cykle zajmujące rozpoznanie źródła i potwierdzenia obsługi).
      Obsługa w jednym długim DLI jest znacznie efektywniejsza. Jest oczywiście kilka "ale":
      1. Flaga I która jest zapalona automatycznie przy wejściu w przerwanie blokuje obsługę innych przerwań IRQ (ale nie NMI i nie BRK). Jeśli dopuszczalna jest obsługa IRQ w trakcie trwania takiego bloku kodu wystarczy skasować I.
      2. Zapis do WSYNC jest bardzo niewydajną techniką bo blokuje CPU aż do 105 cyklu linii skanningowej. W tym czasie CPU nie wejdzie w sekwencję obsługi przerwania nawet jeżeli ono wystąpi. Jeśli w międzyczasie może nadejść jakieś IRQ, które chcemy szybko obsłużyć (np szybkie SIO) to WSYNC może go skutecznie opóźnić.
      3. Przerwanie obsługiwane jest przez CPU dopiero po zakończeniu aktualnego cyklu rozkazowego więc to nie jest tak, że DLI zawsze zacznie się od 10 cykli linii. Ono zostanie zgłoszone w 10 cyklu, ale CPU najpierw musi zakończyć aktualny rozkaz w głównej linii przetwarzania i dopiero przystąpi do wejścia w przerwanie. Opóźnienie może więc być od 2 do 7 cykli. Można to ominąć odpowiednio konstruując kod który będzie przerywany (o ile da się przewidzieć momenty w których kod może być przerywany) - to takie "lokalne" synchronizowanie wejścia w przerwanie za pomocą CPU :)
      4. Jeśli kod ma być wykonany przez akcelerator (np. Rapidus) wtedy synchronizacja się trochę komplikuje, bo CPU działa szybciej. Można wtedy użyć dwóch technik:
      a) odczyt/zapis z obszaru I/O jest ZAWSZE synchronizowany z zegarem 1.77. Oznacza to że dostęp do I/O będzie zawsze w cyklach wypadających na poszczególne takty zegara 1.77MHz,
      b) zapis do WSYNC wstrzyma CPU zawsze do 105 cyklu linii skanningowej.
      No i warto wtedy mieć świadomość, że układy I/O pracują zawsze z zegarem 1.77MHz.
      Ale to taka dygresja w sumie bardziej związana z cyklowaniem niż ze specyfiką WSYNC.
      • 20:
         
        CommentAuthorxeen
      • CommentTime14 Mar 2016 14:03
       
      Ok, chodziło mi o te 7 cykli wejścia. Bo o rejestry itp bym sobie zadbał. No i RTI bym zrobił "prze końcem" - ale to nie ma znaczenia.
      Lamerskie pytanie - profesjonalna odpowiedź - dziękuję :)
      • 21:
         
        CommentAuthorshanti77
      • CommentTime19 Mar 2016 12:03
       
      Teraz mam problem z drganiem kolorów, używam przerwania POKEY'a do zmiany kolorów od danej linii, jednak po uruchomieniu VSCROL'a wszystko zaczyna drgać i nie potrafię tego ustabilizować. Przykładowy program (wychylenie joystick'a zatrzymuje scroll'a):
      • 22:
         
        CommentAuthorshanti77
      • CommentTime19 Mar 2016 12:03
       
      Plik w wersji xex:
      • 23: CommentAuthormono
      • CommentTime19 Mar 2016 18:03 zmieniony
       
      Wydaje mi się, że przyczyny są dwie:
      1. Opóźnienie odebrania przerwania rzędu 1..6 cykli.
      2. Podczas scrolla pionowego w linii z przerwaniem co 8 przesunięć trafi się badline, co zablokuje obsługę przerwania IRQ na prawie całą linię.
      W załączniku zmodyfikowany kod, który co sekundę scrolluje o linię ekran. Widać wyraźnie że raz na 8 następuję wyraźne przesunięcie.
      Zmieniłem też obsługę IRQ na główną procedurę VIMIRQ, ponieważ opóźnienie obsługi TIMER4 (przez procedurę systemową) jest rzędu 100 cykli.
      W załączniku zmodyfikowany kod.
      • 24: CommentAuthormono
      • CommentTime19 Mar 2016 19:03 zmieniony
       
      A w drugim załączniku Twój kod trochę poprawiony.
      Nie mam aktualnie możliwości przetestować na żywym Atari, ale Altirra pokazuje stabilny obraz.

      Edit: Niestety na Atari to nie wygląda stabilnie :/ Trzeba nad tym jeszcze popracować - może uda się tę procedurę docyklować.
      • 25:
         
        CommentAuthorshanti77
      • CommentTime19 Mar 2016 22:03
       
      Prościej będzie jednak dopasowanie grafiki tak aby przesunięcie o tą 1 linię nie będzie widoczne. W moim projekcie koloruje w ten sposób duszki, dołożenie 1 duszka o odpowiednim kształcie niweluje niepożądany efekt.