CC65 – volanie ASM subroutines

Je to zvláštne, nikdy som nezvykol písať takéto veci, ale asi ma to fakt baví alebo čo, lebo ináč si to neviem vysvetliť. Odniekiaľ sa proste berie pocit, že sa treba podeliť o skúsenosti…

Poďme teda na to.

Ako som v predošlom článku písal, pracujem na gamese roxblox. Nie je to o tom, že by som nad tym strávil nejako veľa času, ale postupne objavujem rôzne nové problémy, ktoré je potrebné riešiť. Zozačiatku to išlo super, ale čím ďalej, tým zložitejšie veci sa vyskytli a použiie Cčka na ich riešenie nie je vždy jednoduchšie ako použitie ASM (teda aspoň pre mňa).

Ono totiž CC65 štandardne všetky premenné, ktoré sa v programe používajú, ukladá do svojho softwarového stacku. To znamená, že aj jednoduchý programík na presun pár bytov z lokácie A na lokáciu B je riešený MRTE komplikovane.

Príklad z praxe… v hre mám kamene, ktoré majú rozmer 3×3 znaky. Tieto potrebujem vykreslovať do vramky. Nekreslím to priamo, ale mám k dispozícii vrambuffer, kde vykreslím čo treba a keď je to hotovo, len to skopírujem do vram všetko naraz. Toto kopírovanie je strašne pomalé, ukážem prečo… Zoberme si rutinu na kopčenie 3×3 grafiky do vrambuffera. V Cčku som to napísal takto:

Ako to funguje? Jednoducho! V cykle sa presúva obsah poľa tiles do vrambuffera po riadkoch, tzn. keď príde na 4. a 7. prvok, posunie sa o riadok nižšie. Optimálnejšie riešenie ma nenapadlo. Mimochodom, skúšal som skrátiť cyklus na 3 kroky (riadky) a zapísať za sebou 3 priradenia znakov v riadku, ale toto sa do ASM kódu premietlo naozaj doslovne, proste 3x po sebe ten istý kód.

Ok pozrime teraz na to, ako sa Cčkový kód preložil do ASM (bez optimalizácií):

Takýto nechutne dlhý kód presúva 9 bytov z jedného miesta na druhé!!!

Ono by sa mohlo zdať, že sa na to dá vyprdnúť: “veď je to ASM, aj tak to bude rýchle…” – nebude! Naozaj nie, mám to odskúšané 😉

Tu mi žiadna built-in optimalizácia nepomôže. Takéto kritické rutiny treba spraviť v ASM ručne. Ukážem ako na to.
V zásade ako prvý krok treba v configu (atari.cfg) skrátiť časť MEMORY ZP(zero page), aby sa dalo použiť nepriame adresovanie cez 0.stránku bez toho aby som sa musel obávať či si môj ASM kód s preloženým CC65 kódom nebudú vzájomne prepisovať údaje. Skrátil som teda ten size zo $7E na $6E, tým som si “alokoval” 16 bytov 0.stránky pre ASM subrutiny, to je viac než dosť. Zmenený riadok configu vyzerá takto:

ZP: start = $0082, size = $006E, type = rw, define = yes;

$82 + $6E = $F0 , takže od $F0 po $FF je môj priestor.

Rutinu napíšem do roxblox_data.asx z ktorej si labels prenášam do C (viď článok). Vstupné premenné vložím rovno do 0.stránky. Cčkový kód bude vyzerať nasledovne:

Dôložité je povedať kompilátoru aby neoptimalizoval inline assembler, pretože v prípade optimalizácie s využitím inline funkcií by to nechodilo. V úvode funkcie presúvam vstupné parametre do 0.stránky, ktorú mám zadefinovanú takto:

Asm rutina vyzerá nasledovne:

Je tu vidieť značný rozdiel v dĺžke kódu, ale hlavne v rýchlosti vykonania.

Takto vyzerá skompilované nové vnútro funkcie C:

Akosi nechápem, čo tam hľadá to ldx #$00, ale tak čo už, ja som to nepísal :D. Čo sa týka optimalizácie, úplne NEDOPORUČUJEM používať -Oi (oprimalizácia na inline funkcie), strašne to vie sprasiť môj kód a aj taká jednoduchá funkcia, ako je na prvom obrázku v tomto článku prestane fungovať. Optimalizáciu registrov som vyskúšal a zatiaľ som nenarazil na problém. Táto optimalizácia sa púšťa kľúčom -Or a dokážne naozaj viditeľne skrátiť výsledný kód oproti neoptimalizovanej kompilácii.

Pre úplnosť takto vyzerá kód s optimalizáciou -Or:

Dva nepotrebné výskyty ldx #$00 zmizli, jeden ostal.

…nikto nie je dokonalý

CC65 a Atari

Ako som písal v predošlých článkoch ohľadom CC65 C-čkového kompilátora pre Atari, tu je spomínaný návod ako to celé rozbehať. […]

h3x0r deluxe – pokec a preview

Dlhá doba prešla, pravý čas na novú gamesu. Tentokrát ide neočakávane o logickú hru, už tradične prihlásenú na Abbuc Software […]

Leave a Reply

Your email address will not be published. Required fields are marked *