Zabawy z przesuwaniem tekstu chyba nie będzie końca. Tym razem do przesuwu typu finescroll realizowanego w ramach VBLANK interrupt dodamy ruchomą tęczę w ramach procedury obsługi przerwania DLI.
int i=[0], j=[0], k=[0] byte wsync=$D40A, vcount=$D40B byte colt=$D017, indx=[0], hscrol=$D404 card pointer pc card tmp include "H1:DEFINES.ACT" proc dli() [pha txa pha tya pha] indx==+1 for i=0 to 7 do wsync=1 if indx>30 then indx=0 fi colt=vcount+indx od [pla tay pla tax pla rti] proc scroll() hscrol=j j==+1 if j=17 then j=0 pc^==-2 k==+1 if k=14 then pc^=tmp k=0 fi fi [jmp xitvbv] proc main() int i card savmsc=88 byte clock=$14 byte nmien=$D40E byte array ndl = [112 112 112 66 64 156 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 130 86 216 159 65 32 156] card dlist=560 card vvblkd=$0224 byte col0=708 byte col1=709 card vdslist=$0200 graphics(0) dlist=ndl savmsc=40000 col0=14 col1=14 for i=1 to 23 do printf("line: %i%E", i) od print("action!") pc=dlist+28 tmp=pc^+6 i=clock while clock=i do od nmien=0 vvblkd=scroll vdslist=dli nmien=$C0 do od return
a w pliku DEFINES.ACT:
define rti="$40", pha="$48", pla="$68", txa="$8A", tax="$AA", tya="$98", tay="$A8", jmp="$4C", php="$08", plp="$28", xitvbv="$E462"
Najwięcej czasu (ze dwa niespokojne tygodnie :)) zajęło mi dojście do tego, dlaczego w dli muszę zmieniać sprzętowy rejestr koloru, a nie jego cień :). Wynika to z faktu, że jeżeli zmienię rejestr cień, to wartości rejestrów cieni są przepisywane do rejestrów sprzętowych GTIA dopiero w systemowej procedurze przerwania VBLANK, czyli po wyświetleniu ramki do końca. Skutek jest taki, że wszystkie linie ekranu malowane są ostatnim kolorem z pętli „wsync=1… colt=” w dli. Po zakończeniu procedury dli() w rejestrze cieniu siedzi sobie tenże ostatni kolor z pętli, bo kolor zmieniony w rejestrze cieniu nie trafia od razu do GTIA, układ graficzny maluje sobie dalej kolorem przepisanym podczas poprzedniego VBLANK. Kończy ramkę, wywołuje przerwanie VBLANK, przepisuje rejestr sprzętowy ostatnią wartością rejestru systemowego i wszystkie linie od pierwszej do tej, dla której dli jest ustawione maluje w tym samym kolorze.
Jeżeli ustawimy rejestr sprzętowy ($D017 zamiast $2C5) to przy wsync=1 nowy kolor jest przepisywany do GTIA w momencie przerwania poziomego, następna linia do końca jest malowana tym kolorem, tak osiem razy bo w tej linii trybowej mamy osiem linii w wierszu, kończy się malowanie ramki, w VBLANK system operacyjny przepisuje rejestry sprzętowe wartościami z rejestrów cieni, czyli maluje od pierwszej linii trybowej, do tej w której ustawione jest dli kolorami z cieni. Potem startuje dli, zmienia rejestr sprzętowy osiem razy maluje w innym kolorze itd, itd.
Muszę jeszcze tylko przetestować binarkę na prawdziwym Atari… (update: działa).
Ciekawe ile jeszcze takich fascynujących „odkryć” na mojej drodze :). Pewnie sporo.
Pingback: VBI finescroll + DLI rainbow (ASM) | greblus:~$ cat /dev/random > /dev/null 2>&1
Pingback: VBL i VBI w MadPascal-u. |
Pingback: VBI i DLI w MadPascal-u. |