Tento clanek je pro me vylozene provokacni ;-) Hrozne rad bych se ztoporil k tomu, neco si pro atarko napsat. Jenze o tom uz mluvim min 5 let a mam obavu, ze aspon 5 let o tom jen mluvit budu:-(
btw umi neco v asm pro atarko vygenerovat AI? ;-)
Tak to už je nejvyšší čas :-) Já si taky vlastně na sebe upletl bič, protože musím do článků dodat něco funkčního a ne ty polovýtvory, co se mi někde válí na discích...
Jinak CodeRabbitAI kupodivu umí udělat review assembleru 6502 a není to úplná halucinace. Klasické generativní AI jsem nezkoušel, mě to baví psát postaru (taky těžko říct, na čem se to učilo; komunita okolo osmibitů není taková ta klasická open sourcová...)
gcc prece neumi tyhle stare 8 bitove procesory a navic se vyvojem cim dal vice vzdaluje od neceho funkcniho co by na nich bezelo. Da se rici ze je gcc v tomhle smeru cim dal tim vic horsi a horsi.
Nemluve o tom ze ani to C zalozene na zasobnikovem ramci a podporujici implicitne rekurzi neni vhodny jazyk pro tyto procesory.
Z80 to zvlada, ale velmi pomalu a neefektivnimi instrukcemi (cti: napsat to jinak je vzdy lepsi, zapomenout na IX a IY a pouzivat HL a spravne organizovana data) a 6502 na to instrukce ma, ale zase velikost pameti je extremne mala. Platit za rekurzi kdyz nemusis, nebo ji ani nevuzivas je proste spatne.
I nejlepsi prekladac primo pro Z80 je asi 10x horsi nez to napsat rucne v asm nebo v jinem jazyce. Pro 6502 to mozna tak hrozne nebude, ale i tam nic asm neprekona.
no je to trošku na vyšší úrovni abstrakce, takže v CC65 se například pomáhá tím, že __A__ znamená akumulátor, __AX__ dvojici registrů A+X atd. Někdy ten překladač pochopí, co se po něm chce (násobení dvěma převede na ASL), někdy moc ne. Ale s pomocí a pokud ukládá proměnné ne na zásobník, ale do zeropage, z toho leze kód tak cca 2x horší, než od vývojáře (což asi není špatný, ale prostě MOS 6502 není "céčkovský" procesor, tím jsou spíš RISCy).
Cecko umoznuje programovat tak, ze nemas ani tuseni jake problemy mu zpusobujes. Umoznuje ti mit libovolny pocet parametru, volat fci a v ni dalsi fci, v kazde mit lokalni promenne.
Pouziva na to elegantni metodu, ze si kazda fce nejak uklada promenne na zasobnik. Kazda zanorena fce ma svoji oblast. Problem se Z80 je ten, ze to krasne ulozis na zasobnik, ale uz se pak k tomu krome posledni polozky nedostanes... Musis okolo toho delat nejakou dalsi rezii, aby k promennym byl pristup a ta rezie je mnohdy vetsi nez co resis.
Cecko se pak snazi vymyslet neco, co porusuje jeho vlastnosti, ktere od nej cekas. Napriklad zjisti, ze z te fce uz nic nevolas, je posledni, takze by ty promenne mohla mit stale v registrech (leaf function optimization).
Ale ty jsi odstinen tak, ze si neuvedomujes, ze prepravovat 1, 2, 3, 4 nebo i 5 osob v aute je neco jine nez mit tech osob (promennych) 6. Reseni bude jine, co fungovalo predtim uz nemusi.
Cecko pak musi premyslet, jak ohnout samotne zakladni reseni, aby bylo efektivni. S tim musi pocitat vsechno. Ze to co normalne plati, nemusi platit. Knihovny atd.
Nektere jazyky ti povoli jen globalni promenne a kupodivu, ty pak navrhnes reseni, co je mnohem lepsi a snazsi na prevod do asm.
Nektere jazyky maji navic emulovany zasobnik, ale jejich zakladni slova jsou zalozene na tom ze pohodlny pristup mas jen k posledni nebo predposledni polozce. To te nuti napsat to reseni zase jinym algoritmem. A ten prekladac ma usnadnenou praci, protoze misto aby se snazil prevest tvoji abstrakci na instrukcni sadu daneho procesoru si to udelal vicemene za nej ty.
V Cecku napises proste nejaky krasny abstraktni algoritmus, kde prekladac bude premyslet, pak zjisti ze existuje jediny pripad, kdy optimalizace nefunguje a tak ji zavrhne. I kdyz ty vis ze takova data nikdy nedostane, ale napsal si to tak ze on to nepozna. Vubec nevis ze mu hazes klacky pod nohy.
V asm naopak vis, ze kdyz neco treba pretece, tak to je presne ten trik ktery vyuzijes, aby to bylo efektivnejsi. Nebo jakakoliv jina specialni vlastnost daneho procesoru.
Z80 a 6502 jsou tak odlisne pristupy, ze i kdyz delas benchmark tak prijdes na to, ze i ty algoritmy budes mit jine, protoze pro kazdy CPU se hodi jine reseni. Takze i ty klacky co mu hazes pod nohy, muzou byt pokazde nekde jinde.
Proste tyto procesory jsou z doby, kdy C nebylo vsude a kdy jim jeste instrukcni sada nesla naproti.
Existuje takova pekna uloha z rossetacode co zjistuje zda dany retezec je pangram a nebo neni. Tzn. zda obsahuje vsechny pismena abecedy.
Je to jednoducha uloha, ale uz pocet osob se nevleze do jedineho auta.
#include <stdio.h>
int is_pangram(const char *s)
{
const char *alpha = ""
"abcdefghjiklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char ch, wasused[26] = {0};
int total = 0;
while ((ch = *s++) != '\0') {
const char *p;
int idx;
if ((p = strchr(alpha, ch)) == NULL)
continue;
idx = (p - alpha) % 26;
total += !wasused[idx];
wasused[idx] = 1;
if (total == 26)
return 1;
}
return 0;
}
int main(void)
{
int i;
const char *tests[] = {
"The quick brown fox jumps over the lazy dog.",
"The qu1ck brown fox jumps over the lazy d0g."
};
for (i = 0; i < 2; i++)
printf("\"%s\" is %sa pangram\n",
tests[i], is_pangram(tests[i])?"":"not ");
return 0;
}
ja to pojal jako benchmark tak ze udelam 32 bitove binarni pole
#include <stdio.h>
int pangram(const char * str)
{
str--;
unsigned char c;
unsigned long int alphabet = 0;
while (c = *++str) {
c |= 32; // uppercase
c -= 'a';
if ( c<26 ) alphabet |= (long unsigned int) 1 << c;
}
return alphabet==0x3FFFFFF;
}
int main()
{
char *str = "The five boxing wizards jump quickly.";
unsigned int i;
for (i = 10000; i > 0; i--)
pangram(str);
printf("%d\n", pangram(str));
return 0;
}
podle vzoru
: pangram? ( addr len -- ? )
0 -rot bounds do
i c@ 32 or [char] a -
dup 0 26 within if
1 swap lshift or
else drop then
loop
1 26 lshift 1- = ;
s" The five boxing wizards jump quickly." pangram? . \ -1
Tohle funguje jen pokud ma forth 32 bitove a vetsi slova.
pseudo forth 16bit kod:
: pangram ( addr -- ? )
1-
0.
BEGIN
ROT 1+ -ROT 2OVER NIP C@ 0 C<> WHILE 2OVER NIP C@
32 OR [CHAR] a -
DUP 26. WITHIN IF
DBITSET ( d index -- d )
ELSE DROP THEN
REPEAT
67108863. D= NIP ;
A kdyz to zkompilujes z88dk nebo forthem, tak C je 6x pomalejsi.
Docela by me zajimalo i jak si vede C prekladac pro 6502. Z80 to trvalo 2m 51.61s a ten jeho kod uplne zkolaboval a jak ten kod pro sebe rozkouskoval na male casti a ty prevadel do asm tak je to kolikrat ze neco spocita a uklada na "stack" a pak to hned zase vraci do stejnych registru a pouzije znova...
Poprve v zivote jsem si naistaloval cc65 a atari800 a vyzkousel to.
str--; unsigned char c; unsigned long int alphabet = 0;
Tady mu vadilo ze pred deklaraci je uz to str-- i kdyz se neumi vyjadrit a zahltil me nesmyslnymi chybovymi vypisy.
Atarko to spocita asi za cca 4m 19s.
Resit to pres 32 bitove pole je ale takove lidske Z80 asm reseni... Ani jeden prekladac to moc nedava. z88dk nedokaze pochopit myslenku, jen vi ze nema misto na to drzet si v registrech trvale 32 bit cislo, tak zacina zonglovat ho neustale ukladat tim nejpomalejsim resenim do RAM a znovu zpet. Znova a znova. Protoze uz si nepamatuje ze s nim pracoval v predchozim kroku, nebo v pristim znovu bude.
A 6502 se to taky nelibi, ten by chtel to mit jako 26 bajtove pole v rychle strance i kdyz to musi cele nulovat. A asi prekladac pro Z80 by vyplodil neco rychlejsiho timto resenim. Protoze to nastavovani nekonstantniho bitu neni uplne trivialni.
Overoval jsem to a u Z80 se jednalo o sdcc prekladac.
zcc asi neumi 32 bitove hodnoty?
Ale po uprave na dve 16 bitove to spocital asi za cca 38 sekund, vypsal 1 a pak se to zhroutilo. Je to ale uz je jiny program, ktery uz nema problem, ze se vsechno nevleze do registru. Slozitejsi C kod, ale lepsi vysledek v asm.
int pangram(const char * str)
{
unsigned int alphabet_lo = 0; // a..p
unsigned int alphabet_hi = 0; // q..z
unsigned char c;
while (c = *str++) {
c |= 32; // uppercase to lowercase
c -= 'a';
if (c < 16) alphabet_lo |= 1 << c;
else if (c < 26) alphabet_hi |= 1 << (c-16);
}
return (alphabet_lo == 0xFFFF) && (alphabet_hi == 0x03FF);
}
PS: Udelat ty promenne globalni, teda na staticke adrese by to zrychlilo a i vzhledem k jednodusimu kodu/pristupu se usetrilo i misto.
8. 3. 2026, 20:42 editováno autorem komentáře
Proste tyto procesory jsou z doby, kdy C nebylo vsude a kdy jim jeste instrukcni sada nesla naproti.
V té době C ani zdaleka nebylo tak rozšířené jako dnes. Bylo tehdy spojené s Unixem a až v 80. letech se začalo více rozšiřovat i mimo toto prostředí.
Jinými slovy - tyto procesory jsou z doby, kdy vám každý řekl, že myslíte-li to s programováním vážně, naučte se co nejdřív Assembler. A jediná prakticky použitelná vyšší alternativa byl FORTH.
parada, na commodore 64 jsem si rucne psal assembler a taky jsem freeznul hru a mel jsem nejaky program monitor a ten byl tak dobry, ze dokazal i pole 64 bytu rozbrazit jako sprite a tak jsem nepratelskym potvoram vynuloval pixely takze nedoslo v kodu k detekci kolize a byl to takovy muj zpusob cheatovani hry.
tyjo to je dobrý monitor, neznáš jeho jméno?
(jinak já kdysi - jako úplnej neználek - hledal v RAM obrázky z her. Normálně jsem hru resetl, načel nějakej prohlížeč (už nevím co to bylo) a procházel celou pamětí, jestli tam není vidět rastr. Samozřejmě na Atárku většina her vůbec neběžela v grafickém režimu, takže to byl smolík...).
hmm to bylo něco z tuzemska asi. Podporovalo to tisk na BT100 a ten průchod pamětí (v GR.8) byl IMHO jemnej (i po bajtu). Tyjo mě to snad donutí někde najít přebaly těch starých kazet. Ale to jméno bylo něco ve stylu PRNBT100 nebo tak nějak.
PS: nejlepší bylo, když ta paměť v GR.8 byla někde na nulté stránce nebo naopak na HW registrech - potom se tam daly sledovat například změny časovačů, stisky kláves, posun joysticku atd. (blikalo pár pixelů). Tehdy jsem to chápal jen dost mlhavě, byl to takovej magic box :-)
To o cem mluvim (a uz si fakt nevzpomenu na jmeno) byla v podstate jednoducha vec:
1) nacetla se do pameti
2) prepnula do GR.8
3) clovek potom "listoval" celou pameti a kdyz nasel obrazek, tak to nejak pres SELECT nebo OPTION slo dumpnout na BT100
Pocitalo se s tim, ze pamet prezije soft reset a tedy tam prezijou i obrazky ze hry.
IMHO to vubec nic dalsiho neumelo. Ale je to 40 let nazpet, tak mozna halucinuju
sprity byl tim padem neviditelne a nesly ani strilet, ale mi v te hre slo o to projit vsechny mistnosti, protoze jich byla hromada.
https://www.zx-spectrum.cz/data/maps/map.php?id=Starquake.png
Jak už tu víc lidí psalo, spousta her byla tehdy neobyčejně těžká. Taky jsem si udělal loni radost a naučil jsem se dohrávat kompletní Starquake - sladké vítězství po téměř 40 letech :) Teď už ho umím tak, že si životy naopak uměle umenšuju, začínám s jedním, aby každá chyba znamenala konec...
Ale zajímavější bylo, jak jsem se k tomu vítězství propracoval, protože to souvisí se současným článkem: stroják 6502 je jako jízda na kole, ani po 35 letech se nezapomíná :) Pro mě bylo vždy nejtěžší se ve hře neztratit, takže jsem rozebral jsem kód hry a kam si ukládá jaká data. A pak jsem hrál v emulátoru, abych si mohl na jeho konsoli kdykoli spustit svou "Starquake GPS" - vyrobí velké PNG s mapou hry a puntíkem, kde jsem. Pro zajímavost jsem zkusil i podbarvit jinak místnosti, kde už jsem byl (i to hra eviduje) a polohu jednotlivých předmětů. Ale to všechno byla jen zkouška, co z toho umím "vytáhnout" - hru to zjednodušovalo už moc, tak jsem to pak nepoužíval.
A ano, i pak nastaly těžké chvíle obratnosti a propočtů a jedna z nejtěžších je ten kousek v levém dolním rohu s teleportem "Z.A.P" alias "Zatracená Autorská Pomsta" :) Ale jsou tam i jiné "špeky", ty ale člověka potkají jen jednou za X her, když je důležitý předmět na jednom z obzvláště vypečených míst - a pak mnoho místností normáľně prolítnutých talířkem za pár vteřin se stane peklem s výpočtem každého jednoho dílku "plošinky"...
Integrovanej monitor ve final cartridge III (a klony ala Final Replay, ...) všechno toto umi - ES a EC příkazy. Pak ještě Hesmon, ten uměl pěkně relokovat (N + E). Taky se pěkně prochází pamět přez I, časem si člověk jak metrixu navikne na instrukce ve znakovce a jde docela rozpoznat kód pohledem :)
Freezer ale nikdy pořádně nefungoval, ono dost dobře nejde nastartovat CIA časovaše a podobně, protože nelze jednoduše načíst a na cykl je pustit přesně. Tak půlka her s tím fungovla druhá půlka to "restore" prostě zamrzla.
P.
Pro zajímavost s tím freezerem. Tyhle starosti ataráci nemaj, ale na druhou stranu díky tomu o moc přichází (realtime mrzaření čítačů v VIC dokáže hodně :) Většina efektů potřebuje přesný sync s paprskem - na cykl přesně. A interupt se zpozdí o 0 - 10 cyklů. Klasicke "cmp" s video lajnou to sníží na 0-5, ale pořád k prdu (CMP+BNE). Pak se to dá odčasovat po řádcích - co cykl, to řádek. Ale těch cyklů. Na to není výkon :)
S timerama to stači udělat jednou a už jedou nafurt správně :) A sesyncrhonizovat se lze pak udělat už poměrně snadno self-mod kódem - pro $05e7 jakozto hodnotu timeru:
nmi_code_tb_begin=<$05e7-26-9+1 ; 9 combinations ldx CIA2_TIMER_LO lda nmi_code_tb_offs,x sta *+3 bne * .byte $ea,$25,$a,$10,$05,$a9,$a9,$a9,$ad,$c5,$ea ... code
Tabulka je pak nekde mimo
; page aligned
*= (*+$ff) & $ff00
; NMI stabilizationt table
nmi_code_tb_offs .rep nmi_code_tb_begin
.byte $0a
.endrep
.byte $0a ; wait 2 cycles
.byte $09 ; wait 3 cycles
.byte $08 ; wait 4 cycles
.byte $07 ; wait 5 cycles
.byte $06 ; wait 6 cycles
.byte $05 ; wait 7 cycles
.byte $01 ; wait 8 cycles
.byte $04 ; wait 9 cycles
.byte $00 ; wait 10 cycles
.rep 256-nmi_code_tb_begin-9
.byte $0a
.endrep
Pokud se CIA zpozdí, v cyklech to jde krásně vyčíst. A tenhle úsek za BNE poběží 2 až 10 cyklů... Podle toho kam ho CIA hodí (nejdelší flow je NOP/AND $00/BPL/NOP).
A přesně tohle freezer moc nedává a když jedne použíje i 2 časovače na NMI jako "další" IRQ (mnoho cyklů se ušetří...) tak freezer hitne další NMI ještě dřív než "vypne" to přechozí. A obnovit tohle je prakticky nemožný.
P.
7. 3. 2026, 10:15 editováno autorem komentáře
Pro mě se vše spustilo loni, kdy se ke mě po mnoha letech dostaly mé vlastní, už dávno ztracené, levely do Boulder Dashe, co jsme dělali jako kluci s bráchou. Mimochodem, to navazuje i na článek o ATARI XE ve sbírce, protože na to se právě hodila ta rozšířená RAM: díky TTDOS z ní byla zařízení D1 - D4, a až na konci práce každý den jsme to vše překopírovali na kazetu (zař. "B" - specialita TTDOS).
To vše se mi vybavilo, následně jsem zjistil, že stroják stále ještě obstojně dobře čtu jako knihu. A že s trochou zamyšlení zvládám i ANTIC aneb jeho Display List. Tak jsem se do toho ponořil, podíval se pár programům, co mě vždycky zajímaly, na zoubek. A nově některé začal obdivovat ještě mnohem víc než tehdy, kdy jsem jejich propracovanost vůbec netušil. Ze všech nejvíc ovladač "A:" k alfigrafu z pražského Atari Klubu. To je neskutečně obří SW a umí fůru věcí, včetně fontů písma, navíc za běhu modifikovatelným.
A tak se jedním z mých hobby projektů stal linuxový prográmek, který odchytí data na "A:" (tj. z joystickových portů) a vykreslí je jako PostScript/PDF :) Udělalo mi to radost, ale zatím je to hodně "Syrové", bylo to jen na mé hrátky. Kdyby byl ale zájem, možná to ještě vyhrabu a můžu dát někam na github.
No a úplně poslední level mého archeologického pátrání bylo, když jsem přes zájem o nově vybádané možnosti grafiky na ATARI sklouznul až do mnohem hlubšího poznání spolupráce 6502 a ANTICu a tím i "střevům" procesoru 6502. Je to neskutečně fascinující (a myslím, že jedinečná) architektura. Možná byla až příliš dobrá, že nešla moc dál rozšiřovat a ujala se místo ní "hrubá síla" procesorů stavěných jako Z80 - Intel 8080 a dál. Stálo by to možná za další historický průzkum, jak to tehdy bylo. Ale přijde mi to tak: je to "vytůněné" na jedno specifické použití (levný 8-bitový procesor) - otázka je, jestli to tak opravdu bylo, jestli to nebyla jen souhra okolností a šikovné obchodní strategie Intelu. Kdybyste někdo věděl víc, budu rád!
Ale co třeba podporuje můj názor, je fakt, že nikdy nezačali ve velkém vyrábět ten původní procesor, jehož levná varianta 6502 je. Zkrátka ve své třídě 6502 naprosto stačí, i s těmi omezeními jako jen osmibitové registry, a další vývoj šel jinudy. Nicméně 6502 se dodnes vyrábí a používá!
důvod obliby 6502 jsem kdysi dávno zmiňoval tady: https://www.root.cz/clanky/jak-se-zrodil-procesor/#k07
TL;DR; byl to strašně až podezřele levný čip, osekanej na samotné jádro (jen jeden akumulátor, X a Y zkrácené na osm bitů, S zkrácený na devět bitů, instrukční sada extrémně ořezaná). Ale bylo to levné, dobře to dokázalo kooperovat na sběrnici třeba právě s ANTICem, takže se to nasazovalo všude možně (Apply, Atárka, Commodory, herní automaty, NES a spol, ale i průmysl).
Keby sa niekomu nechcelo to celé nastavovať tak pripomínam
https://8bitworkshop.com/v3.12.1/?platform=atari8-800&file=siegegame.c
8mi bity jsou v tomto jiné kafe, než přebujelý svět gigaherců/gigaram :) Na C64 existuje tuna věcí pro cross-compile použitelných i pro ataráka. Já nakonec skončil u toho, že jsem si napsal vlastni casm, protože mi scházelo dost věcí, zejména hlídání přetýkání stránek (cykl navíc a hned je to v .... však vi víte kde). U toho vývoje byl u nativu velký problém s RAM. Sem tam jsem měl volno par stovej bajtů rozesený po RAM a jinak nic... U někteýrch věcí jsem musel překládat na disk a pak to linkovat dokupy, protože to prostě už nešlo ani 'zkusmo' přeložit. Jedno z prvních rozšíření RAM bylo jen přepínaní 2 64K defacto (prakticky paralelně napájený DRAM na sobě), jedna na vývoj a druhá na "běh" :) Nejlepší hry ala Creatures, Turrican byly dělaný na kompu o generaci novějším, typicky C128/AmstradPC a překládaný na C64. Taky jste to tak na ataráku měli ? Ikdyž vlastně pěkný hry nemáte že ? :-)
Osobně jsem skončil s paralelním přenosem a cross-asm, protože emulátory rád nemám. Hádám, že to je jak sex s nafukovací panou :) Asi lepší než nic, ale.... Ad AI - sem tam jsem zkoušel co to dokáže a při posledním pokusu si to pletlo SEI a CLI, nezvladalo rozdíl mezi IRQ na CPU/KERNAL vektory, ... Ale BASIC to poskladálo, sice s chybama, ale zálo se to od pohledu dobře. Nakonec se omluvil, že nízkoúrovňovej ASM neumí a vypl se (o:
R.
To bylo jen rýpnuti, já náhodou atary HW znám pomerně slušně... Až a pár prvků je VIC někde jinde. Krom toho filozofie displaylistu je (IMHO samozřejmně) prakticky hodně omezující, ale pro BASIC nutná... VIC zobrazí stovky spritů naráz a nestojí to ani moc výkonu. Dokonce i 8 spritů horizontálně jde obejít, ale to už je brutus na CPU... Naproti tomu vaše vertikální limitace je právě daná touhle filzofií. Netuším, jestli autoři VICu něco podobného předpokládali, nebo je to jen side efekt.
Nicméně, to je debata k pivu :) A to se nezmiňuju o hudbě :o)
Já si myslím, že za scénou na C64 a celkově stojí právě nekvalitní BASIC. Jsem rád, že nebyl "dostatečně" dobrej jako na ataráku. Pokud někdo chtěl něco víc dělat, nestačilo zůstat tady v té rovině. Dost lidí co z atárka znám zakyslo právě na BASICu, protože "byl dostatečně dobrej". Já taky zabředl do ASM už někdy v 10letech právě kvůli absenci BASICu. HaleluJá :)
Někdy míň znamená víc a IMHO je tohle toho krásný příklad.
P.
Btw. letos po mnoha letech se našel odvážlivec/blázen/sadomasochista*:
https://schlimeisch2026.netlify.app
Kouzlo minimalismu se zkombinuje s maximalizací bolesti hlavy po pivu druhý den :) Aneb co jsme dřív rozdýchávali dopoledne už je na 2 dny (o:
Třeba letos tam nebude víc ataristů než 64kařů :)
* nehodící se skrtni
P.