Emulator konsoli NES w systemie Linux na komputerze SoMLabs VisonSOM
W artykule, na przykładzie komputera VisionSOM (z procesorem NXP i.MX6 ULL Cortex-A7) firmy SoMLabs, wyposażonego w dedykowany moduł wyświetlacza LCD-TFT, uruchomiony zostanie emulator konsoli Famicon/NES (w Polsce znanej głównie dzięki klonowi oryginalnego projektu – konsoli Pegasus). Aby zwiększyć walor dydaktyczny projektu oraz pod kątem grywalności jak najbardziej zbliżyć się do wspomnień z minionych lat, sterowanie za pomocą tradycyjnej klawiatury zastąpiono podłączeniem i konfiguracją kontrolera konsoli Playstation 3/4 oraz prostym prototypem własnego 8-przyciskowego gamepada (co pozwoli również na zapoznanie się z konfiguracją magistrali SPI oraz wyprowadzeń GPIO w systemie Linux).
Zaczynajmy więc…
Przygotowanie karty z systemem Debian
Do budowy emulatora konsoli Famicon/NES wykorzystamy moduł komputera VisionSOM wyposażony w gniazdo karty pamięci SD (fotografia 1). Prace nad projektem rozpoczną się od przygotowania karty z systemem operacyjnym Linux. Producent komputera – firma SoMLabs – na stronach Wiki swojego produktu dostarcza użytkownikowi wsparcie w postaci gotowych obrazów z dystrybucją Debian oraz opisem budowy obrazów z wykorzystaniem takich narzędzi jak Buildroot oraz Yocto.
Fot. 1. Wygląd modułu VisionSOM-6ULL w wersji z kartą MicroSD
Przy wstępnym wyborze odpowiedniej dystrybucji lub narzędzi do budowy obrazu, pomocne jest jasne określenie celu projektu. Jeżeli finalnym celem projektu jest zbudowanie jak najwierniejszej kopii samej konsoli (z minimalnym obrazem systemu, wyposażonym wyłącznie w niezbędne oprogramowanie umożliwiające uruchomienie emulatora bezpośrednio po starcie urządzenia), wówczas zalecaną opcją jest wykorzystanie narzędzia Buildroot. Jeśli natomiast chcemy osiągnąć docelowy efekt jak najmniejszym nakładem pracy, a sam komputer jednopłytkowy ma pełnić również inne funkcje (np. korzystamy z pełnego środowiska graficznego, a emulacja konsoli NES jest wyłącznie dodatkową opcją), warto jest skorzystać z gotowych pakietów środowiska Debian – pozwoli to uniknąć m.in. samodzielnej kompilacji oprogramowania emulatora. W artykule wykorzystano drogę „na skróty” i użyto gotowych obrazów z dystrybucją Debian (autor na własnym przykładzie przekonał się, że wybór drugiej ścieżki jest bardziej „optymalny” – zaoszczędzony czas można wówczas poświęcić na „testowanie” projektu i radosny powrót do czasów dzieciństwa). Przygotowanie karty SD rozpoczynamy od pobrania obrazu systemu. W środowisku Linux operację tę można zrealizować poleceniem:
wget http://somlabs.com/os_images/debian-stretch-visionsom-6ull.img.xz
Po pobraniu pliku rozpakujmy jego zawartość za pomocą narzędzia unxz:
unxz debian-stretch-visionsom-6ull.img.xz
Przed przystąpieniem do dalszych prac, warto również sprawdzić integralność pobranych danych poprzez obliczenie sumy kontrolnej SHA256 i porównanie jej z informacjami udostępnianymi na stronie producenta:
sha256sum debian-stretch-visionsom-6ull.img
Po pobraniu oraz rozpakowaniu pliku, możemy przystąpić do wgrania obrazu systemu na kartę micro-SD. Jedną najprostszych metod zapisania obrazu z pliku jest wykorzystanie linuksowego narzędzia dd. Ogólna składnia polecenia dd może może zostać zapisana następująco:
dd if=<pliku_wejściowy> of=<plik_wyjściowy> <dodatkowe opcje>
Plik wejściowy polecenia (if – Input File) będzie stanowił pobrany w uprzednim kroku obraz systemu debian-stretch-visionsom-6ull.img. Plik wyjściowy (of – Output File) to umieszczona w czytniku i podłączona do komputera karta SD, która jest reprezentowana w systemie jako plik specjalny w katalogu /dev. W celu zweryfikowania, który wpis jest odpowiedzialny za podłączone urządzenie, korzystając z terminala systemowego możemy wydać polecenie dmesg, które wyświetli komunikaty wypisywane w buforze komunikatów jądra, w tym informacje o ostatnio podłączonych urządzeniach, np:
[21870.506727] sdb: sdb1 sdb2 [21870.509486] sd 1:0:0:0: [sdb] Attached SCSI removable disk
W powyższym przypadku wpis /dev/sdb odnosi się do całej karty SD, natomiast wpisy /dev/sdb1, /dev/sdb2, dev/sdbX – do kolejnych partycji urządzenia, o ile zostały one uprzednio utworzone. W przypadku wykorzystania czytnika kart wbudowanego w komputer PC, sterownik urządzenia może zarejestrować kartę SD w postaci pliku o nazwie /dev/mmcblk0.
Polecenia dd używamy korzystając z praw administratora, tak więc należy bezwzględnie upewnić się, że wprowadzono poprawną wartość dla pliku wyjściowego. Błędnie określenie wyjścia może spowodować nadpisanie danych na głównym dysku użytkownika. Z powodu pomyłek, akronim narzędzia dd jest czasem rozwijany do „destroy disk” lub „delete data”. Poprawne określenie pliku wyjściowego reprezentującego podłączoną do czytnika kartę SD, pozwala na ostateczne określenie formy polecenia dd:
sudo dd if=./debian-stretch-visionsom-6ull.img of=/dev/sdX bs=4M oflag=dsync
Powyższe polecenie skopiuje obraz debian-stretch-visionsom-6ull.img na wskazaną kartę SD. Dodatkowe parametry polecenia dd określają zapis w blokach po 4 MB (bs – Block Size) w sposób synchroniczny (bez buforowania). Ponieważ polecenie dd nie umożliwia nam monitorowania postępu zapisu danych na kartę SD, co w zależności od wielkości obrazu systemu może być dość czasochłonne, wygodnym rozwiązaniem jest wykorzystanie narzędzia pv, które wyświetla informacje o postępie odczytu danych z pliku. Przykładowa składnia polecenia z wykorzystaniem narzędzia pv, wygląda następująco:
pv debian-stretch-visionsom-6ull.img | dd of=/dev/sdX bs=4M ofag=dsync
Po wgraniu obrazu na kartę, do konsoli systemu możemy zalogować się wykorzystując wbudowany w płytę bazową VisionCB-STD konwerter UART-USB oraz dowolny program emulatora terminalu:
picocom -b 115200 /dev/ttyUSBX
Po otwarciu połączenia należy zalogować się konto użytkownika root (bez hasła):
Debian GNU/Linux 9 localhost.localdomain ttymxc0 localhost login: root root@localhost:~#