Nakolko mi nápad portuvať Bobbyho na PAXa vŕtal a vŕtal v gebuli som sa pustil do prieskumu jak by to najlepšie bolo spraviť. Hra je J2ME ale celú JVM s podporou J2ME som moc chuť portuvať nemal, tak som sa kukol na opensource prerábky klasického starého zajáca. Napriek tomu že póvodná mobilná hra je z 2004 tak sa z nevysvetlitelného dóvodu v nedávnej dobe roztrhlo vreco s remakami ešte k tomu v šelijakých "trenduvacích" moderných jazykoch. Už dlhší som vedel
o tomto odinovom ale keďže sa jenná o jazyk o kerom nikdy nikdo nepočul a ešte to vyzeralo aj dosť vázané na windows, tak som sa poobzíral ďalej.
Našov som toto
čínske repo, ktoré obsahuje port zajáca v Ruste, Zigu a v Haxe (zas voláky neznámy moderný jazyk). Rozhodol som sa zamerať na Rustovú verziu hlavne kóli lákavému SDL2 v mene a tomu že to bude asi najpodporuvanejší a najvyzretejší jazyk z ponúkaných možností.
SDL2 "DRIVERLESS"
SDL2 síce zní jak ulahčení roboty, no SDL2 neni SDL1.2 (ktoré už
máme funkčné). Problém je hlavne v tom, že dvojka už nemá podporu pre priamy výstup do framebuffera (fbcon v 1.2ke) a na PAXovi je len framebuffer. Pri snahe nájsť ríšení tohoto problému som narazev na
tento post. Autor mal podobný problém, a vyríšev ho celkom originálne a jennoducho ešte aj bez potreby zásahu do SDLka!
Fígel bol celkom jennoduchý, video driver z SDLka uplne vyradíme a sami budeme valiť pixely ze SDL surface rovno do framebuffera z nášho aplikačného kódu. Toť je ukážka kódu z og postu:
Code: Select all
def refresh():
# We open the TFT screen's framebuffer as a binary file. Note that we will write bytes into it, hence the "wb" operator
f = open("/dev/fb1","wb")
# According to the TFT screen specs, it supports only 16bits pixels depth
# Pygame surfaces use 24bits pixels depth by default, but the surface itself provides a very handy method to convert it.
# once converted, we write the full byte buffer of the pygame surface into the TFT screen framebuffer like we would in a plain file:
f.write(lcd.convert(16,0).get_buffer())
# We can then close our access to the framebuffer
f.close()
time.sleep(0.1)
(pygame2 je vlastne binding SDL 2ky do pythona)
Ohurený touto ideou (kerá neni voláka revolučná ale mňa by to hneď nenapallo lebo já som sprostý) som sťáhol SDL 2ku zdroják a vykompiluval ho s túto konfiguráciu:
Code: Select all
CC='/home/parallels/arm-2012.03-57-arm-none-linux-gnueabi-i686-pc-linux-gnu/arm-2012.03/bin/arm-none-linux-gnueabi-gcc' ./configure --disable-audio --disable-video --disable-joystick --disable-haptic --disable-hidapi --disable-sensor --disable-video-vulkan --disable-dbus --prefix=/home/parallels/sdlout/ --host=arm-none-linux-gnueabi
CC='/home/parallels/arm-2012.03-57-arm-none-linux-gnueabi-i686-pc-linux-gnu/arm-2012.03/bin/arm-none-linux-gnueabi-gcc' make
CC='/home/parallels/arm-2012.03-57-arm-none-linux-gnueabi-i686-pc-linux-gnu/arm-2012.03/bin/arm-none-linux-gnueabi-gcc' make install
prakticky mi išlo o to vyvaliť šecky driver komponenty a využiť SDL len na skladaní obrazu, šecko ostatné vyríšiť pomimo, takto si to nevyžaduvalo zásah do kódu ani rozumení tomu jak to funguje. Knižnice mi to pekne vyprdlo do príčinku nastaveného do --prefix=
Prvotná próba s jennoduchým Cčkovým test kódom bola úspešná, pocit eufórie značný:
Code: Select all
#include "./SDL2/SDL.h"
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
__attribute__((constructor))
int app_start() {
SDL_Surface *surface = SDL_CreateRGBSurface(0, 320, 240, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
SDL_FillRect(surface, NULL, SDL_MapRGB(surface->format, 0, 0, 0));
SDL_Rect rect = { 50, 50, 100, 100 }; // x, y, width, height
SDL_FillRect(surface, &rect, SDL_MapRGB(surface->format, 255, 0, 0));
SDL_Surface *convertedsurface = SDL_ConvertSurface(surface, SDL_AllocFormat(SDL_PIXELFORMAT_RGB565),0);
int fb = open("/dev/fb", O_RDWR);
write(fb, convertedsurface->pixels, surface->pitch * surface->h);
close(fb);
SDL_FreeSurface(surface);
SDL_Quit();
return 0;
}
- Prvý štvorec z SDL 2ky!
- IMG_20241106_214749.jpg (169.95 KiB) Viewed 33 times
Treba ale ešte bolo aj SDL_image a SDL_gfx. Tam kompilácia prebehla bezproblémovo, tak jak pri okresanom hlavnom SDLku.
Z imagea som nehal len hlavné obrázkové formáty, bmp, gif, jpg, png, neh tam neni kadejaký webp a podobný bordel čo moc treba nebolo. Kompiluval som takto:
Code: Select all
CC='/home/parallels/arm-2012.03-57-arm-none-linux-gnueabi-i686-pc-linux-gnu/arm-2012.03/bin/arm-none-linux-gnueabi-gcc' ./configure --disable-avif --disable-jpg-shared --disable-jxl --disable-png-shared --disable-svg --disable-tif --disable-xcf --disable-xpm --disable-xv --disable-webp --disable-qoi --disable-lbm --disable-pcx --disable-sdltest --with-sdl-prefix=/home/parallels/sdlout/ -prefix=/home/parallels/sdlout/ --host=arm-none-linux-gnueabi
CC='/home/parallels/arm-2012.03-57-arm-none-linux-gnueabi-i686-pc-linux-gnu/arm-2012.03/bin/arm-none-linux-gnueabi-gcc' make
CC='/home/parallels/arm-2012.03-57-arm-none-linux-gnueabi-i686-pc-linux-gnu/arm-2012.03/bin/arm-none-linux-gnueabi-gcc' make install
Ze SDL_gfx bol minimálny problém že bolo treba do
config.sub prihodiť
aarch64 medzi rozpoznané procesor typy. SDL_gfx je staré, aarch64 nefičalo vtedy a mašina na kerej som crosscompiluval aarch64 je, configure skriptu to voláko prekážalo že to nepozná, vyríšlo sa to teda takto. Hentak volák jak v tomto príklade by to malo stačiť pridať:
Code: Select all
# Decode aliases for certain CPU-COMPANY combinations.
case $basic_machine in
# Recognize the basic CPU types without company name.
# Some are omitted here because they have special meanings below.
1750a | 580 \
| a29k \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
| arc | arm| aarch64 | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
| be32 | be64 \
| bfin \
a takto skompiluvať:
Code: Select all
CC='/home/parallels/arm-2012.03-57-arm-none-linux-gnueabi-i686-pc-linux-gnu/arm-2012.03/bin/arm-none-linux-gnueabi-gcc' ./configure --with-sdl-prefix=/home/parallels/sdlout/ -prefix=/home/parallels/sdlout/ --disable-mmx --host=arm-none-linux-gnueabi --build=aarch64-linux-gnu
CC='/home/parallels/arm-2012.03-57-arm-none-linux-gnueabi-i686-pc-linux-gnu/arm-2012.03/bin/arm-none-linux-gnueabi-gcc' make
CC='/home/parallels/arm-2012.03-57-arm-none-linux-gnueabi-i686-pc-linux-gnu/arm-2012.03/bin/arm-none-linux-gnueabi-gcc' make install
(ano to --disable-mmx je také absurdné ale fakt to sťelo kompiluvať s mmx podporu na arm)
Na sťáhnutí ponúkam vykompiluvané knižnice s headermi. gfx a img aj zdílané ale samotné SDLko len statické, keďže s takúto podivnú implementáciu je lepšé systém radšej nešpiniť a nalinkuvať si ju staticky len do vlastnej aplikácie de víme, o čo sa jedná
Rust (na nepodporuvanom systéme )
SDLko máme poríšené (divne ale máme), no na kompletného zajáca treba aj Rust. Keď sa kukneme na podporuvané platformy v dokumentácii tak to moc ružovo nevyzerá. Čo Čil?
- Ani kernel ani glibc, čo s tým..
- Screenshot 2024-11-11 at 01.57.10.png (138.48 KiB) Viewed 33 times
Nemáme na to ani správnu verziu jadra a ani glibc. Crosscompile v Ruste je celkom jednoduchý, stačí pridať podporu pre target
Code: Select all
rustup target add arm-unknown-linux-gnueabi
a pri kompilovaní špecifikovať cross gcc na linkuvaní. Lenže, ze starým klasickým dobrým sourcery 2012 toolchainom to funguvať nechcelo a s novým z debian repa to síce skompiluvalo, no samozrejme pri spustení na PAXe vyhodilo klasickú chybu, kerú vyhadzuje keď je použité moc nové glibc. Samozrejme sťeli sme dynamickú knižnicu takže v cargo.toml je treba špecifikuvať takto
To nám ale pomóže trt, keďže to nejde.
Ríšením sa ukázalo použiť místo gnueabi
arm-unknown-linux-musleabi a musl staticky nalinkuvať. Tým pádom obijdeme potrebu nového glibc. No prúser 2, rust nesťel vyrobiť cdylib knižnicu pri použití musleabi. Ríšení sa ukázalo byť celkom zaujímavým spósobom. V ruste vykompilujeme jak statickú knižnicu a nalinkujeme si to do dynamickej knižnice ručne pomocou gcc.
Cargo.toml treba zmeniť takto:
Vykompilujeme potom pomocou:
Code: Select all
cargo build --release --target=arm-unknown-linux-musleabi
a Rust nám vypluje .a statickú knižnicu, linker v tomto prípade ani špecifikuvať neni treba, ten použijeme teraz čil ručne. Místo klasického toolchainu s glibc nám bude treba muslový, ten som zebral
odťálto arm-linux-musleabi-cross.tgz
zalinkujeme to do .so knižnice takto:
Code: Select all
/home/parallels/arm-linux-musleabi-cross/bin/arm-linux-musleabi-gcc -shared -fPIC -o sharedlib.so -Wl,--whole-archive libfromrust.a -Wl,--no-whole-archive -nostartfiles -static
musl sa zalinkuje staticky a takáto knižnica už na PAXe pójde
Poďme s tým na zajáca
cargo.toml som upravil aby místo normálnej binárky urobil knižnicu, tú potom načítavame pre zjednodušení ešte z loader medziknižnice kóli špecifikáciám spúšťaňá vecí v PAXe. Zdroják zajáca som upravil tak aby rval sdl surface do framebuffera a čítal klávesy místo cez SDLko rovno z /dev/keypad evdevu. Renderuvaní obrazu bolo treba otočiť o devadesát stupňov aby to bolo správne na výšku. Nesťem moc ten rust kód popisuvať, nakolko je dosť chujovo spravený a nerozumím sa do toho, bolo to skór len pokus omyl. Každý si ho móže prečítať ve zdrojáku. Na záver zajáca vykompilujeme takto:
Code: Select all
RUSTFLAGS='-L /home/parallels/sdlout/lib' cargo build --release --target=arm-unknown-linux-musleabi
/home/parallels/arm-linux-musleabi-cross/bin/arm-linux-musleabi-gcc -shared -fPIC -o rustbobbytest.so -Wl,--whole-archive '/home/parallels/bobby-carrot/rust-sdl2/target/arm-unknown-linux-musleabi/release/libbobby_carrot.a' '/home/parallels/sdlout/lib/libSDL2_gfx.a' '/home/parallels/sdlout/lib/libSDL2_image.a' -Wl,--no-whole-archive -nostartfiles -static
podotknúť toť sťem ešte to, že RUSTFLAGS='-L tam mosí byť kóli tomu, že SDLko rust zapakuje do tej statickej knižnice čo vyprdne už sám (features = ["static-link"] v cargo.toml)
ostatné knižnice ale ten debil nezapakuje, preto su zas špecifikuvané ve finálnom linkuvacom príkaze, keďže som sťel šecky sdlkoviny mať staticky
pre kompletnosť ešte príkaz na skompiluvaní loader medziknižnice:
Code: Select all
/home/parallels/arm-2012.03-57-arm-none-linux-gnueabi-i686-pc-linux-gnu/arm-2012.03/bin/arm-none-linux-gnueabi-gcc -shared -fPIC -o rustload.so rustload.c -nostartfiles -ldl
Zdrojáky toť:
Na záver ešte voláke obrázky jak to prebíhalo:
- Prýv štvorec vyplutý cez SDLko z Rustu, hurá hurá
- sdlrust.jpg (87.77 KiB) Viewed 33 times
- Už tam máme zajáca
- prvyrender.jpg (53.4 KiB) Viewed 33 times
- Konečne aj správne otočeného
- renderspravne.jpg (144.98 KiB) Viewed 33 times