Powrót do spisu treści

3.2.5. Operacje specjalne na ekranie

    Poza procedurami standardowymi na ekranie można jeszcze wykonać dwie operacje specjalne: DRAW (kod $11) i FILL (kod $12). Pierwsza z nich służy do rysowania linii, druga dodatkowo wypełnia kolorem obraz w prawo od rysowanej linii. Dla realizacji tych funkcji trzeba przed wywołaniem procedury CIO umieścić kursor na pozycji docelowej (do której ma być narysowana linia), a w przypadku FILL dodatkowo w rejestrze FILDAT (FILl DATa) należy umieścić numer koloru (wzoru bitowego) do wypełniania obrazu. Procedura CIOMAIN po rozpoznaniu kodu operacji specjalnej wywołuje procedurę DRAW. Jest ona stosunkowo długa ze względu na dużą ilość obliczeń.

    Najpierw sprawdzany jest kod operacji. Gdy jest równy $11 (DRAW), to rejestr FILFLG otrzymuje wartość 0, gdy $12, to wartość 1. Inne kody powodują umieszczenie w rejestrze Y kodu błędu $84 (INVALID COMMAND) i przerwanie procedury.
0100 ;DRAW routine            0570     STA NEWCOL+1
0110 ;                        0580     LDA #$01
0120 ATACHR = $02FB           0590     STA ROWINC
0130 COLAC = $72              0600     STA COLINC
0140 COLCRS = $55             0610     SEC
0150 COLINC = $02F9           0620     LDA NEWROW
0160 COUNTR = $7E             0630     SBC OLDROW
0170 DELTAC = $77             0640     STA DELTAR
0180 DELTAR = $76             0650     BCS DLC
0190 ENDPT = $74              0660     LDA #$FF
0200 FILDAT = $02FD           0670     STA ROWINC
0210 FILFLG = $02B7           0680     LDA DELTAR
0220 GETPLT = $F18F           0690     EOR #$FF
0230 HOLD4 = $02BC            0700     CLC
0240 ICCOMZ = $22             0710     ADC #$01
0250 KBOPN = $F21E            0720     STA DELTAR
0260 NEWCOL = $02F6           0730 DLC SEC
0270 NEWROW = $02F5           0740     LDA NEWCOL
0280 OLDCOL = $5B             0750     SBC OLDCOL
0290 OLDROW = $5A             0760     STA DELTAC
0300 OUTPLT = $F1CA           0770     LDA NEWCOL+1
0310 PHACRS = $F94C           0780     SBC OLDCOL+1
0320 PLACRS = $F957           0790     STA DELTAC+1
0330 RANGE = $F6CA            0800     BCS SAV
0340 ROWAC = $70              0810     LDA #$FF
0350 ROWCRS = $54             0820     STA C0LINC
0360 ROWINC = $02F8           0830     LDA DELTAC
0370 SCRIBT = $F612           0840     EOR #$FF
0380 SUBEND = $F6AE           0850     STA DELTAC
0390 ;                        0860     LDA DELTAC+1
0400     *=  $F9AF            0870     EOR #$FF
0410 ;                        0880     STA DELTAC+1
0420     LDX #$00             0890     INC DELTAC
0430     LDA ICCOMZ           0900     BNE SAV
0440     CMP #$11             0910     INC DELTAC+1
0450     BEQ DRW              0920 SAV LDX #$02
0460     CMP #$12             0930     LDY #$00
0470     BEQ FIL              0940     STY COLAC+1
0480     LDY #$84             0950 NXT TYA
0490     RTS                  0960     STA ROWAC,Y
0500 FIL INX                  0970     LDA OLDROW,X
0510 DRW STX FILFLG           0980     STA ROWCRS,X
0520     LDA ROWCRS           0990     DEX
0530     STA NEWROW           1000     BPL NXT
0540     LDA COLCRS           1010     LDA DELTAC
0550     STA NEWCOL           1020     INX
0560     LDA COLCRS+1         1030     TAY

1040     LDA DELTAC+1         1550     BNE CRS
1050     STA COUNTR+1         1560     LDA COLAC
1060     STA ENDPT+1          1570     CMP ENDPT
1070     BNE CKE              1580     BCC PLOT
1080     LDA DELTAC           1590 CRS BIT COLINC
1090     CMP DELTAR           1600     BPL ICC
1100     BCS CKE              1610     DEC COLCRS
1110     LDA DELTAR           1620     LDA COLCRS
1120     LDX #$02             1630     CMP #$FF
1130     TAY                  1640     BNE POINT
1140 CKE TYA                  1650     LDA COLCRS+1
1150     STA COUNTR           1660     BEQ POINT
1160     STA ENDPT            1670     DEC COLCRS+1
1170     PHA                  1680     BPL POINT
1180     LDA ENDPT+1          1690 ICC INC COLCRS
1190     LSR A                1700     BNE POINT
1200     PLA                  1710     INC COLCRS+1
1210     ROR A                1720 POINT LDX #$02
1220     STA ROWAC,X          1730     JSR SUBEND
1230 LOOP LDA COUNTR          1740 PLOT JSR RANGE
1240     ORA COUNTR+1         1750     JSR OUTPLT
1250     BNE CONT             1760     LDA FILFLG
1260     JMP EXIT             1770     BEQ NPT
1270 CONT CLC                 1780     JSR PHACRS
1280     LDA ROWAC            1790     LDA ATACHR
1290     ADC DELTAR           1800     STA HOLD4
1300     STA ROWAC            1810 LOOP2 LDA ROWCRS
1310     BCC SKIP             1820     PHA
1320     INC ROWAC+1          1830     JSR SCRIBT
1330 SKIP LDA ROWAC+1         1840     PLA
1340     CMP ENDPT+1          1850     STA ROWCRS
1350     BCC COL              1860     JSR RANGE
1360     BNE ROW              1870     JSR GETPLT
1370     LDA ROWAC            1880     BNE FIN
1380     CMP ENDPT            1890     LDA FILDAT
1390     BCC COL              1900     STA ATACHR
1400 ROW CLC                  1910     JSR OUTPLT
1410     LDA ROWCRS           1920     JMP LOOP2
1420     ADC ROWINC           1930 FIN LDA HOLD4
1430     STA ROWCRS           1940     STA ATACHR
1440     LDX #$00             1950     JSR PLACRS
1450     JSR SUBEND           1960 NPT SEC
1460 COL CLC                  1970     LDA COUNTR
1470     LDA COLAC            1980     SBC #$01
1480     ADC DELTAC           1990     STA COUNTR
1490     STA COLAC            2000     LDA COUNTR+1
1500     LDA COLAC+1          2010     SBC #$00
1510     ADC DELTAC+1         2020     STA COUNTR+1
1520     STA COLAC+1          2030     BMI EXIT
1530     CMP ENDPT+1          2040     JMP LOOP
1540     BCC PLOT             2050 EXIT JMP KBOPN
    Przed rozpoczęciem rysowania linii muszą zostać określone jej parametry. W tym celu aktualna pozycja kursora (na końcu rysowanej linii) jest przepisywana z rejestrów ROWCRS i COLCRS do NEWROW i NEWCOL. Następnie przez odjęcie poprzedniej pozycji (na początku linii) przechowywanej w rejestrach OLDROW i OLDCOL obliczany jest przyrost obu współrzędnych, który jest zapisywany odpowiednio do DELTAR (DELTA Row) i DELTAC (DELTA Column). Z kolei według znaku przyrostu ustalane są kroki zmiany wiersza i kolumny (ROWINC - ROW INCrement i COLINC - COLumn INCrement). Dla przyrostów dodatnich mają one wartość $01, a dla ujemnych $FF.

    W dalszej części zerowane są liczniki rysowanej linii COLAC (COLumn ACtual) i ROWAC (ROW ACtual) oraz odtwarzana jest poprzednia pozycja kursora z rejestrów OLD... . Większa z wartości przyrostów (DELTAR lub DELTAC) jest następnie umieszczana w liczniku COUNTR i rejestrze ENDPT (END PoinTer) oraz, po podzieleniu przez dwa w rejestrze ROWAC lub COLAC.

    Teraz rozpoczyna się rysowanie linii w pętli, która jest przerywana po całkowitym wyzerowaniu licznika COUNTR. Po opuszczeniu pętli następuje skok do KBOPN i zakończenie procedury.

    Najpierw do rejestrów aktualnej pozycji kursora na rysowanej linii (ROWAC i COLAC) dodawany jest przyrost (DELTAR i DELTAC), a wynik jest porównywany ze wskaźnikiem końca rysowania (ENDPT). Znalezienie większej z różnic powoduje zwiększenie odpowiedniego rejestru pozycji kursora (ROWCRS lub COLCRS) i uaktualnienie wartości w COLAC lub ROWAC poprzez wywołanie procedury SUBEND. Przedtem do rejestru X wpisywana jest wartość określająca aktualizowany rejestr. $00 oznacza rejestr ROWAC, a $02 - COLAC.
            0100 ;SUBtract END point
            0110 ;
            0120 ENDPT = $74
            0130 ROWAC = $70
            0140 ;
            0150     *=  $F6AE
            0160 ;
            0170     SEC
            0180     LDA ROWAC,X
            0190     SBC ENDPT
            0200     STA ROWAC,X
            0210     LDA ROWAC+1,X
            0220     SBC ENDPT+1
            0230     STA ROWAC+1,X
            0240     RTS
    Teraz przez wywołanie RANGE sprawdzane jest, czy obliczona pozycja kursora mieści się na ekranie. Z kolei wywołanie OUTPLT umieszcza punkt na pozycji kursora. Jeżeli znacznik FILFLG jest równy zero, to po zmniejszeniu o jeden licznika COUNTR następuje powrót do początku pętli rysującej.

    Znacznik FILFLG różny od zera powoduje rozpoczęcie wewnętrznej pętli, której zadaniem jest wypełnienie obrazu w prawo do najbliższego punktu. Pętla ta w ogólnym zarysie jest podobna do pętli rysującej linię. Na jej początku aktualna pozycja kursora jest zapisywana przez procedurę PHACRS do tymczasowych rejestrów TMPROW i TMPCOL, a znak z rejestru ATACHR przepisywany jest do HOLD4. Teraz kolejno wywoływane są procedury SCRIBT, RANGE i GETPLT.
            0100 ;PusH A CuRSor
            0110 ;
            0120 ROWCRS = $54
            0130 TMPROW = $02B8
            0140 ;
            0150     *=  $F94C
            0160 ;
            0170     LDX #$02
            0180 NEXT LDA ROWCRS,X
            0190     STA TMPROW,X
            0200     DEX
            0210     BPL NEXT
            0220     RTS
    Jeżeli punkt odczytany z ekranu przez GETPLT jest zerem, to zostaje wypełniony. Zawartość FILDAT jest w tym celu przepisywana do ATACHR i poprzec procedurę OUTPLT umieszczana na ekranie. Potem następuje skok do początku pętli wewnętrznej i operacja się powtarza.

    Odczytanie przez GETPLT punktu różnego od zera kończy pętlę wypełniającą. Przed powrotem do rysowania linii odtwarzany jest z rejestru HOLD4 znak w ATACHR, a procedura PLACRS odtwarza pozycję kursora. Taki sposób postępowania pozwala na wypełnienie obszaru kolorem innym niż kolor rysowanej linii.
            0100 ;PulL A CuRSor
            0110 ;
            0120 ROWCRS = $54
            0130 TMPROW = $02B8
            0140 ;
            0150     *=  $F957
            0160 ;
            0170     LDX #$02
            0180 NEXT LDA TMPROW,X
            0190     STA ROWCRS,X
            0200     DEX
            0210     BPL NEXT
            0220     RTS

3.3. Procedury obsługi edytora

    Edytor jest urządzeniem wejścia i wyjścia będącym połączeniem klawiatury i ekranu w trybie 0. Z tego względu większość procedur obsługi edytora jest wspólna w całości lub znacznej części z procedurami obsługi tych dwóch urządzeń. Wektory edytora w tabeli EDTVEC wskazują następujące procedury:
         OPEN     - EDOPN
         CLOSE    - SCRFIN
         GET      - EGETCH
         PUT      - EOUTCH
         STATUS   - KBOPN
         SPECIAL  - EDSP
    Z tego wykazu widać od razu, że procedura zamknięcia edytora jest identyczna z procedurą zamknięcia ekranu (SCRFIN), a procedura odczytu statusu jest wspólna dla klawiatury i edytora (KBOPN). Etykietą EDSP jest natomiast oznaczony rozkaz RTS, bowiem tej funkcji edytor nie posiada.

3.3.1. Procedura otwarcia edytora

    Procedura otwarcia edytora jest identyczna z procedurą otwarcia ekranu w trybie 0 (SCOPN). Są one opisane razem w rozdziale 3.2.1. (str. 49). Przy rozpatrywaniu tej i innych procedur trzeba pamiętać, że otwarcie edytora zawsze kasuje zawartość ekranu. Edytor nie może również posiadać okna tekstowego. Natomiast w trybach graficznych z oknem tekstowym zawsze obraz należy do ekranu, a okno do edytora.

3.3.2. Zapis do edytora

    Kod rozkazu PUT powoduje wywołanie przez CIO procedury EOUTCH. Przed jej wywołaniem w akumulatorze umieszczany jest znak do zapisu na ekranie. Na początku procedury znak ten jest wpisywany do rejestru ATACHR. Następnie wywoływana jest procedura SWAP, której zadaniem jest przenoszenie kursora z ekranu do okna tekstowego (jeśli istnieje) i odwrotnie. Po niej wywoływana jest procedura ERANGE, która z kolei sprawdza, czy pozycja kursora mieści się w dopuszczalnych granicach. Etap początkowy kończy się wyzerowaniem znacznika SUPERF.

    Od tego miejsca, które jest oznaczone etykietą PRCCHR i wykorzystywane także przy odczycie znaku, rozpoczyna się właściwa obsługa znaku wyprowadzanego na ekran.

    Najpierw wywoływana jest procedura OFFCRS, która odczytuje znak znajdujący się pod kursorem i umieszcza go na pozycji kursora. Następnie procedura TSTCNT sprawdza, czy jest to znak kontrolny edytora, przy czym po znalezieniu znaku jego numer w tabeli CNTRLS znajduje się w rejestrze X. Jeżeli nie jest to znak kontrolny, to po skasowaniu zawartości rejestru ESCFLG i wywołaniu TSTRET sprawdzającej, czy jest to znak RETURN, procedura kończy się skokiem do SWAP. Jeśli znak został znaleziony w CNTRLS, to sprawdzane są znaczniki ekranu DSPFLG (DiSPlay FLaG) i znaku Escape ESCFLG (ESCape FLaG). Gdy oba są równe zero, również procedura kończy się poprzez TSTRET i SWAP.
            0100 ;Editor OUTput CHaracter
            0110 ;
            0120 ADRESS = $64
            0130 ATACHR = $02FB
            0140 CNTRLS = $FB0D
            0150 DSPFLG = $02FE
            0160 ERANGE = $F6BC
            0170 ESCFLG = $02A2
            0180 JSRIND = $F2AD
            0190 OFFCRS = $F718
            0200 RETURM = $F20B
            0210 SUPERF = $03E8
            0220 SWAP =  $F962
            0230 TSTCNT = $F93C
            0240 TSTRET = $F1B4
            0250 ;
            0260     *=  $F2B0
            0270 ;
            0280     STA ATACHR
            0290     JSR SWAP
            0300     JSR ERANGE
            0310     LDA #$00
            0320     STA SUPERF
            0330 ;
            0340 ;PRoCeed CHaRacter
            0350 ;
            0360 PRCCHR JSR OFFCRS
            0370     JSR TSTCNT
            0380     BEQ TCN
            0390 CHR ASL ESCFLG
            0400     JSR TSTRET
            0410     JMP SWAP
            0420 TCN LDA DSPFLG
            0430     ORA ESCFLG
            0440     BEQ CHR
            0450     ASL ESCFLG
            0460     INX
            0470     LDA SUPERF
            0480     BEQ CNT
            0490     TXA
            0500     CLC
            0510     ADC #$2D
            0520     TAX
            0530 CNT LDA CNTRLS,X
            0540     STA ADRESS
            0550     LDA CNTRLS+1,X
            0560     STA ADRESS+1
            0570     JSR JSRIND
            0580     JSR RETURM
            0590     JMP SWAP
    Po rozpoznaniu znaku kontrolnego i możliwości jego wykonania jest kasowany znacznik ESCFLG i sprawdzany rejestr SUPERF. Jest to potrzebne jedynie w przypadku rozpoczęcia procedury od PRCCHR, gdyż po wywołaniu od EOUTCH jest on skasowany. Jeśli SUPERF jest różny od zera, to numer znaku kontrolnego jest zwiększany o $2D. Przyczyna tej operacji będzie oczywista po analizie procedury KBGBYT (str. 39).

    Następnie według numeru znaku z tabeli CNTRLS jest pobierany adres jego procedury. Zostaje on umieszczony w rejestrze ADRESS i procedura ta jest wywoływana poprzez JSRIND. Po jej zakończeniu i wywołaniu RETURM procedura EOUTCH kończy się skokiem do SWAP.

    Procedura OFFCRS w celu odtworzenia znaku znajdującego się pod kursorem pobiera jego kod z rejestru OLDCHR (OLD CHaRacter) i umieszcza go w miejscu określonym przez wektor OLDADR (OLD ADdRess).
            0100 ;OFF CuRSor
            0110 ;
            0120 OLDADR = $5E
            0130 OLDCHR = $5D
            0140 ;
            0150     *=  $F718
            0160 ;
            0170     LDY #$00
            0180     LDA OLDADR+1
            0190     BEQ EXIT
            0200     LDA OLDCHR
            0210     STA (OLDADR),Y
            0220 EXIT RTS
    Do wywoływania procedur znaków kontrolnych została wykorzystana możliwość wykonywania skoków pośrednich według adresu zapisanego w dowolnym miejscu pamięci. Funkcję tą pełni w tym przypadku rejestr ADRESS, do którego EOUTCH wpisuje wektor odpowiedniej procedury.
            0100 ;Jump SubRoutine INDirect
            0110 ;
            0120 ADRESS = $64
            0130 ;
            0140     *=  $F2AD
            0150 ;
            0160     JMP (ADRESS)
    Pierwszym rozkazem wykonywanym po wywołaniu JSRIND jest więc skok do adresu zawartego w rejestrze ADRESS. Teraz zostaną opisane w kolejności umieszczenia w CNTRLS procedury poszczególnych znaków kontrolnych.

3.3.3. Znaki kontrolne

    Znaki kontrolne są to znaki, które normalnie nie są wyświetlane na ekranie, lecz powodują wykonanie przez edytor jakiejś czynności. Umieszczenie znaku kontrolnego na ekranie (zamiast wykonywania) jest możliwe, gdy znacznik ESCFLG ma wartość $80 lub znacznik DSPFLG jest różny od zera.

    Pierwszym znakiem w tabeli CNTRLS jest właśnie znak Escape uzyskiwany przez naciśnięcie klawisza ESC. Powoduje on wpisanie wartości $80 do rejestru ESCFLG, czyli wyświetlenie następnego znaku nawet wtedy, gdy będzie to znak kontrolny.
            0100 ;ESCAPE key
            0110 ;
            0120 ESCFLG = $02A2
            0130 ;
            0140     *=  $F3E0
            0150 ;
            0160     LDA #$80
            0170     STA ESCFLG
            0180     RTS
    Naciśnięcie klawiszy CONTROL i - przesuwa kursor o jeden wiersz w górę (CRSUP), a klawiszy CONTROL i = o jeden w dół (CRSDWN). Jeżeli przedtem kursor znajdował się na krawędzi ekranu, to po tej operacji pojawia się na przeciwległej krawędzi. Procedura CRSUP zmniejsza rejestr pionowej pozycji kursora (ROWCRS), a gdy wynik jest ujemny, to wpisuje do niego liczbę wierszy ekranu (BOTSCR) zmniejszoną o jeden. Procedura CRSDWN zwiększa natomiast ROWCRS oraz porównuje go z BOTSCR i, gdy kursor znalazł się poza ekranem, to umieszcza go w wierszu zerowym. Oba warianty kończą się skokiem do procedury STRBEG.
            0100 BOTSCR = $02BF
            0110 ROWCRS = $54
            0120 STRBEG = $F90C
            0130 ;
            0140     *=  $F3E6
            0150 ;
            0160 ;CuRSor UP
            0170 ;
            0180     DEC ROWCRS
            0190     BPL EXIT
            0200     LDX BOTSCR
            0210     DEX
            0220 STORE STX ROWCRS
            0230 EXIT JMP STRBEG
            0240 ;
            0250 ;CuRSor DoWN
            0260 ;
            0270     INC ROWCRS
            0280     LDA ROWCRS
            0290     CMP BOTSCR
            0300     BCC EXIT
            0310     LDX #$00
            0320     BEQ STORE
    STRBEG oblicza aktualny wiersz logiczny, w którym znajduje się kursor, przez wywołanie procedury COMLOG i zapisuje współrzędne jego początku do rejestru BUFSTR.
            0100 ;SToRe BEGin
            0110 ;
            0120 BUFSTR = $6C
            0130 COMLOG = $F88E
            0140 HOLD1 = $51
            0150 LMARGN = $52
            0160 ;
            0170     *=  $F90C
            0180 ;
            0190     JSR COMLOG
            0200     LDA HOLD1
            0210     STA BUFSTR
            0220     LDA LMARGN
            0230     STA BUFSTR+1
            0240     RTS
    Naciśnięcie klawiszy CONTROL i + przesuwa kursor o jedno miejsce w lewo (CRSLFT), a klawiszy CONTROL i * o jedno w prawo (CRSRGT). Jeżeli przedtem kursor znajdował się na marginesie ekranu, to po tej operacji pojawia się na przeciwległym marginesie (niekoniecznie na krawędzi ekranu).
            0100 COLCRS = $55
            0110 COMLOG = $F88E
            0120 LMARGN = $52
            0130 RMARGN = $53
            0140 ;
            0150     *=  $F400
            0160 ;
            0170 ;CuRSor LeFT
            0180 ;
            0190     DEC COLCRS
            0200     LDA COLCRS
            0210     BMI CRSRMR
            0220     CMP LMARGN
            0230     BCS EXIT
            0240 ;
            0250 ;CuRSor to Right MaRgin
            0260 ;
            0270 CRSRMR LDA RMARGN
            0280 STORE STA COLCRS
            0290 EXIT JMP COMLOG
            0300 ;
            0310 ;CuRSor RiGhT
            0320 ;
            0330     INC COLCRS
            0340     LDA COLCRS
            0350     CMP RMARGN
            0360     BCC EXIT
            0370     BEQ EXIT
            0380 ;
            0390 ;CuRSor to Left MaRgin
            0400 ;
            0410 CRSLMR LDA LMARGN
            0420     JMP STORE
    Procedura CRSLFT zmniejsza rejestr poziomej pozycji kursora (COLCRS) oraz porównuje go z lewym marginesem ekranu (LMARGN). Gdy wartość marginesu jest większa od pozycji kursora, to jest on przenoszony na prawy margines. Natomiast CRSRGT zwiększa COLCRS i umieszcza kursor na lewym marginesie, gdy przekroczy on prawy (RMARGN). Dodatkowe dwa punkty wejścia do procedury oznaczają odpowiednio ustawienie kursora na lewym i prawym marginesie (jest to osiągane przez odpowiednią kombinację klawiszy w modelu 1200XL). We wszystkich przypadkach procedura kończy się skokiem do COMLOG.

    Kombinacja klawiszy CONTROL-CLEAR lub SHIFT-CLEAR oznacza czyszczenie ekranu i powoduje wywołanie procedury CLRSCR. Po odczytaniu adresu pamięci obrazu poprzez PUTMSC wypełnia ona zerami cały obszar od tego adresu do RAMTOP (dokładnie). Następnie kasowana jest mapa wierszy logicznych przez nadanie czterem bajtom LOGMAP wartości $FF.
            0100 ;CLeaR SCReen
            0110 ;
            0120 ADRESS = $64
            0130 BUFSTR = $6C
            0140 COLCRS = $55
            0150 LOGCOL = $63
            0160 LOGMAP = $02B2
            0170 PUTMSC = $F9A6
            0180 RAMTOP = $6A
            0190 ROWCRS = $54
            0200 SCLED = $F997
            0210 ;
            0220     *=  $F420
            0230 ;
            0240     JSR PUTMSC
            0250     LDY ADRESS
            0260     LDA #$00
            0270     STA ADRESS
            0280 LOOP STA (ADRESS),Y
            0290     INY
            0300     BNE LOOP
            0310     INC ADRESS+1
            0320     LDX ADRESS+1
            0330     CPX RAMTOP
            0340     BCC LOOP
            0350     LDA #$FF
            0360 NEXT STA LOGMAP,Y
            0370     INY
            0380     CPY #$04
            0390     BCC NEXT
            0400 ;
            0410 ;CuRSor HOMe
            0420 ;
            0430     JSR SCLED
            0440     STA LOGCOL
            0450     STA BUFSTR+1
            0460     LDA #$00
            0470     STA ROWCRS
            0480     STA COLCRS+1
            0490     STA BUFSTR
            0500     RTS
    Procedura CLRSCR nie kończy się przez RTS, lecz przechodzi bezpośrednio do procedury CRSHOM, która powoduje umieszczenie kursora w lewym, górnym rogu ekranu.

    Procedura CRSBS jest wywoływana po naciśnięciu klawisza Back Space. Jeżeli kursor znajduje się na pierwszym miejscu wiersza logicznego, to procedura jest przerywana skokiem do COMLOG. Jeśli jest to lewy margines, ale nie początek wiersza logicznego, to najniższa linia wiersza jest kasowana przez procedurę DELEML.
            0100 ;CuRSor BackSpace
            0110 ;
            0120 ATACHR = $02FB
            0130 COLCRS = $55
            0140 COMLOG = $F88E
            0150 CRSLFT = $F400
            0160 CRSUP = $F3E6
            0170 DELEML = $F923
            0180 LMARGN = $52
            0190 LOGCOL = $63
            0200 OUTPLT = $F1CA
            0210 RMARGN = $53
            0220 ROWCRS = $54
            0230 ;
            0240     *=  $F450
            0250 ;
            0260     LDA LOGCOL
            0270     CMP LMARGN
            0280     BEQ EXIT
            0290     LDA COLCRS
            0300     CMP LMARGN
            0310     BNE LFT
            0320     JSR DELEML
            0330 LFT JSR CRSLFT
            0340     LDA COLCRS
            0350     CMP RMARGN
            0360     BNE SPC
            0370     LDA ROWCRS
            0380     BEQ SPC
            0390     JSR CRSUP
            0400 SPC LDA #$20
            0410     STA ATACHR
            0420     JSR OUTPLT
            0430 EXIT JMP COMLOG
    Następnie wywoływana jest procedura CRSLFT, a gdy przeniesie ona kursor na prawy margines, to przez wywołanie CRSUP kursor przesuwany jest o jedną linię do góry. Na końcu w miejscu, w którym poprzednio znajdował się kursor umieszczona jest spacja (przez OUTPLT).

    Procedura CRSTAB realizująca naciśnięcie klawisza TAB wywołuje w pętli procedurę CRSRGT. Pętla jest przerywana po ustawieniu kursora na lewym marginesie lub po natrafieniu na ustawiony bit w mapie tabulacji (jest to sprawdzane przez procedurę BITGET). W pierwszym przypadku sprawdzany jest jeszcze poprzez RETURN i LOGGET początek nowego wiersza logicznego. Gdy kursor nie znajduje się na początku wiersza, to pętla jest kontynuowana. W przeciwnym razie oraz w drugim przypadku przerwania pętli następuje skok do COMLOG.
            0100 ;CuRSor TABulate
            0110 ;
            0120 BITGET = $F75D
            0130 COLCRS = $55
            0140 COMLOG = $F88E
            0150 CRSRGT = $F411
            0160 LMARGN = $52
            0170 LOGCOL = $63
            0180 LOGGET = $F758
            0190 RETURN = $F665
            0200 ;
            0210     *=  $F47A
            0220 ;
            0230 CRSTAB JSR CRSRGT
            0240     LDA COLCRS
            0250     CMP LMARGN
            0260     BNE BGT
            0270     JSR RETURN
            0280     JSR LOGGET
            0290     BCS EXIT
            0300 BGT LDA LOGCOL
            0310     JSR BITGET
            0320     BCC CRSTAB
            0330 EXIT JMP COMLOG
    Procedura DELLIN jest wywoływana przez naciśnięcie klawiszy SHIFT i DELETE. Usuwa ona z ekranu wiersz logiczny, w którym aktualnie znajduje się kursor. W tym celu wiersz jest przeliczany i kasowana jest odpowiednia liczba linii fizycznych. Procedura DELLIN kończy się skokiem do CRSLMR.
            0100 ;DELete LINe
            0110 ;
            0120 BITPUT = $F73C
            0130 COLCRS = $55
            0140 COMADR = $F82A
            0150 COMLOG = $F88E
            0160 CONVRT = $F5AC
            0170 CRSLMR = $F41B
            0180 HOLD1 = $51
            0190 LGET3 = $F75B
            0200 LOGGET = $F758
            0210 LOGMAP = $02B2
            0220 ROWCRS = $54
            0230 ;
            0240     *=  $F520
            0250 ;
            0260     JSR COMLOG
            0270     LDY HOLD1
            0280     STY ROWCRS
            0290 DELROW LDY ROWCRS
            0300 NEXT TYA
            0310     SEC
            0320     JSR LGET3
            0330     PHP
            0340     TYA
            0350     CLC
            0360     ADC #$78
            0370     PLP
            0380     JSR BITPUT
            0390     INY
            0400     CPY #$18
            0410     BNE NEXT
            0420     LDA LOGMAP+2
            0430     ORA #$01
            0440     STA LOGMAP+2
            0450     LDA #$00
            0460     STA COLCRS
            0470     JSR CONVRT
            0480     JSR COMADR
            0490     JSR LOGGET
            0500     BCC DELROW
            0510     JMP CRSLMR
    Do dokonania zmian w mapie tabulacji TABMAP wykorzystywana jest procedura BITPUT. Po zamianie znaku na wzór bitowy przez BITCON umieszcza ona określony bit w rejestrze TABMAP.
            0100 ;BIT PUT
            0110 ;
            0120 BITCLR = $F74A
            0130 BITCON = $F723
            0140 BITMSK = $6E
            0150 TABMAP = $02A3
            0160 ;
            0170     *=  $F73C
            0180 ;
            0190     BCC BITCLR
            0200 BITPT2 JSR BITCON
            0210     LDA TABMAP,X
            0220     ORA BITMSK
            0230     STA TABMAP,X
            0240     RTS
    Jeżeli przed rozpoczęciem procedury BITPUT zostanie skasowany bit Carry, to zamiast ustawiania bitu jest on kasowany przez procedurę BITCLR. Przebieg obu procedur jest podobny, z tą różnicą, że jedna dodaje bit do maski tabulacji, a druga odejmuje.
            0100 ;BIT CLeaR
            0110 ;
            0120 BITCON = $F723
            0130 BITMSK = $6E
            0140 TABMAP = $02A3
            0150 ;
            0160     *=  $F74A
            0170 ;
            0180     JSR BITCON
            0190     LDA BITMSK
            0200     EOR #$FF
            0210     AND TABMAP,X
            0220     STA TABMAP,X
            0230     RTS
    Procedura INSLIN dokonuje operacji odwrotnej do DELLIN - wstawia wiersz logiczny na aktualnej pozycji kursora (klawisze SHIFT i INSERT). Przeprowadzane jest to prawie wyłącznie przez wywołania innych procedur.
            0100 ;INSert LINe
            0110 ;
            0120 CLRLIN = $F7E2
            0130 COLCRS = $55
            0140 COMLOG = $F88E
            0150 CONVRT = $F5AC
            0160 EXTEND = $F7C2
            0170 LININS = $F78E
            0180 LMARGN = $52
            0190 ;
            0200     *=  $F50C
            0210 ;
            0220     SEC
            0230 INSLN2 JSR EXTEND
            0240     LDA LMARGN
            0250     STA COLCRS
            0260     JSR CONVRT
            0270     JSR LININS
            0280     JSR CLRLIN
            0290     JMP COMLOG
    Najpierw wywoływana jest procedura EXTEND, która dokonuje zmian w mapie tabulacji (przez BITPUT) i mapie wierszy logicznych (przez LOGGET).

            0100 ;EXTEND logical line
            0110 ;
            0120 BITPUT = $F73C
            0130 LGET2 = $F75A
            0140 ROWCRS = $54
            0150 ;
            0160     *=  $F7C2
            0170 ;
            0180     PHP
            0190     LDY #$16
            0200 LOOP TYA
            0210     JSR LGET2
            0220     PHP
            0230     TYA
            0240     CLC
            0250     ADC #$79
            0260     PLP
            0270     JSR BITPUT
            0280     DEY
            0290     BMI EXIT
            0300     CPY ROWCRS
            0310     BCS LOOP
            0320 EXIT LDA ROWCRS
            0330     CLC
            0340     ADC #$78
            0350     PLP
            0360     JMP BITPUT
    Następnie procedura LININS przesuwa zawartość pamięci obrazu o jeden wiersz, tworząc na pozycji kursora miejsce na nową linię.
            0100 ;LINe INSert
            0110 ;
            0120 BOTSCR = $02BF
            0130 MLTTMP = $66
            0140 RAMTOP = $6A
            0150 ROWCRS = $54
            0160 SAVADR = $68
            0170 ;
            0180     *=  $F78D
            0190 ;
            0200 EXIT RTS
            0210 LININS LDX RAMTOP
            0220     DEX
            0230     STX SAVADR+1
            0240     STX MLTTMP+1
            0250     LDA #$B0
            0260     STA SAVADR
            0270     LDA #$D8
            0280     STA MLTTMP
            0290     LDX ROWCRS
            0300 LOOP INX
            0310     CPX BOTSCR
            0320     BEQ EXIT
            0330     LDY #$27
            0340 NXT2 LDA (SAVADR),Y
            0350     STA (MLTTMP),Y
            0360     DEY
            0370     BPL NXT2
            0380     SEC
            0390     LDA SAVADR
            0400     STA MLTTMP
            0410     SBC #$28
            0420     STA SAVADR
            0430     LDA SAVADR+1
            0440     STA MLTTMP+1
            0450     SBC #$00
            0460     STA SAVADR+1
            0470     JMP LOOP
    Na zakończenie procedura CLRLIN wypełnia nowoutworzoną linię zerami. Ponieważ zerowanie jest wykonywane od lewego do prawego marginesu, to na ekranie pozostaną znaki znajdujące się poza marginesami.
            0100 ;CLeaR LINe
            0110 ;
            0120 ADRESS = $64
            0130 COLCRS = $55
            0140 CONVRT = $F5AC
            0150 LMARGN = $52
            0160 RMARGN = $53
            0170 ;
            0180     *=  $F7E2
            0190 ;
            0200     LDA LMARGN
            0210     STA COLCRS
            0220     JSR CONVRT
            0230     SEC
            0240     LDA RMARGN
            0250     SBC LMARGN
            0260     TAY
            0270     LDA #$00
            0280 NEXT STA (ADRESS),Y
            0290     DEY
            0300     BPL NEXT
            0310     RTS
    Procedura CRSCTB obsługuje kombinację klawiszy CONTROL i TAB. Powoduje ona skasowanie punktu tabulacji na aktualnej pozycji kursora.
            0100 ;CuRSor Clear TaBulate
            0110 ;
            0120 BITCLR = $F74A
            0130 LOGCOL = $63
            0140 ;
            0150     *=  $F49A
            0160 ;
            0170     LDA LOGCOL
            0180     JMP BITCLR
    Operacja odwrotna - ustawienie tabulacji na pozycji kursora (klawisze SHIFT i TAB) jest wykonywana przez procedurę CRSSTB.
            0100 ;CuRSor Set TaBulate
            0110 ;
            0120 BITPT2 = $F73E
            0130 LOGCOL = $63
            0140 ;
            0150     *=  $F495
            0160 ;
            0170     LDA LOGCOL
            0180     JMP BITPT2
    Kombinacja klawiszy CONTROL-2 powoduje wywołanie procedury BELL. Jest ona także wywoływana dla zasygnalizowania końca wiersza logicznego. Przez wywołanie 32 razy procedury KEYCLK uzyskiwany jest tu dźwięk brzęczyka.
            0100 ;BELL
            0110 ;
            0120 KEYCLK = $F983
            0130 ;
            0140     *=  $F556
            0150 ;
            0160     LDY #$20
            0170 LOOP JSR KEYCLK
            0180     DEY
            0190     BPL LOOP
            0200     RTS
    Procedura DELCHR usuwa znak znajdujący się pod kursorem i przesuwa o jedno miejsce w lewo wszystkie znaki z prawej strony kursora w danym wierszu logicznym. W miejscu ostatniego znaku wstawiana jest przez procedurę GETPLT wartość zero. Na czas wykonywania tych operacji pozycja kursora jest zapamiętywana poprzez wywołanie PHACRS i potem odtwarzana przez PLACRS.
            0100 ;DELete CHaRacter
            0110 ;
            0120 ADRESS = $64
            0130 BOTSCR = $02BF
            0140 CONVRT = $F5AC
            0150 COMLOG = $F88E
            0160 DELTIE = $F918
            0170 GETPLT = $F18F
            0180 INCRSB = $F60A
            0190 LOGCOL = $63
            0200 PHACRS = $F94C
            0210 PLACRS = $F957
            0220 ROWCRS = $54
            0230 SAVADR = $68
            0240 ;
            0250     *=  $F4D5
            0260 ;
            0270     JSR PHACRS
            0280 LOOP JSR CONVRT
            0290     LDA ADRESS
            0300     STA SAVADR
            0310     LDA ADRESS+1
            0320     STA SAVADR+1
            0330     LDA LOGCOL
            0340     PHA
            0350     JSR INCRSB
            0360     PLA
            0370     CMP LOGCOL
            0380     BCS EXIT
            0390     LDA ROWCRS
            0400     CMP BOTSCR
            0410     BCS EXIT
            0420     JSR GETPLT
            0430     LDY #$00
            0440     STA (SAVADR),Y
            0450     BEQ LOOP
            0460 EXIT LDY #$00
            0470     TYA
            0480     STA (SAVADR),Y
            0490     JSR DELTIE
            0500     JSR PLACRS
            0510     JMP COMLOG
    Ponieważ przesunięcie znaków w lewo może spowodować opróżnienie ostatniej linii wiersza logicznego, to wywoływana jest procedura DELTIE, która sprawdza ten przypadek. Jeżeli ostatnia linia jest pusta, to zostaje skasowana i procedura kończy się skokiem do DELROW. W przeciwnym wypadku po RTS następuje powrót do DELCHR. Procedura ta jest także wykorzystywana przez CRSBS, lecz od etykiety DELEML.
            0100 ;DELeTe If Empty
            0110 ;
            0120 ADRESS = $64
            0130 COMLOG = $F88E
            0140 CONVRT = $F5AC
            0150 DELROW = $F527
            0160 LMARGN = $52
            0170 LOGCOL = $63
            0180 RMARGN = $53
            0190 ROWCRS = $54
            0200 ;
            0210     *=  $F917
            0220 ;
            0230 EXIT RTS
            0240 DELTIE LDA LOGCOL
            0250     CMP LMARGN
            0260     BNE BPS
            0270     DEC ROWCRS
            0280 BPS JSR COMLOG
            0290 ;
            0300 ;DELete EMpty Line
            0310 ;
            0320 DELEML LDA LOGCOL
            0330     CMP LMARGN
            0340     BEQ EXIT
            0350     JSR CONVRT
            0360     LDA RMARGN
            0370     SEC
            0380     SBC LMARGN
            0390     TAY
            0400 LOOP LDA (ADRESS),Y
            0410     BNE EXIT
            0420     DEY
            0430     BPL LOOP
            0440     JMP DELROW
    Odwrotną operację - wstawienia znaku na pozycji kursora i przesunięcia pozostałych znaków o jedno miejsce w prawo - wykonuje procedura INSCHR. Jest to uzyskiwane przez naciśnięcie klawiszy CONTROL i INSERT.
            0100 ;INSert CHaRacter
            0110 ;
            0120 COMLOG = $F88E
            0130 DISPLY = $F1E9
            0140 GETPLT = $F18F
            0150 INSDAT = $7D
            0160 LOGCOL = $63
            0170 PHACRS = $F94C
            0180 PLACRS = $F957
            0190 ROWCRS = $54
            0200 SCRFLG = $02BB
            0210 SCRIBT = $F612
            0220 ;
            0230     *=  $F49F
            0240 ;
            0250     JSR PHACRS
            0260     JSR GETPLT
            0270     STA INSDAT
            0280     LDA #$00
            0290     STA SCRFLG
            0300 LOOP JSR DISPLY
            0310     LDA LOGCOL
            0320     PHA
            0330     JSR SCRIBT
            0340     PLA
            0350     CMP LOGCOL
            0360     BCS FND
            0370     LDA INSDAT
            0380     PHA
            0390     JSR GETPLT
            0400     STA INSDAT
            0410     PLA
            0420     JMP LOOP
            0430 FND JSR PLACRS
            0440 NEXT DEC SCRFLG
            0450     BMI EXIT
            0460     DEC ROWCRS
            0470     BNE EXIT
            0480 EXIT JMP COMLOG
    System operacyjny zawiera jeszcze jedną procedurę - BTMLIN, której nie odpowiada żaden znak kontrolny. Jedynie w modelu 1200XL wywołuje ją kombinacja SHIFT-F2. Składa się ona tylko z wywołania CRSHOM i skoku do CRSUP.
            0100 ;BoTtoM LINe
            0110 ;
            0120 CRSHOM = $F440
            0130 CRSUP = $F3E6
            0140 ;
            0150     *=  $F55F
            0160 ;
            0170     JSR CRSHOM
            0180     JMP CRSUP

3.3.4. Odczyt z edytora

    Odczyt znaku z edytora jest przeprowadzany przez procedurę EGETCH. Oczywiście na początku przełącza ona kursor przez wywołanie SWAP i sprawdza jego pozycję poprzez ERANGE. Następnie sprawdzany jest licznik bufora BUFCNT (BUFfer CouNTer). Jeśli jest on różny od zera, to wykonywany jest skok do końcowej fazy procedury.

    W przeciwnym razie do rejestru wskazującego początek bufora (BUFSTR) przepisywane są wartości z ROWCRS i COLCRS. Teraz rozpoczyna się pętla odczytu z klawiatury. Po wywołaniu procedury KBGBYT zwrócony przez nią status operacji jest zapisywany do DSTAT, a odczytany znak jest porównymany z $9B (kod RETURN). Wykrycie znaku RETURN przerywa pętlę odczytu. Każdy inny znak powoduje kolejno wywołanie procedur PRCCHR i SWAP. Jeżeli został przy tym przekroczony 114 znak wiersza logicznego, to wywoływana jest procedura BELL w celu wygenerowania sygnału ostrzegawczego. Dalej pętla odczytu jest powtarzana.

    Po przerwaniu odczytu przez znak RETURN, kursor wyłączany jest procedurą OFFCRS i wywoływana jest procedura DOBUFC. Po obliczeniu przez nią chwilowej długości bufora bajty BUFSTR są przepisywane ponownie do ROWCRS i COLCRS. Następnie długość bufora jest zmniejszana i jeśli status (w DSTAT) jest mniejszy od $80, to po wywołaniu GETCH i zapisaniu odczytanego znaku do rejestru ATACHR procedura kończy się skokiem do SWAP. Przy statusie większym od $7F długość bufora jest zmniejszana do zera.

    Zerowa długość bufora powoduje wywołanie procedury RTWSCR i zapisanie do rejestru ATACHR znaku RETURN ($9B). Następnie wywoływana jest procedura RETURM i, po zapisaniu uzyskanego przez nią statusu do DSTAT, wykonywany jest skok do procedury SWAP.
            0100 ;Editor GET CHaracter
            0110 ;
            0120 ADRESS = $64
            0130 ATACHR = $02FB
            0140 BELL =  $F556
            0150 BUFCNT = $6B
            0160 BUFSTR = $6C
            0170 COLCRS = $55
            0180 DOBUFC = $F8B1
            0190 DSTAT = $4C
            0200 ERANGE = $F6BC
            0210 GETCH = $F180
            0220 KBGBYT = $F2FD
            0230 LOGCOL = $63
            0240 OFFCRS = $F718
            0250 PRCCHR = $F2BE
            0260 RETURM = $F20B
            0270 ROWCRS = $54
            0280 RTWSCR = $F661
            0290 SWAP =  $F962
            0300 ;
            0310     *=  $F24A
            0320 ;
            0330     JSR SWAP
            0340     JSR ERANGE
            0350     LDA BUFCNT
            0360     BNE CBF
            0370     LDA ROWCRS
            0380     STA BUFSTR
            0390     LDA COLCRS
            0400     STA BUFSTR+1
            0410 GET JSR KBGBYT
            0420     STY DSTAT
            0430     LDA ATACHR
            0440     CMP #$9B
            0450     BEQ EOL
            0460     JSR PRCCHR
            0470     JSR SWAP
            0480     LDA LOGCOL
            0490     CMP #$71
            0500     BNE BPS
            0510     JSR BELL
            0520 BPS JMP GET
            0530 EOL JSR OFFCRS
            0540     JSR DOBUFC
            0550     LDA BUFSTR
            0560     STA ROWCRS
            0570     LDA BUFSTR+1
            0580     STA COLCRS
            0590 CBF LDA BUFCNT
            0600     BEQ RET
            0610 NXT DEC BUFCNT
            0620     BEQ RET
            0630     LDA DSTAT
            0640     BMI NXT
            0650     JSR GETCH
            0660     STA ATACHR
            0670     JMP SWAP
            0680 RET JSR RTWSCR
            0690     LDA #$9B
            0700     STA ATACHR
            0710     JSR RETURM
            0720     STY DSTAT
            0730     JMP SWAP
    Wywoływana przez EGETCH procedura DOBUFC służy do obliczenia chwilowej długości aktualnego bufora edytora, a więc wiersza, w którym znajduje się kursor. W tym celu najpierw przez procedurę PHACRS zapamiętywana jest pozycja kursora, a zawartość rejestru LOGCOL jest odkładana na stos. Następnie do rejestrów ROWCRS i COLCRS przepisywana jest zawartość BUFSTR, licznik bufora BUFCNT otrzymuje wartość 1 i rozpoczyna się pętla obliczająca.

    Do rejestru X wpisywany jest maksymalny numer wiersza - 23 dla całego ekranu lub 3 dla okna tekstowego. Jeżeli kursor znajduje się na prawym marginesie ostatniej linii, to licznik jest zwiększany o jeden i pętla jest opuszczana. W przeciwnym razie licznik jest zwiększany dopiero po wywołaniu procedury INCRSB. Jeśli teraz adres kursora w wierszu logicznym jest różny od lewego marginesu, to następuje powtórzenie pętli. Jeśli nie, to kursor jest przesuwany na koniec poprzedniej linii fizycznej i pętla się kończy.
            0100 ;DO BUFfer Count
            0110 ;
            0120 BUFCNT = $6B
            0130 BUFSTR = $6C
            0140 COLCRS = $55
            0150 CRSLFT = $F400
            0160 GETPLT = $F18F
            0170 INCRSB = $F60A
            0180 LMARGN = $52
            0190 LOGCOL = $63
            0200 PHACRS = $F94C
            0210 PLACRS = $F957
            0220 RMARGN = $53
            0230 ROWCRS = $54
            0240 SWPFLG = $7B
            0250 ;
            0260     *=  $F8B1
            0270 ;
            0280     JSR PHACRS
            0290     LDA LOGCOL
            0300     PHA
            0310     LDA BUFSTR
            0320     STA ROWCRS
            0330     LDA BUFSTR+1
            0340     STA COLCRS
            0350     LDA #$01
            0360     STA BUFCNT
            0370 LOOP LDX #$17
            0380     LDA SWPFLG
            0390     BPL ROW
            0400     LDX #$03
            0410 ROW CPX ROWCRS
            0420     BNE ISB
            0430     LDA COLCRS
            0440     CMP RMARGN
            0450     BNE ISB
            0460     INC BUFCNT
            0470     JMP GET
            0480 ISB JSR INCRSB
            0490     INC BUFCNT
            0500     LDA LOGCOL
            0510     CMP LMARGN
            0520     BNE LOOP
            0530     DEC ROWCRS
            0540     JSR CRSLFT
            0550 GET JSR GETPLT
            0560     BNE EXIT
            0570     DEC BUFCNT
            0580     LDA LOGCOL
            0590     CMP LMARGN
            0600     BEQ EXIT
            0610     JSR CRSLFT
            0620     LDA COLCRS
            0630     CMP RMARGN
            0640     BNE LBC
            0650     DEC ROWCRS
            0660 LBC LDA BUFCNT
            0670     BNE GET
            0680 EXIT PLA
            0690     STA LOGCOL
            0700     JMP PLACRS
    Teraz rozpoczyna się druga pętla, w której wywoływana jest procedura GETPLT i zmniejsza się stan licznika. Jest ona przerywana po znalezieniu znaku innego niż spacja, po osiągnięciu początku wiersza logicznego lub po wyzerowaniu licznika. Procedura DOBUFC kończy się odtworzeniem ze stosu wartości LOGCOL i skokiem do PLACRS dla odtworzenia pozycji kursora.

3.4. Procedury obsługi drukarki

    Drukarka jest urządzeniem wyjścia, z którym komunikacja odbywa się przez złącze szeregowe komputera, a więc za pośrednictwem procedur SIO. Tabela adresowa PRTVEC zawiera następujące wektory procedur obsługi:
         OPEN     - PROPN
         CLOSE    - PRCLS
         GET      - PRRDSP
         PUT      - PRWRT
         STATUS   - PRSTAT
         SPECIAL  - PRRDSP
    Kolejność opisu przyjęta dla tych procedur odbiega zarówno od porządku powyższej listy, jak i od kolejności ich wykorzystywania. Umożliwia to jednak łatwiejsze ich zrozumienie i upraszcza analizę.

3.4.1. Zapis na drukarkę

    Podstawową czynnością wykonywaną na drukarce jest zapis danych. Procedura CIO wywołuje do przeprowadzenia tej operacji procedurę PRWRT.

    Na początku, po umieszczeniu na stosie znaku do zapisania, odtwarzany jest numer urządzenia z odpowiedniego rejestru ICDNO. Następnie wywoływana jest procedura PRMODE ustalająca tryb pracy drukarki. Teraz zawartość licznika PBPNT (PRinter Buffer PoiNTer) przepisywana jest do rejestru X i według niej odtworzony ze stosu znak jest umieszczany w buforze drukarki PRNBUF (PRiNter BUFfer). Po zwiększeniu licznika jest on porównywany z zapisaną w rejestrze PBUFSZ (Printer BUFfer SiZe) długością bufora.

    Gdy bufor nie został jeszcze zapełniony, to sprawdzany jest kod zapisywanego znaku. Jeśli nie jest to RETURN ($9B), to po wpisaniu do rejestru Y wartości 1 (SUCCESS) procedura się kończy rozkazem RTS. Znak RETURN powoduje natomiast wypełnienie całej pozostałej części bufora znakiem spacji.

    Po zapełnieniu bufora licznik PBPNT jest zerowany, a do rejestrów X i Y wpisywany jest odpowiednio młodszy i starszy bajt adresu bufora. Adres ten jest oznaczony etykietą PRCHAR i zapisany w pamięci ROM. Z tego powodu przeniesienie bufora drukarki jest możliwe tylko po zmianie procedury PRWRT. Teraz procedura kończy się wywołaniem SETDCB, która ustala parametry dla operacji SIO i skokiem do głównej procedury SIO poprzez JSIOINT.
            0100 ;PRinter WRiTe
            0110 ;
            0120 ICDNO = $0341
            0130 ICDNOZ = $21
            0140 JSIOINT = $E459
            0150 PBPNT = $02DE
            0160 PBUFSZ = $02DF
            0170 PRMODE = $FF4B
            0180 PRNBUF = $03C0
            0190 SETDCB = $FF14
            0200 ;
            0210     *=  $FEA1
            0220 ;
            0230 PRCHAR .WORD PRNBUF
            0240 ;
            0250     *=  $FECB
            0260 ;
            0270 PRWRT PHA
            0280     LDA ICDNO,X
            0290     STA ICDNOZ
            0300     JSR PRMODE
            0310     LDX PBPNT
            0320     PLA
            0330     STA PRNBUF,X
            0340     INX
            0350     CPX PBUFSZ
            0360     BEQ PPPUT
            0370     STX PBPNT
            0380     CMP #$9B
            0390     BEQ SPC
            0400     LDY #$01
            0410     RTS
            0420 SPC LDA #$20
            0430 ;
            0440 ;Fill Printer BUFfre
            0450 ;
            0460 FPBUF STA PRNBUF,X
            0470     INX
            0480     CPX PBUFSZ
            0490     BNE FPBUF
            0500 PPPUT LDA #$00
            0510     STA PBPNT
            0520     LDX PRCHAR
            0530     LDY PRCHAR+1
            0540     JSR SETDCB
            0550     JMP JSIOINT
    Procedura PRMODE służy do ustalenia trybu pracy drukarki i związanej z nim długości bufora. Najpierw do rejestru Y wpisywana jest wartość $57, która oznacza rozkaz PUT WITH VERIFY (zapis z weryfikacją). Następnie odczytywana jest zawartość rejestru ICAX2 i kolejno porównywana z ustalonymi wartościami. Gdy jest ona równa $4E (78), to do rejestru X wpisywane jest $28. Gdy jest równa $44 (68), to rejestr X otrzymuje wartość $14, a gdy $53 (83), to wartość $1D. Jeśli zawartość ICAX2 nie odpowiada żadnej z wymienionych liczb, to przyjmowana jest wartość $4E.

    Teraz zawartość rejestru X zostaje przepisana do PBUFSZ, rejestru Y do DCMND (Device CoMmaND), a akumulatora do DAUX1 (Device AUXiliary 1) i procedura się kończy.

    Wyjaśnienia wymagają jeszcze kontrolowane wartości z rejestru ICAX2. Określają one rodzaj druku, który ma być zastosowany przez drukarkę. Wartość $4E oznacza druk normalny (10 znaków na cal), $44 - druk szeroki (5 znaków na cal), a $53 - druk znakami obróconymi o 90°. Niestety wszystkie te parametry dotyczą drukarki Atari 1020 i nie są rozpoznawane przez drukarkę Atari 1029. Jako ciekawostkę można natomiast dodać, że Atari 1029 reaguje na wywołanie jako urządzenia "P1:" (lub po prostu "P:") oraz jako "P6:"!
            0100 ;PRinter MODE
            0110 ;
            0120 DAUX1 = $030A
            0130 DCMND = $0302
            0140 ICAX2Z = $2B
            0150 PBUFSZ = $02DF
            0160 ;
            0170     *=  $FF4B
            0180 ;
            0190     LDY #$57
            0200     LDA ICAX2Z
            0210 NRM CMP #$4E
            0220     BNE WID
            0230     LDX #$28
            0240     BNE EXIT
            0250 WID CMP #$44
            0260     BNE SDW
            0270     LDX #$14
            0280     BNE EXIT
            0290 SDW CMP #$53
            0300     BNE STN
            0310     LDX #$1D
            0320 EXIT STX PBUFSZ
            0330     STY DCMND
            0340     STA DAUX1
            0350     RTS
            0360 STN LDA #$4E
            0370     BNE NRM
    Procedury PRWRT i PRSTAT (opisana dalej) wywołują procedurę SETDCB. Służy ona do ustalenia parametrów w bloku kontroli urządzeń DCB (Device Control Block). Jest to konieczne przed wywołaniem procedury SIO, tak jak przed wywołaniem CIO trzeba ustawić parametry w IOCB. Dokładny opis bloku DCB oraz znaczenia poszczególnych jego rejestrów znajduje się w rozdziale 4.1. (str. 115). Tu zajmiemy się tylko procedurą SETDCB bez rozpatrywania szczegółowego znaczenia przekazywanych wartości.
            0100 ;SET Device Control Block
            0110 ;
            0120 DBUFA = $0304
            0130 DBYT =  $0308
            0140 DCMND = $0302
            0150 DDEVIC = $0300
            0160 DSTATS = $0303
            0170 DTIMLO = $0306
            0180 DUNIT = $0301
            0190 ICDNOZ = $21
            0200 PBUFSZ = $02DF
            0210 PTIMOT = $0314
            0220 ;
            0230     *=  $FF14
            0240 ;
            0250     STX DBUFA
            0260     STY DBUFA+1
            0270     LDA #$40
            0280     STA DDEVIC
            0290     LDA ICDNOZ
            0300     STA DUNIT
            0310     LDA #$80
            0320     LDX DCMND
            0330     CPX #$53
            0340     BNE NST
            0350     LDA #$40
            0360 NST STA DSTATS
            0370     LDA PBUFSZ
            0380     STA DBYT
            0390     LDA #$00
            0400     STA DBYT+1
            0410     LDA PTIMOT
            0420     STA DTIMLO
            0430     RTS
    Umieszczony przed wywołaniem SETDCB w rejestrach X i Y adres bufora jest najpierw przepisywany do DBUFA (Device BUFfer Address). Potem kolejno: w DDEVIC umieszczany jest kod drukarki ($40); w DUNIT - jej numer z ICDNOZ, w DSTATS kod zapisu $80, a przy żądaniu statusu - kod odczytu $40; w DBYT - długość bufora z PBUFSZ i w DTIMLO - czas oczekiwania na odpowiedź z PTIMOT.

3.4.2. Odczyt statusu drukarki

    Odczyt statusu drukarki jest jedyną operacją, podczas której komputer otrzymuje dane od drukarki. Status drukarki jest zawarty w czterech bajtach umieszczanych po odczycie w rejestrze DVSTAT (DeVice STATus). Wykonywane jest to przez procedurę PRSTAT. Jest ona w ogólnym zarysie podobna do PRWRT. Najpierw ustawia na cztery bajty długość bufora i umieszcza w rejestrach X i Y jego adres (również pobrany z pamięci ROM). Potem po wpisaniu do DCMND i DAUX1 kodu $53 (odczyt statusu) wywołuje kolejno procedury SETDCB i SIOINT.

    Gdy po zakończeniu procedury SIO sygnalizowany jest błąd, to PRSTAT się kończy. W przeciwnym razie wywoływana jest jeszcze procedura PRPUT.
            0100 ;PRinter STATus
            0110 ;
            0120 DAUX1 = $030A
            0130 DCMND = $0302
            0140 DVSTAT = $03EA
            0150 JSIOINT = $E459
            0160 PBUFSZ = $02DF
            0170 PRPUT = $FF44
            0180 SETDCB = $FF14
            0190 ;
            0200     *=  $FE9F
            0210 ;
            0220 PRSTAD .WORD DVSTAT
            0230 ;
            0240     *=  $FEA3
            0250 ;
            0260 PRSTAT LDA #$04
            0270     STA PBUFSZ
            0280     LDX PRSTAD
            0290     LDY PRSTAD+1
            0300     LDA #$53
            0310     STA DCMND
            0320     STA DAUX1
            0330     JSR SETDCB
            0340     JSR JSIOINT
            0350     BMI PRRDSP
            0360     JSR PRPUT
            0370 ;
            0380 ;PRinter ReaD/SPecial
            0390 ;
            0400 PRRDSP RTS
    Trzeci bajt odczytanego adresu (DVTMOT - DeVice TiMe OuT) zawiera rzeczywistą wartość czasu oczekiwania na odpowiedź (dla konkretnego typu drukarki). Procedura PRPUT przepisuje tą wartość do rejestru PTIMOT (Printer TIMeOuT) zastępując w nim wartość ustaloną podczas inicjowania drukarki.
            0100 ;PRinter PUT
            0110 ;
            0120 DVTMOT = $02EC
            0130 PTIMOT = $0314
            0140 ;
            0150     *=  $FF44
            0160 ;
            0170     LDA DVTMOT
            0180     STA PTIMOT
            0190     RTS
    Kończący procedurę odczytu statusu rozkaz RTS jest oznaczony etykietą PRRDSP. System operacyjny nie przewiduje dla drukarki operacji odczytu i operacji specjalnych. Wywołanie którejkolwiek z nich powoduje więc natychmiastowy powrót do CIO. W rezultacie rejestr Y zawiera kod błędu $92 (zob. opis procedury GOHAND - str. 24).

3.4.3. Pozostałe procedury drukarki

    Nie zostały jeszcze opisane dwie procedury rozpoczynające (PROPN) i kończące (PRCLS) współpracę komputera z drukarką. Wykorzystują one wcześniej opisane procedury i z tego powodu zostały umieszczone na końcu.

    Procedura PROPN otwierająca kanał komunikacji z drukarką wywołuje jedynie procedurę PRSTAT i zeruje licznik bufora PBPNT. Dzięki temu uaktualniona zostaje wartość Timeout. Warto zauważyć, że otwarcie drukarki zawsze zeruje jej bufor. Przy jednoczesnej pracy z dwoma drukarkami (lub drukarką i plotterem) należy kanały dla obu urządzeń otwierać przed rozpoczęciem transmisji, gdyż inaczej można utracić część informacji.
            0100 ;PRinter OPeN
            0110 ;
            0120 PBPNT = $02DE
            0130 PRSTAT = $FEA3
            0140 ;
            0150     *=  $FEC2
            0160 ;
            0170     JSR PRSTAT
            0180     LDA #$00
            0190     STA PBPNT
            0200     RTS
    Procedura zamykająca kanał komunikacji z drukarką (PRCLS) musi zapewniać wydrukowanie wszystkich danych umieszczonych przedtem w buforze. W tym celu, po wywołaniu PRMODE, w akumulatorze umieszczany jest kod RETURN i wykonywany jest skok do procedury FPBUF (jest to część PRWRT). Powoduje to wypełnienie pustej części bufora znakami RETURN i wysłanie całej jego zawartości do drukarki. Jeżeli licznik PBPNT wskazywał pusty bufor, to zamiast skoku do FPBUF w rejestrze Y umieszczana jest wartość 1 i procedura się kończy.
            0100 ;PRinter CLoSe
            0110 ;
            0120 FPBUF = $FEED
            0130 PBPNT = $02DE
            0140 PRMODE = $FF4B
            0150 ;
            0160     *=  $FE07
            0170 ;
            0180     JSR PRMODE
            0190     LDA #$9B
            0200     LDX PBPNT
            0210     BNE FPBUF
            0220     LDY #$01
            0230     RTS

3.5. Procedury obsługi magnetofonu

    Magnetofon jest urządzeniem wejścia i wyjścia służącym jako pamięć masowa, to znaczy do przechowywania dużej ilości informacji (programów i danych). Komunikacja z magnetofonem odbywa się przez złącze szeregowe, a więc także za pośrednictwem SIO. Tabela adresowa CASVEC zawiera wektory, które wskazują na następujące procedury:
         OPEN     - CASOPN
         CLOSE    - CASCLS
         GET      - CASRDBT
         PUT      - CASWRT
         STATUS   - CASST
         SPECIAL  - CASSP
    Dla magnetofonu nie przewiduje się operacji specjalnych, Etykietą CASSP jest oznaczony tylko rozkaz RTS w procedurze CASINIT. W wyniku wywołania tej operacji otrzymamy więc jedynie kod błędu FUNCTION NOT IMPLEMENTED.

    Ponieważ magnetofon nie jest urządzeniem "inteligentnym", tj. nie posiada własnego układu sterującego (procesora), to procedury obsługi nie mogą żądać żadnych sygnałów dodatkowych. System operacyjny zakłada więc, że magnetofon jest stale dołączony i gotowy do pracy. Z takiego założenia wynika procedura CASST, która na żądanie statusu zawsze zwraca w rejestrze Y wartość 1 (SUCCESS).
            0100 ;CASsette STatus
            0110 ;
            0120     *=  $FDCC
            0130 ;
            0140     LDY #$01
            0150     RTS

3.5.1. Otwarcie magnetofonu

    Przed otwarciem kanału dla magnetofonu należy określić w rejestrze ICAX1 sposób dostępu ($04 - odczyt, $08 zapis) oraz w rejestrze ICAX2 rodzaj przerw między rekordami na kasecie ($00 - długie, $80 - krótkie). Następnie po przejściu do CIO wywoływana jest procedura CASOPN.

    Na początku, po przeniesieniu zawartości ICAX2 do rejestru GAPTYP, sprawdzany jest sposób dostępu. Wartość $04 powoduje skok do etykiety CASOPIN, $08 - do COPOUT, a każda inna kończy procedurę przez RTS - wynikiem jest więc błąd FUNCTION NOT IMPLEMENTED.

    Schemat przebiegu obu wariantów procedury jest bardzo zbliżony. Różnice występują przede wszystkim w wartościach wpisywanych do rejestrów. Dokładnie będzie więc opisany odczyt z magnetofonu, a następnie podane zostaną różnice występujące przy zapisie.

    W fazie przygotowawczej ustawiane są na zero znaczniki WMODE i FEOF. Potem z wartością $01 w akumulatorze wywoływana jest procedura BPWT, która oczekuje na naciśnięcie klawisza. Negatywny wynik tej procedury powoduje przerwanie CASOPN.
            0100 ;CASsette OPeN
            0110 ;
            0120 AUDF3 = $D204
            0130 AUDF4 = $D206
            0140 BLIM =  $028A
            0150 BPTR =  $3D
            0160 BPWT =  $FDFC
            0170 DDEVIC = $0300
            0180 FEOF =  $3F
            0190 GAPTYP = $3E
            0200 ICAX1Z = $2A
            0210 ICAX2Z = $2B
            0220 IRQSTAT = $11
            0230 JSETVBV = $E45C
            0240 JSNDENB = $E468
            0250 PACTL = $D302
            0260 PALNTS = $62
            0270 TABCAS = $FE8D
            0280 TIMFLG3 = $022A
            0290 WMODE = $0289
            0300 ;
            0310     *=  $FCE6
            0320 ;
            0330     LDA ICAX2Z
            0340     STA GAPTYP
            0350     LDA ICAX1Z
            0360     AND #$0C
            0370     CMP #$04
            0380     BEQ CASOPIN
            0390     CMP #$08
            0400     BEQ COPOUT
            0410     RTS
            0420 CASOPIN LDA #$00
            0430     STA WMODE
            0440     STA FEOF
            0450     LDA #$01
            0460     JSR BPWT
            0470     BMI ER2
            0480     LDA #$34
            0490     STA PACTL
            0500     LDX PALNTS
            0510     LDY TABCAS+6,X
            0520     LDA TABCAS+4,X
            0530     TAX
            0540     LDA #$03
            0550     STA TIMFLG3
            0560     JSR JSETVBV
            0570 WAIT LDA TIMFLG3
            0580     BNE WAIT
            0590     LDA #$80
            0600     STA BPTR
            0610     STA BLIM
            0620     JMP SUC
            0630 ERR LDY #$80
            0640     DEC IRQSTAT
            0650 ER2 LDA #$00
            0660     STA WMODE
            0670     RTS
            0680 COPOUT LDA #$80
            0690     STA WMODE
            0700     LDA #$02
            0710     JSR BPWT
            0720     BMI ER2
            0730     LDA #$CC
            0740     STA AUDF3
            0750     LDA #$05
            0760     STA AUDF4
            0770     LDA #$60
            0780     STA DDEVIC
            0790     JSR JSNDENB
            0800     LDA #$34
            0810     STA PACTL
            0820     LDX PALNTS
            0830     LDY TABCAS+2,X
            0840     LDA TABCAS,X
            0850     TAX
            0860     LDA #$03
            0870     JSR JSETVBV
            0880     LDA #$FF
            0890     STA TIMFLG3
            0900 WT2 LDA IRQSTAT
            0910     BEQ ERR
            0920     LDA TIMFLG3
            0930     BNE WT2
            0940     LDA #$00
            0950     STA BPTR
            0960 SUC LDY #$01
            0970     RTS
    Teraz do rejestru PACTL wpisywana jest wartość $34, która powoduje uruchomienie silnika magnetofonu. Według znacznika PALNTS pobierane są z tabeli TABCAS wartości, które po wywołaniu procedury SETVBLV ustalają stan początkowy licznika TIMCNT3 (TIMer CouNTer 3).
            0100 ;TABle for CASsette
            0110 ;
            0120     *=  $FE8D
            0130 ;
            0140     .BYTE $04,$03,$80,$C0
            0150     .BYTE $02,$01,$40,$E0
            0160     .BYTE $1E,$19,$0A,$08
    Procedura czeka teraz w pętli WAIT na wyzerowanie tego licznika sygnalizowane w TIMFLG3 (TIMer FLaG 3). Po upływie ustalonego czasu oraz ustawieniu długości bufora i jego licznika na $80 procedura kończy się przez RTS.

    Podczas zapisu do rejestru WMODE wpisywana jest wartość $80, a procedura BPWT jest wywoływana z wartością $02 w akumulatorze. W tym miejscu występuje największa różnica między odczytem i zapisem. Do rejestrów AUDF3 i AUDF4 wpisywane są wartości określające częstotliwość pracy generatorów sygnału. Rejestr DDEVIC uzyskuje wartość $60, która oznacza magnetofon i wywoływana jest procedura SNDENBL. Kończąca tą fazę pętla WT2 oprócz znacznika TIMFLG3 sprawdza także rejestr IRQSTAT.

    Zadaniem procedury BPWT jest wygenerowanie odpowiedniego sygnału dźwiękowego i oczekiwanie na naciśnięcie przez użytkownika dowolnego klawisza (oprócz BREAK). Liczba dźwięków jest umieszczana w akumulatorze przed wywołaniem procedury.
            0100 ;BeeP and WaiT
            0110 ;
            0120 CONSOL = $D01F
            0130 FREQ =  $40
            0140 PALNTS = $62
            0150 PHVRT = $FE36
            0160 RTCLOCK = $12
            0170 TABCAS = $FE8D
            0180 ;
            0190     *=  $FDFC
            0200 ;
            0210     STA FREQ
            0220 LP1 LDA RTCLOCK+2
            0230     CLC
            0240     LDX PALNTS
            0250     ADC TABCAS+8,Y
            0260     TAX
            0270 LP2 LDA #$FF
            0280     STA CONSOL
            0290     LDA #$00
            0300     LDY #$F0
            0310 WT1 DEY
            0320     BNE WT1
            0330     STA CONSOL
            0340     LDY #$F0
            0350 WT2 DEY
            0360     BNE WT2
            0370     CPX RTCLOCK+2
            0380     BNE LP2
            0390     DEC FREQ
            0400     BEQ KEY
            0410     TXA
            0420     CLC
            0430     LDX PALNTS
            0440     ADC TABCAS+10,X
            0450     TAX
            0460 WT3 CPX RTCLOCK+2
            0470     BNE WT3
            0480     BEQ LP1
            0490 KEY JSR PHVRT
            0500     TYA
            0510     RTS
    Dźwięk jest uzyskiwany przez naprzemienne wpisywanie do rejestru CONSOL wartości $00 i $FF, a czas jego trwania określany jest według zegara RTCLOCK (Real Time CLOCK) na podstawie wartości odczytanych z TABCAS. Po emisji dźwięku (jednego lub dwóch sygnałów - zależnie od zawartości FREQ) wywoływana jest procedura PHVRT, a po jej zakończeniu kończy się także BPWT.
            0100 ;PusH Vector & ReTurn
            0110 ;
            0120 KBDVEC = $E420
            0130 ;
            0140     *=  $FE36
            0150 ;
            0160     LDA KBDVEC+5
            0170     PHA
            0180     LDA KBDVEC+4
            0190     PHA
            0200     RTS
    Działanie procedury PHVRT jest identyczne jak opisywanej wcześniej procedury GOHAND. Odczytuje ona z tabeli adresowej KBDVEC wektor odczytu z klawiatury i umieszcza go na stosie. Teraz po rozkazie RTS jest wykonywana ta procedura, a po jej zakończeniu następuje powrót bezpośrednio do BPWT.

    Przez CASOPN wywoływana jest jeszcze procedura SNDENBL. Stanowi ona część SIO (szeregowego wejścia/wyjścia - Serial Input/Output) i jest opisana razem z nim w rozdziale 4.

3.5.2. Odczyt z magnetofonu

    Dla dokonania odczytu z magnetofonu wywoływana jest procedura CASRDBT. Sprawdza ona najpierw znacznik FEOF (Flag End Of File) i gdy jest on ustawiony ($80), to procedura jest przerywana po umieszczeniu w rejestrze Y kodu błędu $88 (END OF FILE - koniec zbioru).

    Jeżeli licznik bufora BPTR (Buffer PoinTeR) jest różny od jego długości BLIM (Buffer LIMit), oznacza to odczyt bajtu. Do akumulatora pobierany jest więc z bufora magnetofonu bajt wskazany przez BPTR. Po zwiększeniu BPTR i wpisaniu 1 do rejestru Y procedura się kończy.

    Równe wartości BPTR i BLIM oznaczają odczyt całego bloku (rekordu). Następuje wtedy skok do drugiej części procedury oznaczonej etykietą CASRDBL. Tam, po zapisaniu w akumulatorze wartości $52 (kod rozkazu GET RECORD), wywoływana jest procedura SYSBUF, która przygotowuje blok DCB do współpracy z magnetofonem i przeprowadza odczyt rekordu.
            0100 ;CASsette ReaD
            0110 ;
            0120 BLIM =  $028A
            0130 BPTR =  $3D
            0140 CASBEN = $047F
            0150 CASBUF = $0400
            0160 CRCB =  $03FF
            0170 FEOF =  $3F
            0180 SYSBUF = $FE3F
            0190 ;
            0200     *=  $FD7A
            0210 ;
            0220 ;CASsette ReaD ByTe
            0230 ;
            0240 CASRDBT LDA FEOF
            0250     BMI ERR
            0260     LDX BPTR
            0270     CPX BLIM
            0280     BEQ CASRDBL
            0290     LDA CASBUF,X
            0300     INC BPTR
            0310     LDY #$01
            0320 EXIT RTS
            0330 ;
            0340 ;CASsette ReaD BLock
            0350 ;
            0360 CASRDBL LDA #$52
            0370     JSR SYSBUF
            0380     TYA
            0390     BMI EXIT
            0400     LDA #$00
            0410     STA BPTR
            0420     LDX #$80
            0430     LDA CRCB
            0440     CMP #$FE
            0450     BEQ EOF
            0460     CMP #$FA
            0470     BNE LIM
            0480     LDX CASBEN
            0490 LIM STX BLIM
            0500     JMP CASRDBT
            0510 EOF DEC FEOF
            0520 ERR LDY #$88
            0530     RTS
    Odczytany z magnetofonu rekord jest umieszczany w akumulatorze i według rejestru CRCB (Cassette Record Control Byte) jest sprawdzany jego rodzaj. Wartość $FE oznacza rekord końcowy zbioru i powoduje przerwanie procedury odczytu. Wartość $FA oznacza niepełny rekord. Wtedy liczba bajtów w buforze jest przenoszona z rejestru CASBEN (CAssette Buffer ENd) do rejestru długości bufora BLIM i wykonywany jest skok do CASRDBT. Trzecią wartością, która może wystąpić w rejestrze CRCB (lecz nie jest sprawdzana), jest $FC. Oznacza ona pełny rekord (128 bajtów) i powoduje jedynie skok do CASRDBT.

    Procedura SYSBUF wywoływana przez CASRDBT i CASWRT pełni dla magnetofonu taką rolę, jak SETDCB dla drukarki. Ustawia ona odpowiednie wartości w bloku DCB i wywołuje procedurę SIOINT. Przed rozpoczęciem SYSBUF do akumulatora musi być wpisany kod wykonywanej operacji (zapisu lub odczytu).

    Po przepisaniu kodu rozkazu z akumulatora do rejestru DCMND kolejno ustalane są pozostałe wartości DCB: długość bufora DBYT ($83), adres bufora DBUFA (adres pierwszego bajtu zapisywanego rekordu - CSCB), rodzaj urządzenia DDEVIC ($60), numer urządzenia DUNIT ($00) i wartość Timeout DTIMLO ($23). Rejestr DSTATS otrzymuje przy odczycie wartość $40, a przy zapisie - $80. Na końcu jeszcze zawartość GAPTYP jest przepisywana do DAUX2 i wywoływana jest procedura SIOINT.
            0100 ;SYStem BUFfer
            0110 ;
            0120 CSCB  = $03FD
            0130 DAUX2 = $030B
            0140 DBUFA = $0304
            0150 DBYT =  $0308
            0160 DCMND = $0302
            0170 DDEVIC = $0300
            0180 DSTATS = $0303
            0190 DTIMLO = $0306
            0200 DUNIT = $0301
            0210 GAPTYP = $3E
            0220 JSIOINT = $E459
            0230 ;
            0240     *=  $FE3F
            0250 ;
            0260     STA DCMND
            0270     LDA #$00
            0280     STA DBYT+1
            0290     LDA #$83
            0300     STA DBYT
            0310     LDA # >CSCB
            0320     STA DBUFA+1
            0330     LDA # <SCSB
            0340     STA DBUFA
            0350     LDA #$60
            0360     STA DDEVIC
            0370     LDA #$00
            0380     STA DUNIT
            0390     LDA #$23
            0400     STA DTIMLO
            0410     LDA DCMND
            0420     LDY #$40
            0430     CMP #$52
            0440     BEQ STS
            0450     LDY #$80
            0460 STS STY DSTATS
            0470     LDA GAPTYP
            0480     STA DAUX2
            0490     JSR JSIOINT
            0500     RTS
    Szczegółowe informacje o DCB znajdują się w rozdziale 4.1. - Blok kontroli urządzeń (str. 115).

3.5.3. Zapis na magnetofon

    Procedura zapisu CASWRT jest znacznie krótsza od procedury odczytu z magnetofonu. Wynika to przede wszystkim z "głupoty" magnetofonu. Po prostu komputer nie może kontrolować przebiegu transmisji i wysyła dane "w ciemno". Oczywiście znakomicie upraszcza to procedurę transmisji.

    Jak we wszystkich procedurach zapisu, także przed wywołaniem CASWRT w akumulatorze musi być umieszczony zapisywany znak. Jest on przepisywany do bufora magnetofonu CASBUF (CASsette BUFfer) w miejsce wskazane przez licznik BPTR. Jeżeli licznik nie osiągnął jeszcze wartości $7F, to po ustawieniu statusu $01 (SUCCESS) procedura się kończy.
            0100 ;CASsette WRiTe
            0110 ;
            0120 BPTR =  $3D
            0130 CASBUF = $0400
            0140 WSIOSB = $FE7C
            0150 ;
            0160     *=  $FDB4
            0170 ;
            0180     LDX BPTR
            0190     STA CASBUF,X
            0200     INC BPTR
            0210     LDY #$01
            0220     CPX #$7F
            0230     BEQ FIN
            0240     RTS
            0250 FIN LDA #$FC
            0260     JSR WSIOSB
            0270     LDA #$00
            0280     STA BPTR
            0290     RTS
    Zapełnienie bufora powoduje wpisanie do akumulatora wartości $FC (bufor pełny) i wywołanie procedury WSIOSB, która wysyła zawartość bufora do magnetofonu. W tym przypadku przed zakończeniem CASWRT jest jeszcze zerowany licznik bufora BPTR.
            0100 ;Write SIO System Buffer
            0110 ;
            0120 CRCB =  $03FF
            0130 CSCB =  $03FD
            0140 SYSBUF = $FE3F
            0150 ;
            0160     *=  $FE7C
            0170 ;
            0180     STA CRCB
            0190     LDA #$55
            0200     STA CSCB
            0210     STA CSCB+1
            0220     LDA #$57
            0230     JSR SYSBUF
            0240     RTS
    Procedura WSIOSB uzupełnia brakujące bajty w buforze magnetofonu. Zawartość akumulatora (rodzaj rekordu) zapisuje do rejestru CRCB, a oba bajty kontroli szybkości CSCB (Cassette Speed Control Byte) ustawia na $55. Wartość ta służy później przy odczycie do regulacji szybkości transmisji i stanowi po prostu naprzemienny ciąg bitów 0 i 1 ($55 jest równe binarnie 01010101). Na końcu do akumulatora wpisywany jest kod rozkazu zapisu $57 (PUT RECORD) i wywoływana jest procedura SYSBUF, która wykonuje właściwy zapis.

3.5.4. Zamknięcie magnetofonu

    Zakończenie współpracy z magnetofonem wymaga przede wszystkim zatrzymania silnika. Ponadto podczas zapisu należy zadbać, aby wszystkie dane umieszczone w buforze zostały wysłane do magnetofonu. Zadania te wykonywane są przez procedurę CASCLS.
            0100 ;CASsette CLoSe
            0110 ;
            0120 BPTR =  $3D
            0130 CASBEN = $047F
            0140 CASBUF = $0400
            0150 PACTL = $D302
            0160 WMODE = $0289
            0170 WSIOSB = $FE7C
            0180 ;
            0190     *=  $FDCF
            0200 ;
            0210     LDA WMODE
            0220     BMI WRT
            0230     LDY #$01
            0240 MST LDA #$3C
            0250     STA PACTL
            0260     RTS
            0270 WRT LDX BPTR
            0280     BEQ FIL
            0290     STX CASBEN
            0300     LDA #$FA
            0310     JSR WSIOSB
            0320     BMI MST
            0330 FIL LDX #$7F
            0340     LDA #$00
            0350 STB STA CASBUF,X
            0360     DEX
            0370     BPL STB
            0380     LDA #$FE
            0390     JSR WSIOSB
            0400     JMP MST
    Na początku procedury sprawdzany jest znacznik WMODE (Write MODE). Gdy jest on równy zero, to w rejestrze Y umieszczana jest wartość 1 i przez wpisanie $3C do rejestru PACTL (Port A ConTroL) zatrzymywany jest silnik magnetofonu.

    Wartość $80 w WMODE oznacza zapis. Sprawdzany jest więc licznik bufora BPTR. Jeśli w buforze znajdują się jakieś dane, to zawartość BPTR jest przepisywana do CASBEN i procedura WSIOSB wywoływana jest z wartością $FA w akumulatorze. Po ewentualnym zapisaniu pozostałych w buforze danych trzeba jeszcze wysłać rekord końcowy zbioru. W tym celu bufor jest wypełniany zerami i po umieszczeniu w akumulatorze wartości $FE jest wywoływana procedura WSIOSB. Po zatrzymaniu silnika CASCLS się kończy.
Zientara Wojciech: Mapa pamięci Atari XL/XE. Procedury wejścia-wyjścia, SOETO, Warszawa, 1988.