Tajemnice ATARI

HANDLER "A:"

    Z pewnością każdy użytkownik stacji dysków zapragnął kiedyś obejrzeć sobie całą zawartość pojedynczego sektora. Niestety, instrukcje NOTE/POINT do tego celu się nie nadają - dają dostęp tylko do sektorów należących do pliku, i oczywiście pomijają przy odczycie ostatnie 3 bajty.

    Także wszelkiego typu monitory dyskowe mają dosyć ograniczone zastosowanie. Przedstawiony na listingu nr 1 program jest próbą rozwiązania powyższego problemu. Tworzy on (w sposób podany w numerze 8/91 TA) urządzenie zewnętrzne o nazwie A:, pozwalające na uzyskanie dostępu do dowolnego sektora dysku.

    Forma handlera jest chyba najbardziej uniwersalną, pozwala bowiem na współpracę z większością programów użytkowych (choć program pomyślany jest przede wszystkim jako narzędzie wspomagające Basic). Dostęp do pojedynczego sektora uzyskujemy (z Basicu) przez wykonanie instrukcji

OPEN #kanał,licz1,licz2,"A:nrsek/T"

gdzie licz1 wybiera kierunek przekazywania danych (4 - odczyt, 8 - zapis), licz2 jest ignorowana, nrsek to numer żądanego sektora (dziesiętnie), rozszerzenie /T ma znaczenie przy instrukcji Close - o tym za moment. Numer sektora musi być liczbą, w innym wypadku zasygnalizowany zostanie błąd nr 255. Gęstość zapisu zostanie rozpoznana automatycznie (w przypadku formatu innego niż jeden z trzech standardowych zasygnalizowany będzie błąd 254). I jeszcze jedno: próba uzyskania dostępu do kilku sektorów Jednocześnie spowoduje błąd nr 161 (to ograniczenie istnieje głównie ze względów oszczędnościowych - każdy sektor wymaga 256 bajtowego bufora).

   Gdy operacja otwarcia kanału przebiegła pomyślnie - możemy już do woli odczytywać (GET/INPUT), lub zapisywać (PUT/PRINT) dane. Dostęp do sektorów jest sekwencyjny, tzn. odczytywane i zapisywane są one kolejno, oczywiście po opróżnieniu, bądź zapełnieniu bufora. Przekroczenie największego dozwolonego numeru sektora powoduje błąd nr 136 - EOF.

   Zamknięcia kanału dokonujemy oczywiście instrukcją CLOSE. W tym miejscu pora na wyjaśnienie tajemniczego rozszerzenia /T w nazwie pliku. Otóż przy zamykaniu kanału po operacji zapisu danych w buforze pozostają pewne dane, które oczywiście trzeba zachować. Można to zrobić na dwa sposoby: po pierwsze - wyzerować sektor i nagrać na nim owe dane, po drugie zaś, można je "nałożyć" na poprzednią zawartość tego sektora. Podanie rozszerzenia /T wymusza właśnie ten drugi sposób zapisu. Każde inne (lub jego brak) wybiera pierwsza z podanych opcji. Tyle informacji na temat obsługi handlera. Sposób jego wykorzystania zależy już od inwencji i wyobraźni użytkownika. Ze swej strony chciałbym zaprezentować dwa najbardziej typowe przykłady.

   Listing nr 2 przedstawia program kopiujący wspomagający handler. Niestety, standardowe kopiery nie radzą sobie dobrze z odczytem z urządzenia - po prostu czytają dane o długości równej objętości swego bufora, co z reguły nie jest nikomu potrzebne. Mój program likwiduje tę niedogodność, pytając użytkownika o liczbę bajtów do odczytu. Kopier pracuje w trybie konwersacji, za każdym razem podając rozmiar dostępnej pamięci RAM (ok. 29 Kb) i długość pliku w buforze. Wpisanie "*" powoduje wyświetlenie katalogu dyskietki, kropka (".") kasuje bufor i przestawia program w tryb odczytu danych, zaś "Q" powoduje zakończenie pracy i przekazanie sterowania do BASIC-a.

   Trzeci listing zainteresuje z pewnością użytkowników Quick Assemblera. Tworzy on malutki programik, który będzie odczytywany jako boot dyskowy. Wystarczy jedynie przed wczytaniem QA uruchomić handler, po czym (już w QA) wybrać opcję OBJ, jako nazwę pliku docelowego podać "A:1" i uruchomić opcję asemblacji. Proszę zwrócić uwagę na instrukcję OPT %1100101 powodującą przesłanie kodu wynikowego na urządzenie zewnętrzne bez nagłówków. Po dokładniejsze wyjaśnienia samego programu odsyłani do artykułu Lesława Pasternaka pt. "BOOT" ("TA" 6/91).
         org   $0700
         opt   %1100101

*----    Naglowek boot

         dta   b(0),b(1)
         dta   a($700)
         dta   a(start)

*----    Inicjalizacja

         clc
         rts

*----    Pisz tekst

start    ldx   txt
         jsr   $c642
         
*----    Wieczna petla

tu       jmp   tu

*----    Dane

txt      dta   c'Boot wykonany!',b($9b)

         end
   I na zakończenie kilka informacji technicznych. Po przepuszczeniu listingu nr 1 przez "Zgrywusa" otrzymujemy program zawarty w pliku binarnym. Pozwala to na używanie go jako komendy zewnętrznej CP.SYS-a. Handler sam się relokuje i podnosi nad siebie MEMLO (użyłem do tego celu metody przedstawionej w TA 8/91), zajmuje zaś około 850 bajtów RAM. Można tę przestrzeń bardzo łatwo zwolnić, naciskając RESET+START. Program został napisany przy pomocy Quick Assemblera.
1000 REM *--------------------------*
1002 REM : Handler "A:"             :
1004 REM :  autor: Maciej Czarnota  :
1006 REM : (c) 1992 Tajemnice ATARI :
1008 REM *--------------------------*
1010 DATA ffff0090e392a240a0902042c6
1020 DATA a200bd1a03c900f01ac941f00d
1030 DATA e8e8e8e021d0eea278a090d004
1040 DATA a25fa09068684c42c6a201b50c
1050 DATA 9d9890bde702950cca10f3a292
1060 DATA a0904c42c6413a2068616e646c
1070 DATA 657220762e204949206279204d
1080 DATA 2e437a61726e6f74619b48616e
1090 DATA 646c6572206a65737420616b74
1100 DATA 79776e79202121fd9b4272616b
1110 DATA 206d69656a7363612077204841
1120 DATA 54414253202121fd9b4f2e6b2e
1130 DATA 9b209790ad1fd0c906d030ad7e
1140 DATA 92c50cd020ad7f92c50dd019a2
1150 DATA 01bd9890950cbd7e929de702ca
1160 DATA 10f2ae8092ac81924c42c6ae82
1170 DATA 92ac83922042c6a241ac8492ad
1180 DATA 85922086e4a9008da892ad8692
1190 DATA 8de702ad87928de80260ada892
1200 DATA f003a0a160a52a8da592a0008c
1210 DATA a492c8c88ca89284f2a52485f3
1220 DATA a52585f42000d89003a0ff6020
1230 DATA d2d9a5d48da292a5d58da392a9
1240 DATA 008da99220dd91b014c92fd010
1250 DATA e6f220dd91b009c954d005a980
1260 DATA 8da992201292adea0229e0a002
1270 DATA d99992f0068810f8a0fe608ca7
1280 DATA 9220f791a00160a0008ca892ad
1290 DATA a592c904f030aca492f02b88b9
1300 DATA e492998004c000d0f59899e492
1310 DATA c8d0faada992f003202092aca4
1320 DATA 9288b9800499e492c000d0f520
1330 DATA 2492a00160aca492d00b202092
1340 DATA 20f79120ee91a000b9e492c8cc
1350 DATA a692d002a0008ca492a00160ac
1360 DATA a49299e492c8cca692d00b2024
1370 DATA 9220ee9120f791a0008ca492a0
1380 DATA 016020a1dba4f2b124c99bf005
1390 DATA c900f0011860eea292d003eea3
1400 DATA 9260aca792b996928da692ada3
1410 DATA 92d00cada292c904b005a9808d
1420 DATA a69260a9048dd502a9008dd602
1430 DATA a953d006a952d002a9508d0203
1440 DATA ada7920aa8b99c928dd502b99d
1450 DATA 928dd602ada2928d0a03ada392
1460 DATA 8d0b03a9018d0103ad7c928d04
1470 DATA 03ad7d928d0503ada392d011ad
1480 DATA a292c904b00aa9808dd502a900
1490 DATA 8dd6022053e41008c08bd002a0
1500 DATA 8868686000e4929790aa92c392
1510 DATA 8892e493ed905f919e91bf915c
1520 DATA 915c9100008080000080208000
1530 DATA 80000001000000000000000041
1540 DATA 3a2068616e646c6572206f6469
1550 DATA 6e7374616c6f77616e799bfd4e
1560 DATA 6965206d6f6765206f64696e73
1570 DATA 74616c6f7761632068616e646c
1580 DATA 657261219be493ae9400200090
1590 DATA a9608de593a90085cfade70285
1600 DATA d4ade80285d538a99785d2e5d4
1610 DATA 85d0a99085d3e5d585d1a000f0
1620 DATA 033866cfa5d2c9e5a5d3e99390
1630 DATA 14ade7021869038daf94ade802
1640 DATA 69008db0946caf9424cf706330
1650 DATA 27b1d285ce91d420a294aaf0cd
1660 DATA c920f017c940f0c8c960f0c429
1670 DATA 0dc908f0be90418a291fc909f0
1680 DATA 3ab1d2c8c997b1d288e9909012
1690 DATA b1d2c8c9e5b1d288e993b006a5
1700 DATA d0a6d1900724cf3090a900aa85
1710 DATA d686d738b1d2e5d691d420a294
1720 DATA b1d2e5d74c9a94b1d291d420a2
1730 DATA 944c1394e6d2d002e6d3e6d4d0
1740 DATA 02e6d560e002e102e593

2 REM Kopier wspomagajacy handler A:
3 REM Autor : Maciej Czarnota ' 02.92
5 GRAPHICS 0:POKE 710,0:? " ACopier ve
r. 1.0":DIM P$(29),F$(17),PR$(20),OP(2
)
10 REM Ustalenie zmiennych
15 PR$="odczytu   zapisu    ":OP(1)=7:
OP(2)=11:OD=1:LM=PEEK(144)+256*PEEK(14
5):HM=PEEK(560)+256*PEEK(561)
20 MX=HM-LM:RESTORE :FOR I=1 TO 29:REA
D A:P$(I,I)=CHR$(A):NEXT I
25 REM Przygotowanie odczytu
30 ILE=MX:BUF=0
35 REM Wlasciwa procedura kopiera
40 ? :? "Bufor : ";MX:? "W buforze : "
;BUF:? :? "Podaj nazwe pliku do ";PR$(
OD*10-9,OD*10)
45 INPUT F$:IF F$="" THEN 40
50 IF F$="*" THEN GOSUB 115:GOTO 40
55 IF F$="Q" THEN GRAPHICS 0:CLR :END 
60 IF F$="." THEN OD=1:? CHR$(125);:GO
TO 30
65 IF F$(1,1)="A" AND OD=1 THEN GOSUB 
100
70 REM Tu zapis/odczyt programu
75 TRAP 90:OPEN #1,4*OD,128,F$:A=USR(A
DR(P$),OP(OD),ILE):CLOSE #1
76 IF OD=1 THEN OD=2:ILE=PEEK(856)+256
*PEEK(857):BUF=ILE
80 GOTO 40
85 REM Obsluga bledow
90 CLOSE #1:? CHR$(253);"ERROR - ";PEE
K(195):GOTO 40
95 REM Podprogram obslugi odczytu z A
100 ? "Ile bajtow ":TRAP 75:INPUT ILE:
IF ILE>MX THEN ? "To przekracza objeto
sc bufora":GOTO 75
105 RETURN 
110 REM Directory
115 TRAP 90:OPEN #1,6,0,"D:*.*"
120 TRAP 125:INPUT #1,F$:? F$:GOTO 120
125 CLOSE #1:RETURN 
130 REM Procedurka JMP $E456
135 DATA 104,104,104,162,16,157,66,3,1
65,144,157,68,3,165,145,157,69,3,104,1
57,73,3,104,157,72,3,76,86,228


Maciej Czarnota



Powrót na start | Powrót do spisu treści | Powrót na stronę główną

Pixel 2001