Ovládání TRDOSu ze strojového kódu
Úvod
Betadisk, resp. jeho systém TRDOS měl oproti ostatním diskovým systémům na počítačích ZX Spectrum jednu zajímavou a rozhodně nezanedbatelnou výhodu. Je od začátku stavěný tak, že se ovládá pomocí služeb s pevně daným rozhraním, které jsou stejné bez ohledu na verzi systému, nebo případné hardwarové odlišnosti. Díky tomu může a také existuje značné množství verzí TRDOSu. Bohužel ne každý programátor toto dodržoval, takže existuje i řada programů, které na jiných verzích TRDOSu nefungují, ale to už není chyba Betadisku, ale autora programu. Ve srovnání s D40, resp. D80, která existuje nejméně ve dvou verzích s různými řadiči a několika modifikacích fandů a která se ovládá ze strojového kódu přímým voláním rutin MDOSu to je výhoda obrovská. Stačí rutiny posunout o jeden byte a je nekompatibilita na světě.
Další zajímavostí je neexistence FAT, resp. filesystém TRDOSu je extrémně jednoduchý a obsahuje prakticky jenom jeden direktorář se jmény a dalšími parametry souborů, několik pomocných sektorů a data. Píšu zajímavostí, protože je sporné jestli se jedná o výhodu, nebo nevýhodu. Výhodné to je kvůli snadnosti a rychlosti zpracování dat, tím spíš, když je CPU pouze osmibitový a dnes už velmi pomalý. Nevýhodné to je při častém zápisu a mazání souborů, protože nelze soubory fragmentovat a je nutno je čas od času "sesypat" příkazem MOVE. Nevýhodné to je i v případě, že na disketě existují vadné sektory, jež nelze nijak obejít (nutno poznamenat, že ze zhruba dvou stovek disket DS DD 5 1/4" 80 stop, které mi prošly rukama byly vadné snad jen dvě, oproti novějším HD 3,5" odcházejícím někdy i v 50 - 100% případů spolehlivost nesrovnatelná, většina starých 5 1/4" disket je čitelná i po mnoha letech archivace).
Zvláštností Betadisku je také absence vlastní RAM (např. D40 má 2kB vyrovnávací paměti na sektory a systémové proměnné), takže veškeré operace, kde je paměť nutná využívají RAM počítače. TRDOS potřebuje pro systémové proměnné 112 bytů o které posouvá Basicový program dolů, případně o dalších 58 (57 bez Betadisku) bytů posune Basic Interface 1 (Microdrive) pokud je používán společně s Betadiskem. Ačkoliv osobně jsem se nikdy s kombinací těchto dvou zařízení nesetkal, měly by se snášet. Krom 112 bytů pro systémové proměnné (do nichž lze zapisovat a s výhodou toho využít) potřebuje TRDOS dalších 256 bytů jako buffer pro právě zpracovávaný sektor (jak čtení souboru, tak CAT, LIST ...). K tomu využívá opět prostor pro Basic, ale tuto paměť po skončení práce zase uvolní. V praxi to znamená, že není rozumné nastavovat RAMTOP výš než 24500 a i tak se do paměti nevejde víc než nejzákladnější basicový zavaděč. Nicméně stačí to k tomu, aby mohl být TRDOS volán ze strojového kódu. Pro srovnání při práci s D40 resp. MDOSem a páskou se často nastavoval RAMTOP na 24200, což činí zbytečné potíže při převodu softwaru z pásky/D40 na Betadisk.
Začátky Basicu pro různé kombinace Betadisk/Interface 1
Adresy začátku Basicu | |
---|---|
bez připojeného zařízení | 23755 |
pouze Interface I | 23812 |
pouze Betadisk | 23867 |
Interface I i Betadisk | 23925 |
rozhraní TRDOSu pro uživatele
Seznam služeb TRDOSu
číslo služby | adresa v ROM 5.03 | Popis a funkce služby |
---|---|---|
0 | 3D98h | RESTORE - hlava na stopu 0 |
výstup: BC kód chyby | ||
1 | 3DCBh | SELECT DRIVE - zvolení mechaniky s níž se bude pracovat |
vstup : A číslo mechaniky | ||
výstup : BC kód chyby | ||
2 | 3E63h | SEEK - posune hlavu na určenou stopu |
vstup: A číslo stopy | ||
výstup: BC kód chyby | ||
3 | 3F02h | STORE SEKTOR NUMBER - uloží číslo sektoru |
vstup: A číslo sektoru | ||
výstup: na 5CFFh číslo sektoru, BC kód chyby | ||
4 | 3F06h | STORE BUFFER ADDRESS - uloží adresu bufferu |
vstup: HL adresa bufferu | ||
výstup: na 5D00h adresa bufferu, BC kód chyby | ||
5 | 1E3Dh | READ SECTOR - čtení sektoru z diskety |
vstup: HL adresa bufferu, D číslo stopy, E číslo sektoru, B počet sektorů | ||
výstup: obsah sektorů na adrese HL, BC kód chyby | ||
6 | 1E4Dh | WRITE SECTOR - zápis sektoru na disketu |
vstup: HL adresa bufferu, D číslo stopy, E číslo sektoru, B počet sektorů, data v bufferu | ||
výstup: sektory na disketě, BC kód chyby | ||
7 | 28D8h | CAT - výpis katalogu diskety (adresáře) |
vstup: A kanál (standardně 2) | ||
výstup: katalog disku v zadaném kanálu (tedy třeba na obrazovce), BC kód chyby | ||
8 | 165Ch | READ HEADER - načtení zvolené hlavičky z adresáře |
vstup: A pořadí hlavičky v adresáři | ||
výstup: od 5CDDh hlavička, BC kód chyby | ||
9 | 1664h | WRITE HEADER - zapsání zvolené hlavičky do adresáře |
vstup: A pořadí hlavičky v adresáři, od 5CDDh hlavička | ||
výstup: BC kód chyby | ||
10 | 1CF0h | HEADER INDEX - vrátí pořadové číslo hlavičky v adresáři |
vstup: od 5CDDh hlavička | ||
výstup: na 5D0Fh číslo hlavičky, jinak FFh, nebo v C číslo hlavičky, jinak 0 (nález Z, jinak NZ) | ||
11 | 28FBh | SAVE BYTES - uloží binární soubor na disketu |
vstup: od 5CDDh hlavička (bez umístění na disketě), HL začátek bloku, DE délka bloku | ||
výstup: BC kód chyby | ||
12 | 28F2h | SAVE BASIC - uloží basicový program na disketu |
vstup: od 5CDDh hlavička, na 5CD1h buď 0, nebo řádek autostartu | ||
výstup: BC kód chyby | ||
13 | 01D3h | << nevyužito>> |
14 | 290Fh | LOAD PROGRAM - načtení programu |
vstup: od 5CDDh hlavička | ||
pro A=0 - start a délka podle hlavičky | ||
pro A=3 - HL start, DE délka | ||
výstup: BC kód chyby | ||
15 | 01D3h | << nevyužito>> |
16 | 01D3h | << nevyužito>> |
17 | 01D3h | << nevyužito>> |
18 | 2926h | ERASE FILE - vymazání souboru |
vstup: od 5CDDh hlavička | ||
výstup: BC kód chyby | ||
19 | 28E0h | MOVE HEADER TO 5CDDh - přenesení hlavičky z adresy v HL na 5CDDh |
vstup: v HL adresa bufferu, v bufferu hlavička | ||
výstup: na 5CDDh hlavička | ||
20 | 28E3h | MOVE HEADER FROM 5CDDh - přenesení hlavičky z 5CDDh na adresu v HL |
vstup: na 5CDDh hlavička, v HL adresa bufferu | ||
výstup: hlavička v bufferu | ||
21 | 2739h | VERIFY TRACK - verifikace stopy |
vstup: D číslo stopy | ||
výstup: na 5CD6h počet chyb, BC kód chyby (např. no disk) | ||
22 | 1FEBh | SELECT SIDE 0 - volba stopy 0 (kvůli verifikaci ???) |
23 | 1FF6h | SELECT SIDE 1 - volba stopy 1 (kvůli verifikaci ???) |
24 | 0405h | TRDOS INIT - ověření značky TRDOSu a nastavení druhu záznamu podle údajů na disku |
výstup: nastavené bity specifikace, BC kód chyby |
Adresy služeb v originální ROM TR-DOSu 5.03 uvádím jen pro pořádek a pro potřebu zkoumání. Rozhodně je NEPOUŽÍVEJTE pro volání funkcí programem. Pravděpodobně by program pracoval jenom Vám, protože verzí TR-DOSu se vyskytuje mnohem více než v případě D40! I v emulátorech většinou (např. X128) fungují služby bez problémů narozdíl od přímého volání ROM.
Co se týče vrácené chyby tak já osobně radši používám systémovou proměnnou než registr BC.
Jedna ze systémových proměnných použitelná pro čtení disket MS DOSu, nebo D40 na Betadisku. Tyto proměnné jsou čtyři. Pro každou mechaniku jedna.
- Drive A - 23752
- Drive B - 23753
- Drive C - 23754
- Drive D - 23755
bit | význam bitu |
---|---|
0 | formát diskety 0=40nbsp;tr. 1=80 tr. |
1 | číslo strany diskety 0=side 0, 1=side 1 |
2 | - |
3 | 0=256 bytů na sektor, 1=512 bytů na sektor (nepoužívat implicitní buffer!) |
4 | - |
5 | - |
6 | - |
7 | drive 0=40 tr., 1=80 tr. (při formátu 40 tr. a mechanice 80 tr. automaticky dvojitý krok) |
Chybové kódy
č. chyby | význam |
---|---|
0 | žádná chyba |
1 | soubor nebyl nalezen |
2 | soubor už existuje |
3 | není místo (disk plný ???) |
4 | katalog je plný |
5 | počet záznamů překročen (???) |
6 | v mechanice není disk |
7 | chyba disku |
8 | chyba syntaxe |
9 | --- |
10 | proud je již otevřen |
11 | Not Disk File - ??? |
12 | proud není otevřen |
13 | chyba verifikace |
Tuto tabulku jsem kompletně opsal z Mikrobáze, ale jsem z ní poněkud zmaten. Prý to funguje v syntaxi LET ERR=USR 15619:REM: příkaz. Jenže co ve strojáku. V praxi mi bohatě stačilo, že 0 znamená vše OK, a něco jiného je chyba. Při volání služeb se mi povedlo rozlišit chybu sektor nečitelný a není disk. S ostatními případy jsem se nesetkal, protože jsem vždy pracoval s diskem po sektorech a nikoliv po souborech. V takovém případě totiž není problém ošetřit mnohem více situací vlastním programem, přitom adresář zabírá dohromady 2304 bytů včetně systémového sektoru. Číslo chyby jsem četl z proměnné na adrese 23823 (i když v BC byla stejná), protože mezitím s registrem BC můžu pracovat a nestarat se o jeho obsah, hlavně stejně musíte číslo chyby na adrese 23823 před použitím služby vynulovat, protože to TRDOS nedělá. TRDOS změní na této adrese hodnotu právě a jedině tehdy když chyba nastane.
Příklady
Příklad nejjednoduššího volání služby
restore ld c,0 call 15635 ret cat ld c,7 ld a,2 call 15635 ret
V C je vždy číslo služby, případná chyba je ignorována, v nejhorším se objeví hlášení Betadisku stejně jako je tomu v BASICu. Je ovšem možné zajistit, aby nedošlo k vrácení do editoru BASICu ani při zvolené možnosti Abort.
Příklad podle manuálu výrobce Technology Research
Příklad uvádím včetně původních komentářů. Odstranil jsem řádek s pseudoinstrukcí org a upravil jsem zápis dat příkazů SAVE a LOAD pro překladač Prometheus. Opravil jsem i adresu volané rutiny z původní hodnoty 15363 na 15619. Původní hodnota se myslím týkala starších verzí TRDOSu a zůstala v manuálu zřejmě nezměněna. Příklad se zdá docela úsporný, data pro LOAD a SAVE je možné sloučit a měnit pouze opcode samotného basicového příkazu, ale není o nic výhodnější než přímé volání služeb (viz. první příklad), protože neodstraňuje výpis chybových hlášení skrze basicový interpreter a je v podstatě stejně náročný.
CHADD equ 23645 ; Location of SOS variable CHADD ld hl,(CHADD) ; Start to save true CHADD ld (TEMP),HL ; Temporary store of true CHADD ld HL,SAVE ; Address of SAVE routine ld (CHADD),HL ; CHADD now points to our routine call 15619 ; ENTER TRDOS SAVE via chadd jp BACK ; Jump to program point from which the whole routine was called ld HL,(CHADD) ld (TEMP),HL ; The routine for LOAD now repeats ld HL,49500 ; the above with just the address ld (CHADD),HL ; changed. call 15619 BACK ld HL,(TEMP) ; Start to restore CHADD ld (CHADD),HL ; Reload original CHADD ret ; Return from where you came TEMP defs 2 ; Label allocating memory for temporary storage SAVE defb 234 ; code for REM defm ":" defb 248 ; code for SAVE defb 34 ; code for " defm "filename" defb 34 ; code for " defb 13 LOAD defb 234 ; code for REM defm ":" defb 239 ; code for SAVE defb 34 ; code for " defm "filename" defb 34 ; code for " defb 13
Složitější příklad
Následující volání služeb umožňuje přenastavit kanál pro výpis a tím zamezit nevhodným výpisům TRDOSU na obrazovku.
DRIVE_A ld a,0 ; volby mechaniky A,B,C,D jp DRIVE DRIVE_B ld a,1 jp DRIVE DRIVE_C ld a,2 jp DRIVE DRIVE_D ld a,3 DRIVE ld (AKDRIVE),a ; zápis do proměnné ld c,1 call BETA ret BETA ld (BETA_A+1),a ; toto je tu proto aby se v ošetření chyb dala snadno ld (BETA_DE+1),de ; zopakovat poslední akce skokem na BETA_2 ld (BETA_BC+1),bc ld (BETABUF+1),hl di BETA_2 xor a push hl ld (23823),a ld (ERROR),a ld hl,(23613) ld (BETA_1+1),hl push de push bc push hl push ix push iy ld hl,BETA_ER push hl ld (23613),sp BETABUF ld hl,BUFFER BETA_BC ld bc,14*256+5 BETA_DE ld de,0 BETA_A ld a,0 call 15635 pop hl BETA_ER di ld sp,(23613) pop hl pop iy pop ix pop hl pop bc pop de BETA_1 ld hl,0 ld (23613),hl ld a,4 out (254),a pop hl ld a,(23823) or a ret z ;nastala chyba, zpracovat ret CHANNE2 ld a,2 ; inicializace kanálu 2, kvůli výpisu na obrazovku call #1601 ld hl,CLSTEXT call TEXTOUT ret CLSTEXT defb 22,0,0,20,0,21,0,16,0,17,7,18,0,19,0+128 TEXTOUT ld a,(hl) and 127 rst 16 bit 7,(hl) inc hl jp z,TEXTOUT ret AKDRIVE defb 0 ERROR defb 0
Update ohledně ruského softwaru
Po světě se šíří spousta více, či méně kvalitního softwaru, který vznikal pro Pentagony a Scorpiony obsahující mimo jiné řadič kompatibilní s Betadiskem. Bohužel tento software velmi často přistupuje přímo na porty řadiče a vůbec všelijak obchází TRDOS ačkoliv to není nutné. Často nefunguje s jinými verzemi TRDOSu. Tento způsob přístupu k řadiči je zavrženíhodný, protože jednak popírá smysl TRDOSových služeb a jednak přináší dost zásadní nekompatibilitu.
Dobře napsaný TRDOS s fungujícími službami může v podstatě ovládat zcela libovolný řadič. Dokonce médiem nemusí být nutně disketa, ale v podstatě cokoliv (HDD, RAMdisk ...). Pokud ovšem hloupý programátor zcela obchází rozhraní určené jako jediné k přístupu ke službám, tak nutně píše software, který nebude fungovat jinde než na jeho a identickém hardwaru.
Zde si můžete přečíst podrobný popis formátu diskety systému TRDOS.
Použitá literatura : Mikrobáze z roku 1989 a k tomu vlastní zkušenosti s provozem i stavbou řadiče.