Problem z DYCPem

Szukasz drobnej pomocy przy kodowaniu, albo chcesz przedstawić światu swoją gotową lub w trakcie realizacji produkcję? To właściwy dział.
Wiadomość
Autor
Gordian
Posty: 318
Rejestracja: 14 cze 2021, 13:32

Problem z DYCPem

#1 Post autor: Gordian »

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ę)
Obrazek
freq=2 (tu widać, że litery zaczynają skakać)
Obrazek

Czy ktoś wie gdzie popełniam błąd lub zna remedium na problem?

Awatar użytkownika
Nitro
Posty: 1551
Rejestracja: 03 wrz 2008, 20:23
Grupa: Black Sun

Re: Problem z DYCPem

#2 Post autor: Nitro »

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.

Gordian
Posty: 318
Rejestracja: 14 cze 2021, 13:32

Re: Problem z DYCPem

#3 Post autor: Gordian »

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:
Obrazek

A tu kiedy następuje zmiana $d016 i text_offset:
Obrazek

Gordian
Posty: 318
Rejestracja: 14 cze 2021, 13:32

Re: Problem z DYCPem

#4 Post autor: Gordian »

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...

Awatar użytkownika
Nitro
Posty: 1551
Rejestracja: 03 wrz 2008, 20:23
Grupa: Black Sun

Re: Problem z DYCPem

#5 Post autor: Nitro »

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:
al C:f5e4 .tab
al C:add .time2
al C:ad7 .time1
al C:acd .event
al C:f8b0 .tex5c
Taki plik podajemy vice komendą x64.exe -moncommands plik_z_etykietami

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

Gordian
Posty: 318
Rejestracja: 14 cze 2021, 13:32

Re: Problem z DYCPem

#6 Post autor: Gordian »

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.

Awatar użytkownika
Nitro
Posty: 1551
Rejestracja: 03 wrz 2008, 20:23
Grupa: Black Sun

Re: Problem z DYCPem

#7 Post autor: Nitro »

Dlaczego pętla w dół, to jedna z klasycznych technik optymalizacyjnych pozwalająca zaoszczędzić rozkaz cmp
ldx #0
loop
... kod pętli

inx
cpx #64
bne loop
vs
ldx #64

loop
... kod pętli

dex
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.
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.

Gordian
Posty: 318
Rejestracja: 14 cze 2021, 13:32

Re: Problem z DYCPem

#8 Post autor: Gordian »

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.

Awatar użytkownika
Nitro
Posty: 1551
Rejestracja: 03 wrz 2008, 20:23
Grupa: Black Sun

Re: Problem z DYCPem

#9 Post autor: Nitro »

Spoko, życzę powodzenia w kolejnych demoscenowych wojażach :)

ODPOWIEDZ