Problem z DYCPem
Problem z DYCPem
Witajcie,
testuję prostego DYCPa.
Nie jest oparty na matrixie znakowym o stałej wysokości bloku, ale "pełnowysokościowy".
Kiedy ustalę częstotliwość pobierania wartości z sinusa co 1 (u mnie stała nazywa się freq), to wszystko gra.
Jeśli zmienię freq na 2, 3, 4, itd., to litery zaczynają skakać (tym mocniej im większa częstotliwość).
Pseudokod:
init:
lda #0
sta scrollx
sta text_offset
sta sinus_offset
irq:
lda scrollx
and #7
tay
eor #7
sta $d016
tya
bne +
inc text_offset (tu daję znać, że muszę przesunąć pobieranie tekstu o jedną literkę)
+
lda sinus_offset
sta sinus_offset_temp
lda text_offset
sta text_offset_temp
pętla dycpa:
for i=0 to 39
lda sinus_offset_temp
clc
adc #freq
sta sinus_offset_temp
pobieram wartość z tabelki sinus na podstawie sinus_offset_temp
rysowanie literki na podstawie sinusa oraz text_offset_temp
text_offset_temp++
endfor
lda sinus_offset
clc
adc #step ;niezależnie od freq, po wyrysowaniu dycpa przesuwam się o 1 po sinusie (czyli mam powolny sinus, ale "gęsty" jeśli freq>1)
sta sinus_offset
inc scrollx
endirq
Jeśli ustawię step=freq, to dycp działa poprawnie, ale zależy mi na tym, aby móc zmieniać częstotliwość, a szybkość pobierania z tabelki pozostawić 1 (step=1).
freq=1 (jest ok, choć jakość gifa słaba, trzeba kilkać aby zobaczyć pełną animację)
freq=2 (tu widać, że litery zaczynają skakać)
Czy ktoś wie gdzie popełniam błąd lub zna remedium na problem?
testuję prostego DYCPa.
Nie jest oparty na matrixie znakowym o stałej wysokości bloku, ale "pełnowysokościowy".
Kiedy ustalę częstotliwość pobierania wartości z sinusa co 1 (u mnie stała nazywa się freq), to wszystko gra.
Jeśli zmienię freq na 2, 3, 4, itd., to litery zaczynają skakać (tym mocniej im większa częstotliwość).
Pseudokod:
init:
lda #0
sta scrollx
sta text_offset
sta sinus_offset
irq:
lda scrollx
and #7
tay
eor #7
sta $d016
tya
bne +
inc text_offset (tu daję znać, że muszę przesunąć pobieranie tekstu o jedną literkę)
+
lda sinus_offset
sta sinus_offset_temp
lda text_offset
sta text_offset_temp
pętla dycpa:
for i=0 to 39
lda sinus_offset_temp
clc
adc #freq
sta sinus_offset_temp
pobieram wartość z tabelki sinus na podstawie sinus_offset_temp
rysowanie literki na podstawie sinusa oraz text_offset_temp
text_offset_temp++
endfor
lda sinus_offset
clc
adc #step ;niezależnie od freq, po wyrysowaniu dycpa przesuwam się o 1 po sinusie (czyli mam powolny sinus, ale "gęsty" jeśli freq>1)
sta sinus_offset
inc scrollx
endirq
Jeśli ustawię step=freq, to dycp działa poprawnie, ale zależy mi na tym, aby móc zmieniać częstotliwość, a szybkość pobierania z tabelki pozostawić 1 (step=1).
freq=1 (jest ok, choć jakość gifa słaba, trzeba kilkać aby zobaczyć pełną animację)
freq=2 (tu widać, że litery zaczynają skakać)
Czy ktoś wie gdzie popełniam błąd lub zna remedium na problem?
Re: Problem z DYCPem
Wreszcie jakieś demoscenowe pytanie
Nie widzę całego kodu ale widzę problem i generalnie kod jest w porządku ale problem leży na poziomie algorytmu.
Najpierw pomyślałem o daniu rozwiązania ale chyba lepiej dać wędkę a nie rybę. Ale jak chcesz rybę to napisz.
Podpowiedź nr 1: Nie widzę użycia rejestru Y w pętli Bo rozumiem, że to for to jest generowanie speedkodu.
Nie widzę całego kodu ale widzę problem i generalnie kod jest w porządku ale problem leży na poziomie algorytmu.
Najpierw pomyślałem o daniu rozwiązania ale chyba lepiej dać wędkę a nie rybę. Ale jak chcesz rybę to napisz.
Podpowiedź nr 1: Nie widzę użycia rejestru Y w pętli Bo rozumiem, że to for to jest generowanie speedkodu.
Re: Problem z DYCPem
Hej Nitro,
dziękuję za zainteresowanie.
Oczywiście, ryby nie chcę.
Tak, w pętli for jest speedcode dla każdej kolumny.
Ale czemu sugerujesz użycie rejestru Y w speedkodzie?
DYCP działa poprawnie dla freq=1 i step=1 lub dla dowolnej wartości freq i step=1 (ale kiedy wyłączę zmianę $d016 oraz zmianę text_offset, czyli kiedy DYCP będzie stał w miejscu).
Coś jakby nie zgrywało się podczas zmiany $d016 oraz zmiany text_offset.
Tu przykład właśnie takiego zatrzymanego DYCPa z freq=8:
A tu kiedy następuje zmiana $d016 i text_offset:
dziękuję za zainteresowanie.
Oczywiście, ryby nie chcę.
Tak, w pętli for jest speedcode dla każdej kolumny.
Ale czemu sugerujesz użycie rejestru Y w speedkodzie?
DYCP działa poprawnie dla freq=1 i step=1 lub dla dowolnej wartości freq i step=1 (ale kiedy wyłączę zmianę $d016 oraz zmianę text_offset, czyli kiedy DYCP będzie stał w miejscu).
Coś jakby nie zgrywało się podczas zmiany $d016 oraz zmiany text_offset.
Tu przykład właśnie takiego zatrzymanego DYCPa z freq=8:
A tu kiedy następuje zmiana $d016 i text_offset:
Re: Problem z DYCPem
Ok, znalazłem przyczynę, choć jeszcze nie analizowałem dlaczego tak się dzieje.
Kreśliłem dycpa w pętli od 0 do 38. Po zmianie pętli od 38 do 0, jest ok...
Kreśliłem dycpa w pętli od 0 do 38. Po zmianie pętli od 38 do 0, jest ok...
Re: Problem z DYCPem
Mhm, to w takim razie jednak gotowego rozwiązania nie mam skoro takie coś naprawia problem.
Ale mam porady odnośnie generalnego debugowania:
1. Frame stepping
Od VICE 3.4 bodajże mamy dwa skróty:
ALT+P - pauza
ALT+SHIFT+P - pauza i uwaga emulacja tylko jednej klatki, kolejne naciśnięcie - kolejna etc.
W starym VICE to alt + p i alt + + ale w zależności od wersji zwykle nie dało się w trybie pauzy otworzyć monitora
2. Eksport etykiet z asemblera i import ich do VICE
Każdy dobry asm ma opcję eksportu etykiet, Kick Assembler od razu potrafi wygenerować plik dla VICE komendą:
-vicesymbols
wyglądający np tak:
3. Monitor - stara szkoła debugowania
Mając etykiety i aktywną pauzę ustawiamy się na 'problematycznej' klatce i odpalamy monitor, ten w VICE to potwór, ale do debugu wystarczy kilka komend:
m <adres> lub etykieta - podgląd pamięci
d <adres> lub etykieta - disasm kodu pod tym adresem, przydatne przy samo modyfikującym się kodzie
break - zatrzymanie się gdy wykonywany jest dany adres
watch - zatrzymanie się gdy wykonywany jest odczyt/zapis pod dany adres
step - kolejna instrukcja
4. Nowa szkoła, tu niestety pomóc nie mogę ale mnóstwo osób chwali sobie C64Debugger, w którym na pewno są narzędzia powyżej i wiele wiele więcej. Trzeba tylko poświęcić kapkę więcej czasu na naukę. (Silnik emulacji to VICE).
https://a.fsdn.com/con/app/proj/c64-deb ... /max/max/1
Ale mam porady odnośnie generalnego debugowania:
1. Frame stepping
Od VICE 3.4 bodajże mamy dwa skróty:
ALT+P - pauza
ALT+SHIFT+P - pauza i uwaga emulacja tylko jednej klatki, kolejne naciśnięcie - kolejna etc.
W starym VICE to alt + p i alt + + ale w zależności od wersji zwykle nie dało się w trybie pauzy otworzyć monitora
2. Eksport etykiet z asemblera i import ich do VICE
Każdy dobry asm ma opcję eksportu etykiet, Kick Assembler od razu potrafi wygenerować plik dla VICE komendą:
-vicesymbols
wyglądający np tak:
Taki plik podajemy vice komendą x64.exe -moncommands plik_z_etykietamial C:f5e4 .tab
al C:add .time2
al C:ad7 .time1
al C:acd .event
al C:f8b0 .tex5c
3. Monitor - stara szkoła debugowania
Mając etykiety i aktywną pauzę ustawiamy się na 'problematycznej' klatce i odpalamy monitor, ten w VICE to potwór, ale do debugu wystarczy kilka komend:
m <adres> lub etykieta - podgląd pamięci
d <adres> lub etykieta - disasm kodu pod tym adresem, przydatne przy samo modyfikującym się kodzie
break - zatrzymanie się gdy wykonywany jest dany adres
watch - zatrzymanie się gdy wykonywany jest odczyt/zapis pod dany adres
step - kolejna instrukcja
4. Nowa szkoła, tu niestety pomóc nie mogę ale mnóstwo osób chwali sobie C64Debugger, w którym na pewno są narzędzia powyżej i wiele wiele więcej. Trzeba tylko poświęcić kapkę więcej czasu na naukę. (Silnik emulacji to VICE).
https://a.fsdn.com/con/app/proj/c64-deb ... /max/max/1
Re: Problem z DYCPem
Hej Nitro,
dzięki za wskazówki.
Ja jeszcze polecam http://icu64.blogspot.com/ Fajny do wglądu grafiki czy śledzenia zmian w pamięci. Nie ma takich możliwości jak C64Debugger.
Jeśli chodzi o DYCPa, to doprecyzuję, bo nie dokładnie opisałem co realnie było przyczyną.
Przeglądając kod "wzorcowy" Pasi Ojala (z CHacking) zauważyłem, że stosuje on fragment kody, który opisał komentarzem: "Compensation for the text scrolling".
Są to dwie linijki:
dec START
dec START
Jeszcze nie wiem dlaczego, ale co cykl przekręcenia scrolla w $d016, zmniejsza główny indeks (START) poruszania się po tabelce sinusa. Zmniejsza do tyle razy, ile wynosi częstotliwość DYCPa w jego kodzie, a tą ustala w linijkach:
inx ; Chars are two positions apart
inx
Gdyby częstotliwość wynosiła 1, wtedy byłby jeden dec i jeden inx.
Dodałem ten kod kompensacji u siebie jako:
lda sinus_offset
sec
sbc #freq
sta sinus_offset
Ale to nie działało. Okazało się, że różnicą była właśnie krok pętli - u mnie w górę, u niego w dół.
Zmieniłem u siebie pętle i zaczęło działać.
Gdybym jednak chciał pozostać przy pętli w górę, to po prostu muszę zmienić odejmowanie na dodawanie do sinus_offset.
dzięki za wskazówki.
Ja jeszcze polecam http://icu64.blogspot.com/ Fajny do wglądu grafiki czy śledzenia zmian w pamięci. Nie ma takich możliwości jak C64Debugger.
Jeśli chodzi o DYCPa, to doprecyzuję, bo nie dokładnie opisałem co realnie było przyczyną.
Przeglądając kod "wzorcowy" Pasi Ojala (z CHacking) zauważyłem, że stosuje on fragment kody, który opisał komentarzem: "Compensation for the text scrolling".
Są to dwie linijki:
dec START
dec START
Jeszcze nie wiem dlaczego, ale co cykl przekręcenia scrolla w $d016, zmniejsza główny indeks (START) poruszania się po tabelce sinusa. Zmniejsza do tyle razy, ile wynosi częstotliwość DYCPa w jego kodzie, a tą ustala w linijkach:
inx ; Chars are two positions apart
inx
Gdyby częstotliwość wynosiła 1, wtedy byłby jeden dec i jeden inx.
Dodałem ten kod kompensacji u siebie jako:
lda sinus_offset
sec
sbc #freq
sta sinus_offset
Ale to nie działało. Okazało się, że różnicą była właśnie krok pętli - u mnie w górę, u niego w dół.
Zmieniłem u siebie pętle i zaczęło działać.
Gdybym jednak chciał pozostać przy pętli w górę, to po prostu muszę zmienić odejmowanie na dodawanie do sinus_offset.
Re: Problem z DYCPem
Dlaczego pętla w dół, to jedna z klasycznych technik optymalizacyjnych pozwalająca zaoszczędzić rozkaz cmp
Więcej tutaj:
https://codebase64.org/doku.php?id=base ... optimizing
Generalnie artykuły optymalizacyjne na codebase64 to złoto, w 2010 ta sekcja nie była aż tak rozwinięta.
vsldx #0
loop
... kod pętli
inx
cpx #64
bne loop
Tak samo można próbować sobie w pętlach darować te clc, problemy wynikające z wyniku niedokładnego czasami o 1 będą niezauważalne kiedy efekt będzie w ruchu.ldx #64
loop
... kod pętli
dex
bne loop
Więcej tutaj:
https://codebase64.org/doku.php?id=base ... optimizing
Generalnie artykuły optymalizacyjne na codebase64 to złoto, w 2010 ta sekcja nie była aż tak rozwinięta.
Re: Problem z DYCPem
Tak, tyle, że ja mam/miałem pętle w górę nie bezpośrednio w kodzie, ale w asemblerze jako dyrektywę !for, więc nie miało to nic związku z optymalizacją. Jak pisałem możliwa jest jej implementacja w obydwu kierunkach, należy jednak pamiętać o magicznej "kompensacji" indeksu tabeli sinusa.
Re: Problem z DYCPem
Spoko, życzę powodzenia w kolejnych demoscenowych wojażach