Jak si možná vzpomenete, opustil jsem javovou versi svého emulátoru poněkud znechucen z důvodu, že bez proprietárního blobu nelze zajistit synchronisaci mezi obrazem a zvukem, resp. vůbec souvislý a nepřerušovaný, výstupům hardwaru odpovídající zvukový proud. V JavaScriptu podobný problém existuje rovněž, avšak je, minimálně s moderními prohlížeči, řešitelný.
Jednou z nedávných vymožeností browserového API je totiž AudioWorkletNode, což je skript generující surový zvukový výstup, který běží v samostatném vlákně. Plynulý zvuk tak mohu zajistit tím, že hlavní event loop nechám pro interakci s uživatelem, emulaci hardwaru spustím ve workeru a ve třetím vlákně mi poběží zvuk. Druhé vlákno bude tomu třetímu posílat, jaký zvuk se má hrát, prostřednictvím message kanálu anebo sdíleným bufferem: obojí jsou víceméně ekvivalentní řešení, přičemž pro osmibitové počítače se jeví kanálové řešení zcela dostačujícím.
Toto řešení zajišťuje dokonalý, nepřerušovaný zvukový výstup, s latencí pod 100 ms, tedy plně v normě (mám ověřeno, že 200 ms uživatel vnímá jako poněkud nepříjemné zpožďování zvuku za obrazem/interakcí, avšak 100 ms je prakticky nepostřehnutelné).
Vyřešeno, jediným problémem je praktická implementace. Tu jsem zvládl, avšak zjistil jsem, že moje aplikace je takříkajíc future friendly, avšak present hostile: žádný z browserů moje řešení ve standardním nastavení nepodporuje. Chrome a Opera se musejí nastavit pro experimentální podporu modulárních skriptů ve workerech (moduly potřebuji, abych mohl spouštět hardware dynamicky na požádání a nemusel mít v paměti javascript pro všechen myslitelný hardware, který lze k danému emulovanému počítači připojit), a Firefox je mimo hru zcela, protože dosud nepodporuje AudioWorkletNode (o IE vůbec nemluvím, to je prohlížeč ve stadiu klinické smrti).
Takže mám s publikací emulátoru několik týdnů až měsíců času, než se minimálně jeden prohlížeč dostane do podoby, kdy bude schopen spustit emulátor bez úprav, a rozhodl jsem se vyplnit ho tím, že si v mezidobí naprogramuji nějaký další hardware.
Ano, tušíte dle titulku správně, jako první jsem se pustil do legendárního mikroprocesoru MOS Technology 6502. S ním jsem v živé podobě nikdy nepřišel do styku: ne snad, že bych o něm špatně smýšlel, naopak, ale náhoda tomu chtěla, a všechny počítače, které jsem až donedávna, do příchodu armů, snapdragonů a dalších mobilních CPU, používal, měly procesory od Intelu.
Měl jsem tedy poprvé příležitost, jak 6502 poznat intimně. Jediné, co musím vyřešit, je, jak jeho existenci v emulátoru osmibitové, převážně československé techniky, řádně ideově zdůvodnit. Tesla ho nevyráběla, a nedovážel se ani z Ruska nebo z Východního Německa, tak jako například ekvivalenty Zilogu Z-80. Na pomoc přišli soudruzi z BLR: ti skutečně po určitou dobu vyráběli počítače Правец kompatibilní s Apple II; a pokud budu chtít naprogramovat i RCA 1802, další pozoruhodný kousek, ten zase používali ve svém stroji Srbové.
6502 je pravděpodobně komerčně vůbec nejúspěšnějším 8bitovým mikroprocesorem všech dob: ačkoli byl výkonnější než Intel 8080 a jen o málo zaostával za Zilogem Z-80, prodával se při uvedení na trh za neuvěřitelnou šestinu ceny konkurenčních CPU. To umožnila důmyslná konstrukce instrukčního souboru, který nahradil relativně velký počet registrů širokou škálou adresovacích modů. Některé z nich pracují s tzv. zero page, což jsou adresy $0000–$00ff. Na těchto 256 bytech lze realisovat pseudoregistry, s nimiž se efektivně zachází rychlostí jen o málo nižší než s registry Intelu nebo Zilogu. Spolu s poněkud jinak řešeným časováním pamětí se podařilo docílit takového poměru cena/výkon, že konkurence neměla, minimálně v segmentu levných domácích počítačů a videoher, proti MOSu vůbec šanci.
Procesory MOS 6502 proto používala řada z nejslavnějších osmibitů vůbec: Apple IIe, Commodore PET/Commodore 64, Atari 800 a řada dalších. Pro emulaci je výhodou, že byl vytvořen open source model vnitřního uspořádání CPU, který dovoluje, samozřejmě nikoli s rychlostí, použitelnou pro emulátor, ale zato velmi věrně, studovat a graficky simulovat přesné chování procesoru. Jestliže jsem tedy příkladmo nevěděl, jak se 6502 chová, pokud po něm chceme arithmetiku s packed BCD operátory, které nerepresentují platné hodnoty (např. kolik je $ae + $6c), stačilo stáhnout Perfect6502, což je verse zmíněného simulátoru v C, a vygenerovat si příslušný soubor. Pak už bylo vytvoření přesné funkce hračkou.
MOS 6502 je známý rovněž velkým počtem nedefinovaných instrukcí, které jsou, na rozdíl od převážně akademických instrukcí Zilogu, užitečné a prakticky použitelné (a používané i ve skutečně vyvíjeném a prodávaném softwaru, včetně operačních systémů). Pochopitelně jsem chtěl mít mikroprocesor naemulovaný absolutně dokonale, a naivně jsem se domníval, že mi pomůže Perfect 6502. Jenže se ukázalo, že to není pravda: příkladmo operace ARR, která na fysických procesorech provede AND a poté rotaci, se na simulátoru chovala úplně jinak.
To je vysvětlitelné tím, že při provádění nepodporované instrukce dochází uvnitř procesoru k nestandardnímu stavu, např. některá vodivá dráha zůstane odpojena od všech výstupů a není k ní připojen ani žádný pull-up resistor. Jak se v takové situaci zachovají vstupy, jež nevyžadují stálý proud, tak jako vstupy TTL, ale postačí jim nabít hradlo nepatrným nábojem, může být výsledkem relativně složitého, dynamického fysikálního procesu, který simulátor nedokáže zachytit. A aby to bylo ještě složitější, existuje několik instrukcí, které se chovají různě u různých klonů, případně vykazují zcela indeterministické chování.
Ježto jde o velmi populární procesor, existuje k 6502 řada testů. Já jsem si vybral dva, které patří k nejznámějším a zároveň nejdůkladnějším. Testem Wolfganga Lorenze i testem Klause Dormanna můj emulátor projde a interpretuje správně i všechny nedokumentové instrukce, proto mám za to, že jsem dosáhl přesné shody s originálem. Naemuloval jsem si i CMOSovou versi WDC W65C02S, s rozšířenou instrukční sadou, tam mi arci důkaz přesné shody chybí, a protože žádný test pro rozšiřující instrukce, který by byl ověřen na skutečné součástce, zřejmě neexistuje, budu, ač nerad, musel investovat cca 50 korun do koupě tohoto procesoru in natura.
Co si se 6502 naemuluji? MOS KIM-1, první jednodeskový počítač, který dosáhl skutečně masového rozšíření, to je povinná jízda
; dál se nabízí možností celá řada, od triviálních zařízení po plně grafické a vyspělý zvukový výstup zahrnující stroje. Ještě se proto rozmyslím.
Komentáře
6502 byl procesor, na kterém jsem se kdysi naučil strojový kód. Od té doby rozděluji všechny technologické počiny na "geniální pro konstruktéra" a "geniální pro uživatele" - obé dohromady jsem ještě nezažil. 6502 patří do té první skupiny - vše je podřízeno tomu, aby pomocí 3000 tranzistorů udělali snad nejjednodušší možný procesor. Dokonce i zásobník má pouhých 256 bajtů a ukazatel zásobníku SP je tím pádem také 8bitový.
Když nechám zvuk generovat v main event loop, nestihnu to, protože některé grafické události trvají déle. Takže, zkrátka a dobře, jinou cestu než zvláštní vlákno pro generování zvuku nemám.
Citace: Jak přiznal sám jeden z autorů (nevím z hlavy, jestli Peddle nebo Deutsch), tento procesor nebyl vůbec pro počítače koncipován, kdyby byl, navrhli by ho jinak. To odpovídá: herní konsole, kde se střílí po spritech, se bez standardního stack framu obejde, tam je důležitá hlavně cena. A tu dostali na neuvěřitelnou hladinu, bez ztráty výkonu.
Pokud se týká snadnosti programování, nezažil jsem v assembleru nikdy nic horšího, než před několika lety psát Reversi pro PMD 85 (github.com/.../reversi). Hyporegistrosa v akutním stadiu. To by se mi se 6502 (ale ani se Z-80) nestalo. Proto se domnívám, že 6502 je i pro programátora lepším procesorem než 8080A.
To je klasická zpupnost konstruktérů - že si myslí, že budou určovat, co se rozšíří a co zapadne. (V dnešní době těžko něco lépe demonstruje tento omyl, než IPv6 - kdy si síťaři mysleli, že jsou ředitelé zeměkoule a pupek světa.)
Podobně "geniální pro konstruktéry" je ARM. Tipuji, že ho také nekoncipovali pro dnešní výkonné počítače a mobily. ARM má v sobě zadrátovaných bambilióny zjednodušujících věcí v instrukční sadě i jinde - že to čím dál více drhne. Snižuje to výkon, způsobuje to, že ARM instrukční sada se velice špatně optimalzuje ručně i v kompilátorech, zbytečně se mnoho přistupuje do pomalé RAM/ROM, atd.
Malý počet univerzálních registrů je vždy problém.
Architektura 6502 jsou přesně ty architektury, na které nelze rozumně rozjet kompilátor C. Jestli si vzpomínáte na naši debatu, k čemu je dobrý Forth. Kompilátor C si nabije rychle ústa na 256 bajtů velikém zásobníku. Nebo bude neefektivně tvořit někde v RAM zásobník vlastné emulovaný, a rychlost a efektivita bude v kytkách.
Mým cílem bylo toliko demonstrovat, k čemu je ten Forth dobrý. Jako odkaz k tehdejší debatě. A zároveň ukázat, že programovací jazyk C je velice vybíravý. V podstatě si jazyk C diktuje přesně architekturu. Není schopen efektivně běžet na velké části architektur.
V zásadě je to tak, že vznik unixu si nadiktoval architekturu, na které bude unix běžet (ten efektivně neběží jen tam na něčem) a jazyk C ten diktát ještě zúžil. Takže nám dnes vznikají procesory, které jsou si podobné jako vejce vejci, neb C nic moc jiného nedovolí. Není pak divu, že konkurenční boj následně počet procesorových architektur velice nemilosrdně redukuje čím dál více.
Teď se vývoj překlopil do opačné polohy. Nyní jsou technologie a hardware tak vyspělé, že je silně brzdí dnešní (koncepčně zastaralé) operační systémy a programovací jazyky.
Bohužel zatímco hardware se vyměňuje relativně snadno, software se přepisuje podstatně hůře.
RSS kanál komentářů k tomuto článku