Sinclair ZX 80

software pro ZX 80

Sinclair ZX 80


Jak jsem již uvedl při popisu stavby své repliky ZX80, vytkl jsem si za cíl využít ladem ležící oblast paměti, kterou počítač standardně adresuje jako ROM, k umístění některých často používaných programů. Konkrétně se jedná o oblast 1000h3FFFh, tedy plných 12 KB volného prostoru. V originálním ZX80 se v této oblasti pouze neúčelně zrcadlí operační systém z prvních 4 KB. Po přivedení signálu A13 je možné prostor ROM obsadit pamětí 16 KB, která oblast plně využije. Popis adaptéru na EPROM jsem přinesl na stránce o své replice ZX80. Na této stránce bude popsáno, jak lze volného prostoru za operačním systémem ZX80 efektivně využít.

V oblasti prvních 16 KB nelze přímo umisťovat a spouštět programy v Basicu. Pouze programy ve strojovém kódu, které lze následně z Basicu spouštět pomocí příkazu USR, třeba takto: PRINT USR(adresa). Strojový program by měl zálohovat všechny používané registry a měl by končit instrukcí RET pro návrat do Basicu. Pro předávání parametrů slouží registrový pár HL. V HL předává příkaz USR strojovému programu adresu spuštění a v HL by měl strojový program předat do Basicu výsledek své činnosti. Pokud se pro volání použije konstrukce PRINT USR(adresa), je navrácený obsah HL dekadicky "vytištěn" na obrazovku. Strojový kód lze ale spustit i jinak, třeba konstrukcí LET A=USR(adresa) a pak je navrácený obsah HL přiřazen do proměnné (zde A).

Mojí ideou ale bylo zde mít Basicovské programy. Jediné řešení tedy spočívalo v napsání strojové rutiny, která by uložený Basicovský program překopírovala do RAM ZX80, kde by bylo možné ho spouštět, editovat a prostě s ním klasicky pracovat. Klíčové ale bylo sehnat Basicovské programy v použitelném (ideálně binárním) tvaru. Ukázalo se, že to nebude žádný problém. Existují totiž softwarové emulátory počítaže ZX80 pro PC a tyto emulátory používají soubory s programy ve tvaru, který je přesně to, co jsem hledal. Jedná se o známé soubory *.O a soubory *.80 (oba typy jsou identické a liší se jen a pouze příponou O nebo 80).


Soubory *.O a *.80

Soubory *.O, resp *.80 nejsou ničím jiným, než binárním obsahem paměti RAM ZX80 odpovídajícímu stavu po nahrání programu z MGF. Zkrátka stačí jen umístit oblíbené O/80 soubory do EPROM a napsat rutinu, která na požádání nakopíruje vybraný O/80 file do RAM ZX80 od adresy 4000h. A je to. Problémem je ovšem různá délka souborů. Zkrátka je nutné kopírovací rutině nějak říci, kolik dat (bajtů) se má kopírovat. Nakonec se to ukázalo být velmi jednoduché. Kromě vlastního Basicovského programu je totiž součástí O/80 souborů i oblast systémových a uživatelských proměnných. Z těchto proměnných je důležitá 2-bajtová proměnná E-LINE, která se nachází na adresách 000Ah a 000Bh, tedy 10. a 11. bajt od začátku O/80 file. E_LINE totiž obsahuje počáteční adresu tzv. pracovního prostoru editoru, neboli první adresu editované příkazové řádky (Edit Line). Zkrátka je to první volná adresa ZA nahraným programem. Nahrání binárních dat z O/80 file tedy musí skončit na adrese E_LINE minus 1 a hodnotou zde ukládanou by mělo být 80h (poslední bajt O-file je vždy 80h, ale nelze se řídit pouze tím).


ZX80_loader

Původně jsem uvažoval o jediné univerzální rutině, které by se předával parametr v podobě čísla požadovaného programu, jež si přejeme nahrát do RAM ZX80. Jenže to vycházelo moc složité a navíc by byla docela složitá celková příprava EPROM pro ZX80. Nakonec jsem tedy dospěl k názoru, že lepší bude kraťoučká rutinka, která se prostě jen "přilepí" k požadovanému O/80 souboru a zajistí jeho nakopírování do RAM. Každý nahrávaný program tedy bude mít svou vlastní kopírovací rutinu. A přesně to se i povedlo. Rutina ZX80_loader má jen 58 bajtů a její použití je velmi snadné. V podstatě jen stačí spojit rutinu v binárním tvaru s požadovaným O/80 souborem v jediný soubor a ten umístit do volného prostoru v EPROM za operační systém ZX80 (tedy od adresy 1000h, maximálně do 3FFFh). Příkazem PRINT USR (adresa), kde "adresa" je počáteční adresa (dekadicky!) rutiny s připojeným O/80 souborem, dojde k natažení programu do RAM a návratu do editoru BASICu. Natažený program lze nyní, editovat či spustit klasicky, jako kdyby byl nahrán z MGF.

    ZX80_Loader

Rutina ZX80_Loader je plně relokovatelná a lze ji tedy spolu s O/80 fajlem umisťovat kdekoliv v uvedeném rozsahu adres v EPROM. Jediným parametrem předávaným rutině je její vlastní počáteční adresa, kterou jí však BASIC automaticky předává v HL. První volný bajt za rutinou musí být zároveň prvním bajtem O/80 file. Ze znalosti své délky a ze znalosti umístění obsahu proměnné E_LINE v O/80 file rutina zjistí koncovou adresu pro kopírování do RAM. Nyní může nakopírovat data z O/80 file do RAM od adresy 4000h až po adresu E_LINE-1.


bacha na velikost RAM!

Rutina obsahuje také dvě základní (byť velmi primitivní) kontroly blbosti uživatele. Během kopírování rutina kontroluje, zdali jsou kopírovaná data stále z oblasti EPROM a také to, zdali je pro kopírování dostatek RAM. Druhá ochrana spočívá pouze v porovnávání aktuální cílové adresy se stackem. Pokud kopírovaná data začnou lézt do zásobníku, nejspíš se pokoušíme nahrát velký program do malé paměti. Jinými slovy: zapoměli jsme si připojit rampack. Já ho mám naštěsí napevno:-) Při jedné z těchto dvou možných chyb se ZX80 resetuje a paměť RAM se smaže. Úspěšné kopírování je zakončeno návratem do BASICu a tzv. autolistem programu. K návratu nebylo možné využít instrukce RET. Řízení se BASICU předává přímým skokem na hlavní smyčku v operačním systému ZX80. Ještě předtím je ale ze zásobníku vytaháno vše, co tam USR natahal:-)


RUN nebo GOTO ?

Ještě poznámka k programům pro ZX80. Některé Basicovské programy obsahují strojový kód, který je umístěn v oblasti uživatelských proměnných. Tyto programy není možné spouštět příkazem RUN, ale je nutné použít příkaz GOTO s počátečním číslem řádku! RUN totiž uživatelské proměnné vynuluje, takže stroják smaže, kdežto GOTO nikoliv! Způsob spouštění je stanovený tvůrcem daného programu. Týká se to především her!


Další strojové rutiny pro EPROM

Ještě než, se dostanu k obrazům EPROM, které jsem pro své ZX80 připravil, popíšu další rutinky, které jsem si vytvořil. Rutiny jsem přidal přímo ke zdrojáku operačního systému ZX80, takže v jediném souboru je vše podstatné:

    ZX80 ROM + rutiny


rutina RAMSIZE

Praktická je rutina na zjištění velikosti dostupné RAM, která slouží třeba k ověření funkčnosti a kapacity připojeného rampacku. Jelikož ZX80 neukládá velikost RAM do systémové proměnné jako třeba ZX81, je zjištění velikosti RAM uživatelským programem docela problém. Existuje primitivní program RAMLEFT, který zjišťuje velikost RAM na základě adresy ukazatele zásobníku. RAMLEFT je sice Basicivský program, ale v podstatě se jedná o primitivní strojovou rutinu, která je nejprve "napoukována" do RAM a spuštěna. Rutina vrátí aktuální stackpointer a pomocí Basicovské aritmetiky je dopočítána velikost RAM.

Vytvořil jsem tedy rutinu RAMSIZE, která je určena pro umístění v EPROM, a která dělá v podstatě totéž. Aritmetická korekce výsledku je nahrazena tím, že se do HL nejprve vloží "to správné číslo", aby po přičtení SP vyšla správná velikost paměti:-) Rutina tedy vrací v HL počet bajtů RAM. Volání je opět provedeno příkazem PRINT USR(adresa) a je možné jak přímo, tak v programu. Velikost RAM lze také přiřadit do proměnné, ale zde je nutná korekce: LET A=USR(adresa)+2.


rutiny RENUM 5 a RENUM 10

Budete-li se dostatečně dlouho šťourat v Basicovkých programech na ZX80 (ať už cizích, či vlastních), jednou dojdete k tomu, že budete potřebovat vložit nový řádek mezi řádky například 21 a 22. Žádný problém, řeknete si. Stačí jeden z nich přečíslovat. Jenže ouha! Pod 21 je řádek 20 a nad 22 je řádek 23. A ještě níže je 19 a výše naopak 24... Pak pochopíte, proč jedním z nejoblíbenějších programů pro ZX80 byl program pro přečíslování řádků Basicu (Line Renumber):-) Jenže dnes není třeba se snažit o minimalistické řešení, které by se nacpalo do RAM spolu s editovaným programem. Dnes máme spoustu místa v EPROM za operačním systémem, kam se takový program ideálně hodí.

Vytvořil jsem dvě jednoduché rutiny: RENUM 5 a RENUM 10. Rutiny po zavolání PRINT USR (adresa) přečíslují Basicovský program v RAM po 5 počínaje pětkou (RENUM 5), resp. po 10 počínaje desítkou (RENUM 10). Opět bylo jednodušší napsat dvě rutiny, než složitě předávat parametr jedné univerzální. POZOR! Rutiny přečíslují pouze řádky programu! Skoky (GOTO a GOSUB) musíte přečíslovat ručně! Po provedeném přečíslování je řízení opět navráceno editoru BASICu a s přečíslovaným programem lze dále pracovat. Rutina vrací číslo posledního přečíslovaného řádku, tím zároveň získáme přehled o rozsahu přečíslovaného programu. POZOR! Rutina nehlídá možné překročení rozsahu Basicovských řádků (max. 9999), nelze tedy přečíslovávat programy s více jak 999 řádky:-)


efektní řádek 0 (nula)

K číslům řádků ještě jedna perlička. Doboví frajeři s oblibou číslovali první řádek programu jako 0 (nula). Velmi často zde byl příkaz REM s poznámkou obsahující jméno autora programu. Efektní na tom je to, že řádek s číslem 0 nelze editorem BASICu smazat, editovat, přečíslovat a vlastně ani vytvořit:-) V listingu se ale objevuje a interptret jej vykonává. Tímto dávali doboví frajeři dobovým BFU na vědomí, že jsou opravdu frajeři, protože doboví BFU s nultým řádkem nehli:-) Jenže dnes je doba jiná. Bezostyšně se vrtáme v programech dobových frajerů a pokud máme systém s 1KB RAM, velmi záhy potřebujeme vyházet zbytečnosti. A REM je zbytečnost. Jenže abychom mohli s řádkem 0 pracovat, musíme ho přečíslovat. Kromě výše popsaných rutin RENUM 5 a 10, které přečíslují i nultý řádek a přidělí mu číslo 5, resp 10, to jde i jednoduššeji: POKE 16425,X kde X je nové číslo v rozsahu 1-255. Stejně tak lze nultý řádek i vytvořit (pokud si myslíte, že to dnes někoho ohromí:-)) Prostě založte první řádek třeba s číslem 1 a poté zadejte POKE 16425,0.


rutina CURLINE

Poslední rutinou je CURLINE. Jedná se o strojovou rutinu, která po zavolání vrátí adresu řádku Basicovského programu, na kterém je aktuálně > kurzor. Konkrétně se jedná o adresu bezprostředně následující po adrese s uloženým číslem řádku. Nemáme-li tam nějaké vložené mezery, je na této adrese token Basicovského příkazu. Není-li > kurzor umístěn nikde, rutina vrací nulu. Rutinu jsem si vytvořil za účelem snadného přímého vkládání inverzních znaků do programu, potažmo do RAM.


přímý zápis inverzních znaků do BASICu

To je totiž další oblíbená efektovka dobových frajerů. Přímo vložené invertované znaky v řetězcích. Tohle totiž normálně nejde... Důvodem je opět úspora drahocenných bajtů, zejména se systémem s 1KB RAM. Malý příklad:

Potřebujeme od uživatele vyjádření, zdali má program pokračovat, nebo skončit. Zároveň je vhodné naznačit uživateli, co má zmáčknout. Nejjednoduššeji to jde velkým počátečním písmenem a zbytek jsou písmena malá, např. takto:

40 PRINT "Pokracovat nebo Konec?"

Jenže ZX80 nezná malých písmen. Jen velká... Co tedy toto?

40 PRINT "(P)OKRACOVAT NEBO (K)ONEC?"

Za prvé to není hezký a za druhé nám to spolkne zbytečně 4 bajty (nesmějte se, s 1KB to byl fakt problém!). A co zkusit inverzní znaky? Problém je, že se musí zadávat pomocí CHR$(x), takže zápis bude vypadat takto:

40 PRINT CHR$(181);"OKRACOVAT, NEBO ";CHR$(176);"ONEC?"

Výsledek bude sice hezkej, ale zdoják vypadá příšerně a schlamstne to hrozně moc bajtů navíc. Ideální zápis je toto:

40 PRINT "POKRACOVAT NEBO KONEC?"

Je to efektní a nestálo to navíc ani bajt! Jenže toto se nedá u ZX80 jednoduše udělat. Nebo dá? Jasně, že dá. Na řádek se umístí > kurzor. Zavolá se CURLINE příkazem PRINT USR(adresa) a z vrácené adresy se dopočítá pozice znaku, který chceme vyměnit. V našem příkladu je to znak P a to bude na adrese vrácené CURLINE plus 2. Příkaz PRINT zabírá jen jeden bajt - tzv. token a následná mezera je součástí příkazu. Po tokenu tedy následují uvozovky a pak již P. Jestli je tam opravdu P se přesvědčíme příkazem PRINT PEEK (vypoctenaadresa). Měli bychom obdržet dekadickou hodnotu odpovídající znaku P z tabulky znaků ZX80, tedy 53. Nyní stačí zadat příkaz POKE vypoctenaadresa,181 kde 181 je kód inverzního P. Obdobně upravíme i písmeno K ve slově KONEC. Upravený program lze poté klasicky uložit.


jak vytvořit vlastní *.O soubor?

Uložit? To jako na kazetu??? Neéééé! My chceme O-file, který si pak dáme do EPROM společně se ZX80_loaderem, že? A jak ten O-file vytvoříme? V emulátoru. Nejlépe Eighty One. Tam budeme mít svou upravenou EPROM s CURLINE. Tam budeme upravovat svůj Basicovský program. Tam vytvoříme O-file. Jak? Příkazem Save Memory Block uložíme obsah RAM emulátoru od adresy 16384 (4000h) na disk. Ukládáme vždy raději více bajtů, než je předpokládaná délka našeho programu. Nejsme-li si jistí, ukládáme celou RAM (třeba 1024 bajtů pro 1K systém). Uložený soubor je binárka. Otevřeme ji v nějakém hexaeditoru (PSpad) a zjistíme už dobře známou adresu E_LINE (viz ZX80_loader výše). Od této adresy (včetně) dále až na konec souboru vše smažeme. Po odmazání balastu musí binárka končit hodnotou 80h! A máme náš program v O-formátu:-) Pro kontrolu ho můžeme nahrát zpět do emulátoru příkazem LOAD Tape. A nebo ho spolu se ZX80_loaderem uložit do EPROM svého milovaného "živého" ZX80.


hotové obrazy EPROM 8KB a 16KB pro ZX80

Nechce-li se vám sestavovat vlastní EPROM, můžete vyzkoušet některou (či všechny), které jsem si nachystal já. Připravil jsem celkem 4 banky po 16KB, ale myslel jsem i na ty, kteří mají jen 8KB banku (třeba EPROM adaptér od Martina Lukáška pro 27256), takže tu máme i dvě 8KB banky.

Ale vlastně neé. Kecám. Pro ZX80 mám jen 3 banky 16KB. Do té čtvrté jsem už neměl co dát a tak jsem tam dal operační systém ZX81 spolu s hrami Paula Farrowa právě pro ZX80 se ZX81 ROM. A ta rutina je vlastně úplně jiná. Jmenuje se ZX81_loader a funguje podobně jako ta pro ZX-80:-) A RAMSIZE je tam vlastně taky jiná protože ZX81 má RAMTOP. A vlastně se tam nepoužívá HL, ale BC. Prostě je tam všechno jiné:-) Ale k ZX81 popis až zase jindy. Já jsem prostě v reálu dycky podstatně dál, než píšu...

Připravené obrazy EPROM obsahují kromě výše popsaných rutin hlavně hry. Vesměs se jedná o skvělé a velmi hratelné hry ze stránek Paula Farrowa. Ale vybral jsem i několik ryze Basicovských her typu hádaní čísel, test paměti (vaší, né počítače:-)), skořápky či mastermind. Dále bych si dovolil upozornit na mnou upravený program Mem Dump 1K, který slouží k hexadecimálnímu výpisu obsahu paměti. A pochopitelně nelze nepřipomenout mé jednoduché ZX80 1K demo:-) Názvy programů a jejich spouštěcí adresy jsou v přiloženém souboru popis.txt. U každého programu je také doporučená velikost RAM packu pro ZX80 a způsob spouštění. Banky 8 KB obsahují pouze 1K programy, aby se tam toho vešlo co nejvíce. Obrazy ROM fungují i v emulátoru Eighty One (vyzkoušeno)!


Volume Tester

Poslední věc, kterou bych rád vypíchl, je velmi praktická rutina Volume Tester od Paula Farrowa. Rutina usnadní nastavení správné úrovně výstupního signálu z magnetofonu, nebo třeba i z PC. Je to perfektní. Zkoušel jsem nahrávat programy ve formátu *.WAV z PC (normálně z Windows Media Playeru) a po nastavení správné úrovně (viz návod na stránkách Paula Farrowa) se dařilo nahrávat programy naprosto spolehlivě. Pro převod programů typu *.O na *.WAV spolehlivě slouží program zx_p2wav.exe, který též naleznete v archivu s připravenými obrazy EPROM:

    ZX80 software (obrazy EPROM)


K čemu je to dobré?

Každý jistě ví, že počítač bez programů je k ničemu. Pokud se budete chtít pochlubit třeba čerstvě postavenou replikou ZX-80, efekt znásobíte tím, když ukážete co to vlastně umí. Jenže k tomu jsou jen dvě možnosti: nahrát program z nějakého přehrávače (zdlouhavé a nespolehlivé), nebo připojit nějaké udělátko s moderní pamětí (třeba paměťovou kartou). Problém je, že v obou případech musíte připojit "něco". Navíc ve druhém případě může být pořízení takového udělátka i docela nákladné. Snažil jsem se tedy navrhnout způsob, jak mít neustále k dispozici pár prográmků BEZ nutnosti cokoliv připojovat. Nutná je jen maličká HW úprava spočívající ve výrobě EPROM adaptéru. Ovšem jde to i bez jakékoliv úpravy. Prostě stačí použít EPROM MC68764 od Motoroly s kapacitou 8 KB, která se prostě jen vloží do patice namísto původní ZX-80 ROM. Získáte tak navíc 4 KB pro pár prográmků. Není to moc, ale alespoň něco. Do této EPROM můžete použít jeden z mých nachystaných obrazů EPROM pro 8 KB banku. Ty 1K programy mají ve skutečnosti maximálně cca 800 bajtů, takže pár se jich tam opravdu vejde.

Sám si ve své bastldílně své ZX-80 občas pustím a s chutí si něco zahraju. Nejsme tady od toho, abychom se udřeli:-)) Oblíbené mám Space Invaders 3K a Breakout 1K. Á propos, víte že Breakout se nedá dohrát bez ztráty míčku? Abyste tu zeď rozbořili celou, alespoň jednou (a šikovně) ten míček prostě upustit musíte:-) Ono je docela zajímavé i to, co se stane po tom, co zeď zcela zlikvidujete:-) Ale co také čekat od 1K hry, že? Dříve se hrálo prostě pro zábavu a ne pro zápisy do tabulky rekordů...

hotový Sinclair ZX80
Nostalcompův Sinclair ZX80
hotový Sinclair ZX80
Nostalcompův Sinclair ZX80


RET



Odladěno na MS IE 8.0 a Firefoxu při rozlišení min. 1024 x 768 pixelů
www.NOSTALCOMP.cz    2010  -  2017