w komentarzach do nowinki ->link<- zadałem larkowi pytanie: "@larek - mam wielką prośbę czy możesz jeszcze raz wytłumaczyć na co są przeznaczone pierwsze 4K DL ? Dzięki i przepraszam, ale jakoś nie mogę sqmać z Twojej dyskusji o so chodzi :( .Krzaki oczywiście wpisując na jej początek mam piękne ;)"
w odpowiedzi larek napisał: "Nie bardzo rozumiem pytanie :( DL raczej nie ma 4KB... Należy wziąć pod uwagę to, że DL to jedno, a obszar pamięci ekranu to drugie. Niestety Antic "lubi", aby obszar pamięci ekranu nie leżał po obu stronach granicy 4KB. Obrazowo to wygląda tak: 1. przykład lubianego przez Antic umieszczenia pamięci obrazu w RAM: .......blok 4KB....blok 4KB....blok 4KB RAM: -----------|-----------|----------- obraz:................====.................
2. przykład mniej lubianego umiejscowienia pamięci obrazu w RAM: .......blok 4KB....blok 4KB....blok 4KB RAM: -----------|-----------|----------- obraz:........====......................
Oczywiście problem powstaje w przypadku standardowego DL. Przy naszym własnym DL, które uwzględnia takie położenie pamięci ekranu powinno być wszystko Ok. Chodzi o to, że przechowując dane pamięci obrazu w zmiennej, tak naprawdę nie mamy wpływu na to, gdzie system je umieści. Jeśli przez przypadek będą leżały, jak w przykładzie 2, to na ekranie ujrzymy obraz z kosmosu. Należy wziąć też pod uwagę, że dane obrazu zajmujące wiecej niż te 4KB zawsze będą umieszczone na dwóch obszarach granicy 4KB, czyli w trybach graficznych 8, 15 itd. zawsze powstanie ten problem! Bez modyfikacji DL nic tu nie zrobimy. W odpowiednim miejscu DL trzeba umieścić specjalne instrukcje wskazujące Antic'owi ten nowy obszar 4KB (nawet jeśli dane obrazu fizycznie zajmują jeden ciągły obszar RAM-u).
Z tego wszystkiego wynika, że do przechowywania danych obrazu (i nie tylko obrazu) basicowe zmienne znakomicie się nadają, bo nie musimy martwić się tym, gdzie system je przechowuje. Natomiast wykorzystywanie tych zmiennych jako fizycznego obszaru pamięci obrazu jest kłopotliwe - właśnie ze względu na to, że system umieszcza je w pamięci, gdzie jemu pasuje i... nie uzgadnia tego z Antic'iem ;-)
DL i pamięć obrazu to szeroki temat i w zasadzie trudno tu przytoczyć dokładne informacje. Zresztą i tak zapewne niewiele o tym wszystkim wiem. Wiele cennych wiadomości można wyczytać w książce DeRe Atari, która jest w archiwum atarionline.pl.
hmm to może opiszę skąd wzięło się pytanie. Dostałem od Krzyśka forward Twojego (larka) maila w którym wyświetlasz w TB obrazek GR8:
"10 DIM PE$(7680) 'tu sobie rezerwujemy zmienną tekstową (P-amiêæ E-kranu) o długooci 7680, czyli tyle ile wynosi obraz w GR8 (192 linie x 40 bajtów każda) 20 PE=ADR(PE$) ' tu odczytujemy adres początku tej zmiennej, żebyśmy wiedzieli, skąd później czytać dane 30 OPEN #1,4,0,"D:OBRAZEK.GR8":BGET#1,PE,7680:CLOSE #1 'odczytujemy obrazek z dysku i umieszczamy w zmiennej 40 GR.24: EK=DPEEK(DPEEK(560)+4) 'włączamy tryb 8 i zapamiętujemy adres początku pamięci obrazu 50 MOVE PE,EK,7680 'składnia instrukcji jest taka: MOVE skąd,dokąd,ile_bajtów. W tym przypadku przenieśliśmy cały blok 7680 bajtów ze zmiennej do pamięci ekranu"
analizując zatrzymałem się w momencie którego nie mogę zrozumieć EK=DPEEK(DPEEK(560)+4) ... jeśli pobiorę adres początku obrazu EK=DPEEK(88) to też ładnie wyświetli obrazek (88-adres początku obrazu). Rozumiem, że w przypadku metody z 88 nie mogę mieszać różnych trybów na jednym ekranie (?). Ponadto piszesz: "Należy wziąć pod uwagę to, że DL to jedno, a obszar pamięci ekranu to drugie" jak mam to rozumieć? Jeśli przykładowo dam: PRINT DPEEK(DPEEK(560)+4) i PRINT DPEEK(88) to będdzie to dokładnie ten sam adres. Jaka więc jest róznica? Szczególnie skąd to "+4"?
Standardowo faktycznie DPEEK(DPEEK(560)+4) i DPEEK(88) dadzą ten sam wynik - początek pamięci ekranu :) Róźnica polega na tym, że DPEEK(88) wskazuje początek pamięci widziany przez system, a DPEEK(DPEEK(560)+4) początek pamięci widziany przez Antic. To mogą być dwa różne obszary! To +4 bierze sie z tego, że w kom.560 i 561 jest przechowywany adres początku DL. Natomiast DL w 4 i 5 bajcie przechowuje właśnie adres początku pamięci. I dlatego DPEEK(560)- wskazuje na DL, a DPEEK(DPEEK(560)+4) odda nam adres początku pamięci.
Uruchom taki program (w TBXL):
10 GR.8+16:C.1 20 F.Q=1 TO 100:DRAWTO RAND(320),RAND(192):N.Q 30 GET KL
Co zobaczymy? Komupter zacznie rysować linie po ekranie.
A teraz taki:
10 GR.8+16:C.1 20 DIM EK$(7680):EK=ADR(EK$) 30 ANTIC=DPEEK(DPEEK(560)+4) 40 PLOT 0,0:DRAWTO 319,191 50 TEXT 10,50,"TO JEST EKRAN WSKAZYWANY PRZEZ ANTIC" 60 DPOKE 88,EK 70 F.Q=1 TO 100:DRAWTO RAND(320),RAND(192):N.Q 80 TEXT 10,100,"A TO EKRAN SYSTEMOWY" 90 DPOKE 88,ANTIC 100 TEXT 10,60,"NACISNIJ KLAWISZ" 110 GET KL 120 MOVE EK,ANTIC,7680 130 GET KL
Przepraszam, jeśli program nie zadziała.Jestem teraz w pracy nie mam jak sprawdzić tego - piszę z pamięci ;-)
W pierwszym przypadku komputer rysuje po ekranie linie - tworzy je na żywo - każdą linię widzimy, jak rysuje. W drugim programie - widzimy inny ekran (ten, który widzi Antic), a system rysuje sobie po innym ekranie (zmiennej EK$). Po naciśnięciu klawisza zobaczymy ten drugi obszar! Komórki pamięci 88 i 89 pozwalają nam wskazać na obszar roboczy, na którym wykonujemy pewne rysunki, ale Antic dalej nam wyświetla na monitorze "swój" obszar! W ten sposób możemy przygotować sobie "po cichu" jakiś rysunek i później przenieść go do obszaru wyświetlanego przez Antic. Tak więc DPEEK(88) i DPEEK(DPEEK(560)+4) mogą wskazywać ten sam obszar, ale nie muszą.
Jak to się ma do granicy 4KB w pamięci? Ano nijak. To zupełnie inna sprawa :)
Jakby progam nie zadziałał, to dajcie znać. Za jakąś godzinkę (może dwie) będę w domu, to poprawię go.
EDIT 1:
I jeszcze jedno. DL to tak naprawdę program dla Antica z informacjami, jak ma wyświetlać obraz - to takie coś, jak asembler zrozumiały dla Antica. Display List też leży gdzieś w pamięci (pod adresem DPEEK(560)) i ma długość zależną od trybu graficznego (jest trochę dłuższy od pionowej rozdzielczości ekranu). DL i miejsce w RAM, gdzie znajdują się dane dla obrazu, to dwie rożne sprawy. Różne tryby wyświetlane na ekranie to kwestia zmiany Display List, a nie zmian w pamięci ekranu. Pod adresem wskazanym przez DPEEK(88) (i DPEEK(DPEEK(560)+4) również) są dane obrazu, a nie Display List.
EDIT 2
No i sprawdziłem - programik działa :) Rysowanie dość długo się wykonuje (kilka sekund), wiec należy być cierpliwym ;-)
Mało tego, tych ekranów możemy mieć więcej! Zróbmy: DIM E1$(7680),E2$(7680):EK1=ADR(EK1$),EK2=ADR(EK2$) teraz wskazując dowolny ekran poprzez DPOKE 88,EK1 lub DPOKE 88,EK2 możemy rysować po naszych dwóch wirtualnych ekranach, a później przenieść dane z nich do normalnego obszaru: MOVE EK1,ANTIC,7680 lub MOVE EK2,ANTIC,7680
Jak widać na przykładzie tego 2 programu zmiana w komórkach 88 i 89 nie daje żadnego efektu wizualnego, natomiast zmiana 4 i 5 bajtu w DL spowodowałaby natychmiast zmianę obrazu na ekranie. Wracając do 4KB i pamięci ekranu. Wyobraźmy sobie taką sytuację:
10 GR.8+16:C.1 20 DIM EK$(7680):EK=ADR(EK$) 30 ANTIC=DPEEK(DPEEK(560)+4) 40 PLOT 0,0:DRAWTO 319,191 50 TEXT 10,50,"TO JEST EKRAN WSKAZYWANY PRZEZ ANTIC" 60 DPOKE 88,EK 70 F.Q=1 TO 100:DRAWTO RAND(320),RAND(192):N.Q 80 TEXT 10,100,"A TO EKRAN SYSTEMOWY" 90 DPOKE 88,ANTIC 100 TEXT 10,60,"NACISNIJ KLAWISZ" 110 GET KL
Jest to dokładnie ten sam program, co wyżej. Daje on nam to, że w zmiennej E$ mamy narysowane przez basic bazgraje. Teraz przyszedł moment, że chcemy pokazać te narysowane linie. W programie powyżej robimy to poprzez 120 MOVE EK,ANTIC,7680 czyli z pamięci zmiennej E$ przenosimy dane do pamięci ekranu widzianego przez Antic. Robi się to poprzez fizyczne przerzucenie ponad 7 tysięcy bajtów. To masa czasu dla procesora! Na szczęście w Atari pamięć ekranu może w zasadzie być w dowolnym miejscu RAM-u (co na to spectrumowcy?) . Wystarczy zmienić Display List, czyli instrukcje dla Antica i wskazać nowy obszar pamięci, żeby natychmiast zmienił się obraz. Dla "krótkich" trybów graficznych/tekstowych (poniżej 4KB) jest to dość proste. Wystarczy modyfikacja w DL 2 (słownie: dwóch) bajtów, żeby Antic zaczął wyświetlać inny obraz. Nie musimy przerzucać tysięcy bajtów! Zmienimy tylko 4 i 5 bajt w DL i już! Jaka oszczędność czasu! Taka zmiana odbywa się błyskawicznie. Jeśli jednak dane mają więcej niż 4KB (lub mniej, ale leżą w RAM po dwóch stronach granicy 4KB), to niestety nie jest to już takie proste. W takim przypadku trzeba zmienić trochę więcej niż te dwa bajty w DL. Jednak i tak jest to dużo szybsze i prostsze od przenoszenia ponad 7 tysięcy bajtów! Wracając do przykładu i do tego, co było napisane w komentarzach do nowinki, czyli przełączenia Antica na początek zmiennej. Bez pełnej modyfikacji DL wyjdą nam krzaki na ekranie, bo część ekranu będzie wyświetlana poprawnie - do momentu, gdy Antic dojdzie w odczycie danych ekranowch do tej nieszczęsnej granicy 4KB. Później na ekranie zobaczymy niekoniecznie to, co chcemy. Przełączmy zatem Antic na początek zmiennej E$: 120 DPOKE (DPEEK(560)+4),EK 130 GET KL
Ładne efekty? To jest właśnie efekt przekroczenia tych 4KB bez odpowiedniej modyfikacji DL.
Pytanko. Czy adres aktualnie wyświetlanego w grze ekranu też powinien być w DPEEK(DPEEK(560)+4)? Nie bardzo mi się to sprawdza. Mam tam 00. Pod DPEEK(88) mam adres $BC40, ale pisanie w tym obszarze nie wpływa na ekran, czyli to chyba też nie to....
te komorki maja znaczenie jesli jest wlaczony system operacyjny. 99% gier nie uzywa systemu operacyjnego (czesc go po prostu wylacza) wiec pod 560 nie bedzie adresu DListy.
Teraz rozumiem. Dzięki za pomoc :-) A tak btw jest jakiś prosty, albo chociaż średnio trudny sposób żeby odnaleźć pamięć ekranu, kiedy system jest wyłączony? Przecież Antic nadal bierze w tym udział...
Oczywiście. Zakładasz pułapkę na hardware-owy adres display listy i emulator sam zatrzyma się w miejscu, gdzie pod ów adres wisywana jest jakaś wartość.
W Atari800 jest to w monitorze, wpisujesz "B ?" i masz usecase.
A tak BTW, to pytania powstały przy okazji tworzenia mapy do Amaurote :-) Mam już prawie cały jeden dystrykt, ale to żmudna praca, nawet z wyłączonymi uszkodzeniami i przemieszczaniem arachnusa za pomocą wpisu do odpowiednich komórek. Ramka na ekranie mi przeszkadza, więc chcę ją wyłączyć. Obszar z "mapą" wiem gdzie jest, dzięki opisowi made by jhusak. Mam nawet częściowo rozpisane typy obiektów vs. wartość na mapie. Aha, jeszcze jedno. Mapa zaczyna się trochę wcześniej niż $C000. Coś koło $BED8.....
Direct Hit! To jest to! DL podawana przez .antic w Altirze i jej 4-ty i 5-ty bajt pokazują pamięć ekranu! Sprawdzone nadpisaniem kawałka - widać to na ekranie. Dziękuję za pomoc! Na forumowiczów zawsze można liczyć :-))))
Jeszcze raz dziękuję. Rozkminiłem wyświetlanie w Amaurote, mam teraz duży prostokątny ekran, bez "zbędnych" zębów. Tworzenie mapy powinno być łatwiejsze (o ile cierpliwości starczy). Pozdrawiam!
Podsyłam to co zrobiłem w marcu/kwietniu. Jest gotowe 8 dystryktów Amaurote, czyli 1/3. Zabrakło mi rozpędu, więc jeśli ktoś chce dokończyć dla dobra ogółu to ok. Chętnie pomogę opisując jak w GIMP'ie szybko nakładać kawałki bez przesuwania pikseli i dam wstawki modyfikujące grę w asm do szybkiego wklejenia w Altirrę (usuwa ramki, chowa muchy, scroll kursorem). Wersja .xcf z podziałem na warstwy też do dyspozycji. Nie wykluczam że będę miał "nawrót" weny i popchnę dalej, ale przy mojej metodzie nakład pracy jest b.duży.
tak mi przyszło do głowy, aby użyć rozszerzonej pamięci i tam przepisywać ekran, a następnie zrzucić (save state) całą pamięć i potem się z tym pobawić.
Ale chyba lepiej jest wyciąć muzykę (ok. 2.5 kb), dane arachnusa (1.5 kb) dane pszczółek (ca 3 kb), dane ramki, i można szaleć z dosem :) a właściwie to lepiej (bo dużo jednak danych) zapisywać sektorami na pustym image dysku od razu cały obraz...
Tak też sobie myślałem, zrzucać ekrany do pamięci lub na dysk. Rozwaliła mnie niestety ta izometria. To był mój największy problem przy łączeniu ekranów w GIMP´ ie. Nie żeby zaraz trudno, ale ciągłe nakładanie się dużej części ekranu z poprzednim zrzutem podwaja pracę....