Portowanie Spelunky na NintendoDS

Kod:

https://github.com/dbeef/spelunky-ds

Plik gotowy do uruchomienia w emulatorze nds (np. na Androidowym NDSBoy):

https://github.com/dbeef/spelunky-ds/blob/master/spelunkyds.nds


Na tym etapie, program w końcu zaczyna przypominać oryginalne Spelunky, zebrałem więc krótkie podsumowanie.

Co większą zmianę kręciłem krótko hmm gameplay? Dlatego postępy krok po kroku można po prostu obejrzeć:


Co zostało?
AI, zbieralne przedmioty, wspinanie się na drabinach/linach, druga warstwa tła (nałożona na mapę kafelkową i sprajty), menu, zastanowienie się na tym, czy zostawić mapę współdzieloną między ekranami.

Po skompilowaniu, Spelunky włączam na nds poprzez kartę R4 , ale jeśli faktycznie uda mi się je dokończyć, to spróbuję znaleźć sposób na (bardzo amatorskie) wyprodukowanie kilku kartridży samemu. Dla przykładu, schematy budowy Game Boy Advance są w internecie:

https://dhole.github.io/post/gameboy_cartridge_emu_1/

Jeśli chodzi o trudności jakie napotkałem podczas reprodukowania gry to były ogromne na początku, później (chyba) takie same jak przy każdej innej grze, bez różnicy czy na konsolę.

Najgorszym problemem było rozwiązanie adresowania pamięci, libnds wystawia odpowiednie funkcje do zarządzania VRAM-bankami, ale adres poszczególnego sprajta (np. ikony liny na górze ekranu) zależy od głębi kolorów (ja używam 4 bitowej, 16 kolorów) i wielkości (libnds dzieli podane mu obrazki na kafelki wielkości 8×8, więc zależy od ilości takich kafelków).

Zaadresować należy też oddzielnie palety kolorów, czcionkę i kafelki tła (mają swoje oddzielne banki).

Nie brzmi to tak srogo, ale jeśli chociażby załaduje się grafikę o innej głębi niż podano w kodzie, to całe adresowanie jest niepoprawne i pojawiają się artefakty takie jak ten:

Problem rozwiązują odpowiednie kalkulatory:

https://mtheall.com/vram.html

Konsola obsłuży max 128 sprajtów per ekran (ograniczenia ze względu na ilość pamięci), nie wiem jeszcze jak łatwo będzie zająć 100% CPU (chociażby sprawdzaniem kolizji między wszystkimi obiektami), ale patrząc na to, że ta konsolka z 2004 roku potrafi coś takiego:

czy coś takiego (Minecraft homebrew, https://github.com/smealum/dscraft):

…to jestem spokojny.


Tutorial libnds, jeśli kogoś to zainteresowało:

https://patater.com/files/projects/manual/manual.html

Advertisements

libnds #4 Wykrywanie kolizji z tłem

Postęp prac na ten moment:

Lista problemów które udało mi się rozwiązać od ostatniego postu:

  • Wyświetlanie mapy większej niż 256×256
  • Znalezienie jakiegoś programu do edycji map kafelkowych, kompatybilnego z gba/nds
  • Zrobienie prostego generatora poziomów
  • Sprawdzanie kolizji poszczególnych kafelków z punktem x,y wyznaczonym przez dotyk na ekranie
  • Znalezienie w gimpie opcji konwersji kolorów do takich, które spodobają się libnds (8 bit, indeksowane bmp/png)

Wyświetlanie mapy większej niż 256×256

Przypominając, wyświetlenie mapy kafelkowej w libnds składało się do skopiowania z pamięci tablicy (w przypadku 256 px na 256 px daje to mapę wielkości 1024, bo każdy element mapy zajmuje 8×8 pikseli) do odpowiedniego rejestru w hardwarze NDS.

Z poniższego postu:

https://www.coranac.com/tonc/text/regbg.htm

…można się dowiedzieć, że rysując mapy większe niż 256×256, trzeba rozpatrzyć specjalny przypadek – weźmy na przykład mapę 512×512 z jakiej teraz korzystam w spelunky-ds.

Dzielę moją tablicę 4096 elementów na 4 sektory, jak szachownicę. Robię to tworząc zapasową tablicę, a następnie przechodzę przez nią tak, aby dojść tylko do odpowiedniej połowy na każdej z osi (wiersz ma szerokość 64 elementów, więc dochodzę do 32). Reszta chyba jest oczywista:

schemat

Da się to skrócić, ale to dobry przykład bo widać każdą oddzielną pętlę for odpowiadającą za oddzielną część szachownicy.

Nie wiem czy to część całego standardu C++, ale zauważyłem, że jeśli nie przydzielę pamięci dla tymczasowej tablicy poprzez malloc, to całość nic nie wyświetla (żadnych błędów, po prostu jakby DMA stwierdzało że nie skopiuje tej tablicy już w runtimie), więc trzeba na to zwrócić uwagę.


Znalezienie jakiegoś programu do edycji map, który generowałby tablicę C++

Tutaj padło na program mappy:

https://tilemap.co.uk/mappy.php

Strona wygląda jakby ledwo się trzymała, więc chyba na wszelki wypadek wrzucę binarkę na moje repozytorium z dopiskiem do readme o odpowiedniej licencji i autorze.

Mappy potrzebuje tilemapy – robię ją w gimpie sklejając odpowiednie pliki i koniecznie konwertując je do .bmp, indeksowanego, 256 kolorów (8bit).

Ten sam plik, ale w formacie .png przekazuję do folderu gfx w folderze od spelunky-ds.

To co wychodzi z mappy, to tablica, którą można wkleić bezpośrednio w kod:

const short mapa[1024] = {
1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4,
1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4

…itd.


Zrobienie prostego generatora poziomów

Tutaj wytłumaczenie generowanie spelunkowych poziomów wyłożył ktoś na youtubie, zresztą bardzo dokładnie z przykładem:

Ja napisałem jedynie szybką implementację powyższego w: source/level_layout/LevelGenerator.cpp:

https://github.com/dbeef/spelunky-ds/blob/master/source/level_layout/LevelGenerator.cpp


Sprawdzanie kolizji poszczególnych kafelków

Najmniejsza jednostka podziału grafiki w libnds to kafelek 8×8 (chociaż pewnie można zmienić to w programie grit), ale moje grafiki ze Spelunky są rozmiarów 16×16, więc aby 4 kafelki trzymały jedną logiczną część (np. dla momentów w którym niszczę cały kafelek) stworzyłem klasę MapTile:

Screenshot from 2018-03-10 20-11-49

values zawiera 4 wartości dla 4 różnych kafelków 8×8, map_index zawiera ich adresy w mapie.

Sposób wybierania adresów w mapie jest dość żmudny i nie ma co go tutaj przedstawiać, kto jest zainteresowany niech zobaczy plik LevelGenerator.cpp, w szczególności funkcje:

  • generateRooms()
  • mapFrame()

Mamy już pozycję każdego kafelka, można więc mając pozycje dotknięcia na ekranie sprawdzić teraz, czy któryś z nich nachodzi na ten x,y.

Trzeba pamiętać jednak o szczególe, takim jak pozycja kamery. Sprawdzając kolizję, trzeba sprawdzać pozycję x i y kafelka PLUS pozycja x i y kamery, tak jak poniżej:

Screenshot from 2018-03-10 20-19-45

 


 

To wszystko na dziś.

libnds #3 Kafelkowe tło

Przygotowanie

Za podstawę do napisania kafelkowego tła posłużą:

Przykład z libnds:
devkitPro/examples/nds/Graphics/Backgrounds/all_in_one

Pojedyńczy obrazek tła ze spelunky community update:

SpelunkyCommunityUpdateProject/spelunky/Sprites/Blocks/Background/sCaveBG.images/image 0.png

Program do edycji map na NDS/GBA:

http://www.tilemap.co.uk/mappy.php

Odpowiednie kroki

1

Obrazek wskazany wyżej trzeba najpierw przepuścić przez poniższą stronę:

https://online-converting.com/image/convert2bmp/

Wybieramy tryb 8 (indexed).

Po pobraniu wrzucam go podpisanego jako cavebg.bmp do folderu gfx/tilemaps. W nim napisałem następującą regułę grit (wytłumaczenie – odsyłam do docsów grit):

-p!
-gt
-gB8
-mRtpf
-mLs
-mu32
-Mw16
-Mh16

Mój Makefile (gdzie wskazuję gritowi jakie foldery ma odwiedzić) możecie sprawdzić na Githubie spelunky-ds.

2

Teraz kopiujemy odpowiednie pliki z przykładowego projektu do naszego projektu:

  • scrolling.cpp
  • TextBackgrounds.s

Do main.cpp wystarczy skopiować jedynie linie (podmieniłem argument tak aby pasował do naszego obrazka cavebg):

dmaCopy(cavebgTiles, bgGetGfxPtr(bg), sizeof(cavebgTiles));
dmaCopy(Layer256x256Map, bgGetMapPtr(bg), Layer256x256MapLen);
dmaCopy(cavebgPal, BG_PALETTE, cavebgPalLen);

3

Robimy mapę. Ściągamy edytor który podlinkowałem wyżej.

Tworzymy nową mapę przez File->New map. Korzystamy z faktu, że pojedyńczy tile w NDS jest rozmiarów 8×8, nasz obrazek to 32×32 a rozmiar mapy jaki wybraliśmy to 256×256 – będzie więc miała szerokość i wysokość 32, szerokość i wysokość tile-a 8×8 co podajemy w oknie które wyskoczy.

Importujemy obrazek .bmp który stworzyliśmy wcześniej opcją File->Import.

Rysujemy cokolwiek i eksportujemy do pliku txt przez File->Export as text, w oknie które się pojawi niczego nie zmieniamy.

W pliku txt który się wygenerował interesuje nas pierwsza tablica od góry.

Ponieważ nie do końca wiem, czy to jakaś rzecz wynikająca z C++ czy mój błąd, na razie nie kopiuję tej tablicy bezpośrednio do kodu, ale podmieniam wartości w pliku TextBackgrounds.s – inaczej nie działa.

Miejsce które trzeba podmienić, to Layer256x256Map (ponieważ taki rozmiar mapy wybraliśmy). Miejsce to deklaruje wygląd mapy.

Screenshot from 2018-02-25 17-50-58

Wyrzucamy wszystko co jest po Layer256x256Map i jest przed:

@}}BLOCK(Layer256x256)

Teraz ważna rzecz – nie wklejamy tu bezpośrednio tej tablicy. Przepuszczamy ją przez prosty program który napisałem (zmienia tablicę 2d na 1d, zmienia wartości z decymalnych na hexy + dodaje “.hword” na początku każdej linii) wklejamy dopiero output, który wypuścił ten program.

Wrzuciłem jego source do Githuba projektu, do folderu utils. Przed uruchomieniem trzeba wkleić swoją własną mapę do jego kodu.

Wynik

Mamy scrollowalną mapę jak poniżej:

myimage

Co dalej

Zastanawiałem się więc w którą stronę pójść – wyświetlać jako tiled background jedynie te faktycznie statyczne elementy (tło które jest za niszczalnymi elementami), wyszczególnione tutaj:

background

…a zniszczalne elementy wyswietalać jako sprajty. Wtedy logika wyświetlania zniszczonych elementów byłaby prostsza, zero kombinowania, tak samo sprawdzanie kolizji, np. z kolcami czy podmiana sprajta, jeśli np. ten element wybuchł. Plus wszystkie wartości pomocnicze trzymane byłyby w jednej strukturze.

Pytanie tylko, czy wyświetlanie tego w ten sposób jest dobre – NintendoDS ma rzekomo oddzielny układ odpowiedzialny za wyświetlanie backgroundów, nie obciążałbym więc CPU, po prostu kopiowałbym pamięć do odpowiedniego rejestru przez Direct Memory Access, gdybym nie używał sprajtów tylko wyłącznie background. Być może NDS ma też oddzielny układ do wyświetlania sprajtów i nie musiałbym zastanawiać się jak będzie to wyglądać wydajnościowo – problem w tym:

On the Nintendo DS, we can have up to 128 sprites.

https://patater.com/files/projects/manual/manual.html#id2614195

Więc raczej by to nie wyszło, mapa w Spelunky to około 40×40, nie mówiąc o postaciach czy przeszkodach.

Size was one of the benefits of using tilemaps, speed was another. The rendering of tilemaps in done in hardware and if you’ve ever played PC games in hardware and software modes, you’ll know that hardware is good. Another nice point is that scrolling is done in hardware too. Instead of redrawing the whole scene, you just have to enter some coordinates in the right registers.

https://www.coranac.com/tonc/text/regbg.htm

Drugi pomysł, wykorzystujący w 100% tylko backgroundy, to napisanie pomocnicznego programu, który przejdzie przez plik txt z generatora map i stworzy tablicę elementów (powiedzmy, że nazwiemy te elementy SpriteElement {x, y, typ elementu (zwykły klocek, klocek tła, itd), boolan czyZniszczony, szerokość, wysokość, wskaźnik na tablicę intów który będzie wskaźnikiem na hexy ekwiwalentu tego samego tile-a, ale zniszczonego}).

Wtedy za każdą zmianą takiego kawałka tła (np. zniszczeniem pojedyńczego klocka) będzie można robić wpis do rejestru ze zmienioną tablicą i tło nadal będzie się jakoś wyglądać – to które to będą element listy i na jaką wartość ją podmienić będzie wiadomo ze SpriteElement. Kolizje i odpowiednia logika również wyszłaby z tego.

Plus, i tak muszę zrobić coś co będzie w stanie wygenerować mapę od zera (w Spelunky każda mapa jest losowa, generowana proceduralnie) więc jakieś makra pod poszczególne kafelki będę musiał gdzieś w kodzie zadeklarować.

 

Wkrótce napiszę jakąś wstępną implementację.

Efekt powyższego tutoriala można zobaczyć na Githubie tego projektu:

https://github.com/dbeef/spelunky-ds

 

PS: Zauważyłem, że kolejne hexy: 0x0001, 0x0002, 0x0003…0x000F to kolejne elementy (8×8 tile) naszego obrazka .bmp. Składa się to w całość – gdyby ułożyć je warstwami po 4, narysowalibyśmy nasz obrazek. Można w ramach eksperymentu wkleić coś takiego do pliku TextBackgrounds.s:

.hword 0x0000,0x0001,0x0002,0x0003,0x0000,0x0000,0x0000,0x0000
.hword 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
.hword 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
.hword 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
.hword 0x0004,0x0005,0x0006,0x0007,0x0000,0x0000,0x0000,0x0000
.hword 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
.hword 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000


.hword 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
.hword 0x0008,0x0009,0x000A,0x000B,0x0000,0x0000,0x0000,0x0000
.hword 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
.hword 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
.hword 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
.hword 0x000C,0x000D,0x000E,0x000F,0x0000,0x0000,0x0000,0x0000

…powinno narysować klocek + powtarzający się, lewy górny róg klocka wokół.

 


Przydatne linki:

libnds

https://www.coranac.com/tonc/text/objbg.htm

https://www.coranac.com/tonc/text/regbg.htm

https://gbatemp.net/threads/ds-programming-for-newbies.322106/

https://gbatemp.net/threads/tile-mapping-libnds-or-palib.325728/

C++

https://stackoverflow.com/questions/1238613/what-is-the-difference-between-the-dot-operator-and-in-c

https://stackoverflow.com/questions/54585/when-should-you-use-a-class-vs-a-struct-in-c

https://stackoverflow.com/questions/38942013/declaring-variables-in-header-files-c

https://stackoverflow.com/questions/10198046/c-member-variables

https://stackoverflow.com/questions/185844/initializing-private-static-members

https://stackoverflow.com/questions/20019441/how-is-a-header-file-being-compiled-into-the-executable-file

Konfiguracja Code::Blocks pod NDS:

https://whatroidoes.wordpress.com/2014/01/09/nds-development-tutorial-how-to-use-devkitpro-with-codeblocks-and-debug-with-insight/

 

 

libnds #2 Piszemy intro – timery

 

Wziąłem się za ustawienie środkowiska pod libnds (nie będę w końcu pisał całej gry w vimie). Pobrałem CLiona, żeby mieć ze sobą wszystkie najlepsze udogodnienia z Intellij którego używam na codzień do Javy – problem w tym, że CLion nie ma wersji community, jedynie 30 dniowy trial. Trzeba będzie pojanuszować i ściągać ponownie za miesiąc (jakoś nie mam ochoty na wydawanie 200€ na rok).

Wrzuciłem też gotowy projekt na githuba, teraz można śledzić progress:

https://github.com/dbeef/spelunky-ds

Co chcemy osiągnąć:

introScreen z intra Spelunky

Na start gry, zdanie po zdaniu, z interwałem ~2.5s, odkrywane są kolejne linie intra. Chcemy napisać klasę, która będzie odpowiedzialna za takie przerywniki.

Za szablon wziąłem sobie plik z przykładów devkitPro/examples/nds/Graphics/Printing/customFont.

To jest miejsce w którym zapoznam się z timerami w libnds. Każda z linii pojawia się co określony odstęp czasu, który trzeba sobie odliczyć. Z tego co znalazłem w docsach i wypróbowałem, za odliczanie czasu odpowiada specjalny układ na płytce DSa, a właściwie jeden z czterech układów, w zależności który wybierzemy.

Start i zatrzymanie układu wygląda następująco:

Screenshot from 2018-02-21 12-44-41

Wygląda to tak:

  • w pierwszym argumencie podajemy który timer używać
  • w drugim podajemy jakiego dzielnika używać, czytaj – co jaki czas ma być naliczany ‘tick’ timera
  • trzeci – liczba ticków która musi minąć, zanim bufor timera się przepełni
  • funkcja która ma być wywołana w momencie, kiedy bufor się przepełni

Przykładowo, napisałem taki kod, który ma za zadanie co około sekundę wypisać na konsolę NDS czas  jaki upłynął (wytłumaczenie w komentarzach):

Screenshot from 2018-02-21 13-06-10

Efekt wygląda tak:

myimage

Wracając więc do tego co mamy zrobić, to inicjalizujemy zmienne int trzymające wartości czasu w milisekundach i zdejmujemy z nich upłynięty czas. Jeśli upłynął i nie ustawiliśmy jeszcze flagi ‘narysowano’, to wywołujemy funkcję wypisującą na konsolę i ustawiamy flagę na 1. Robimy tak dla każdej z trzech linii.

Timery dla każdej z linii ustawiłem jako tablicę:

{1000, 3500, 6000}

Z czego można się domyślić, że pierwsza linia wyskoczy po sekundzie, druga po 3.5, trzecia po 6.

Efekt:

myimage

 


 

Linki:

https://devkitpro.org/viewtopic.php?f=6&t=1622

Kindle 4 jako linuksowy terminal

Przyszło mi do głowy, aby zrobić użytek z rozbitego Kindla którego już nie używam. Myślałem na początku o stacji pogodowej (Kindle obsługuje javę, więc może nawet  mógłbym napisać coś własnego po wrzuceniu jailbreak-a), ale wtedy zobaczyłem to:

Okazuje się, że sporo osób włożyło wysiłek w to, aby móc używać Kindle jako ekranu terminala (mógłby mi się przydać, jako dodatkowy ekran na listę rzeczy do zrobienia, do wrzucenia htop-a i monitorowania zasobów albo irca).

Udało mi się, efekt wrzucam tutaj, a poniżej zagregowałem wszystkie materiały, które są potrzebne aby krok po kroku przeprowadzić to samo na innym Kindlu 4 (non-touch), razem z własnymi uwagami i zdjęciami (efekt spodobał mi się na tyle, że zrobiłem to samo także na drugim, sprawnym Kindlu, więc była okazja na spisanie/zrobienie zdjęć ze wszystkiego).

Przykładowy manual wyświetlony na Kindlu:

man

Htop z mojego laptopa, wyświetlany na kindlu:

htop

Midnight commander

mc

Irc

irc

 


Instrukcje

Nie ponoszę odpowiedzialności za zepsute Kindle!!!

Max czas jaki zajmie wszystkiego poniżej to 60 minut.

1

Pierwszym co trzeba zrobić, to zainstalować jailbreak stworzony przez społeczność.

Wersja pod Kindle 4 NT wraz z instrukcjami i odpowiednim plikiem jest tutaj:

https://wiki.mobileread.com/wiki/Kindle4NTHacking#Jailbreak

Ważna rzecz – spiszcie sobie gdzieś lub zróbcie zdjęcie numeru seryjnego waszego Kindla – będzie potrzebny w punkcie 4.

Numer seryjny będzie wyświetlony w menu diagnostycznym które pojawi się, kiedy będziecie przechodzić przez instrukcje od jailbreaka, będzie wygladać tak jak na zdjęciu poniżej:

 

Inna rzecz którą wydaje mi się, że nie można pominąć, to sprawdzić wersję softu – u mnie na obu Kindlach było to 4.1.3, a podlinkowany jailbreak powinien działać od 4.0.0 do 4.1.3. Wersję softu można sprawdzić w ustawieniach, będzie wypisana na dolnym pasku.

Poza tym, wydaje mi się, że nie ma tu zbyt wiele do tłumaczenia.

Paranoicy mogą też podładować baterię do 100% przed całą operacją.

Po skopiowaniu wskazanych w tutorialu plików na wierzch pamięci Kindla i przejściu przez resztę kroków, podczas uruchamiania pojawi się taki ekran:

jailbroken

2

Drugi krok, to instalacja usbnetwork – pozwoli to po podłączeniu Kindla kablem USB udawać komunikację przez ethernet (mniam), zainstaluje serwer ssh na Kindlu plus zdejmie ekran “USB Drive Mode”, kiedy Kindle jest podłączony do komputera (przyda się później).

Odpowiedni plik wskazany jest tutaj:

https://wiki.mobileread.com/wiki/Kindle4NTHacking#SSH

Przy czym na dzisiaj (i pewnie już na zawsze, patrząc na to kiedy stworzony był ten hack), aktualną wersją pod Kindle 4 jest:

https://www.mobileread.com/forums/attachment.php?attachmentid=141341&d=1440341478

Instrukcje z README_FIRST.txt z pobranego pliku powinny być jasne, ale je powtórzę:

  • Kopiujemy plik Update_usbnetwork_0.57.N_k4_uninstall.bin na wierzch pamięci Kindla (tak jak w przypadku jailbreaka)
  • Uruchamiamy instalację poprzez:
    • [Menu] -> Settings -> [Menu] -> Update Your Kindle.

Stosowne zdjęcie wymienionego ekranu:

update

3

Po restarcie poprzedzonym instalacją usbnetwork jesteśmy gotowi, żeby połączyć się z Kindlem przez ssh.

Noooo prawie. To co trzeba zrobić po każdym restarcie, aby uaktywnić usbNetwork, to:

  • Wcisnąć przycisk klawiatury, wpisać ;debugOn (razem ze średnikiem), wcisnąć klawiaturowe “Done”, a następnie search my items” z paska. Po wszystkim nie będzie żadnej widocznej reakcji, Kindle po prostu odświeży ekran.
  • Po tym, zrobić to samo, ale wpisać ~usbNetwork (razem z tyldą)

 

Teraz można podłączyć Kindle przez kabel usb.

Po podłączeniu Kindla, można ustawić sobie adres poprzez ifconfig, ale z tego co zauważyłem, połączenie lubi się zrywać po kilkudziesięciu sekundach, jeśli połączenie nie będzie dodane do Network Managera.

Z readme dowiadujemy się, że Kindle 4 będzie przyjmował połączenia tylko z adresu 192.168.15.201, więc po podłączeniu go edytujemy powstałe połączenie (Ubuntu -> “Network connections”) i ustawiamy taki przez interfejs gnome do Network Managera.

Screenshot from 2018-02-18 21-04-57

Dla niezaznajomionych z notacją CIDR aka “dlaczego tam jest 24”:
https://pl.wikipedia.org/wiki/Classless_Inter-Domain_Routing

W tym momencie jesteśmy gotowi do połączenia ssh!

4

Noooo i znów, prawie.

Statyczny adres, pod jakim Kindle będzie w sieci, to 192.168.15.244.

Tutaj przyda się numer seryjny który spisaliśmy wcześniej. Po nim dowiemy się, jakie są możliwe hasła roota do Kindla. Wpisujemy go pod poniższym adresem:

https://www.sven.de/kindle/

I sprawdzamy, które z wygenerowanych haseł będzie pasować.

pass

Zostało już tylko zainstalować emulator terminala i jesteśmy w domu!!!

5

To od czego trzeba zacząć, aby terminal w ogóle miał szansę się uruchomić, to wrzucić keystore deweloperów Kindle.

Opisane jest to tutaj:

https://wiki.mobileread.com/wiki/Kindlet_Developer_HowTo#How_To_install_the_merged_developer.keystore_on_the_Kindle

Polecam jednak rozegrać to trochę inaczej – w końcu mamy teraz dostęp przez ssh.

Rozpakowujemy na komputerze pobrany keystore (na tę chwilę jest to 2012-11-06) i odpalamy Midnight Commander.

W otwartej wcześniej sesji ssh, wpisujemy mntroot rw, a w oknie Midnight Commandera. Wybieramy w lewym górnym rogu [Left] -> [Shell link] -> [root@192.168.15.244].

Po zalogowaniu się, przechodzimy do /var/local/java/keystore/.

Jest możliwość, że zastaniemy tam już istniejący plik o takiej samej nazwie, wtedy zatrzymujemy go w razie czego pod inną nazwą, np. poprzez [F6] i wpisanie *_old i kopiujemy nasz developer.keystore.

keystores

Po całości trzeba zrestartować Kindle (keystore ładowany jest tylko raz, na start), co za tym idzie od nowa wpisywać ;debugOn i ~usbNetwork – jeśli chcecie sobie tego zaoszczędzić, to przejdźcie od razu do następnego punktu, bo po nim również przyda się restart.

6

Instalujemy i włączamy emulator terminala.

Autor bloga z tego linku:

http://pepijndevos.nl/2012/10/08/kindle-4-as-a-paper-terminal.html

zrobił super robotę, zmienił i skompilował javowy emulator z Kindle w wersji dotykowej/w wersji z klawiaturą na wersję która uruchomi się na Kindle 4 który nie ma żadnego z wymienionych.

Powstaje pytanie – jak w takim razie wpisać jakąkolwiek komendę na takim Kindlu? To za chwilę.

Ściągamy jego wersję terminala:

https://github.com/pepijndevos/KindleTerm/downloads

I kopiujemy ją (kindleterm.azw2) do katalogu ‘documents‘ który jest na wierzchu pamięci Kindla (jeśli chcemy to zrobić przez mc, to miejsce to jest zamontowane w /mnt/us).

Po tym modyfikujemy plik /opt/amazon/ebook/security/external.policy w taki sposób, aby po “grant signedBy “Kindlet” {”  zawierał linie:

permission java.net.SocketPermission "localhost:1024-", "accept, connect, listen";
permission java.net.SocketPermission "192.168.15.201", "connect, accept";
permission java.net.SocketPermission "localhost", "connect, accept";

Jeśli pojawia się błąd podczas zapisu pliku, w terminalu trzeba wcześniej wpisać mntroot rw.

Po całości wpisujemy mntroot ro i reboot. Teraz Kindle powinien się zrestartować.

6

Po restarcie standardowo – odłączamy Kindla od kabla, ;debugOn, ~usbNetwork i znów podłączamy.

Po ostatnim punkcie, w bibliotece Kindla powinna pojawić się pozycja KindleTermPV:

kidnleterm34

Otwieramy KindleTermPV.

kindleterm

Program ma jakiś bug i po włączeniu nie zawsze wszystko się wyświetla, wtedy są 3 możliwości:

  • Kilka razy kliknąć enter na joysticku
  • Przycisk ‘return’ i włączyć od nowa
  • Wcisnąć jednocześnie ‘return’ + ‘keyboard’.

Teraz wracamy do pytania – jak tu coś wpisać?

Tymczasowo (dopóki nie podłączymy się na Kindlu do sesji tmuxa) potrzebny będzie program robiący za wirtualną klawiaturę.

Opis i autor jest tutaj:

https://www.mobileread.com/forums/showpost.php?p=2251897&postcount=60

Wykonujemy instrukcje, czyli na Kindlu:

iptables -I INPUT -p tcp --dport 3333 -j ACCEPT

a na komputerze tworzymy plik o nazwie remote_keyboard.properties z taką zawartością:

host 192.168.15.244
port 3333

Wtedy umieszczamy w tym samym miejscu co powyższy plik wrzucony wcześniej na Kindla KindleTERM i odpalamy:

java -cp kindletermpv.azw2 kindle.RemoteKeyboard

cat

Powinno pojawić się okno swingowej aplikacji – klikamy w jego środek i piszemy cokolwiek – dokładnie to samo powinno pokazać się na ekranie Kindla!

dbeef

Jak pozbyć się tej aplikacji i pisać bezpośrednio w terminalu z komputera? Z pomocą przychodzi tmux i serwer telnet. Wszystko idzie po kablu usb, więc wątpię żeby użycie telnetu było jakimś zabezpieczeniowym faux-pas, chyba że ktoś zdecyduje się łączyć z Kindlem po wifi (nie próbowałem).

Jeśli jeszcze nie mamy, to instalujemy serwer telnet i aplikację tmux.

Gdy już mamy to:

  • Na komputerze wpisujemy ‘tmux’
  • Na Kindlu wpisujemy ‘telnet 192.168.15.201’ i logujemy się na swoje konto z komputera.
  • Na Kindlu wpisujemy  export TERM=ansi (bez tego nie zadziała tmux ani praktycznie nic innego)
  • Na Kindlu wpisujemy ‘tmux ls’, zapamiętujemy numer sesji która ma najnowszą datę utworzenia
  • Na Kindlu wpisujemy ‘tmux attach -t [numer sesji, np. 2]

Gotowe !!!

Teraz cokolwiek będzie wpisanego na komputerze, pojawi się na oknie na Kindlu (można wyłączyć już javową apkę).

28217548_1625339264185793_1093522813_o

Koniec.

Duże podziękowania dla wszystkich osób które udostępniły potrzebne materiały na blogach/forach.

Wpis na blogu w którym opisane jest jak zautomatyzować proces łączenia tak, żeby używać Kindla w charakterze ekranu dla Raspberry:

https://projectdp.wordpress.com/2012/09/24/pi-k3w-kindle-3-display-for-raspberry-pi/

 


Linki

 

Instalacja linuksowych aplikacji na kindlu ( i mikro package manager):

http://www.timelesssky.com/blog/linux-apps-for-kindle

Stacja pogodowa na kindlu 4 NT:

https://github.com/ufuchs/weather-on-kindle4nt

Co zrobić jeśli przerywa połączenie:

https://www.mobileread.com/forums/showthread.php?t=158015

 

 

John the ripper, myślałem na początku o wydobyciu hasła do roota z zakodowanego /etc/shadow (defaultowo można zalogować się na użytkownika o standardowych uprawnieniach bez generatora haseł, u:framework p:mario, wtedy można wydobyć ten plik).

Zastanawiało mnie trochę zrobienie tego na kilku urządzeniach jednocześnie (jeśli byłoby konieczne iteracyjne odgadywanie haseł), bo okazuje się że JTR używa tylko jednego rdzenia – odgadnięcie hasła zajęłoby tygodnie działania.

Obeszło się bez użycia JTR, ale to jest to co znalazłem przy okazji:

http://www.openwall.com/john/doc/EXAMPLES.shtml

https://en.wikipedia.org/wiki/Data_Encryption_Standard

https://blog.thireus.com/crack-passwords-using-john-the-ripper-with-multiple-cpu-cores-openmp/

http://www.admin-magazine.com/Articles/John-the-Ripper

http://www.cs.tufts.edu/comp/116/archive/fall2013/tlubeck.pdf

https://www.oiepoie.nl/2007/02/11/high-speed-password-cracking-with-john-the-ripper/

https://moveaxeip.wordpress.com/2011/11/10/distributed-password-cracking-with-john-the-ripper/