forum speccy.pl
ZX Spectrum => GRAFIKA => Wątek zaczęty przez: Micky w 2013.02.03, 00:06:02
-
Jako kontynuacja watku z dzialu muzyki
http://speccy.pl/forum/index.php/topic,335.msg9786.html#msg9786 (http://speccy.pl/forum/index.php/topic,335.msg9786.html#msg9786)
Do tego celu uzywalem SGE a dzisiaj znalazlem Tile Molester i Tiledggd.
Wiecej na http://www.zophar.net/utilities/graphutil.html (http://www.zophar.net/utilities/graphutil.html)
SGE uzywalem wczesniej do prac zwiazanych z reverse engineering na roznych mikroprocesorach.
Ostatnio widzialem Renegade Levels http://www.worldofspectrum.org/infoseekid.cgi?id=0019052 (http://www.worldofspectrum.org/infoseekid.cgi?id=0019052) i chcialbym sie dowiedziec w jaki sposob zostaly wyciagniete grafiki. Prakryczne wskazowki mile widziane :)
-
Aaaach, Renegade :) Jedna z moich ulubionych gier. Całkiem sporo dłubałem przy tej grze i jak się kiedyś uda to wypuszczę do niej moda czyli grę z pozmienianym tym i owym.
To co zrobiono w tym demie to trochę bardziej zaawansowana szkoła jazdy niż proste wyciągnięcie sprajta ale podzielę się tym co wiem i pewnymi moimi sztuczkami :)
Dobrym nawykiem jest zacząć od SGE by spróbwać zobaczyć w trybie graficznym jak zapisane są dane
Trochę eksperymentów z szerokością kolumny i adresem początkowym i mamy coś takiego:
(http://www.image-share.com/upload/2071/144.png) (http://www.image-share.com/ipng-2071-144.html)
Nie wiem jak inni ale ja tu potrafię dostrzec bloczki (tiles) budujące tło ;), rozmiarów 8 na 8.
Jeśli przyjrzymy się ekranowi podczas gry to zobaczymy że niektóre takie bloczki jak np. okna, podłoga powtarzają się wiele razy. Stąd podejrzenie że obszar gry musi być zapisany w postaci jakieś mapy typu:
N11 N12 N13...
N21 N22 N23...
N31 N32 N33...
..... ..... .....
Gdzie np. N21 to numer wyświetlanego bloczka w drugim rzędzie i pierwszej kolumnie.
Później okaże się że istotnie tak jest :)
cdn...
-
właśnie o to mi chodziło - interesuje mnie metodologia jak szukać odnośników do tych 'cegiełek',
czyli gdzie i jak jest zakodowana mapa.
Z niecierpliwością czekam na kolejne odcinki :)
p.s. Renegade i u mnie cieszyło się dużym wzięciem :)
EDIT: jeśli admini nie mają nic przeciwko, to dołącz proszę plik r2.sna na którym pracujesz - będą pliki do tutoriala :)
-
Plik to zwykły snapshot zrobiony na pierwszym poziomie.
Jedna uwaga do Renegade - kod wersji pod 48 kB i 128 kB dość istotnie się różni. Ja bawiłem się wersją 48 kB i moje dotychczasowe i dalsze postępowanie tej wersji dotyczy.
Co robimy dalej?
Przyjrzyjmy się ekranowi i polu gry. Czasem w grach jest one węższe niż 256 pikseli, ale w przypadku Renegade zajmuje ono całą szerokość ekranu i zaczyna się na samej górze. Dlatego możemy przyjąć że lewy górny bloczek mapy zostanie skopiowany pod adres 16384 - początek pamięci ekranu Spectrum.
(http://www.image-share.com/upload/2072/120.png) (http://www.image-share.com/ipng-2072-120.html)
-
Użyjemy dalej emulatora Spin v0.7 Wersja jest ważna, bo wcześniejsze wersje nie potrafią robić pewnych rzeczy.
Wczytujemy grę do emulatora. Jest menu i leci muzyka. Wchodzimy w debugger i ustawiamy breakpoint Tools/Debugger/Breakpoints/SetBreakpoint
(http://www.image-share.com/upload/2072/125.png) (http://www.image-share.com/ipng-2072-125.html)
Ważne by wyczyścić pole Adres. Inaczej nasz warunek będzie sprawdzany tylko wtedy gdy wykonujemy rozkaz pod danym adresem a chcemy wejść do debuggera zawsze gdy odbywa się zapis pod adres 16384
-
To może powstałby z tego interesujący artykuł w dziale Technikalia? ;-)
-
Zatwierdzamy breakpoint (emulator spyta czy na pewno) i zaczynamy grę
Emulator powinien prawie od razu wejsc do debuggera. Okazuje się że najpierw ustrzeliliśmy coś takiego:
ld hl, 16384 ; 40521
ld de, 16385 ; 40524
ld bc, 6144 ; 40527
ld (hl), l ; 40530
ldir ; 40531
Tutaj niestety trzeba znać assembler. Jak ktoś nie zna to nic dalej nie zrobi, ale jak zna to widzi że jest to czyszczenie ekranu. Dajemy "Kontynuuj" i za chwilę powinniśmy mieć coś takiego:
39481: ld ix, (24444)
39485: ld de, 22528
39488: ld c, 32
39490: push de
39491: ld b, 17
39493: push bc
39494: push de
39495: ld l, (ix+0)
39498: set 7, l
39500: ld h, 127
39502: ld a, (hl)
39503: ld (de), a
39504: ld a, d
39505: and 3
39507: rlca
39508: rlca
39509: rlca
39510: add a, 64
39512: ld d, a
39513: res 7, l
39515: ld h, 16
39517: add hl, hl
39518: add hl, hl
39519: add hl, hl
39520: ld b, 8
39522: ld a, (hl) <------------- tutaj mamy kopiowanie bloczka
39523: ld (de), a
39524: inc l
39525: inc d
39526: djnz 39522
39528: pop de
39529: ld hl, 32
39532: add hl, de
39533: ex de, hl
39534: inc ix
39536: pop bc
39537: djnz 39493
39539: pop de
39540: inc e
39541: dec c
39542: jr nz, 3949
I tu się muszę chwilę zastanowić :) Widzimy że kopiowanie 8 bajtów bloczka jest w adresie 39552 i dane są kopiowane spod adresu 33432 pod adres 16384 (trzeba spojrzeć na wartości rejestrów w debuggerze)
-
To może powstałby z tego interesujący artykuł w dziale Technikalia? ;-)
Można pomyśleć ;) Na razie mam wenę więc jadę dalej ;)
-
Trochę przeanalizowałem kod i wyszło mi że:
- w 39480 jest RET więc nowa procedura zaczyna się w 39481
- DE jest na początku procedury ustawiane na 22528 - początek pamięci atrybutów
- w rozkazie pod adresem 39503 kopiujemy do wspomnianych atrybutów wartość przechowywaną w HL
-wartość w HL jest wyliczana tak że czytamy L z (IX+0), ustawiamy 7 bit a H ustawiamy na sztywno H=127; Intuicja podpowiada mi tutaj że na każdym poziomie jest możliwych 128 bloczków i L czytane z (IX+0) może mieć wartości 0-127
- patrzę w okienko z rejestrami i widzę że IX=31892, czyli tam muszą się zaczynać dane mapy!!!
39481: ld ix, (24444) -------pod adresem 24444 musi być początek danych mapy !!!
39485: ld de, 22528
39488: ld c, 32 ------------------32 kolumny bloczków
39490: push de
39491: ld b, 17 -------------------17 bloczków w każdej kolumnie
39493: push bc
39494: push de
39495: ld l, (ix+0) --------- L musi być numerem bloczka !!!!
39498: set 7, l
39500: ld h, 127
39502: ld a, (hl) ------------czytaj spod adresu 127*256+128+L=32640+L
39503: ld (de), a ------------pisz atrybut bloczka (bo de=22528 a to obszar atrybutów)
-
Można to zresztą sprawdzić czy tam rzeczywiście dane mapy zaczynają się od 31892
W tym celu będać dalej w debugerze zatrzymanym na breakpoincie zmienie parę wartości zaraz po adresie 31892
Widzę że w Spinie robi się to jakoś niewygodnie więc może nie będę tego opisywał. W tym momencie możemy z resztą zrobić tak:
- uruchamiamy dowolny emulator i wczytujemy Renegade
- ustawiamy breakpoint (tym razem już najzwyklejszy) na adresie 39481 który już poznaliśmy
- uruchamiamy grę
- gdy emulator wejdzie do debuggera zmieniamy kilka wartości komórek po adresie 31892. Ja zmieniałem je na wartość 20.
-Dajemy "Kontynuuj"
Efekt:
(http://www.image-share.com/upload/2072/147.png) (http://www.image-share.com/ipng-2072-147.html)
Działa ! :) Widzimy teraz wyraźnie że plansza jest rysowana kolumnami, od góry do dołu i od lewej kolumny do prawej.
Pojawiają się teraz dalsze pytania - czy adres mapy gry który znaleźliśmy to już ostateczny adres pod którym jest ona przechowywana, czy też jest to jakiś bufor do którego zostały one skopiowane/rozpakowane jeszcze spod jakiegoś innego adresu.
Ale ja już zatrzymam się w tym miejscu.... ;)
I tak to wygląda. Programista który napisał Renegade miał koncepcję i zamienił ją na instrukcje, my poruszamy sie w drugą stronę - na podstawie instrukcji próbujemy odgadnąć jego koncepcję. Jest to trochę żmudne i nie da się ukryć że trzeba się orientować w assemblerze ale też daje satysfakcję.
KONIEC :)
-
Tygrys, jeśli uważasz że się to nadaje to daj jakieś wskazówki i mogę to przerobić na artykuł.
-
Oczywiście że się nadaje! ;-)
-
Zaglądanie za kulisy zawsze jest interesujące!
Szkoda że nie piszę właśnie dema, czy czegoś. Podane na tacy. :D
-
@RafalM - o coś takiego mi właśnie chodziło! Serdecznie dziękuję za wyjaśnienia i poświęcony czas - przy najbliższym spotkaniu masz u mnie złocisty
nektar zwanym piwem :)
Ja spróbuję swoich sił przy innej grze jak tylko czas mi pozwoli i podzielę się spostrzeżeniami.
I tak to wygląda. Programista który napisał Renegade miał koncepcję i zamienił ją na instrukcje, my poruszamy sie w drugą stronę - na podstawie instrukcji próbujemy odgadnąć jego koncepcję. Jest to trochę żmudne i nie da się ukryć że trzeba się orientować w assemblerze ale też daje satysfakcję.
Dlatego reverse engineering jest taki ekscytujący a wiedza, którą do tego trzeba posiadać jest dużo większa niż tego co ten program pisał :)
-
Po długim czasie udało się przerobić powyższy wątek na artykuł. Jest tam w zasadzie to samo co tutaj powyżej, ale troszkę też rozbudowałem, dodałem linki i napisałem nieco staranniej. Jakby ktoś miał ochotę to zachęcam do poczytania:
http://www.speccy.pl/articles.php?article_id=24
-
Juz przeczytalem :)
Moim zdaniem rewelacja !
-
Tak, świetny artykuł! Oby więcej takich ;)
Poza tym, tekst się trochę przeleżał, ale to z mojej winy (niektórzy zauważyli że praktycznie zniknąłem prawie na tydzień).
-
Trochę to skomplikowane (czytałem artykuł). Bez debuggera i assemblera można też się obyć :)
Wystarczy w emulatorze wcisnąć pauzę (w Spin jest to F3 lub klawisz Pause/Break),
wejść do menu i zapisać ekran jako .scr, snapshot lub plik binarny. Później kolejny ekran itd.
Wyciągnąć sprite można w Art Studio, po załadowaniu obrazka (binary ładuje się pod 24320).
Zaznaczyć okno Window/Define Window, następnie Text/Font Editor/Capture Font.
Przeniesie zawartość okna do edytora, który później można zapisać jako plik 768B.
W Fuse można także zapisać jako tap/tzx lub dysk.
-
Zalezy do czego.
Jesli chce sie zobaczyc ukryte poziomy to sposob Rafala jest jedynym
-
Piszesz trochę o czymś innym.
Jeśli chcemy po prostu dostać sprajty czy czcionki to rzeczywiście wystarczy robić zrzuty ekranu.
Chociaż moim zdaniem Sge i tak jest tutaj lepszym rozwiązaniem. Dostajemy sprajty w czystej postaci, nie musimy się zastanawiać czy jakiś piksel należy jeszcze do sprajta czy już do tła. Dostajemy maski od sprajtów, których na ekranie przecież wprost nie widać.
Moim celem jest nie tyle wyripować grafikę, ale raczej zrozumieć jak jest napisana gra. A akurat o Renegade napisałem nie bez przyczyny. Być może już gdzieś wspominałem że jednym spośród moich różnych projektów jest zrobienia moda do Renegade - zmodyfikowanej wersji z podmianą grafiki, niektórych opcji gry.
Zresztą co ja się będę rozpisywał :) Może pokaże screenshot z work in progress :
(http://www.image-share.com/upload/2115/.png) (http://www.image-share.com/ipng-2115-.html)
-
fajny ten progress ;)
Ja uzywam licz dzisietnych z powodzeniem. :)
-
Zmieniając temat, co to się dzisiaj dzieje ze wstawionymi obrazkami? Czy też macie jakieś zupełnie inne rzeczy niż normalnie?
-
Ja odkod sie temat pojawil mam jakies nienormalne, z bledami windowsa, czy skanem antywirusa, a teraz z jakiejs gry na PC...
-
Rafał, załączaj obrazki do swoich postów, wtedy nie będzie problemu wynikającego z błędnego(?) działania zewnętrznych serwisów.
-
Ale w Twoim ostatnim poscie tez jest screen z instalacji jakiegos sterownika na PC...
-
Zgadza się. Jest to kopia obrazka, który pojawił się zamiast, jak się domyślam, tego właściwego.
Teraz jest na przykład ten w moim załączniku.
-
Czy to jest podgląd na czyjś pulpit???