Dostęp do plików
From Atariki
Wersja z dnia 22:23, 9 paź 2012 KMK (Dyskusja | wkład) ← Previous diff |
Aktualna wersja Mono (Dyskusja | wkład) (→Odczyt katalogu - bibodos tez wyswietla - i ?) |
||
Linia 3: | Linia 3: | ||
== Adresowanie IOCB == | == Adresowanie IOCB == | ||
- | Bloki IOCB konwencjonalnie adresuje się podając adres wewnątrz pierwszego z nich - czyli $034x - jako argument rozkazu w trybie absolutnym indeksowanym X, przy czym w rejestrze X powinien znajdować się numer bloku IOCB (z zakresu od 0 do 7), pomnożony przez 16. Numer kanału IOCB, pełniący rolę uchwytu (ang. ''handle'') pliku, powinien zostać właśnie w tej postaci, i w tym rejestrze, przekazany do głównej procedury CIO (CIOV lub JCIOMAIN, $E456) przy jej wywoływaniu. | + | Bloki IOCB konwencjonalnie adresuje się podając adres wewnątrz pierwszego z nich - czyli $034x - jako argument rozkazu w trybie absolutnym indeksowanym X, przy czym w rejestrze X powinien znajdować się numer bloku IOCB (z zakresu od 0 do 7) pomnożony przez 16. Numer kanału IOCB, pełniący rolę uchwytu (ang. ''handle'') pliku, powinien zostać właśnie w tej postaci, i w tym rejestrze, przekazany do głównej procedury CIO (CIOV lub JCIOMAIN, $E456) przy jej wywoływaniu. |
== Etykiety IOCB == | == Etykiety IOCB == | ||
Linia 25: | Linia 25: | ||
* ICCMD - zapisuje się w nim jeden bajt symbolizujący rodzaj operacji (OPEN, CLOSE itd.) | * ICCMD - zapisuje się w nim jeden bajt symbolizujący rodzaj operacji (OPEN, CLOSE itd.) | ||
* ICBUFA - to adres bufora | * ICBUFA - to adres bufora | ||
- | * ICBUFL - to wielkośc bufora w bajtach | + | * ICBUFL - to wielkość bufora w bajtach |
* ICAX1/2 - to bajty pomocnicze, zawierające różne dodatkowe parametry | * ICAX1/2 - to bajty pomocnicze, zawierające różne dodatkowe parametry | ||
- | Czasem przydaje się też ICSTAT, po zakończeniu operacji zawiera bowiem jej status (czyli $01 albo kod błędu). Ale rzadko się tę wartość odczytuje stamtąd, bo przekazywana jest też przez OS bezpośrednio w rejestrze Y. | + | Czasem przydaje się też ICSTAT, po zakończeniu operacji zawiera bowiem jej status (czyli $01 albo [[Kody statusowe Atari OS|kod błędu]]). Ale rzadko się tę wartość odczytuje stamtąd, bo przekazywana jest też przez OS bezpośrednio w rejestrze Y. |
Reszty bajtów IOCB nie dotykamy i w ogóle (na ogół) nie zawracamy sobie nimi głowy. | Reszty bajtów IOCB nie dotykamy i w ogóle (na ogół) nie zawracamy sobie nimi głowy. | ||
Linia 34: | Linia 34: | ||
== Funkcje IOCB == | == Funkcje IOCB == | ||
- | W teorii wszystkie bloki mają to samo przeznaczenie: każdy służy jako deskryptor pojedynczego, otwartego pliku. Wynika z tego, że w teorii można otworzyć do ośmiu plików na raz. W praktyce jeden blok - IOCB #$00 - jest defaultowo otwarty dla edytora ekranowego. Można go wprawdzie zamknąć i wykorzystać do czegoś innego, ale nie ma potrzeby tego czynić, gdyż w praktyce przeciętny DOS nie pozwoli otworzyć więcej niż 3-4 pliki na raz. | + | W teorii wszystkie bloki mają to samo przeznaczenie: każdy służy jako deskryptor pojedynczego, otwartego pliku. Wynika z tego, że w teorii można otworzyć do ośmiu plików na raz. W praktyce jeden blok - IOCB #$00 - jest defaultowo otwarty dla edytora ekranowego. Można go wprawdzie zamknąć i wykorzystać do czegoś innego, ale nie ma potrzeby tego czynić, gdyż przeciętny DOS nie pozwoli otworzyć więcej niż 3-4 pliki na raz. |
- | Bloki IOCB służą tylkodo przekazywania parametrów do DOS-u, nie są zaś właściwymi deskryptorami plików. Dlatego nie da się przeskoczyć limitu jednocześnie otwartych plików przez sprytną podmianę zawartości IOCB i zastąpienie jej przechowywanymi gdzieś indziej danymi innego otwartego pliku - żaden DOS nie da się tak oszukać. | + | Bloki IOCB służą tylko do przekazywania parametrów do DOS-u, nie są zaś właściwymi deskryptorami plików. Dlatego nie da się przeskoczyć limitu jednocześnie otwartych plików przez sprytną podmianę zawartości IOCB i zastąpienie jej przechowywanymi gdzieś indziej danymi innego otwartego pliku - żaden DOS nie da się tak oszukać. |
Pierwszy wolny IOCB to IOCB #1, i ten właśnie będzie używany w przykładach. | Pierwszy wolny IOCB to IOCB #1, i ten właśnie będzie używany w przykładach. | ||
Linia 45: | Linia 45: | ||
* plik otwierany do odczytu musi istnieć, w przeciwnym wypadku wystąpi błąd 170 (FILE NOT FOUND); | * plik otwierany do odczytu musi istnieć, w przeciwnym wypadku wystąpi błąd 170 (FILE NOT FOUND); | ||
- | * plik otwierany do zapisu, jeśli nie istnieje, zostanie utworzony, natomiast jeśli istnieje, jego dotychczasowa zawartość zostanie skasowana; | + | * plik otwierany do zapisu, jeśli nie istnieje, zostanie utworzony, natomiast jeśli istnieje, jego dotychczasowa zawartość zostanie skasowana i zostanie on otwarty; |
- | * plik otwierany do odczytu i zapisu, jeśli istnieje, zostanie otwarty, natomiast jeśli nie istnieje, zostanie utworzony; | + | * plik otwierany do odczytu i zapisu, jeśli istnieje, zostanie otwarty; jeśli nie istnieje, pod niektórymi DOS-ami (np. [[DOS 2.5]], [[DOS XL]]) wystąpi błąd 170 (FILE NOT FOUND), natomiast pod innymi (np. [[SpartaDOS]], [[SpartaDOS X]]) plik zostanie utworzony (i otwarty); |
- | * plik otwierany do dopisywania jeśli istnieje, zostanie otwarty, a wskaźnik miejsca, do któego trafią zapisywane dane, zostanie ustawiny na jego końcu; jeśli zaś taki plik nie istnieje, zostanie utworzony. | + | * plik otwierany do dopisywania jeśli istnieje, zostanie otwarty, a wskaźnik miejsca, do którego trafią zapisywane dane, zostanie ustawiony na jego końcu; jeśli zaś taki plik nie istnieje, pod niektórymi DOS-ami (np. DOS 2.5, DOS XL) wystąpi błąd 170 (FILE NOT FOUND), natomiast pod innymi (np. SpartaDOS, SpartaDOS X) plik zostanie utworzony (i otwarty). |
Kod: | Kod: | ||
<pre> | <pre> | ||
+ | ; OPEN #1,xx,0,"D:FOOBAR12.DAT" | ||
+ | |||
ciov = $e456 | ciov = $e456 | ||
Linia 64: | Linia 66: | ||
lda #>fname | lda #>fname | ||
sta icbufa+1,x | sta icbufa+1,x | ||
- | lda #$xx ;kod dostępu: $04 odczyt, $08 zapis, $09 dopisywanie, $0c odczyt/zapis, $0d odczyt/dopisywanie | + | lda #$xx ;kod dostępu: $04 odczyt, $08 zapis, $09 dopisywanie, $0c odczyt/zapis |
sta icax1,x | sta icax1,x | ||
- | lda #$00 ;dodatkowy parametr, zawsze $00 | + | lda #$00 ;dodatkowy parametr, $00 jest zawsze dobre |
sta icax2,x | sta icax2,x | ||
jsr ciov | jsr ciov | ||
+ | ... | ||
</pre> | </pre> | ||
Linia 75: | Linia 78: | ||
* na początku musi się znajdować specyfikacja urządzenia, na ogół będzie to "D:", co oznacza stację dysków (a ściślej: DOS). Można tu podać numer stacji, np. "D2:", jednak najlepiej poprzestać na "D:" - pozwala to bardziej zaawansowanym DOS-om na zapis tego pliku do bieżącego podkatalogu, czyli na ogół tego, w którym użytkownik trzyma cały program. | * na początku musi się znajdować specyfikacja urządzenia, na ogół będzie to "D:", co oznacza stację dysków (a ściślej: DOS). Można tu podać numer stacji, np. "D2:", jednak najlepiej poprzestać na "D:" - pozwala to bardziej zaawansowanym DOS-om na zapis tego pliku do bieżącego podkatalogu, czyli na ogół tego, w którym użytkownik trzyma cały program. | ||
- | * za dwukropkiem podajemy nazwę pliku w konwencji "8.3", tj. składającą się z najwyżej ośmiu znaków nazwę właściwą, kropkę oraz liczące do trzech znaków rozszerzenie. Znakami dopuszczalnymi w nazwie są duże litery alfabetu angielskiego (A-Z), cyfry (0-9) oraz znak podkreślenia. Cześć DOS-ów wymaga, żeby pierwszym znakiem całej nazwy była litera. | + | * za dwukropkiem podajemy nazwę pliku w konwencji "8.3", tj. składającą się z najwyżej ośmiu znaków nazwę właściwą, kropkę oraz liczące do trzech znaków rozszerzenie. Znakami dopuszczalnymi w nazwie są duże litery alfabetu angielskiego (A-Z) i cyfry (0-9). Niektóre DOS-y (w tym [[SpartaDOS]] i [[MyDOS]]) dopuszczają również znak podkreślenia (_) i "małpę" (@). Część DOS-ów wymaga, żeby pierwszym znakiem całej nazwy była litera. |
- | * za ostatnim znakiem nazwy pliku obowiązkowo powinien się znaleźć znak jej końca, czyli EOL (znak Return, ASCII $9B). | + | * DOS-y pozwalające na organizację plików w hierarchiczne struktury umożliwiają podanie w nazwie pliku ścieżki. Nazwy podkatalogów i pliku separowane są wtedy znakami ">" oraz "<" ([[SpartaDOS]]), "\" ([[SpartaDOS X]]) lub ":" ([[MyDOS]]). |
- | Po wywołaniu <code>JSR OPEN_FILE</code> w rejestrze X będzie się znajdował (nadal) numer kanału pomnożony przez 16, a w rejestrze Y kod statusu, natomiast bit N rejstru znaczników będzie odzwierciedlał stan rejestru Y: jeśli N=1, to znaczy, że wystąpił błąd o kodzie przekazanym w Y. W przeciwnim wypadku (N=0) operacja się powiodła. | + | * za ostatnim znakiem nazwy pliku obowiązkowo powinien się znaleźć znak EOL (Return, kod ASCII $9B). |
- | UWAGA: specyfiką Atari jest to, że po każdym OPEN, ''nawet jeśli zakończyło się błędem'', kanał IOCB pozostaje otwarty i trzeba go zamknąć do ponownego użycia. Zakonczenie programu '''nie''' powoduje automatycznego zamknięcia otwartych kanałów. | + | Po wywołaniu <code>jsr open_file</code> w rejestrze X będzie się znajdował (nadal) numer kanału pomnożony przez 16, a w rejestrze Y kod statusu, natomiast bit N rejstru znaczników będzie odzwierciedlał stan rejestru Y: jeśli N=1, to znaczy, że wystąpił błąd o kodzie przekazanym w Y. W przeciwnim wypadku (N=0) operacja się powiodła. |
+ | |||
+ | UWAGA: specyfiką Atari jest to, że po każdym OPEN, ''nawet jeśli zakończyło się błędem'', kanał IOCB pozostaje otwarty i trzeba go zamknąć do ponownego użycia. Zakończenie programu '''nie''' powoduje automatycznego zamknięcia otwartych kanałów. | ||
+ | |||
+ | UWAGA: przy komunikacji z magnetofonem (C:) ICAX2 zawiera informację o rodzaju przerw między rekordami - $00 oznacza długie przerwy, $80 - krótkie. | ||
== Zamknięcie pliku == | == Zamknięcie pliku == | ||
Linia 88: | Linia 95: | ||
<pre> | <pre> | ||
+ | ; CLOSE #1 | ||
+ | |||
ciov = $e456 | ciov = $e456 | ||
Linia 95: | Linia 104: | ||
sta iccmd,x | sta iccmd,x | ||
jsr ciov | jsr ciov | ||
+ | ... | ||
</pre> | </pre> | ||
- | == Odczyt danych z pliku == | + | Zamknięcie kanału już zamkniętego nie powoduje błędu. |
+ | |||
+ | == Odczyt z pliku == | ||
Plik otwarty do odczytu będzie czytany sekwencyjnie od początku do końca. Jeśli nie wystąpią żadne błędy, i odczytano wszystkie dane z pliku, następna próba odczytu zwróci błąd nr 136 (EOF). Ważne jest, żeby status operacji testować na okoliczność wystąpienia błędu (N=1, Y>127), a nie na okoliczność powodzenia (Y=$01), gdyż część DOS-ów w pewnych warunkach zwraca wartość $03 jako status dla udanej operacji odczytu. | Plik otwarty do odczytu będzie czytany sekwencyjnie od początku do końca. Jeśli nie wystąpią żadne błędy, i odczytano wszystkie dane z pliku, następna próba odczytu zwróci błąd nr 136 (EOF). Ważne jest, żeby status operacji testować na okoliczność wystąpienia błędu (N=1, Y>127), a nie na okoliczność powodzenia (Y=$01), gdyż część DOS-ów w pewnych warunkach zwraca wartość $03 jako status dla udanej operacji odczytu. | ||
+ | |||
+ | Ponadto, po powrocie z systemu ICBUFL,X i ICBUFL+1,X (odpowiednio: młodszy i starszy bajt) zawiera liczbę bajtów odczytanych do bufora, którego adres (nadal) znajduje się w ICBUFA,X i ICBUFA+1,X. | ||
=== Odczyt bloku danych binarnych === | === Odczyt bloku danych binarnych === | ||
Linia 106: | Linia 120: | ||
<pre> | <pre> | ||
+ | ; BGET #1,buffer,buflen | ||
+ | |||
ciov = $e456 | ciov = $e456 | ||
Linia 121: | Linia 137: | ||
sta icbufl+1,x | sta icbufl+1,x | ||
jsr ciov | jsr ciov | ||
+ | ... | ||
</pre> | </pre> | ||
Linia 128: | Linia 145: | ||
<pre> | <pre> | ||
+ | ; GET #1,A | ||
+ | |||
ciov = $e456 | ciov = $e456 | ||
Linia 138: | Linia 157: | ||
sta icbufl+1,x | sta icbufl+1,x | ||
jsr ciov | jsr ciov | ||
+ | ... | ||
</pre> | </pre> | ||
Linia 147: | Linia 167: | ||
<pre> | <pre> | ||
+ | ; INPUT #1,buffer$ | ||
+ | |||
ciov = $e456 | ciov = $e456 | ||
Linia 162: | Linia 184: | ||
sta icbufl+1,x | sta icbufl+1,x | ||
jsr ciov | jsr ciov | ||
+ | ... | ||
</pre> | </pre> | ||
== Zapis do pliku == | == Zapis do pliku == | ||
- | Zapis przeprowadza się analogicznie do odczytu, może się jedynie zmieniać miejsce, gdzie dane zostaną zapisane. Jest to zależne od trybu otwarcia pliku: przy zwykłym zapisie (tryb otwarcia 8) lub wymianie danych (tryb otwarcia 12) dane będą wpisywane do pliku sekwencyjnie od początku. Przy dopisywaniu (tryb 9) lub odczycie/dopisywaniu (tryb 13) wpisane do pliku dane znajdą się na jego końcu. | + | Zapis przeprowadza się analogicznie do odczytu, może się jedynie zmieniać miejsce, gdzie dane zostaną zapisane. Jest to zależne od trybu otwarcia pliku: przy zwykłym zapisie (tryb otwarcia 8) lub wymianie danych (tryb otwarcia 12) dane będą wpisywane do pliku sekwencyjnie od początku. Przy dopisywaniu (tryb 9) wpisane do pliku dane znajdą się na jego końcu. |
+ | |||
+ | Po powrocie z systemu ICBUFL,X i ICBUFL+1,X (odpowiednio: młodszy i starszy bajt) zawiera liczbę bajtów zapisanych do pliku z bufora, którego adres (nadal) znajduje się w ICBUFA,X i ICBUFA+1,X. | ||
UWAGA: po zapisie wszystkich danych plik należy obowiązkowo zamknąć, dopiero wtedy DOS zapisuje do niego wszystkie dane, jakie ewentualnie może jeszcze tymczasowo trzymać w buforach, oraz uaktualnia wpis w katalogu. | UWAGA: po zapisie wszystkich danych plik należy obowiązkowo zamknąć, dopiero wtedy DOS zapisuje do niego wszystkie dane, jakie ewentualnie może jeszcze tymczasowo trzymać w buforach, oraz uaktualnia wpis w katalogu. | ||
Linia 173: | Linia 198: | ||
<pre> | <pre> | ||
+ | ; BPUT #1,buffer,buflen | ||
+ | |||
ciov = $e456 | ciov = $e456 | ||
Linia 188: | Linia 215: | ||
sta icbufl+1,x | sta icbufl+1,x | ||
jsr ciov | jsr ciov | ||
+ | ... | ||
</pre> | </pre> | ||
Linia 195: | Linia 223: | ||
<pre> | <pre> | ||
+ | ; PUT #1,A | ||
+ | |||
ciov = $e456 | ciov = $e456 | ||
Linia 207: | Linia 237: | ||
pla | pla | ||
jsr ciov | jsr ciov | ||
+ | ... | ||
</pre> | </pre> | ||
- | === Zapis rekordu === | + | === Zapis rekordu tekstowego === |
Na końcu bufora danych powinien się znajdować znak EOL (ASCII $9B). Zadeklarowana wielkość bufora powinna być większa lub równa liczbie zapisywanych danych. Kod: | Na końcu bufora danych powinien się znajdować znak EOL (ASCII $9B). Zadeklarowana wielkość bufora powinna być większa lub równa liczbie zapisywanych danych. Kod: | ||
<pre> | <pre> | ||
+ | ; PRINT #1,buffer$ | ||
+ | |||
ciov = $e456 | ciov = $e456 | ||
Linia 229: | Linia 262: | ||
sta icbufl+1,x | sta icbufl+1,x | ||
jsr ciov | jsr ciov | ||
+ | ... | ||
</pre> | </pre> | ||
+ | == Status pliku == | ||
+ | |||
+ | Odczyt statusu pliku ma na celu stwierdzenie jego dostępności bez konieczności robienia OPEN. Wynikiem jest $01 (sukces), gdy plik jest dostępny, lub odpowiedni kod błędu, gdy nie jest. Niektóre DOS-y zwracają kod błędu 167 (FILE LOCKED), kiedy plik istnieje, lecz jest zabezpieczony przed zapisem. | ||
+ | |||
+ | <pre> | ||
+ | ; XIO 13,#1,0,0,"D:FOOBAR12.DAT" | ||
+ | |||
+ | ciov = $e456 | ||
+ | |||
+ | fname .byte "D:FOOBAR12.DAT",$9b | ||
+ | |||
+ | get_status | ||
+ | ldx #$10 ;IOCB #1 | ||
+ | lda #$0d ;komenda: STATUS | ||
+ | sta iccmd,x | ||
+ | lda #<fname ;adres nazwy pliku | ||
+ | sta icbufa,x | ||
+ | lda #>fname | ||
+ | sta icbufa+1,x | ||
+ | lda #$00 | ||
+ | sta icax1,x | ||
+ | sta icax2,x | ||
+ | jsr ciov | ||
+ | ... | ||
+ | </pre> | ||
+ | |||
+ | Odczyt statusu można też przeprowadzić dla otwartego pliku. Podawanie jego nazwy i innych parametrów jest wtedy zbędne: | ||
+ | |||
+ | <pre> | ||
+ | ; STATUS #1,A | ||
+ | |||
+ | ciov = $e456 | ||
+ | |||
+ | get_status | ||
+ | ldx #$10 ;IOCB #1 | ||
+ | lda #$0d ;komenda: STATUS | ||
+ | sta iccmd,x | ||
+ | jsr ciov | ||
+ | ... | ||
+ | </pre> | ||
+ | |||
+ | Wywołanie operacji STATUS dla urządzenia C: da zawsze wynik $01 niezależnie od tego, czy magnetofon jest rzeczywiście podłączony. | ||
+ | |||
+ | == Odczyt katalogu == | ||
+ | |||
+ | Odczyt katalogu dyskietki nie jest realizowany za pomocą specjalnej funkcji XIO, lecz poprzez komendę OPEN ale w specjalnym trybie odczytu katalogu. W tym celu w rejestrze ICAX1 umieszcza się wartość 6 (lub 7 w [[BiboDOS]] i [[SuperDOS]], co pozwala na wyświetlenie niepoprawnych i usuniętych plików), a w nazwie urządzenia należy podać maskę pliku. | ||
+ | |||
+ | Kod: | ||
+ | |||
+ | <pre> | ||
+ | ; OPEN #1,6,0,"D:*.*" | ||
+ | |||
+ | ciov = $e456 | ||
+ | |||
+ | fname .byte "D:*.*",$9b | ||
+ | |||
+ | open_file | ||
+ | ldx #$10 ;IOCB #1 | ||
+ | lda #$03 ;komenda: OPEN | ||
+ | sta iccmd,x | ||
+ | lda #<fname ;adres maski plików | ||
+ | sta icbufa,x | ||
+ | lda #>fname | ||
+ | sta icbufa+1,x | ||
+ | lda #$06 ;kod dostępu: $06 odczyt katalogu, $07 rozszerzony odczyt katalogu | ||
+ | sta icax1,x | ||
+ | lda #$00 ;dodatkowy parametr, $00 jest zawsze dobre | ||
+ | sta icax2,x | ||
+ | jsr ciov | ||
+ | ... | ||
+ | </pre> | ||
+ | |||
+ | Zawartość katalogu odczytywana jest zwykłymi operacjami GET BYTES lub GET RECORD aż do napotkania końca strumienia danych, po którym należy najzwyczajniej w świecie zamknąć plik komendą CLOSE. | ||
+ | |||
+ | W przypadku [[DOS 2.5]] i kompatybilnych każda pozycja katalogu zwracana jest w postaci sformatowanego ciągu znaków zawierających kolejne znaki: | ||
+ | |||
+ | * $00: znacznik zabezpieczenia pliku ("*") lub spacja, | ||
+ | * $01: spacja; w DOS 2.5 znacznik zajętości sektorów gęstości rozszerzonej ("<"), | ||
+ | * $02-$09: nazwa pliku, | ||
+ | * $0A-$0C: rozszerzenie pliku, | ||
+ | * $0D: spacja; w DOS 2.5 znacznik zajętości sektorów gęstości rozszerzonej (">"), | ||
+ | * $0E-$10: liczba sektorów jaką zajmuje plik na dysku. | ||
+ | * $11: EOL ($9B). | ||
+ | |||
+ | W ostatniej linii listingu znajduje się zawsze informacja o liczbie wolnych sektorów na dysku: | ||
+ | |||
+ | * $00-$02: liczba wolnych sektorów nie więcej niż 999, | ||
+ | * $03: spacja lub znacznik przekroczenia liczby sektorów możliwej do wyświetlenia na 3 pozycjach ("+"), | ||
+ | * $04-$0F: napis "FREE SECTORS", | ||
+ | * $10: EOL ($9B). | ||
+ | |||
+ | Przykładowy listing katalogu: | ||
+ | |||
+ | * DOS SYS 037 | ||
+ | * CP SYS 012 | ||
+ | INIT COM 009 | ||
+ | * RAMDISK COM 001 | ||
+ | QA COM 099 | ||
+ | BH COM 066 | ||
+ | XLF COM 059 | ||
+ | _IO ASM 028 | ||
+ | _PM ASM 043 | ||
+ | _SOUND ASM 024 | ||
+ | TRANS ASM 043 | ||
+ | DEMO ASM 051 | ||
+ | QA SET 001 | ||
+ | <CZYTAJ COM>032 | ||
+ | 505 FREE SECTORS | ||
+ | |||
+ | [[SpartaDOS X]] począwszy od wersji 4.47 na pozycji $01 wprowadza znacznik katalogu (":"): | ||
+ | |||
+ | * USD DOS 006 | ||
+ | AUTORUN SYS 357 | ||
+ | :TEST D 000 | ||
+ | 661 FREE SECTORS | ||
+ | |||
+ | [[MyDOS]] 4.53 prócz znacznika katalogu rozszerza pole liczby sektorów do 4 znaków: | ||
+ | |||
+ | * DOS SYS 0035 | ||
+ | * DUP SYS 0054 | ||
+ | :TEST D 0001 | ||
+ | 0619 FREE SECTORS | ||
+ | |||
+ | Z kolei [[SpartaDOS]] 3.2 oraz [[SpartaDOS X]] do wersji 4.47, a także [[BW-DOS]] 1.30 zezwala tylko na 8 znaków nazwy katalogu i zamiast znacznika katalogu (":") wyświetla rozszerzenie "DIR" w inverse-video: | ||
+ | |||
+ | * USD DOS 006 | ||
+ | AUTORUN SYS 363 | ||
+ | TEST <span style="color: white; background: black;">DIR</span> 002 | ||
+ | 661 FREE SECTORS | ||
+ | |||
+ | [[BiboDOS]] 7.0 inaczej wyświetla linię statusową: | ||
+ | |||
+ | * DOS SYS 017 | ||
+ | * DUP SYS 021 | ||
+ | CMC COM 050 | ||
+ | 339 Free Sectors | ||
+ | |||
+ | Podobnież [[LiteDOS]] ale dla odmiany podając liczbę wolnych sektorów za pomocą 5 cyfr: | ||
+ | |||
+ | LiteDOS DUP 018 | ||
+ | LITEINITXEX 034 | ||
+ | LITEREMUXEX 009 | ||
+ | LITE850 DRV 003 | ||
+ | LITEHDD DRV 009 | ||
+ | LITEHSIODRV 006 | ||
+ | LITERD DRV 010 | ||
+ | LITELZ4 XEX 002 | ||
+ | LITEBAS XEX 001 | ||
+ | 00272 FreeSpace | ||
+ | |||
+ | Czy [[DOS 3.0]] poprzedzając ją dodatkowo pustym wierszem: | ||
+ | |||
+ | * FMS SYS 004 | ||
+ | * KCP SYS 001 | ||
+ | * KCPOVER SYS 005 | ||
+ | * COPY UTL 005 | ||
+ | * DUPDISK UTL 004 | ||
+ | * INIT UTL 006 | ||
+ | * CONVERT UTL 005 | ||
+ | * HELP UTL 002 | ||
+ | * HELP TXT 012 | ||
+ | * HANDLERSSYS 001 | ||
+ | |||
+ | 037 FREE BLOCKS | ||
+ | |||
+ | A [[DOS XE]] 1.0 dla odmiany wyświetla rozmiary plików w KB a katalog oznacza znakiem ">": | ||
+ | |||
+ | * DOSXE SYS 14 | ||
+ | * DOS2 SYS 3 | ||
+ | * SETUP COM 9 | ||
+ | * RDRIVER SYS 0 | ||
+ | * COPY3_XECOM 6 | ||
+ | * WELCOME BAS 0 | ||
+ | TEST D > | ||
+ | 052 K BYTES FREE | ||
+ | |||
+ | [[BiboDOS]] i [[SuperDOS]] wyświetla dodatkowe informacje o usuniętych (-) i niedomkniętych (?) plikach, ale w ICAX1 należy podać kod 7: | ||
+ | |||
+ | * DOS SYS 038 | ||
+ | * SDUP SYS 040 | ||
+ | ? 5 038 | ||
+ | - 6 DTA 021 | ||
+ | 588 FREE SECTORS | ||
[[Kategoria:Niezbędnik kodera]] | [[Kategoria:Niezbędnik kodera]] |
Aktualna wersja
Jak napisano w haśle CIO, z dostępem do plików związane są w Atari tak zwane bloki kontroli wejścia i wyjścia (ang. Input/Output Control Blocks, albo IOCB). Jest ich osiem, każdy liczy 16 bajtów, ulokowane są w pamięci RAM, w obszarze od $0340 do $03BF. Ich struktura opisana jest w wyżej wymienionym haśle CIO, opis ten tutaj zostanie zatem pominięty. Wystarczy napisać, że block IOCB służy do zdefiniowania operacji na pliku i nadaniu jej parametrów wejściowych a także - odebraniu wyników (na ogół: kodu statusu).
Spis treści |
Adresowanie IOCB
Bloki IOCB konwencjonalnie adresuje się podając adres wewnątrz pierwszego z nich - czyli $034x - jako argument rozkazu w trybie absolutnym indeksowanym X, przy czym w rejestrze X powinien znajdować się numer bloku IOCB (z zakresu od 0 do 7) pomnożony przez 16. Numer kanału IOCB, pełniący rolę uchwytu (ang. handle) pliku, powinien zostać właśnie w tej postaci, i w tym rejestrze, przekazany do głównej procedury CIO (CIOV lub JCIOMAIN, $E456) przy jej wywoływaniu.
Etykiety IOCB
icchid = $0340 icdno = $0341 iccmd = $0342 icstat = $0343 icbufa = $0344 icputb = $0346 icbufl = $0348 icax1 = $034a icax2 = $034b icax3 = $034c icax4 = $034d icax5 = $034e icax6 = $034f
Z całego bloku dla omawianego tu zagadnienia istotne są:
- ICCMD - zapisuje się w nim jeden bajt symbolizujący rodzaj operacji (OPEN, CLOSE itd.)
- ICBUFA - to adres bufora
- ICBUFL - to wielkość bufora w bajtach
- ICAX1/2 - to bajty pomocnicze, zawierające różne dodatkowe parametry
Czasem przydaje się też ICSTAT, po zakończeniu operacji zawiera bowiem jej status (czyli $01 albo kod błędu). Ale rzadko się tę wartość odczytuje stamtąd, bo przekazywana jest też przez OS bezpośrednio w rejestrze Y.
Reszty bajtów IOCB nie dotykamy i w ogóle (na ogół) nie zawracamy sobie nimi głowy.
Funkcje IOCB
W teorii wszystkie bloki mają to samo przeznaczenie: każdy służy jako deskryptor pojedynczego, otwartego pliku. Wynika z tego, że w teorii można otworzyć do ośmiu plików na raz. W praktyce jeden blok - IOCB #$00 - jest defaultowo otwarty dla edytora ekranowego. Można go wprawdzie zamknąć i wykorzystać do czegoś innego, ale nie ma potrzeby tego czynić, gdyż przeciętny DOS nie pozwoli otworzyć więcej niż 3-4 pliki na raz.
Bloki IOCB służą tylko do przekazywania parametrów do DOS-u, nie są zaś właściwymi deskryptorami plików. Dlatego nie da się przeskoczyć limitu jednocześnie otwartych plików przez sprytną podmianę zawartości IOCB i zastąpienie jej przechowywanymi gdzieś indziej danymi innego otwartego pliku - żaden DOS nie da się tak oszukać.
Pierwszy wolny IOCB to IOCB #1, i ten właśnie będzie używany w przykładach.
Otwarcie pliku
W Atari można otworzyć plik dyskowy do odczytu, zapisu, wymiany danych (naprzemiennego odczytu i zapisu) oraz dopisywania. Ogólne zasady są takie, jak wszędzie indziej, to znaczy:
- plik otwierany do odczytu musi istnieć, w przeciwnym wypadku wystąpi błąd 170 (FILE NOT FOUND);
- plik otwierany do zapisu, jeśli nie istnieje, zostanie utworzony, natomiast jeśli istnieje, jego dotychczasowa zawartość zostanie skasowana i zostanie on otwarty;
- plik otwierany do odczytu i zapisu, jeśli istnieje, zostanie otwarty; jeśli nie istnieje, pod niektórymi DOS-ami (np. DOS 2.5, DOS XL) wystąpi błąd 170 (FILE NOT FOUND), natomiast pod innymi (np. SpartaDOS, SpartaDOS X) plik zostanie utworzony (i otwarty);
- plik otwierany do dopisywania jeśli istnieje, zostanie otwarty, a wskaźnik miejsca, do którego trafią zapisywane dane, zostanie ustawiony na jego końcu; jeśli zaś taki plik nie istnieje, pod niektórymi DOS-ami (np. DOS 2.5, DOS XL) wystąpi błąd 170 (FILE NOT FOUND), natomiast pod innymi (np. SpartaDOS, SpartaDOS X) plik zostanie utworzony (i otwarty).
Kod:
; OPEN #1,xx,0,"D:FOOBAR12.DAT" ciov = $e456 fname .byte "D:FOOBAR12.DAT",$9b open_file ldx #$10 ;IOCB #1 lda #$03 ;komenda: OPEN sta iccmd,x lda #<fname ;adres nazwy pliku sta icbufa,x lda #>fname sta icbufa+1,x lda #$xx ;kod dostępu: $04 odczyt, $08 zapis, $09 dopisywanie, $0c odczyt/zapis sta icax1,x lda #$00 ;dodatkowy parametr, $00 jest zawsze dobre sta icax2,x jsr ciov ...
Nazwa pliku musi spełniać następujące warunki:
- na początku musi się znajdować specyfikacja urządzenia, na ogół będzie to "D:", co oznacza stację dysków (a ściślej: DOS). Można tu podać numer stacji, np. "D2:", jednak najlepiej poprzestać na "D:" - pozwala to bardziej zaawansowanym DOS-om na zapis tego pliku do bieżącego podkatalogu, czyli na ogół tego, w którym użytkownik trzyma cały program.
- za dwukropkiem podajemy nazwę pliku w konwencji "8.3", tj. składającą się z najwyżej ośmiu znaków nazwę właściwą, kropkę oraz liczące do trzech znaków rozszerzenie. Znakami dopuszczalnymi w nazwie są duże litery alfabetu angielskiego (A-Z) i cyfry (0-9). Niektóre DOS-y (w tym SpartaDOS i MyDOS) dopuszczają również znak podkreślenia (_) i "małpę" (@). Część DOS-ów wymaga, żeby pierwszym znakiem całej nazwy była litera.
- DOS-y pozwalające na organizację plików w hierarchiczne struktury umożliwiają podanie w nazwie pliku ścieżki. Nazwy podkatalogów i pliku separowane są wtedy znakami ">" oraz "<" (SpartaDOS), "\" (SpartaDOS X) lub ":" (MyDOS).
- za ostatnim znakiem nazwy pliku obowiązkowo powinien się znaleźć znak EOL (Return, kod ASCII $9B).
Po wywołaniu jsr open_file
w rejestrze X będzie się znajdował (nadal) numer kanału pomnożony przez 16, a w rejestrze Y kod statusu, natomiast bit N rejstru znaczników będzie odzwierciedlał stan rejestru Y: jeśli N=1, to znaczy, że wystąpił błąd o kodzie przekazanym w Y. W przeciwnim wypadku (N=0) operacja się powiodła.
UWAGA: specyfiką Atari jest to, że po każdym OPEN, nawet jeśli zakończyło się błędem, kanał IOCB pozostaje otwarty i trzeba go zamknąć do ponownego użycia. Zakończenie programu nie powoduje automatycznego zamknięcia otwartych kanałów.
UWAGA: przy komunikacji z magnetofonem (C:) ICAX2 zawiera informację o rodzaju przerw między rekordami - $00 oznacza długie przerwy, $80 - krótkie.
Zamknięcie pliku
Jedynym parametrem wymaganym tutaj jest numer kanału IOCB pomnożony przez 16, czyli "uchwyt pliku". Kod:
; CLOSE #1 ciov = $e456 close_file ldx #$10 ;IOCB #1 lda #$0c ;komenda: CLOSE sta iccmd,x jsr ciov ...
Zamknięcie kanału już zamkniętego nie powoduje błędu.
Odczyt z pliku
Plik otwarty do odczytu będzie czytany sekwencyjnie od początku do końca. Jeśli nie wystąpią żadne błędy, i odczytano wszystkie dane z pliku, następna próba odczytu zwróci błąd nr 136 (EOF). Ważne jest, żeby status operacji testować na okoliczność wystąpienia błędu (N=1, Y>127), a nie na okoliczność powodzenia (Y=$01), gdyż część DOS-ów w pewnych warunkach zwraca wartość $03 jako status dla udanej operacji odczytu.
Ponadto, po powrocie z systemu ICBUFL,X i ICBUFL+1,X (odpowiednio: młodszy i starszy bajt) zawiera liczbę bajtów odczytanych do bufora, którego adres (nadal) znajduje się w ICBUFA,X i ICBUFA+1,X.
Odczyt bloku danych binarnych
Kod:
; BGET #1,buffer,buflen ciov = $e456 read_binary ldx #$10 ;IOCB #1 lda #$07 ;komenda: GET BYTES / BINARY READ sta iccmd,x lda #<buffer ;adres w pamieci, gdzie maja trafic dane sta icbufa,x lda #>buffer sta icbufa+1,x lda #<buflen ;wielkosc bloku danych w bajtach sta icbufl,x lda #>buflen sta icbufl+1,x jsr ciov ...
Odczyt pojedynczego bajtu
Do odczytania pojedynczego bajtu nie potrzeba deklarować bufora: jeśli zadeklarujemy zerową wielkość bufora, system odczyta 1 bajt i przekaże go w akumulatorze:
; GET #1,A ciov = $e456 read_one_byte ldx #$10 ;IOCB #1 lda #$07 ;komenda: GET BYTES / BINARY READ sta iccmd,x lda #$00 sta icbufl,x sta icbufl+1,x jsr ciov ...
Odczyt rekordu tekstowego
Rekord tekstowy jest to ciąg znaków ATASCII zakończony znakiem Return (EOL, ASCII $9B). Rekord musi mieścić się w zadeklarowanym buforze, jeśli bufor zapełni się zanim odczytany zostanie znak EOL, wystąpi błąd 137 (TRUNCATED RECORD).
Kod jest prawie taki sam, jak w przypadku danych binarnych, różni się tylko kodem operacji:
; INPUT #1,buffer$ ciov = $e456 read_text ldx #$10 ;IOCB #1 lda #$05 ;komenda: GET RECORD sta iccmd,x lda #<buffer ;adres w pamieci, gdzie maja trafic dane sta icbufa,x lda #>buffer sta icbufa+1,x lda #<buflen ;wielkosc rekordu w bajtach sta icbufl,x lda #>buflen sta icbufl+1,x jsr ciov ...
Zapis do pliku
Zapis przeprowadza się analogicznie do odczytu, może się jedynie zmieniać miejsce, gdzie dane zostaną zapisane. Jest to zależne od trybu otwarcia pliku: przy zwykłym zapisie (tryb otwarcia 8) lub wymianie danych (tryb otwarcia 12) dane będą wpisywane do pliku sekwencyjnie od początku. Przy dopisywaniu (tryb 9) wpisane do pliku dane znajdą się na jego końcu.
Po powrocie z systemu ICBUFL,X i ICBUFL+1,X (odpowiednio: młodszy i starszy bajt) zawiera liczbę bajtów zapisanych do pliku z bufora, którego adres (nadal) znajduje się w ICBUFA,X i ICBUFA+1,X.
UWAGA: po zapisie wszystkich danych plik należy obowiązkowo zamknąć, dopiero wtedy DOS zapisuje do niego wszystkie dane, jakie ewentualnie może jeszcze tymczasowo trzymać w buforach, oraz uaktualnia wpis w katalogu.
Zapis bloku danych binarnych
; BPUT #1,buffer,buflen ciov = $e456 write_binary ldx #$10 ;IOCB #1 lda #$0b ;komenda: PUT BYTES / BINARY WRITE sta iccmd,x lda #<buffer ;adres w pamieci, gdzie znajduja sie dane sta icbufa,x lda #>buffer sta icbufa+1,x lda #<buflen ;wielkosc bloku danych w bajtach sta icbufl,x lda #>buflen sta icbufl+1,x jsr ciov ...
Zapis pojedynczego bajtu
Analogicznie jak przy odczycie, zdefiniowanie zerowej wielkości bufora spowoduje, że do pliku zostanie zapisana zawartość akumulatora:
; PUT #1,A ciov = $e456 write_one_byte pha ldx #$10 ;IOCB #1 lda #$0b ;komenda: PUT BYTES / WRITE BINARY sta iccmd,x lda #$00 sta icbufl,x sta icbufl+1,x pla jsr ciov ...
Zapis rekordu tekstowego
Na końcu bufora danych powinien się znajdować znak EOL (ASCII $9B). Zadeklarowana wielkość bufora powinna być większa lub równa liczbie zapisywanych danych. Kod:
; PRINT #1,buffer$ ciov = $e456 write_text ldx #$10 ;IOCB #1 lda #$09 ;komenda: PUT RECORD sta iccmd,x lda #<buffer ;adres w pamieci, skad maja byc pobrane dane sta icbufa,x lda #>buffer sta icbufa+1,x lda #<buflen ;wielkosc rekordu w bajtach sta icbufl,x lda #>buflen sta icbufl+1,x jsr ciov ...
Status pliku
Odczyt statusu pliku ma na celu stwierdzenie jego dostępności bez konieczności robienia OPEN. Wynikiem jest $01 (sukces), gdy plik jest dostępny, lub odpowiedni kod błędu, gdy nie jest. Niektóre DOS-y zwracają kod błędu 167 (FILE LOCKED), kiedy plik istnieje, lecz jest zabezpieczony przed zapisem.
; XIO 13,#1,0,0,"D:FOOBAR12.DAT" ciov = $e456 fname .byte "D:FOOBAR12.DAT",$9b get_status ldx #$10 ;IOCB #1 lda #$0d ;komenda: STATUS sta iccmd,x lda #<fname ;adres nazwy pliku sta icbufa,x lda #>fname sta icbufa+1,x lda #$00 sta icax1,x sta icax2,x jsr ciov ...
Odczyt statusu można też przeprowadzić dla otwartego pliku. Podawanie jego nazwy i innych parametrów jest wtedy zbędne:
; STATUS #1,A ciov = $e456 get_status ldx #$10 ;IOCB #1 lda #$0d ;komenda: STATUS sta iccmd,x jsr ciov ...
Wywołanie operacji STATUS dla urządzenia C: da zawsze wynik $01 niezależnie od tego, czy magnetofon jest rzeczywiście podłączony.
Odczyt katalogu
Odczyt katalogu dyskietki nie jest realizowany za pomocą specjalnej funkcji XIO, lecz poprzez komendę OPEN ale w specjalnym trybie odczytu katalogu. W tym celu w rejestrze ICAX1 umieszcza się wartość 6 (lub 7 w BiboDOS i SuperDOS, co pozwala na wyświetlenie niepoprawnych i usuniętych plików), a w nazwie urządzenia należy podać maskę pliku.
Kod:
; OPEN #1,6,0,"D:*.*" ciov = $e456 fname .byte "D:*.*",$9b open_file ldx #$10 ;IOCB #1 lda #$03 ;komenda: OPEN sta iccmd,x lda #<fname ;adres maski plików sta icbufa,x lda #>fname sta icbufa+1,x lda #$06 ;kod dostępu: $06 odczyt katalogu, $07 rozszerzony odczyt katalogu sta icax1,x lda #$00 ;dodatkowy parametr, $00 jest zawsze dobre sta icax2,x jsr ciov ...
Zawartość katalogu odczytywana jest zwykłymi operacjami GET BYTES lub GET RECORD aż do napotkania końca strumienia danych, po którym należy najzwyczajniej w świecie zamknąć plik komendą CLOSE.
W przypadku DOS 2.5 i kompatybilnych każda pozycja katalogu zwracana jest w postaci sformatowanego ciągu znaków zawierających kolejne znaki:
- $00: znacznik zabezpieczenia pliku ("*") lub spacja,
- $01: spacja; w DOS 2.5 znacznik zajętości sektorów gęstości rozszerzonej ("<"),
- $02-$09: nazwa pliku,
- $0A-$0C: rozszerzenie pliku,
- $0D: spacja; w DOS 2.5 znacznik zajętości sektorów gęstości rozszerzonej (">"),
- $0E-$10: liczba sektorów jaką zajmuje plik na dysku.
- $11: EOL ($9B).
W ostatniej linii listingu znajduje się zawsze informacja o liczbie wolnych sektorów na dysku:
- $00-$02: liczba wolnych sektorów nie więcej niż 999,
- $03: spacja lub znacznik przekroczenia liczby sektorów możliwej do wyświetlenia na 3 pozycjach ("+"),
- $04-$0F: napis "FREE SECTORS",
- $10: EOL ($9B).
Przykładowy listing katalogu:
* DOS SYS 037 * CP SYS 012 INIT COM 009 * RAMDISK COM 001 QA COM 099 BH COM 066 XLF COM 059 _IO ASM 028 _PM ASM 043 _SOUND ASM 024 TRANS ASM 043 DEMO ASM 051 QA SET 001 <CZYTAJ COM>032 505 FREE SECTORS
SpartaDOS X począwszy od wersji 4.47 na pozycji $01 wprowadza znacznik katalogu (":"):
* USD DOS 006 AUTORUN SYS 357 :TEST D 000 661 FREE SECTORS
MyDOS 4.53 prócz znacznika katalogu rozszerza pole liczby sektorów do 4 znaków:
* DOS SYS 0035 * DUP SYS 0054 :TEST D 0001 0619 FREE SECTORS
Z kolei SpartaDOS 3.2 oraz SpartaDOS X do wersji 4.47, a także BW-DOS 1.30 zezwala tylko na 8 znaków nazwy katalogu i zamiast znacznika katalogu (":") wyświetla rozszerzenie "DIR" w inverse-video:
* USD DOS 006
AUTORUN SYS 363
TEST DIR 002
661 FREE SECTORS
BiboDOS 7.0 inaczej wyświetla linię statusową:
* DOS SYS 017 * DUP SYS 021 CMC COM 050 339 Free Sectors
Podobnież LiteDOS ale dla odmiany podając liczbę wolnych sektorów za pomocą 5 cyfr:
LiteDOS DUP 018 LITEINITXEX 034 LITEREMUXEX 009 LITE850 DRV 003 LITEHDD DRV 009 LITEHSIODRV 006 LITERD DRV 010 LITELZ4 XEX 002 LITEBAS XEX 001 00272 FreeSpace
Czy DOS 3.0 poprzedzając ją dodatkowo pustym wierszem:
* FMS SYS 004 * KCP SYS 001 * KCPOVER SYS 005 * COPY UTL 005 * DUPDISK UTL 004 * INIT UTL 006 * CONVERT UTL 005 * HELP UTL 002 * HELP TXT 012 * HANDLERSSYS 001 037 FREE BLOCKS
A DOS XE 1.0 dla odmiany wyświetla rozmiary plików w KB a katalog oznacza znakiem ">":
* DOSXE SYS 14 * DOS2 SYS 3 * SETUP COM 9 * RDRIVER SYS 0 * COPY3_XECOM 6 * WELCOME BAS 0 TEST D > 052 K BYTES FREE
BiboDOS i SuperDOS wyświetla dodatkowe informacje o usuniętych (-) i niedomkniętych (?) plikach, ale w ICAX1 należy podać kod 7:
* DOS SYS 038 * SDUP SYS 040 ? 5 038 - 6 DTA 021 588 FREE SECTORS