C64Power Forum
Archiwum => Meonlawel => Wątek zaczęty przez: BagoZonde w 28 Listopada 2010, 04:45
-
Witam, kolejny problem z assemblerem, który chciałem rozgryźć ale po wielu godzinach bezowocnych poszukiwań chciałbym poradzić się starych wyjadaczy.
Korzystam ze standardowego wczytywania danych z dyskietki, więc IRQ na chwilę przerywa swoje działanie. Objawia się to nieprzyjemnym \'zawieszeniem\' muzyki na pewien czas.
Czytałem o wszelkiej maści loaderach, jednakże temat ten trochę mnie jednak przerasta.
Generalnie z tego co wywnioskowałem z sieci, o ile dobrze to zrozumiałem: możliwe jest switchowanie między IRQ a wczytywaniem w taki sposób, by wczytywanie danych czekało na zakończenie wykonywania przerwania IRQ.
Innymi słowy chciałbym zaimplementować prosty loader, który może i nie będzie przez to zbyt szybki, ale nie będzie powodował \'zawieszek\' odgrywanej muzyki. Generalnie chodzi mi o wczytywanie plików po 5 bloków, więc nie są one duże.
Czy znacie rejestry, których sprawdzanie mogłoby zwalniać tak jakby \'bramkę\' do wczytywania nowych danych? Chyba, że trzeba odwołać się do innych rejestrów niż SETFLS ($FFBA), SETNAM ($FFBD) czy OPEN FILE ($FFC0), etc.
Z góry dzięki za pomoc i wyrozumiałość!
-
http://www.codebase64.org/doku.php?id=base:disk_loader_with_flashing_border_for_non-fastload
to powinno Cię zadowolić, zamień tylko :
flashload inc $d020
dec $d020
jmp $f6fe
na:
flashload jsr $1003
jmp $f6fe
-
Dzięki Skull za cynka, jednak nie o to do końca mi chodziło.
Sprawa jest tego typu, że mam już przerwanie IRQ pod ($0314), które odtwarza muzykę, następuje więc z niego powrót przez skok do $EA31. I w trakcie odtwarzania tej muzyki program doczytuje dane z dyskietki takie jak plansze czy zmieniające się charsety, etc. Wtedy właśnie następuje ten problem.
Wydedukowałem, że zawiesza mi muzykę nawet przy próbie otwierania i zamykania pliku bez pobierania z niego danych.
Postanowiłem więc samemu wymyśleć co i jak. Kombinowałem więc z włożeniem loadera do IRQ, który odczytuje sobie np: wartość spod $7000. W niej zapisuję poszczególne kroki a w każdym kroku po jednym odwołaniu do jakiegoś JSR. A jest trochę tych JSR: $FFBA, $FFBD, $FFC0, $FFC6, w końcu input czyli $FFCF (wykonywane więc co przerwanie po odegraniu kawałka muzyki) no i $FFCC i $FFC3. I udało mi się. Co prawda wczytuje się teraz o wiele wolniej niestety i zdarzają się jakieś dwa czy trzy momenty, w których lekko szarpie, ale prawie tego nie słychać (powiedzmy ;)).
Dodatkowo pod $7001 ustawiłem bramkę, która przepuszcza do następnego kroku dopiero po wykonaniu danego JSR. Dopiero po dobrej pół godzinie zauważyłem, że pewnie o to chodzi, bo przechodziło mi wszystkie kroki i zamykało plik zanim zdążyło coś z niego odczytać ;). No i oczywiście przy każdym wejściu do odczytu danych muszę odwoływać się do JSR $FFC6 z numerem logicznym urządzenia.
Nie jest to piękna metoda, zajmuje troszkę miejsca w IRQ, choć akurat tymi IRQ zamierzam przełączać w zależności od tego czy ma być coś wczytywane czy wykonywana inna część programu.
Jeżeli jest jakaś prostsza metoda \'chackingowa\' - proszę o garść kodu lub cynk ;).
Dzięki Skull BARDZO SERDECZNIE za tego linka, co prawda nie skorzystałem z tego kodu ale i tak wyłapałem z niego to co najlepsze. Chodzi mi o wartość jaka znajduje się pod $BA. Rewelacja.
Pozdrawiam!! Dzięki!
-
no to przykładowe loadery http://elysium.filety.pl//tools/disk/loaders/
http://noname.c64.org/csdb/release/?id=58462
http://noname.c64.org/csdb/release/?id=85881&show=notes#notes
poszukaj sobie jeszcze level crunchera bodaj by kmm+mms.
Wśród tych wszystkich źródeł masz napewno system dostępu do danych z dysku z muzyczką.
Uważam temat za zamknięty.
PS. Jeżeli używasz jakiś system stworzony przez kogoś innego dajesz mu credits.
-
spoko, wiem na czym polega problem - właśnie to co podałem powinno Ci pomóc, z tym że zapomniałem jeszcze o synchronizacji z ramką (w podanym przypadku muzyczka będzie grała za szybko).
Niestety przerwania $0314/$0315 (a właściwe $fffe/$ffff) irq rastra, nie mają bezwględnej wyłączności na czas procesora. Wystrczy SEI w wykonywanym aktualnie kodzie i nie wywołają się dopuki blokada przerwań nie zostanie zwolniona (CLI). Ameryki nie odkrywam, ale dla Twojej wiadomości - procedury kernala do ładowania pliku ($ffd5 - a właściwie głównie procedura pod $ed40 w kernalu) - dość często blokują przerwania bo inaczej gubią synchronizację ze stacją dysków (i load error), niestety twórcy kernalowskiej transmisji mieli gdzieś, inne procedury wymagajace synchronizacji (twoja muzyczka) i priorytet stanowi ładowanie stąd te przerwy w płyynności odtwarzania muzyki. Problem trzeba obchodzić albo tak jak podałem albo jak Ty wykombinowałałeś, oczywiścia załatwia to tylko w jakimś stopniu, albo skorzystać z innego sposobu ładowania danych nie korzystającego z obsługi kernala zawartego w romie c64 (linki Kisiela), albo napisać własny program (ale to już trochę wyższa szkoła jazdy (trzeba dodatkowo poznać chociaż trochę drugi komputer jakim jest stacja c1541)
-
programik podany wczesniej - \'podkleja się\' pod procedurkę sprawdzania klawisza run/stop (nacisnięty przerywa wgrywanie) , zasada analogiczna jak przy wektorze przerwań 0314/0315, tyle że tu podklejamy się nie pod przerwania rastra, ale pod coś co działa na tej samej zasadzie w czasie wgrywania pliku (tyle że częściej niż raz na ramkę).
-
w sumie to z 200-cie osób wymyśliło to przed Wami, w 10 razy lepszy sposób, po co wyważać otwarte drzwi i męczyć się z kernalem?
-
@Skull
No ok Skull, ale po co tam warm resety skoro w trakcie działania programu chcę doczytywać/wymieniać dane? Zresztą drugą sprawą jest dla jsr $a659 i jmp $a7ae. Te skoki z tego co się domyślam powodują uruchomienie programu basic, który został wczytany. Napisałem sobie ten kod i rzeczywiście mi wgrywa program po resecie. A tak jak pisałem, zależy mi na loaderze danych, które w czasie działa programu zrzucam sobie gdzieś do pamięci i przetwarzam potem. Za to Twoje wskazówki odnośnie częstszego \'wchodzenia\' (NMI) niż do rastra (IRQ) postaram się rozkminić.
@Kisiel
Oczywiście masz rację, sęk w tym, że w assemblerze jestem nowy i część z tych loaderów to dla mnie czarna magia a z drugiej strony nie ma to jak mięso ;). Fajnie się pobawić we własny loader. Polubiłem zresztą takie dyskusje ;) nt. assemblera i co najważniejsze, dzięki Wam można do rzeczy podyskutować :). Mi udało się napisać na podwalinach swojej nikłej wiedzy taki loader, który przy niewielkiej optymalizacji np: podczas 30-sekundowego wczytywania danych - lekko mi szarpie muzykę 3x (akurat nie wiem dlaczego tak bo w trakcie wczytywania danych) i to tak, że prawie tego nie słychać. Wziąłem na widelec z filetów pierwszy program, fastload.prg, potem turbo v25 no ale po przejrzeniu kodu musiałbym sobie wszystko rozpisać, co z czym się je i ciężko znaleźć mi w tym surówkę, którą mógłbym załączyć do swojego programu. Assembler sam w sobie i fakt, że to czyjś program sprawia, że ciężko łapać w locie o co w danym miejscu w programie chodzi.
-
no to faktycznie masz problem.
-
;) Problem nie problem, coś tam działa. Powiedziałbym, że jest przyzwoicie.
-
eee no.. przecież nie kazałem Ci tego kopiować - oczywiście że niektóre rozkazy są zbędne - to jest po prostu jedno z rozwiązań problemu. Co Ty z tymi NMI? przecież to nie NMI, przerwań rastra można wywoływać również do woli w jednej ramce - nie w tym są różnice :)
To w końcu co tam wypłodziłeś ?
-
Hello Skull!
Próbowałem na nowo rozkminić ten loader, który mi podesłałeś na początku tego tematu. Brakuje mi tam takich rzeczy jak pobieranie danych i sprawdzenie końca pliku. Oczywiście wyciąłem środkową rzecz kodu od SEI (pomijając STA $01) do zamknięcia default input (JSR $FFCC) i co się okazało. Raz, że printuje mi tekst LOADING: $FFD5 wczytuje plik. Ja korzystam z wczytywania znaku, czyli $FFCF. Dwa, że zawiesza mi się to wczytywanie w jakieś infinity loop. Cały kod po przepisaniu rzeczywiście wczytuje program, ale co do danych trzeba by podmienić to właśnie na JSR $FFCF.
Jeżeli chcesz, mogę podesłać Ci moją wersję w .d64 do rozkminienia. Spróbowałbym zrobić jeszcze może indirect jump w miejsce rozpatrywanych warunków skoku, ale nie sądzę, by coś to przyspieszyło.
W sumie pomyślałem też, by po prostu wyciszać szybko muzykę przed ładowaniem daty i potem po wczytaniu ją zgłaśniać, nawet by to jakoś wyglądało - a mówię o projekcie gry, do którego owy loader chcę zastosować.
-
rozumiem że masz to mniej-wiecej tak jak tu:
http://www.codebase64.org/doku.php?id=base:reading_a_file_byte-by-byte
zresztą polecam przeglądnięcie tej strony - może być nie raz pomocna.
Sorry ale aby muzyka sie odgrywała \'pewnie\', na kernalowskich procedurach to nie znam sposobu.
Fakt, że ten problem nie jest taki rzadki, wtedy najcześciej korzystamy po prostu z loaderów (czyli substytutów kernelowskiej transmisji).
Chociaż ja np, całkiem niedawno, aby uniknać podobnego problemu, skopiowałem te procedury z kernala odpowiednio je obcinając i likwidująć wszystkie sei i cli. Ważne jest wtedy, aby przy części odpowiedzialnej za komunikację (rejestr $dd00) wstawić warunek dla $d012, aby transmisja nie trafiała w ten sam czas co przerwanie irq (np. odtwarzające muzykę), wtedy da się to jakoś kontrolować.
Do zalet tego rozwiązania należy (w porównaniu z loaderami), że powinno ono działać z każdym napędem kompatybilnym z transmisją kernalowską (a nie tylko z c1541).
ps. odpowiadać mogę dopiero po 16-stej
-
Dzięki za odpowiedź! Właśnie w taki sposób dokonuję wczytywania danych. Wziąłem to z xiążki Jima Butterfielda bodajże (z tym, że tam nie ma rozpatrywanego przypadku błędu z plikiem lub jego braku). Podzieliłem to sobie na kroki, żeby na każdy skok do IRQ wykonać jak najmniejszą liczbę JSR. I wiesz co, podpiąłem sobie $D012 i $DD00 i okazało się, że tak jak piszesz: dzięki $D012 można kontrolować inne rzeczy by nie wchodziły na przerwanie! Extra!
Wsadziłem więc do miejsca odpowiedzialnego za wczytywanie danych warunek, że gdy $D012 jest różne od zera to nie czytaj tylko loopuj się i co się okazało? Działa to dokładnie tak samo jak moja kombinacja z loaderem w IRQ! To znaczy jest nawet trochę szybciej i przerywa też nieznacznie w dwóch czy trzech miejscach. Tak jakby czasem jakiś skok w czasie wczytywania danych nie wyrabiał się i wchodziła już kolejna ramka IRQ. Nie mam niestety jak to przetestować na razie na prawdziwym C64 z powodu braku kabla do monitora (a dokładniej poszukuję DIN-8) ale chyba ten sam efekt i na Ceśku bym uzyskał. Dzięki serdeczne za cynk, myślę, że jest znośnie, choć temat można by jeszcze podrążyć ;). Warto poczytać o tych rastrach, robi się soczyście ;).
Inny temat to zapis danych w trackach dyskietki tak aby nie były widoczne przy odczytaniu directory dyskietki, ale na to jeszcze za wcześnie ;). Przynajmniej na etapie deweloperskim, bo wszystkie dane przygotowuję pod swoimi programami na Amidze i przerzucam na D64. Potem jak starczy mi czasu, to i ten temat będę zgłębiał ;).