INPUT/OUTPUT CONTROL BLOCKS
(IOCBS)

Back at locations 32 through 47, we ran across something called the Zero-page Input/Output Control Block (ZIOCB). The ZIOCB gets its values from one of the eight Input/Output Control Blocks (IOCBs) located at locations 832 through 959. Basically, the IOCBs are nothing more than a bundle of information used to communicate between the user and the handlers. BASIC usually takes care of them for you in commands like OPEN, PLOT, LPRINT, and so on (all the BASIC I/O commands).

Each IOCB is 16 bytes long, and those bytes are named and used as follows:

ICHID (one byte)
This is an offset into HATABS (794 through 831) that points to the name of the device that the IOCB is OPENed for. For example, try the following:

100 IOCB1=848:HATABS=794
110 OPEN #1,4,0,"K:"
120 INDEX=PEEK(IOCB1)
130 PRINT "You just OPENed device ";CHR$(PEEK(HATABS+INDEX));":"

ICHID is set by the OS.

ICDNO (one byte)
This is the device number. One for D1, two for R2, etc. It is also set by the OS.

ICCOM (one byte)
This is the command that specifies what kind of I/O operation we are going to be doing. See the appendices for a list of possible commands. It is set by the user.

ICSTA (one byte)
This is the status of the last I/O operation. See the OS manual (pp. 165-166) for a list of possible values.

ICBAL/H (two bytes)
This is either the address of the data buffer, or the address of the user's filename (depending on the command).

ICPTL/H (two bytes)
This is the address minus one of the put one-byte routine for the device being used. If the IOCB isn't OPEN, then it points to CIO's error routine for an illegal put.

ICBLL/H (two bytes)
This is the number of bytes that still have to be transferred. Note that under some circumstances not all bytes will be transferred.

ICAX1 (one byte)
This is an auxiliary byte (and is also called AUX1), meaning that it helps out ICCOM in specifying what is to be done. It is usually used to modify the OPEN command, but you can use it for your own handlers. With the OPEN command, it is the first value after the IOCB number (#n is the IOCB number), with the bit meanings in Figure 27.

 -------1 (1)
  append
 ------1- (2)
  directory
 -----1-- (4)
  read
 ----1--- (8)
  write
 --1----- (32)
  OPEN screen without erasing screen memory

            FIGURE 27. ICAX1 bit meanings

Some combinations are not allowed on some devices. For example, OPEN#1,12,0,"D:TEST" would open a disk file called TEST, and let you read and write to that file. This wouldn't work on a cassette file though.

ICAX2 (one byte)
This is the second auxiliary byte, and is also called AUX2. There is no common use for this or any of the other auxiliary bytes; their use depends on the handler. For example, if AUX2 is equal to 128, the cassette handler will put shorter gaps between the records on the tape when it writes data.

ICAX3/4 (two bytes)
These auxiliary bytes are used by BASIC's NOTE and POINT commands to keep track of the sector number. They are not also called AUX3 and AUX4.

ICAX5 (one byte)
This is the fifth auxiliary byte and is also used by NOTE and POINT as the number of the byte within the sector.

ICAX6 (one byte)
OK, enough of the "this is" garbage. I won't even insult your intelligence by telling you it's the sixth auxiliary byte. It has no specific use.

You can use the IOCBs directly by POKEing the values you want into them and then doing a JSR CIOV (58454). See CIOV for more details.

Note that the descriptions for the ZIOCB (32-47) are worded differently from the preceding descriptions, so be sure to read them as well for a better understanding.

IOCB0
832-847         0340-034F

This is, obviously, IOCB zero. If you're using the screen editor, then don't use IOCB0; that's what the screen editor uses. If you are using the screen editor though, you can do neat things by telling the IOCB to send the data somewhere else, like the printer. Try this if you have a printer:

100 GRAPHICS 0
110 PRINT "Now we're on the screen"
120 POKE 838,166:POKE 839,238
130 PRINT "now we're on the printer"
140 POKE 838,163:POKE 839,246
150 PRINT "Now we're back on the screen"

professor


What we're doing here is changing ICPTL/H to point to the printer's put-one-byte routine rather than the screen editor's. Note that this doesn't turn your computer into a typewriter. The screen editor isn't responsible for putting characters you type on the screen; it only works for things the computer prints on the screen.

Another neat thing you can do to the screen editor is give AUX1(842) a value of 13. This tells it to "append," which doesn't really make any sense. What it does, though, is act as though you were continually pressing the return key. This lets you write a program that will change itself. You simply print some program instructions on the screen, position the cursor on the line of the first instruction, and POKE 842 with 13 to start the computer generating RETURNS, which reads in each line. When the computer POKE's 842 with a 12, the process stops and everything is back to normal. While you do this, the lines of code will appear on the screen, but you can make them invisible by setting the color of the letters to the color of the screen. Try this:


10 ? "{CLR}":LIST 30
20 FOR I=1 TO 1000:NEXT I
30 ? "NOW LINE 30 SAYS EVERYTHING ELSE"
40 FOR I=1 TO 1000:NEXT I

50 ? "{CLR}"
60 POSITION 2,10:? "30 ?";CHR$(34);"NOW LINE 30 SAYS SOMETHING ELSE"

70 POSITION 0,2
80 POKE 842,13

90 POSITION 2,17:? "CONT"
100 POSITION 0,2:STOP

110 POKE 842,12
120 ? "{CLR}":? "NOW LETS SEE WHAT LINE 30 SAYS"
130 ? "THE PROGRAM MODIFIED ITSELF"

140 LIST 30

Keep in mind that if you try and delete the lines that change location 842, you'll confuse the heck out of the computer and it will just keep on "pressing" RETURN forever

The screen editor, and therefore IOCB zero, is used in graphics mode zero and in other graphics modes that use text windows. Since IOCB zero is dedicated to the screen editor, however, you should stay away from it even if you're not using the text editor.

IOCB zero is not closed by a NEW, RUN, or LOAD command. All the others are.

IOCB1
848-863         0350-035F

IOCB one.

palm


IOCB2
864-879         0360-036F

IOCB two.

IOCB3
880-895         0370-037F

IOCB three.

IOCB4
896-911         0380-038F

IOCB four.

IOCB5
912-927         0390-039F

IOCB five.

IOCB6
928-943         03A0-03AF

IOCB six. If you're in a mode other than zero, then IOCB six is used for the screen (IOCB0 is used for the text window).

IOCB7
944-959         03B0-03BF

IOCB seven is used by BASIC for I/O to the printer, disk drive, and cassette. That means that this is a pointer to the buffer that will be used to store the data that is to be sent or received during I/O. It's set by the handler to the system buffer at CASBUF (1021) unless you tell the handler differently.

If a GET STATUS command is given, then DBUFLO/HI is set to point to DVSTAT (746).

If you're communicating with SIO directly, you should make sure you set DBUFLO/HI yourself.

PRNBUF
960-999         03C0-03E7

This is the print buffer, 40 bytes long, used in sending data to a printer. See PBPNT (29; $001C) and PBUFSZ (30; $001E) for details on how this works.

buffer


Forty bytes, as you may be aware, is somewhat shorter than most printer lines (most have 80 character lines). The OS can usually handle this, but sometimes it runs into problems. Semi-colons and commas at the end of LPRINT statements especially tend to mess it up. Several sources briefly mention that the Atari can deal with an 80 column printer if you call it "P2". If this is true, then you would have to OPEN a special IOCB for it and therefore couldn't use LPRINT (you'd have to use PUT and the likes). You're probably better off just to put up with the quirks.

Noname
1000-1020         03E8-03FC

These bytes are marked as being spare, but again, be careful about using them.

CASBUF
1021-1151         03FD-047F

This is the cassette buffer, which is where the cassette handler reads and writes data from and to. It's also used to hold the first disk record when a disk is booted (the OS doesn't know where to put the disk file in memory until it gets a chance to look at this record; see BOOTAD [578,579]).

A cassette record is made up of 132 bytes. Only 128 of these are actual data; the other 4 help out the cassette handler. How? I'm glad you asked. The first 2 bytes, as we learned at CBAUDL/H (750,751), are used to help the handler figure out the correct baud rate. The third byte tells the handler how much data is in the file. It can have the following values:

250 means that there are less than 128 bytes of meaningful data (there will still be 128 bytes, but some of them toward the end will be zeroes). The 128th data byte will give the actual number of meaningful bytes.

252 means that all 128 bytes are important.

254 means that this is the last record in the file and all 128 bytes will be equal to 0.

The next 128 bytes are the actual data. Notice that they will be stored in CASBUF starting at 1024 and ending at 1151.

light


But wait, that was only 131 bytes and you said there were 132. Where does the 132nd go if we already filled the buffer? The last byte in a cassette record is the checksum, which is used to make sure that the rest of the data was read correctly. It gets stored at CHKSUM (49), and you should take a look at CHKSUM for a more detailed description of how a checksum works.

Take a look at BPTR (61) and BLIM (650) for more information on the way the buffer is used.

buffer RAM


Locations 1152 through 1791 are not used by the OS. Most of them are, however, used by BASIC and/or the floating point package. Only the locations in page six (1536 to 1791) are not used by either. See page six for more information.

SYNSTK
1152-1405         0480-057D

This is BASIC's syntax stack. Unfortunately, since there doesn't seem to be any information on what it's for, I can't explain it to you (I never claimed to be perfect). I suspect, however, that it's used during the tokenization of the BASIC program, since BASIC has the runtime stack (see RUNSTK [142,143]) to use when the program is actually running.

LBPR1
1406         057E

LBUFF prefix one. Again, no information on this one.

LBPR2
1407         057F

LBUFF prefix two, also not explained anywhere.

LBUFF
1408-1535         0580-05FF

Before I go on, a few words on locations like these. Atari was very nice in releasing the OS listing; a lot of other computer companies don't. Atari did not, however, because of legal restrictions, extend that niceness to BASIC and the floating point package. Therefore, locations that are used by these two are very difficult to explain. The useful locations have been documented, so they can be understood and used by yourself. Ones like these, however, are somewhat obscure, so that you should never have to use them. In other words, don't feel that you're not getting something you'll need.

Now that I've freed myself from the responsibility of properly explaining these locations, I'll actually give you some information on this one. This is a buffer used in converting floating point values to ATASCII values. It's pointed to by INBUFF at locations 243 and 244. Now INBUFF supposedly points to the buffer used to convert ATASCII to floating point, so I suspect that LBUFF swings both ways.

LBUFF is also referred to as the "input line buffer," which implies that this is where a BASIC line is stored when you first type it in.

PROTO


Location 1535 is the last byte in the buffer and so it is also called LBFEND. Notice that the next three locations are all within LBUFF.

PLYARG
1504-1509         05E0-05E5

Polynomial arguments. Sure!

FPSCR
1510-1515         05E6-05EB

This is like a work area for the floating point package, eh.

FPSCR1
1516-1535         05EC-05FF
The same, only bigger.


Return to Table of Contents | Previous Chapter | Next Chapter