Marca 28, 2024, 09:31:02 *
Witamy, Gość. Zaloguj się lub zarejestruj.

Zaloguj się podając nazwę użytkownika, hasło i długość sesji
Aktualności:
Nowa strona główna  : http://www.emunes.pl
Zapraszamy do testowania !

Chat: http://chat.emunes.pl
Galeria cartów: http://carts.emunes.pl
 
   Strona główna   Pomoc Zaloguj się Rejestracja  

Reklama
Strony: [1]
  Drukuj  
Autor Wątek: Sposoby debugowania i analizy kodu ROM'ów.  (Przeczytany 3757 razy)
0 użytkowników i 1 Gość przegląda ten wątek.
CodAsm
Szeregowy
*
Offline Offline

Wiadomości: 49


« : Kwietnia 28, 2012, 07:29:40 »

Nie zauważyłem, żeby istniał już wcześniej wątek dotyczący zabawy ze zdeasemblowanym kodem 6502 i debuggerem. Oczywiście są wątki traktujące o konkretnych HACKACH gier jak Green Dizzy. Celem, który przyświeca mi przy zakładaniu tego wątku jest chęć dowiedzenia się jak robią to ludzie, którzy mają nieco doświadczenia w romhackingu (a może i w modyfikacji kodu ROM'ów). Nie pytam o adresy do kokretnych gier, bo wiem ile trzeba się nasiedzieć, żeby coś znaleźć. Poza tym z pomocą przychodzą takie źródła informacji jak:
http://romhacking.net.
http://datacrystal.romhacking.net/
http://www.the-interweb.com/serendipity/index.php?/categories/1-Faxanadu/P2.html

Ale jak usystematyzować metody używane przez osobę analizującą ROM'y. Jak nie pogubić się w gąszczu adresów i wybierać te, które faktycznie mają dla nas znaczenie? Ogólne metody, których ja używałem dotychczas to:

*Spojrzenie na koniec ROM'u i sprawdzenie adresów wektorów przerwań
*Jeżeli chcę dostać się do kodu ładującego grafikę zastawiam breakpointy na odczyty/zapisy $2006 lub $2007
*Jeżeli chcę dostać się do kodu ładującego dźwięk zastawiam breakpointy na odczyty zapisy do portów $4000-$4017 (wyłączając port $4014 do transferów DMA (choć przy DMC też się go używa do transferu sampli) oraz port $4016 służący do obsługi pada i odczyt portu $4017)
*Po znalezieniu np. procedur graficznych idziemy po sznurku i szukamy procek, które je wywołują i z jakich tablic pobierają dane (podobnie z prockami APU)
*Po ograrnięciu działania procek graficznych odnalezienie danych grafiki (i ewentualnie procedury dokonującej dekompresji grafiki)

 Przykładowe problemy:
*Jak znaleźć procki ładujące kolumnę Tilesów z bufora? (bo bufor kolumny Tilesów pojawia się w w wielu grach)
*Jak znaleźć procki wykrywające kolizję? (zapewne dużo instrukcji cmp, ale co dalej?)
*Jak znaleźć dane grafiki tła (jak dość po sznurku do odczytów z tablic zawierających dane Metatilesów, tablic układających ich indeksy w ekrany i wreszcie tablic układających indeksy ekranów w poziomy?)
*Jak dostać się do kodu obsługującego "inteligencję" ruchu przeciwników?
*Jak poradzić sobie z ROM'ami, które zawierają dużo banków ROM?
*Jak znaleźć odczyty/zapisy rejestrów mappera?
*Jak znaleźć i rozpracować tablice skoków RTS?
*Jak poradzić sobie z kodem samomodyfikującym?
*Jaki debugger radzi sobie z deasemblacją wszystkich banków PRG w locie? (zdaje się, że ten załączony do FCEU tego nie potrafi)
*Czy język skryptowy LUA obsługiwany przez emulatory FCEU może wspomóc debugging?

Wiele czasu bawiłem się różnymi ROM'ami i w większości przypadków zniechęcałem się gubiąc się w gąszczach adresów. I praktyka pokazuje, że jestem jednak laikiem w tym temacie. Moje pytanie brzmi: jak robią to doświadczone osoby i jakich narzędzi (np. z RHDN) używają?Smile
« Ostatnia zmiana: Kwietnia 28, 2012, 07:46:23 wysłane przez CodAsm » Zapisane
Dizzy9
Nadworny programista.
Kapitan
****
Offline Offline

Wiadomości: 351



WWW
« Odpowiedz #1 : Maja 04, 2012, 01:32:14 »

Cytuj
Celem, który przyświeca mi przy zakładaniu tego wątku jest chęć dowiedzenia się jak robią to ludzie, którzy mają nieco doświadczenia w romhackingu
Nie jestem jakimś wybitnym przypadkiem geniuszu, ale spróbuję coś popisać.

Ponieważ nie wiem czy powinienem sypać jakimś kodem, póki co się wstrzymam.

Cytuj
Jeżeli chcę dostać się do kodu ładującego grafikę zastawiam breakpointy na odczyty/zapisy $2006 lub $2007
Jeśli gra ma CHR ROM to nie wiele Ci to da.Jest tak dlatego że procesor nie zapisuje danych graficznych do 2007\2006 gdy gra posiada CHR ROM.Gra zapisuje w takiej sytuacji numer banku CHR do odpowiedniego rejestru.
Po za tym ja bym sprawdzał zapis na dane grafiki a nie rejestry, te są często modyfikowane przed zapisem danych i można dostać...eee..wkurzyć się czekając "aż w końcu kod dojdzie do tego momentu o który mi chodzi".

Cytuj
Jak znaleźć procki ładujące kolumnę Tilesów z bufora? (bo bufor kolumny Tilesów pojawia się w w wielu grach)
Ja robię to tak.Podczepiam się pod podmieniany Tiles w PPU.Jeśli wiesz gdzie jest buffer to jest jeszcze łatwiej-możesz ustawić breakpoint na jakąś wartość buffora.

Cytuj
Jak znaleźć procki wykrywające kolizję? (zapewne dużo instrukcji cmp, ale co dalej?)
Hm, nigdy takiego czegoś nie szukałem, poza Dizzy Adventurer.Ta gra jednak nie jest chyba najlepszym przykładem.Wziąłem więc sobie przed chwilą i sprawdziłem  na grze TTNTII. Postanowiłem znaleźć hitbox żółwi.Najpierw znalazłem Licznik HP żółwia.Logiczne jest że od licznika zostanie odjęta wartość tylko gdy przeciwnik go zaatakuje, a hitbox ataku wroga będzie w hitboxie gracza.Nastawiłem breakpoint na HP gracza.Potem już tylko po sznurku.Instrukcje cmp są, bo muszą być, ale o wiele większe znaczenie mają adresy z których dane do porównania są wczytywane:) Dane hiboxów były odczytywane z tablicy.Na marginesie, jakby ktoś był ciekawy, powiem że Raphael jako jedyny ma inne wymiary hitboxów.
PS.Fajnie jest zabijać wrogów z odległości 3 metrów naughty

Cytuj
Jak znaleźć dane grafiki tła (jak dość po sznurku do odczytów z tablic zawierających dane Metatilesów, tablic układających ich indeksy w ekrany i wreszcie tablic układających indeksy ekranów w poziomy?)
Breakpoint na Name Table.Najczęściej będzie to wczytanie z Meta tilesów.Zależnie od tego co pokazuje kod, należy dojść po sznurku do miejsca gdzie jest pobieranie ID Meta Tilesa.Może to być na różne sposoby.Użycie pointerów z tablicy, multiplikacja adresu czy zwykłe użycie Y lub X.

Cytuj
Jak dostać się do kodu obsługującego "inteligencję" ruchu przeciwników?
Jeśli przeciwnik może się ruszyć w prawo\lewo\skakać itp, itd. to wystarczy break point to zmieniany przez niego zmienne, nie? Załóżmy że AI wroga jest proste.Wróg stoi w miejscu aż gracz nie podejdzie do niego na odległość 30 pikseli.Wtedy wróg strzela.Kiedy to się dzieje musi być wygenerowany pocisk, oczywiste.
Wystarczy się podpiąć pod miejsce gdzie ma być zapisany np. X pocisku i sprowokować wroga do strzału.potem po sznureczku do sprawdzania czy gracz jest w zasięgu.

Cytuj
Jak poradzić sobie z ROM'ami, które zawierają dużo banków ROM?
Nie rozumiem pytania.

Cytuj
Jak znaleźć odczyty/zapisy rejestrów mappera?]
Nie zbyt rozumiem, ale jeśli chodzi "jak znaleźć możliwe rejestry mappera" to zlokalizuj mapper gry i użyj numeru mappera by znaleźć info w
Dokumentacji mapperów Disch'a.

Cytuj
Jak znaleźć i rozpracować tablice skoków RTS?
Jeśli Ci chodzi o RTS Trick to..poczytaj artykuł kilka razy, w końcu załapiesz.

Cytuj
Jak poradzić sobie z kodem samomodyfikującym?
Przyznam że się z takim nie spotkałem, więc nie mam na to odpowiedzi.

Reszta pytań-Brak odpowiedzi.

Cytuj
jak robią to doświadczone osoby i jakich narzędzi (np. z RHDN) używają?
Jak pisałem wyżej, nie jestem dobrym programistą, więc jak ktoś zauważył błąd w tym co napisałem to niech mnie poprawia:)
BT:Ja używam FCEUX do debugowania, Tile molester do bazgrania, Hex Workshop do grzebania w hexie.Czasem też używam NESASM jako narzędzia do szybkiego wytwarzania i wstrzykiwania kodu.Niestety, nie mam żadnego portfolio, ponieważ dwa hacki które z tego by korzystały są ciągle (i pewnie przez jeszcze jakiś czas) nie skończone.
« Ostatnia zmiana: Maja 04, 2012, 01:43:47 wysłane przez Dizzy9 » Zapisane

CodAsm
Szeregowy
*
Offline Offline

Wiadomości: 49


« Odpowiedz #2 : Maja 04, 2012, 12:51:05 »

Cytat: Dizzy9
Ponieważ nie wiem czy powinienem sypać jakimś kodem, póki co się wstrzymam.
Jeżeli chodzi o kod to chętnie bym spojrzał. Mój odwieczny problem zawsze polegał na gubieniu się w tysiącach wierszy i całych garściach adresów, które najczęściej nie prowadziły do żadnego ciekawego miejsca. (Albo tak mi się zdawało).
Jeżeli masz rozkminiony jakiś kod z grafiką Dizzy choćby najkrótszy fragment, to jeszcze chętniej.Smile

Cytat: Dizzy9
Jeśli gra ma CHR ROM to nie wiele Ci to da.Jest tak dlatego że procesor nie zapisuje danych graficznych do 2007\2006 gdy gra posiada CHR ROM.Gra zapisuje w takiej sytuacji numer banku CHR do odpowiedniego rejestru.
Po za tym ja bym sprawdzał zapis na dane grafiki a nie rejestry, te są często modyfikowane przed zapisem danych i można dostać...eee..wkurzyć się czekając "aż w końcu kod dojdzie do tego momentu o który mi chodzi".

Trochę nie rozumiem tego akapitu. Może jestem w błędzie, ale zawsze mi się zdawało, że rejestry $2006/$2007 to jedyna droga, którą Tiles'y mogą się wydostać z Pattern Tables do VRAM (a dokładniej indeksy Tilesów zapisanych w Pattern Tables). Oczywiście jeżeli Pattern Tables istnieją (bo wszystko może być w PRG-ROM). Inną sprawą jest fakt, że jeżeli jest kilka banków CHR-ROM to po przełączeniu aktualnego banku CHR za pomocą rejestru mappera, pod tym samym indeksem ma się już inny Tiles. A żadna poważniejsza gra niestety nie będzie korzystać z NROM. Jeżeli chodzi o gry CHR-RAM to, jeżeli dobrze rozumiem dane są w locie ładowane z PRG-ROM do pamięci CHR-RAM. Słyszałem jeszcze o grach z VROM wbudowanym w karta. Natomiast zdaję sobie sprawę, że mogą istnieć krótsze metody i najprościej świecie mogłem czegoś dokładnie nie doczytać.

Cytat: Dizzy9
Ja robię to tak.Podczepiam się pod podmieniany Tiles w PPU.Jeśli wiesz gdzie jest buffer to jest jeszcze łatwiej-możesz ustawić breakpoint na jakąś wartość bufora.
Cytat: Dizzy9
Breakpoint na Name Table.Najczęściej będzie to wczytanie z Meta tilesów.Zależnie od tego co pokazuje kod, należy dojść po sznurku do miejsca gdzie jest pobieranie ID Meta Tilesa.Może to być na różne sposoby.Użycie pointerów z tablicy, multiplikacja adresu czy zwykłe użycie Y lub X.

Próbowałem tak, ale gubiłem się w miejscu, w którym metatiliesy są dzielone na pojedyńcze Tilesy, które idą do kolumny. Gubię się w pointerach najprościej mówiąc. Czuję, że mam zbyt bałaganiarski sposób notowania i wyłuskiwania istotnych adresów.

Cytat: Dizzy9
Hm, nigdy takiego czegoś nie szukałem, poza Dizzy Adventurer.Ta gra jednak nie jest chyba najlepszym przykładem.Wziąłem więc sobie przed chwilą i sprawdziłem  na grze TTNTII. Postanowiłem znaleźć hitbox żółwi.Najpierw znalazłem Licznik HP żółwia.Logiczne jest że od licznika zostanie odjęta wartość tylko gdy przeciwnik go zaatakuje, a hitbox ataku wroga będzie w hitboxie gracza.Nastawiłem breakpoint na HP gracza.Potem już tylko po sznurku.Instrukcje cmp są, bo muszą być, ale o wiele większe znaczenie mają adresy z których dane do porównania są wczytywane:) Dane hiboxów były odczytywane z tablicy.Na marginesie, jakby ktoś był ciekawy, powiem że Raphael jako jedyny ma inne wymiary hitboxów.

Cytat: Dizzy9
Cytat: CodAsm
Jak dostać się do kodu obsługującego "inteligencję" ruchu przeciwników?
Jeśli przeciwnik może się ruszyć w prawo\lewo\skakać itp, itd. to wystarczy break point to zmieniany przez niego zmienne, nie? Załóżmy że AI wroga jest proste.Wróg stoi w miejscu aż gracz nie podejdzie do niego na odległość 30 pikseli.Wtedy wróg strzela.Kiedy to się dzieje musi być wygenerowany pocisk, oczywiste.
Wystarczy się podpiąć pod miejsce gdzie ma być zapisany np. X pocisku i sprowokować wroga do strzału.potem po sznureczku do sprawdzania czy gracz jest w zasięgu.

Wiele jest tutoriali w necie o ROMHACKING'u, ale zawsze brakowało mi takich, które w kilku zdaniach potrafią tak zrozumiale opisać w jednym akapicie, jak dostać się do porcji kodu o danej funkcjonalności i jak to rozumieć bardziej wysokopoziomowo.

Cytat: CodAsm
Jak poradzić sobie z ROM'ami, które zawierają dużo banków ROM?
Miałem na myśli banki CHR-ROM/PRG-ROM.

Cytuj
Jak znaleźć odczyty/zapisy rejestrów mappera?

Cytat: Dizzy9
Cytat: CodAsm
Jak poradzić sobie z kodem samomodyfikującym?
Przyznam że się z takim nie spotkałem, więc nie mam na to odpowiedzi.

NMI z gry Chip&Dale2 wygląda tak:

Kod:
07:FFE0:78          SEI
07:FFE1:EE E1 FF  INC $FFE1 = #$EE
07:FFE4:D8          CLD
07:FFE5:4C 00 C0  JMP $C000

Druga instrukcja (inc) nadpisuje samą siebie. Po tej czynności zamiast opkodu $ee będzie $ef. Jeżeli dobrze sprawdziłem to $ef jest nieudokumentowanym opkodem ISC $FFE1, który robi coś takiego:

{adr} = {adr}+1;
A       = A-{adr};


Czyli:

{$FFE1} = {$FFE1}+1;
A = A-{$FFE1};


Niespodzianką jest, że dalej powstała kolejna samomodyfikująca się instrukcja...Więc sprawdzając dalej mamy instrukcję $f0 czyli

  
Kod:
BEQ $FFE1 ; // Sprawdz czy ustawione zero

I w tym miejscu się gubię, bo to tak jakby kod miał się zapętlić do kolejnego NMI/IRQ?
« Ostatnia zmiana: Maja 04, 2012, 13:20:53 wysłane przez CodAsm » Zapisane
Koks
Major
*****
Offline Offline

Wiadomości: 580



« Odpowiedz #3 : Maja 04, 2012, 13:44:22 »

Kod:
07:FFE1:EE E1 FF  INC $FFE1 = #$EE
Zapis pod adresem należącym do ROMa nie zmienia jego zawartości, tylko wysyła coś do mappera, możliwe że to jest wykonywane tylko raz po resecie i służy do zmiany banku.
Zapisane

Częste mycie skraca życie.
"If you have a fast, shiny new Pentium II, you might try using 44 kHz for the ultimate in sound quality." - readme od Unreala
https://drive.google.com/folderview?id=0B2TXQD5v-ZIVfjVQdTl2TTZiWmJ2LWZJajJzS0V4cDZBay04WjVGQkdQdnBDQzRlYkdQVGc&usp=sharing
Dizzy9
Nadworny programista.
Kapitan
****
Offline Offline

Wiadomości: 351



WWW
« Odpowiedz #4 : Maja 04, 2012, 15:42:14 »

Cytuj
Jeżeli masz rozkminiony jakiś kod z grafiką Dizzy choćby najkrótszy fragment, to jeszcze chętniej.
.Rozkimanie kompresji grafiki to męcząca robota, po za tym nie pisałem jakim kodem mógłbym sypnąć więc wyciągnę to co już mam.

Cytuj
05:8B36:A9 68     LDA $0068 = #$25   
05:8B38:C9 23     CMP #$23      ;Jeżeli animacja brania NIE równa 23(dizzy się nachyla)
05:8B3A:D0 30     BNE $8B6C      ;To skocz do "Rysuj_Dozy_Zzz"

05:8B3C:A9 0E     LDA #$0E      ;Załaduj ID postaci
05:8B3E:20 1F C9  JSR $C91F      ;Skocz do rutyny sprawdzania położenia dizzy
05:8B41:90 29     BCC $8B6C      ;jeżeli w strefie to skocz do "Rysuj_Dozy_Zzz"

05:8B43:A9 73     LDA #$73
05:8B45:8D 17 06  STA $0617 = #$73   ;Zapisz postać diza w rozmowie

05:8B48:A9 76     LDA #$76
05:8B4A:8D 18 06  STA $0618 = #$85   ;Zapisz postać Dozy'ego w rozmowie

05:8B4D:A2 4A     LDX #$4A
05:8B4F:A0 09     LDY #$09

05:8B51:AD C1 03  LDA $03C1 = #$01   ;Sprawdź czy już było gadane z Dozym
05:8B54:F0 0B     BEQ $8B61      ;Jeśli nie(wartość 00) to skocz do "Dozy_Gada_Pierwszy"

05:8B56:30 14     BMI $8B6C      ;Jeżeli mniejsze w zasięgu 80 to skocz do"Rysuj_Dozy_Zzz"

05:8B58:A9 FF     LDA #$FF
05:8B5A:8D C1 03  STA $03C1 = #$01   ;Ustaw ze Dozy wyczerpał limit wypowiedzi;]

05:8B5D:A2 1D     LDX #$1D
05:8B5F:A0 0A     LDY #$0A

Dozy_Gada_Pierwszy:
05:8B61:A9 01     LDA #$01
05:8B63:8D C1 03  STA $03C1 = #$01   ;Ustaw ze pierwszy raz już gadałeś z Dozym

05:8B66:20 1D CB  JSR $CB1D      ;Wywołaj dialog z Dozym(w Y ID a w X...coś?)

Rysuj_Dozy_Zzz:
05:8B6C:A5 16     LDA $0016 = #$87   ;Pobierz globalny licznik
05:8B6E:4A        LSR         ;Przesuń bity w prawo(dzielenie)
05:8B6F:4A        LSR
05:8B70:4A        LSR
05:8B71:4A        LSR
05:8B72:4A        LSR
05:8B73:29 01     AND #$01      ;Wyczyść bit 0
05:8B75:18        CLC         ;Czyść Carry
05:8B76:69 4D     ADC #$4D      ;Dodaj 4D
05:8B78:A2 94     LDX #$94      ;Załaduj do X 94
05:8B7A:A0 7B     LDY #$7B      ;Załaduj do Y 7B
05:8B7C:20 2B FA  JSR $FA2B      ;Skocz do rysowania Dozy'ego
05:8B7F:A2 9A     LDX #$9A      
05:8B81:A0 69     LDY #$69
05:8B83:A5 16     LDA $0016 = #$87
05:8B85:4A        LSR
05:8B86:4A        LSR
05:8B87:4A        LSR
05:8B88:29 07     AND #$07
05:8B8A:18        CLC
05:8B8B:69 A2     ADC #$A2
05:8B8D:4C 2B FA  JMP $FA2B      ;Skocz do rysowania Zzz
Łatwiejszy kod-Kompletny skrypt dla Dozy.

Cytuj
Może jestem w błędzie, ale zawsze mi się zdawało, że rejestry $2006/$2007 to jedyna droga, którą Tiles'y mogą się wydostać z Pattern Tables do VRAM (a dokładniej indeksy Tilesów zapisanych w Pattern Tables).
Tak, ale ty napisałeś że szukasz kodu ładującego grafikę, nie Name Table.

Cytuj
jak dostać się do porcji kodu o danej funkcjonalności i jak to rozumieć bardziej wysokopoziomowo.
To nie zabrzmi miło, ale musisz więcej się przyłożyć do zrozumienia assemblera i tyle.

Cytuj
Miałem na myśli banki CHR-ROM/PRG-ROM.
To dalej mi nie pomaga.Jakie konkretnie masz pytanie? Bo "Jak sobie poradzić z bankami PRG ROM\CHR ROM" niewiele mi mówi.
Jak rozpoznać ich przełączanie? Jak wyszukiwać kod\dane w banku który nie jest obecnie w CPU?

Odnośnie tego kodu co zapodałeś (Chip i Dales2) to jest jak mówi kolega Koksu.Kod w obszarze PRG nie może sam się zmodyfikować.Niektóre gry zapisują kod do wykonania w RAMie i tam może, ale nie w PRG ROM.A co te "NMI" robi, już wyjaśniam.

Używając dokumentacji do których zapodałem wcześniej linki łatwo ustaliłem że mapper to MMC1.Mapper ten, wg dokumentacji Disch'a ma banki PRG zawsze losowo ustawione banki PRG przy resecie.
Podczas pomocy Alzenowi przy jego hacku Siliusa dowiedziałem się jak gra radzi sobie z takim problemem(Silius to także MMC1).Otóż rozwiązanie jest proste należy w każdym banku zwyczajnie trzymać kopię pointerów do przerwań i mieć tą samą funkcję.Nie ważne który bank zostanie przełączony-wynik będzie zawsze taki sam.A Co dokładnie robi ten kod?
Robi zapisz na obszarze PRG, oczywiście.Powiesz "Aleś wyjaśnił". No właśnie, dużo! Po sprzawdzeniu (po raz kolejny) dokumentacji Disch'a odkrywamy
Cytuj
  $E000-FFFF:  [...W PPPP]
    W = WRAM Disable (0=enabled, 1=disabled)
    P = PRG Reg
Ponieważ liczba którą zwiększamy poleceniem INC to EE, zwiększy się na EF.Używając kalkulatora odkryjemy że $EF to binarne 11101111.
Teraz, 3 ostatnie bity zostają odrzucone.(Pamiętamy ze bit 0 to ten po prawej, bit 7 to ten po lewej).Potem mamy 0 które odpowiada nam za WRAM-Gra nie będzie używać WRAMu.Pozostałe bity oznaczają nam numer banku PRG-zostanie on przełączony na najwyższy możliwy.I to tyle.Potem gra już robi te swoje czary mary by wystartować.

Cytuj
I w tym miejscu się gubię, bo to tak jakby kod miał się zapętlić do kolejnego NMI/IRQ?
Żeby było jasne-"BEQ $FFE1 ; // Sprawdz czy ustawione zero" nigdy się nie wydarzy(w tamtym momencie) gdyż, jak rzekł Koksu, nie można modyfikować PRG ROM.

Cytuj
Próbowałem tak, ale gubiłem się w miejscu, w którym metatiliesy są dzielone na pojedyńcze Tilesy, które idą do kolumny. Gubię się w pointerach najprościej mówiąc. Czuję, że mam zbyt bałaganiarski sposób notowania i wyłuskiwania istotnych adresów.
Kiedyś miałem ochotę zrobić jakiś video tutorial, ale brakowało mi chęci...może tym razem...
Zapisane

CodAsm
Szeregowy
*
Offline Offline

Wiadomości: 49


« Odpowiedz #5 : Maja 04, 2012, 23:36:53 »

Cytat: Koks
Kod:
07:FFE1:EE E1 FF  INC $FFE1 = #$EE
Zapis pod adresem należącym do ROMa nie zmienia jego zawartości, tylko wysyła coś do mappera, możliwe że to jest wykonywane tylko raz po resecie i służy do zmiany banku.

To co napisałem pod koniec ostatniego posta było głupie, bo trochę zapomniałem, że mowa o  (PRG)ROM Tongue. Wielkie dzięki za uświadomienie mnie i wyprowadzenie z błędu Koks. I Tobie Dizzy9 również dzięki za stos informacji.

Cytat: Dizzy
Otóż rozwiązanie jest proste należy w każdym banku zwyczajnie trzymać kopię pointerów do przerwań i mieć tą samą funkcję.Nie ważne który bank zostanie przełączony-wynik będzie zawsze taki sam.

To rozwiązanie chyba rozumiem. Po prostu w każdym banku PRG-ROM skopiowane są adresy wektorów przerwań (Reset,IRQ,NMI). Natomiast nie jestem pewien czy kopiowany jest ich kod.

Cytat:  Dizzy9
Ponieważ liczba którą zwiększamy poleceniem INC to EE, zwiększy się na EF.Używając kalkulatora odkryjemy że $EF to binarne 11101111.
Teraz, 3 ostatnie bity zostają odrzucone.(Pamiętamy ze bit 0 to ten po prawej, bit 7 to ten po lewej).Potem mamy 0 które odpowiada nam za WRAM-Gra nie będzie używać WRAMu.Pozostałe bity oznaczają nam numer banku PRG-zostanie on przełączony na najwyższy możliwy.I to tyle.Potem gra już robi te swoje czary mary by wystartować.

*Jeżeli Ch&D2 posiada odmianę mappera MMC1A, której bit d4( piąty licząc od LSB) jest ignorowany to to by wyjaśniało wpisywane tam zero.
*Według loga FCEUXD gra Ch&D2 używa banków PRG-ROM o rozmiarze 16K, więc młodszy nibbles ustawiany przez tą instrukcję INC wybiera bank PRG-ROM numer 0xf jak napisał Dizzy9
*Wnioskuję, że INC $ffe1 będzie robić w NES coś takiego:
  -pobierz
  -inkrementruj
  -wyślij do PRG-ROM (po drodze do pamięci jest chip mappera, więc przechwytuje on zapis)

*Przy okazji czy to jakoś wiąże się z terminem Otwarta-Magistrala? (Open-Bus).

Cytat: Dizzy9
Cytat: CodAsm
Może jestem w błędzie, ale zawsze mi się zdawało, że rejestry $2006/$2007 to jedyna droga, którą Tiles'y mogą się wydostać z Pattern Tables do VRAM (a dokładniej indeksy Tilesów zapisanych w Pattern Tables).
Tak, ale ty napisałeś że szukasz kodu ładującego grafikę, nie Name Table.

Kiedy włączasz zupełnie nieznany wcześniej ROM to na samym początku do dyspozycji masz (tak mi się zdaje) tylko zapisy do NameTable (VRAM) i w ten sposób możesz dowiedzieć się skąd płyną dane grafiki do VRAM (indeksy), czyli skąd ładowana jest grafika.

Cytat: Dizzy9
To nie zabrzmi miło, ale musisz więcej się przyłożyć do zrozumienia assemblera i tyle.
Gdy to zrozumiałem, jak mało jeszcze rozumiem to assembler trochę odszedł w odstawkę, ale coś ciągle kusi, żeby do niego wrócić.

Cytat: Dizzy9
Kiedyś miałem ochotę zrobić jakiś video tutorial, ale brakowało mi chęci...może tym razem...
Ze swojej strony zachęcam jak najbardziej, bo o takie źródła informacji trudno.


Co do kodu dam sobie trochę czasu, żeby się rozeznać lepiej co tam się dzieje i skąd wołany jest kod, który pokazałeś. Jak coś już mam to może będzie łatwiej się wgryźć.Smile


Są wtyczki do IDA Pro umożliwiające deasemblację kodu NES, ale są problemy ze zdeasemblowaniem bank'ów i jak zauważyłem wiele zdeasemblowanych fragmentów kodu nie zgadza się z kodem ASM zdeasemblowanym przez emulatory (FCEUX, Nintendulator), a szkoda bo narzędzie to wygodne.
« Ostatnia zmiana: Maja 05, 2012, 11:54:15 wysłane przez CodAsm » Zapisane
CodAsm
Szeregowy
*
Offline Offline

Wiadomości: 49


« Odpowiedz #6 : Września 19, 2012, 22:12:08 »

Moje pytanie może nie tyle dotyczy konkretnego kawałka kodu co niezrozumiałych dla mnie instrukcji.
Fragment kodu pochodzi ze strony
http://www.the-interweb.com/serendipity/index.php?/archives/10-Faxanadu-level-data-Part-III-Doors.html

Kod:
$E5b2-> 4a: LSR A
$E5b3-> ad 35 04: LDA $0435
$E5b6-> 2a: ROL A ; A is an index into the tables
$E5b7-> 48: PHA
$E5b8-> a8: TAY
[b]$E5b9-> b9 db e5: LDA $e5db,Y ; Load the door requirements (Key, ...)[/b]
$E5bc-> 8d 2b 04: STA $042b
$E5bf-> 20 2f eb: JSR $eb2f ; Check if the player has a valid key.
$E5c2-> 68: PLA
$E5c3-> a8: TAY
$E5c4-> ad 2b 04: LDA $042b
$E5c7-> d0 11: BNE $E5da ; No valid key
[b]$E5c9-> b9 e7 e5: LDA $e5e7,Y ; Load the section ID of the new screen[/b]
$E5cc-> 8d 35 04: STA $0435
[b]$E5cf-> b9 f3 e5: LDA $e5f3,Y ; Load the screen ID of the new screen[/b]
$E5d2-> 85 64: STA $64
$E5d4-> 20 2f da: JSR $da2f
$E5d7-> 4c dc da: JMP $dadc

Niezrozumiałe instrukcje:
Kod:
LDA $e5db,Y
LDA $e5e7,Y
LDA $e5f3,Y


Faxanadu to gra oparta na Mapperze 1 (MMC1), a dokładniej 256K = 16x16K PRG-ROM + CHR-RAM [SGROM]. Zatem zaznaczone  instrukcje (lda w trybie absolutnym indeksowanym odczytujące z PRG-ROM) teoretycznie powinny coś robić  z rejestrami MMC1. Adresy e5db+y, $e5e7, $e5f3,Y wskazują, że byłby to rejestr 3, czyli ten odpowiedzialny za przełączanie banków PRG-ROM, zaś lda to oczywiście odczyt. W dokumentacjach o mapperach jest powiedziane, że rejestry mappera są raczej do zapisu. Oto źródla informacji o MMC1, z których korzystam:

http://kevtris.org/mappers/mmc1/index.html
http://nesdev.com/mmc1.txt
http://wiki.nesdev.com/w/index.php/Programming_MMC1

Jednak opis na blogu i komentarze wskazują na zgoła coś innego, jakby była to pamięć do odczytu na kolejnych podstronach trafiam na jakieś szczątki informacji

Cytuj
Other cartridges have a CHR RAM that holds data that the CPU has copied from PRG ROM through a port on the PPU.

Źródło: http://wiki.nesdev.com/w/index.php/CHR_ROM_vs._CHR_RAM

Cytuj
Apart from Pinbot and High Speed, which use the TQROM board, this combination is used for games in the Chinese language, which need to mix logographic characters arbitrarily. They are thought to follow a similar strategy to Faxanadu and Super Bat Puncher, reserving some CHR RAM for software-rendered text boxes.

Źródło: http://wiki.nesdev.com/w/index.php/MMC3_with_CHR_ROM_and_CHR_RAM

Cytuj
Note that VRAM is banked through the MMC1, so you can have 1 8K bank or 2 4K banks.

Źródło: http://kevtris.org/mappers/mmc1/NES_SGROM.html

Cytuj
Additional Notes:
 ----------------------------
 
 Consecutive writes that are too close together are apparently ignored.  One game where this is significant
 is Bill & Ted's Excellent Video Game Adventure.  That game does the following HORRIBLY SLOPPY code to reset
 the mapper:
 
   INC $FFFF  (where $FFFF contains $FF when read)
 
 For those of you who really know your 6502... you know that this will read $FFFF (getting $FF), write that
 value ($FF) back to $FFFF, increment it by one, then write the new value ($00) to $FFFF.  This results in
 two register writes:  $FF, then $00.

Źródło: http://wiki.nesdev.com/w/index.php/INES_Mapper_001

Na koniec cytat z samego bloga:

Cytuj
Things are a bit different for doors of value 0xFE and 0xFF. There are some tables in the Faxanadu ROM file that are used when moving between levels. The first one (located at offset 0x3E5F7) contains the levels you end up in when moving between levels. The current level is used as an index into that table, the value read from the table is the level a door from the index level leads to. There are two values for each level, the first one is for going back one level, the other one is for moving forward. Here's the original table.


Mogę mieć domysły, że są to po prostu odczyty jakich danych z PRG-ROM, ale nie mam co do tego pewności i nie rozumiem skąd pewność autora bloga z artykułami o zdeasemblowanym kodzie Faxanadu, że adresy te zawierają dane, które można poprawnie odczytać.

Być może nie czytam wystarczająco dokładnie lub brakuje mi jakiejś podstawowej wiedzy o Mapperach. Proszę o pomoc, albo o naprowadzenie mnie na rozwiązanie tej zagadki.
« Ostatnia zmiana: Września 19, 2012, 22:31:27 wysłane przez CodAsm » Zapisane
Koks
Major
*****
Offline Offline

Wiadomości: 580



« Odpowiedz #7 : Września 20, 2012, 11:10:17 »

Kod:
LDA $e5db,Y
LDA $e5e7,Y
LDA $e5f3,Y
Cytuj
są to po prostu odczyty jakich danych z PRG-ROM
Mapper jest podłączony do tej samej szyny co PRG-ROM. LDA powoduje inne ustawienie pinu PRG R/W niż STA (nie wiem jak jest z /CE) i w ten sposób mapper odróżnia zapis od odczytu, który ignoruje.
Cytuj
cartridges have a CHR RAM that holds data that the CPU has copied from PRG ROM through a port on the PPU.
To zupełnie inna sprawa, te porty są na $2000-$2007.
Cytuj
skąd pewność autora bloga z artykułami o zdeasemblowanym kodzie Faxanadu, że adresy te zawierają dane, które można poprawnie odczytać
ROMy mają tak dobraną pojemność, że zajmują całą przestrzeń adresową. Nawet jak jest 16kB, "widać" dwa razy to samo. Poza tym, te adresy są w tym samym banku zaraz pod kodem.
Zapisane

Częste mycie skraca życie.
"If you have a fast, shiny new Pentium II, you might try using 44 kHz for the ultimate in sound quality." - readme od Unreala
https://drive.google.com/folderview?id=0B2TXQD5v-ZIVfjVQdTl2TTZiWmJ2LWZJajJzS0V4cDZBay04WjVGQkdQdnBDQzRlYkdQVGc&usp=sharing
CodAsm
Szeregowy
*
Offline Offline

Wiadomości: 49


« Odpowiedz #8 : Września 22, 2012, 17:02:52 »

Więc dane grafiki są zapisane w niektórych z 16 banków PRG-ROM?

EDIT1:
Powyższe pytanie jest głupie, ponieważ w MMC1 dane są pobierane z przełączanych banków CHR ładowanych do PPU pod adres $0000 i $1000.
*Rejestr #1 określa, który bank CHR załadować pod $0000
*Rejestr #2, który bank CHR załadować pod $1000
Pozostaje jednak pytanie czy w PRG-ROM są jakieś poprawne dane, które można odczytać?

Cytat: Koks
w ten sposób mapper odróżnia zapis od odczytu, który ignoruje.

Jeżeli dobrze zrozumiałem post Koksa to Mapper ignoruje odczyty. Tak więc czym są te odczyty we wspomnianym kodzie i komentarze sugerujące, że z obszaru $e000-$ffff ładowane są jakieś ID'y.


BTW: Zauważyłem, że teksty znajdujące się w oknach dialogów są pobierane bezpośrednio z CHR-ROM (PPUViewer we FCEUXD), tzn. w Pamięci
Charakterów mamy nie alfabet, a gotowy tekst, który znajdzie się w kolejnej ramce. Przed pojawieniem się kolejnego tekstu w ramce do CHR-ROM ładowany jest nowy tekst.
« Ostatnia zmiana: Września 27, 2012, 12:41:39 wysłane przez CodAsm » Zapisane
Koks
Major
*****
Offline Offline

Wiadomości: 580



« Odpowiedz #9 : Września 27, 2012, 13:35:53 »

Cytuj
Więc dane grafiki są zapisane w niektórych z 16 banków PRG-ROM?
Tak, bo nie ma CHR-ROM. Używane elementy są na bieżąco kopiowane z PRG-ROM do CHR-RAM.

Cytuj
*Rejestr #1 określa, który bank CHR załadować pod $0000
*Rejestr #2, który bank CHR załadować pod $1000
Tylko wtedy, gdy jest CHR-ROM z przełączanymi bankami, a w tym przypadku jest
Cytuj
16x16K PRG-ROM + CHR-RAM [SGROM]
RAM raczej ma 8kB i się go nie przełącza.

Cytuj
Tak więc czym są te odczyty we wspomnianym kodzie i komentarze sugerujące, że z obszaru $e000-$ffff ładowane są jakieś ID'y.
To po prostu odczyty danych z tablicy w PRG-ROM ($8000-$ffff), np.
Kod:
LDA $e5de7,Y
$e5e7 to początek tablicy zawierającej ID, a w Y jest indeks. Odczytana wartość jest umieszczana w RAM konsoli i trzymana tam do użycia przez funkcję rysującą ekran czy coś w tym rodzaju.

Cytuj
Pozostaje jednak pytanie czy w PRG-ROM są jakieś poprawne dane, które można odczytać?
Nie wiem czy dobrze rozumiem pytanie, raczej nie ma możliwości zmiany danych w PRG-ROM (chyba że się uszkodzi).
« Ostatnia zmiana: Września 27, 2012, 13:50:23 wysłane przez Koks » Zapisane

Częste mycie skraca życie.
"If you have a fast, shiny new Pentium II, you might try using 44 kHz for the ultimate in sound quality." - readme od Unreala
https://drive.google.com/folderview?id=0B2TXQD5v-ZIVfjVQdTl2TTZiWmJ2LWZJajJzS0V4cDZBay04WjVGQkdQdnBDQzRlYkdQVGc&usp=sharing
CodAsm
Szeregowy
*
Offline Offline

Wiadomości: 49


« Odpowiedz #10 : Września 28, 2012, 18:47:07 »

Szczerze mówiąc to mi się w momencie edycji poprzedniego posta wszystko pokiełbasiło, bo niby log emulatora wskazywał na istnienie samych banków PRG-ROM, a z drugiej strony w dokumentacji o Mapperach pojawiły się informacje o przełączaniu banków CHR-ROM, a dane planarne charakterów muszą być skądś pobierane. Jeżeli dobrze zrozumiałem to dane te pobierane są z niektórych banków PRG-ROM w locie do pamięci CHR-RAM, ktora jak wspomniałeś ma 8K, dzięki czemu mapy 2bpp dla BKG+SPR (512 Tilesów) mogą tam zostać umieszczone.

Co do odczytu danych z PRG-ROM, chodziło mi m.in o odczyt tablicy $e5e7,y, bo nie wiedziałem, że z PRG-ROM można czytać dane, zdawało mi się, że możliwe są tylko zapisy (a Mapper, jak zresztą wszystkie dostępy do obszaru PRG, łapie te zapisy i wrzuca do odpowiedniego rejestru).

Jeżeli chodzi o mnie to wydaje się, że odpowiedzi na pytania są wyczerpujące. Wielkie dzięki za cierpliwość Koks.

Gdy zaczynałem na tym forum od razu zainteresowałem się assemblerem NES'a i technicznymi sprawami z tym związanymi, czasem potrafiłem przesiedzieć nad tym po 12 godzin dziennie (dziś już o wiele rzadziej), tłumaczyłem sobie artykuły i wiele własnoręcznie stworzonych opracowań mam do dziś. Kiedy tyle nad tym ślęczałem odbijała mi woda sodowa jaki to ja nie jestem oczytany, z czasem przychodzi dopiero świadomość jak wielu rzeczy nie rozumie się i że pewne rzeczy zrozumiało się błędnie. Tak na marginesie mogę zdradzić, że częścią tematu mojej pracy inżynierskiej jest napisanie asemblera 6502 w C++, jednak w tym momencie jestem w fazie projektu i mam jedynie analizator leksykalny w kodzie (w wersji testowej).
Mam nadzieję, że darujecie mi ten offtop, ale nie mogłem się powstrzymać. Cheesy
« Ostatnia zmiana: Września 29, 2012, 19:11:34 wysłane przez CodAsm » Zapisane
Strony: [1]
  Drukuj  
 
Skocz do:  

Działa na MySQL Działa na PHP Powered by SMF 1.1.11 | SMF © 2006-2008, Simple Machines LLC Prawidłowy XHTML 1.0! Prawidłowy CSS!
Strona wygenerowana w 0.078 sekund z 18 zapytaniami.