MEMORY MAP
Locations zero to 255 ($0 to $FF) are called "page zero" and have
special importance for assembly language programmers since these
locations are accessed faster and easier by the machine.
Locations zero to 127 ($0 to $7F) are reserved as the OS page zero,
while 128 to 255 ($80 to $FF) are the BASIC and the user zero page
RAM. Locations zero to 1792 ($0 to $700) are all used as the OS and (if
the cartridge is present) 8K BASIC RAM (except page six). Locations
zero to 8191 ($0 to $1FFF) are the minimum required for operation
(8K).
Locations two through seven are not cleared on any start operation.
DECIMAL        HEX            LABEL
0,1          	0,1          	LINZBS
 
-      LINBUG RAM, replaced by the monitor RAM See the OS
     Listing, page 31. It seems to be used to store the VBLANK timer
     value. One user application I've seen for location zero is in a
     metronome program in De Re Atari. Also used in cross-
     assembling the Atari OS.
2,3          	2,3          	CASINI
 
-      Cassette initialization vector: JSR through here if the cassette
     boot was successful. This address is extracted from the first six
     bytes of a cassette boot file. The first byte is ignored. The second
     contains the number of records, the third and fourth contain the
     low and high bytes of the load address, and the fifth and sixth
     contain the low and high bytes of the initialization address.
     Control upon loading jumps to the load address plus six for a
     multi-stage load and through CASINI for initialization. JSR
     through DOSVEC (10 and 11; $A,$B) to transfer control to the
     application.
4,5          	4,5          	RAMLO
 
-      RAM pointer for the memory test used on powerup. Also used to
     store the disk boot address--normally 1798 ($706)--for the
     boot continuation routine.
6          	6          	TRAMSZ
 
-      Temporary Register for RAM size; used during powerup
     sequence to test RAM availability. This value is then moved to
     RAMTOP, location 106 ($6A). Reads one when the BASIC or the
     A (left) cartridge is plugged in.
7          	7          	TSTDAT
 
-      RAM test data register. Reads one when the B or the right
     cartridge is inserted.
     RAMLO, TRAMSZ and TSTDAT are all used in testing the RAM
     size on powerup. On DOS boot, RAMLO and TRAMSZ also act as
     temporary storage for the boot continuation address. TRAMSZ
     and TSTDAT are used later to flag whether or not the A (left)
     and/or B (right) cartridges, respectively, are plugged in (non-
     zero equals cartridge plugged in) and whether the disk is to be
     hooted.
Locations eight through 15 ($8-$F) are cleared on coldstart only.
8          	8          	WARMST
 
-      Warmstart flag. If the location reads zero, then it is in the middle
     of powerup; 255 is the normal RESET status. Warmstart is similar
     to pressing RESET, so should not wipe out memory, variables, or
     programs. WARMST is initialized to zero and will not change
     values unless POKEd or until the first time the RESET button is
     pressed. It will then read 255 ($FF).
     Warmstart normally vectors to location 58484 ($E474). WARMST
     is checked by the NMI status register at 54287 ($D40F) when
     RESET is pressed to see whether or not to re-initialize the
     software or to re-boot the disk.
9          	9          	BOOT?
 
-      Boot flag success indicator. A value of 255 in this location will
     cause the system to lockup if RESET is pressed. If BOOT? reads
     one, then the disk boot was successful; if it reads two, then the
     cassette boot was successful. If it reads zero, then neither
     peripheral was booted.
     If it is set to two, then the cassette vector at locations two and
     three will be used on RESET. Set to one, it will use the DOS
     vector at 10 and 11 ($A and $B). Coldstart attempts both a
     cassette and a disk boot and flags this location with the success or
     failure of the boots. BOOT? is checked during both disk and
     cassette boot.
10,11          	A,B          	DOSVEC
 
-      Start vector for disk (or non-cartridge) software. This is the
     address BASIC jumps to when you call up DOS. Can be set by
     user to point to your own routine, but RESET will return DOSVEC
     to the original address. To prevent this, POKE 5446 with the LSB
     and 5450 with the MSB of your vector address and re-save DOS
     using the WRITE DOS FILES option in the menu. Locations 10
     and 11 are usually loaded with 159 and 23 ($9F and $17),
     respectively. This allows the DUPSYS section of DOS to be
     loaded when called. It is initially set to blackboard mode vector
     (58481; $E471--called by typing "BYE" or "B." from BASIC); it
     will also vector to the cassette run address if no DOS vector is
     loaded in. If you create an AUTORUN.SYS file that doesn't end
     with an RTS instruction, you should set BOOT? to one and 580
     ($244) to zero.
12,13          	C,D          	DOSINI
 
-      Initialization address for the disk boot. Also used to store the
     cassette-boot RUN address, which is then moved to CASINI (2,
     3). When you powerup without either the disk or an autoboot
     cassette tape, DOSINI will read zero in both locations.
14,15          	E,F          	APPMHI
 
-      Applications memory high limit and pointer to the end of your
     BASIC program, used by both the OS and BASIC. It contains the
     lowest address you can use to set up a screen and Display List
     (which is also the highest address usable for programs and data
     below which the display RAM may not be placed). The screen
     handler will not OPEN the "S:" device if it would extend the
     screen RAM or the Display List below this address; memory
     above this address may be used for the screen display and other
     data (PM graphics, etc.).
     If an attempted screen mode change would extend the screen
     memory below APPMHI, then the screen is set up for GRAPHICS
     mode zero; MEMTOP (locations 741, 742; $2E5, $2E6) is updated
     and an error is returned to the user. Otherwise, the memory is not
     too small for the screen editor; the mode change will take effect
     and MEMTOP will be updated. This is one of five locations used
     by the OS to keep track of the user and display memory.
     Initialized to zero by the OS at powerup. Remember, you cannot
     set up a screen display below the location specified here.
     If you use the area below the Display List for your character sets,
     PM graphics or whatever, be sure to set APPMHI above the last
     address used so that the screen or the DL data will not descend
     and destroy your own data. See RAMTOP location 106 ($6A),
     MEMTOP at 741, 742 ($2E5, $2E6), PMBASE at 54279 ($D407)
     and CHBASE at 54281 ($D409) for more information.
Locations 16 through 127 ($10-$7F) are cleared on either cold- or
warmstart.
16          	10          	POKMSK
 
-      POKEY interrupts: the IRQ service uses and alters this location.
     Shadow for 53774 ($D20E). POKE with 112 ($70; also POKE this
     same value into 53774) to disable the BREAK key. If the following
     bits are set (to one), then these interrupts are enabled (bit
     decimal values are in parentheses):
     BIT   DECIMAL   FUNCTION
      7      128     The BREAK key is enabled.
      6       64     The "other key" interrupt is enabled.
      5       32     The serial input data ready interrupt is
                     enabled.
      4       16     The serial output data required interrupt is
                     enabled.
      3        8     The serial out transmission finished
                     interrupt is enabled.
      2        4     The POKEY timer four interrupt is enabled
                     (only in the "B" or later versions of the OS
                     ROMs).
      1        2     The POKEY timer two interrupt is enabled.
      0        1     The POKEY timer one interrupt is enabled.
     Timer interrupt enable means the associated AUDF registers are
     used as timers and will generate an interrupt request when they
     have counted down to zero. See locations 528 to 535 ($210 to
     $217) and the POKEY chip from locations 53760 ($D200) on, for a
     full explanation. 192 ($C0) is the default on powerup.
     You can also disable the BREAK key by POKEing here with 64
     ($40; or any number less than 128; $80) and also in location
     53774. The problem with simple POKEs is that the BREAK key is
     re-enabled when RESET is pressed and by the first PRINT
     statement that displays to the screen, or any OPEN statement that
     addresses the screen (S: or E:), or the first PRINT statement after
     such an OPEN and any GRAPHICS command. In order to
     continually disable the BREAK key if such commands are being
     used, it's best to use a subroutine that checks the enable bits
     frequently during input and output operations, and POKEs a
     value less than 128 into the proper locations, such as:
     1000   BREAK = PEEK(16) - 128: IF BREA
            K < 0 THEN RETURN
     1010   POKE 16, BREAK: POKE 53774, BRE
            AK: RETURN
     The new OS "B" version ROMs have a vector for the BREAK key
     interrupt, which allows users to write their own routines to
     process the interrupt in the desired manner. It is located at 566,
     567 ($236, $237).
17          	11          	BRKKEY
 
-      Zero means the BREAK key is pressed; any other number means
     it's not. A BREAK during I/O returns 128 ($80). Monitored by
     both keyboard, display, cassette and screen handlers. See
     location 16 ($A) for hints on disabling the BREAK key. The latest
     editions of OS provide for a proper vector for BREAK interrupts.
     The BREAK key abort status code is stored in STATUS (48; $30).
     It is also checked during all I/O and scroll/draw routines. During
     the keyboard handler routine, the status code is stored in DSTAT
     (76; $4C). BRKKEY is turned off at powerup. BREAK key abort
     status is flagged by setting BIT 7 of 53774 ($D20E). See the note
     on the BREAK key vector, above.
18,19,20          	12,13,14          	RTCLOK
 
-      Internal realtime clock. Location 20 increments every stage one
     VBLANK interrupt (1/60 second = one jiffy) until it reaches 255
     ($FF); then location 19 is incremented by one and 20 is reset to
     zero (every 4.27 seconds). When location 19 reaches 255, it and
     20 are reset to zero and location 18 is incremented by one (every
     18.2 minutes or 65536 TV frames). To use these locations as a
     timer of seconds, try:
     TIME = INT((PEEK(18) * 65536 + PEEK(19) * 256 +
            PEEK(20) )/60)
     To see the count in jiffies, eliminate the "/60" at the end. To see
     the count in minutes, change "/60" to "/360." The maximum
     value of the RT clock is 16,777,215. When it reaches this value, it
     will be reset to zero on the next VBLANK increment. This value is
     the result of cubing 256 (i.e., 256 * 256 * 256), the maximum
     number of increments in each clock register. The RT clock is
     always updated every VBLANK regardless of the time-critical
     nature of the code being processed.
     A jiffy is actually a long time to the computer. It can perform
     upwards of 8000 machine cycles in that time. Think of what can
     be done in the VBLANK interval (one jiffy). In human terms, a
     jiffy can be upwards of 20 minutes, as witnessed in the phrase "I'll
     be ready in a jiffy." Compare this to the oft-quoted phrase, "I'll
     be there in a minute," used by intent programmers to describe a
     time frame upwards of one hour.
     Users can POKE these clock registers with suitable values for
     their own use. The realtime clock is always updated during the
     VBLANK interval. Some of the other timer registers (locations
     536 to 544; $218 to $220) are not always updated when the OS is
     executing time critical code.
     Here's one way to use the realtime clock for a delay timer:
     10 GOSUB 100 
     .
     .
     .
     100 POKE 20,0: POKE 19,0 
     110 IF NOT PEEK(19) THEN 110
     120 RETURN
Line 110 waits to see if location 19 returns to zero and, when it
does, passes control to the RETURN statement.
     See COMPUTE!, August 1982, for a useful program to create a
     small realtime clock that will continue to display during your
     BASIC programming. See also De Re Atari for another realtime
     clock application.
21,22          	15,16          	BUFADR
 
-      Indirect buffer address register (page zero). Temporary pointer
     to the current disk buffer.
23          	17          	ICCOMT
 
-      Command for CIO vector. Stores the CIO command; used to find
     the offset in the command table for the correct vector to the
     handler routine.
24,25          	18,19          	DSKFMS
 
-      Disk file manager pointer. Called JMPTBL by DOS; used as
     vector to FMS.
26,27          	1A,1B          	DSKUTL
 
-      The disk utilities pointer. Called BUFADR by DOS, it points to
     the area saved for a buffer for the utilities package (data buffer;
     DBUF) or for the program area (MEMLO; 743, 744; $2E7, $2E8).
28          	1C          	PTIMOT
 
-      Printer timeout, called every printer status request. Initialized to
     30, which represents 32 seconds (the value is 64 seconds per 60
     increments in this register); typical timeout for the Atari 825
     printer is five seconds. The value is set by your printer handler
     software. It is updated after each printer status request operation.
     It gets the specific timeout status from location 748 ($2EC), which
     is loaded there by SIO.
     The new "B" type OS ROMs have apparently solved the problem
     of timeout that haunted the "A" ROMs; you saw it when the
     printer or the disk drive periodically went to sleep (timed out) for
     a few seconds, causing severe anxiety attacks in the owners who
     thought their Ataris had just mysteriously died. This is
     compounded when one removes a disk from the drive, believing
     the I/O process to be finished--only to have the drive start up
     again after the timeout and trying to write to or read from a
     nonexistent disk. Usually both the system and the user crash
     simultaneously at this point. See the appendix for more
     information on the new ROMs.
29          	1D          	PBPNT
 
-      Print buffer pointer; points to the current position (byte) in the
     print buffer. Ranges from zero to the value in location 30.
30          	1E          	PBUFSZ
 
-      Print buffer size of printer record for current mode. Normal
     buffer size and line size equals 40 bytes; double-width print
     equals 20 bytes (most printers use their own control codes for
     expanded print); sideways printing equals 29 bytes (Atari 820
     printer only). Printer status request equals four. PBUFSZ is
     initialized to 40. The printer handler checks to see if the same
     value is in PBPNT and, if so, sends the contents of the buffer to
     the printer.
31          	1F          	PTEMP
 
-      Temporary register used by the printer handler for the value of
     the character being output to the printer.
----------------------------------------------------------------------
Locations 32 to 47 ($20 to $2F) are the ZIOCB: Page zero Input-Output
Control Block. They use the same structure as the IOCB's at locations
832 to 959 ($340 to $3BF). The ZIOCB is used to communicate I/O con-
trol data between CIO and the device handlers. When a CIO opera-
tion is initiated, the information stored in the IOCB channel is moved
here for use by the CIO routines. When the operation is finished, the
updated information is returned to the user area.
32          	20          	ICHIDZ
 
-      Handler index number. Set by the OS as an index to the device
     name table for the currently open file. If no file is open on this
     IOCB (IOCB free), then this register is set to 255 ($FF).
33          	21          	ICDNOZ
 
-      Device number or drive number Called MAXDEV by DOS to in-
     dicate the maximum number of devices. Initialized to one.
34          	22          	ICCOMZ
 
-      Command code byte set by the user to define how the rest of the
     IOCB is formatted, and what I/O action is to be performed.
35          	23          	ICSTAZ
 
-      Status of the last IOCB action returned by the device, set by the
     OS. May or may not be the same status returned by the STATUS
     command.
36,37          	24,25          	ICBALZ/HZ
 
-      Buffer address for data transfer or the address of the file name for
     commands such as OPEN, STATUS, etc.
38,39          	26,27          	ICPTLZ/HZ
 
-      Put byte routine address set by the OS. It is the address minus
     one byte of the device's "put one byte" routine. It points to CIO's
     "IOCB not OPEN" on a CLOSE statement.
40,41          	28,29          	ICBLLZ/HZ
 
-      Buffer length byte count used for PUT and GET operations;
     decreased by one for each byte transferred.
42          	2A          	ICAX1Z
 
-      Auxiliary information first byte used in OPEN to specify the type
     of file access needed.
43          	2B          	ICAX2Z
 
-      CIO working variables, also used by some serial port functions. 
     Auxiliary information second byte.
44,45          	2C,2D          	ICAX3Z/4Z
 
-      Used by BASIC NOTE and POINT commands for the transfer of
     disk sector numbers. These next four bytes to location 47 are also
     labelled as: ICSPRZ and are defined as spare bytes for local CIO
     use.
46          	2E          	ICAX5Z
 
-      The byte being accessed within the sector noted in locations 44
     and 45. It is also used for the IOCB Number multiplied by 16.
     Each IOCB block is 16 bytes long. Other sources indicate that the
     6502 X register also contains this information.
47          	2F          	ICAX6Z
 
-      Spare byte. Also labelled CIOCHR, it is the temporary storage
     for the character byte in the current PUT operation.
-------------------------------------------------------------------
48          	30          	STATUS
 
-      Internal status storage. The SIO routines in ROM use this byte to
     store the status of the current SIO operation. See page 166 of the
     OS User's Manual for status values. STATUS uses location 793
     ($319) as temporary storage. STATUS is also used as a storage
     register for the timeout, BREAK abort and error values during
     SIO routines.
49          	31          	CHKSUM
 
-      Data frame checksum used by SIO: single byte sum with carry to
     the least significant bit. Checksum is the value of the number of
     bytes transmitted (255; $FF). When the number of transmitted
     bytes equals the checksum, a checksum sent flag is set at location
     59 ($3B). Uses locations 53773 ($D20D) and 56 ($38) for com-
     parison of values (bytes transmitted).
50,51          	32,33          	BUFRLO/HI
 
-      Pointer to the data buffer, the contents of which are transmitted
     during an I/O operation, used by SIO and the Device Control
     Block (DCB); points to the byte to send or receive. Bytes are
     transferred to the eight-bit parallel serial output holding register
     or from the input holding register at 53773 ($D20D). This register
     is a one-byte location used to hold the eight bits which will be
     transmitted one bit at a time (serially) to or from the device. The
     computer takes the eight bits for processing when the register is
     full or replaces another byte in it when empty after a
     transmission.
52,53          	34,35          	BFENLO/HI
 
-      Next byte past the end of the SIO and DCB data buffer described
     above.
54          	36          	CRETRY
 
-      Number of command frame retries. Default is 13 ($0D). This is the
     number of times a device will attempt to carry out a command
     such as read a sector or format a disk.
55          	37          	DRETRY
 
-      Number of device retries. The default is one.
56          	38          	BUFRFL
 
-      Data buffer full flag (255; $FF equals full).
57          	39          	RECVDN
 
-      Receive done flag (255; $FF equals done).
58          	3A          	XMTDON
 
-      Transmission done flag (255; $FF equals done).
59          	3B          	CHKSNT
 
-      Checksum sent flag (255; $FF equals sent).
60          	3C          	NOCKSM
 
-      Flag for "no checksum follows data." Not zero means no
     checksum follows; zero equals checksum follows transmission
     data.
61          	3D          	BPTR
 
-      Cassette buffer pointer: record data index into the portion of data
     being read or written. Ranges from zero to the current value at
     location 650 ($28A). When these values are equal, the buffer at
     1021 ($3FD) is empty if reading or full if writing. Initialized to 128
     ($80).
62          	3E          	FTYPE
 
-      Inter-record gap type between cassette records, copied from
     location 43 ($2B; ICAX2Z) in the ZIOCB, stored there from
     DAUX2 (779; $30B) by the user. Normal gaps are a non-zero
     positive number; continuous gaps are zero (negative number).
63          	3F          	FEOF
 
-      Cassette end of file flag. If the value is zero, an end of file (EOF)
     has not been reached. Any other number means it has been
     detected. An EOF record has been reached when the command
     byte of a data record equals 254 ($FE). See location 1021 ($3FD).
64          	40          	FREQ
 
-      Beep count retain register. Counts the number of beeps required
     by the cassette handler during the OPEN command for play or
     record operations; one beep for play, two for record.
65          	41          	SOUNDR
 
-      Noisy I/O flag used by SIO to signal the beeping heard during
     disk and cassette I/O. POKE here with zero for blessed silence
     during these operations. Other numbers return the beep. In-
     itialized to three. The hardware solution to this problem is to turn
     your speaker volume down. This can also be used to silence the
     digital track when playing synchronized voice/data tapes. See
     location 54018.
66          	42          	CRITIC
 
-      Critical I/O region flag; defines the current operation as a time-
     critical section when the value here is non-zero. Checked at the
     NMI process after the stage one VBLANK has been processed.
     POKEing any number other than zero here will disable the repeat
     action of the keys and change the sound of the CTRL-2 buzzer.
     Zero is normal; setting CRITIC to a non-zero value suspends a
     number of OS processes including system software timer coun-
     ting (timers two, three, four and five; see locations 536 to 558;
     $218 to $22E). It is suggested that you do not set CRITIC for any
     length of time. When one timer is being set, CRITIC stops the
     other timers to do so, causing a tiny amount of time to be "lost."
     When CRITIC is zero, both stage one and stage two VBLANK
     procedures will be executed. When non-zero, only the stage one
     VBLANK will be processed.
67-73          	43-49          	FMZSPG
 
-      Disk file manager system (FMS) page zero registers (seven
     bytes).
67,68          	43,44          	ZBUFP
 
-      Page zero buffer pointer to the user filename for disk I/O.
69,70          	45,46          	ZDRVA
 
-      Page zero drive pointer. Copied to here from DBUFAL and
     DBUFAH; 4905 and 4913 ($1329, $1331). Also used in FMS "free
     sector," setup and "get sector" routines.
71,72          	47,48          	ZSBA
 
-      Zero page sector buffer pointer.
73          	49          	ERRNO
 
-      Disk I/O error number. Initialized to 159 ($9F) by FMS.
74          	4A          	CKEY
 
-      Cassette boot request flag on coldstart. Checks to see if the
     START key is pressed and, if so, CKEY is set. Autoboot cassettes
     are loaded by pressing the START console key while turning the
     power on. In response to the beep, press the PLAY button on the
     recorder.
75          	4B          	CASSBT
 
-      Cassette boot flag. The Atari attempts both a disk and a cassette
     boot simultaneously. Zero here means no cassette boot was suc-
     cessful. See location 9
76          	4C          	DSTAT
 
-      Display status and keyboard register used by the display handler.
     Also used to indicate memory is too small for the screen mode,
     cursor out of range error, and the BREAK abort status.
77          	4D          	ATRACT
 
-      Attract mode timer and flag. Attract mode rotates colors on your
     screen at low luminance levels when the computer is on but no
     keyboard input is read for a long time (seven to nine minutes).
     This helps to save your TV screen from "burn-out" damage suf-
     fered from being left on and not used. It is set to zero by IRQ
     whenever a key is pressed, otherwise incremented every four
     seconds by VBLANK (see locations 18 - 20; $12 - $14). When the
     value in ATRACT reaches 127 ($7F), it is then set to 254 ($FE) un-
     til attract mode is terminated. This sets the flag to reduce the
     luminance and rotate the colors when the Atari is sitting idle.
     POKE with 128 ($80) to see this effect immediately: it normally
     takes seven to nine minutes to enable the attract mode. The OS
     cannot "attract" color generated by DLI's, although your DLI
     routine can, at a loss of time.
     Joysticks alone will not reset location 77 to zero. You will have to
     add a POKE 77,0 to your program periodically or frequently call
     in a subroutine to prevent the Atari from entering attract mode if
     you are not using any keyboard input.
78          	4E          	DRKMSK
 
-      Dark attract mask; set to 254 ($FE) for normal brightness when
     the attract mode is inactive (see location 77). Set to 246 ($F6)
     when the attract mode is active to guarantee screen color
     luminance will not exceed 50% . Initialized to 254 ($FE).
79          	4F          	COLRSH
 
-      Color shift mask; attract color shifter; the color registers are
     EORd with locations 78 and 79 at the stage two VBLANK (see
     locations 18 - 20; $12 - $14). When set to zero and location 78
     equals 246, color luminance is reduced 50%. COLRSH contains
     the current value of location 19, therefore is given a new color
     value every 4.27 seconds.
Bytes 80 to 122 ($50 to $7A) are used by the screen editor and display
handler.
80          	50          	TEMP
 
-      Temporary register used by the display handler in moving data to
     and from screen. Also called TMPCHR.
81          	51          	HOLD1
 
-      Same as location 80. It is used also to hold the number of Display
     List entries.
82          	52          	LMARGN
 
-      Column of the left margin of text (GR.0 or text window only).
     Zero is the value for the left edge of the screen; LMARGN is
     initialized to two. You can POKE the margin locations to set them
     to your specific program needs, such as POKE 82,10 to make the
     left margin start ten locations from the edge of the screen.
83          	53          	RMARGN
 
-      Right margin of the text screen initialized to 39 ($27). Both
     locations 82 and 83 are user-alterable, but ignored in all
     GRAPHICS modes except zero and the text window.
     Margins work with the text window and blackboard mode and are
     reset to their default values by pressing RESET. Margins have no
     effect on scrolling or the printer. However, DELETE LINE and
     INSERT LINE keys delete or insert 40 character lines (or delete
     one program line), which always start at the left margin and wrap
     around the screen edge back to the left margin again. The right
     margin is ignored in the process. Also, logical lines are always
     three physical lines no matter how long or short you make those
     lines.
     The beep you hear when you are coming to the end of the logical
     line works by screen position independent of the margins. Try
     setting your left margin at 25 (POKE 82,25) and typing a few lines
     of characters. Although you have just a few characters beyond
     60, the buzzer will still sound on the third line of text.
84          	54          	ROWCRS
 
-      Current graphics or text screen cursor row, value ranging from
     zero to 191 ($BF) depending on the current GRAPHICS mode
     (maximum number of rows, minus one). This location, together	
     with location 85 below, defines the cursor location for the next
     element to be read/written to the screen. Rows run horizontally,
     left to right across the TV screen. Row zero is the topmost line;
     row 192 is the maximum value for the bottom-most line.
85,86          	55,56          	COLCRS
 
-      Current graphics or text mode cursor column; values range from
     zero to 319 (high byte, for screen mode eight) depending on
     current GRAPHICS mode (maximum numher of columns minus
     one). Location 86 will always be zero in modes zero through
     seven. Home position is 0,0 (upper left-hand corner). Columns
     run vertically from the top to the bottom down the TV screen, the
     leftmost column being number zero, the rightmost column the
     maximum value in that mode. The cursor has a complete top to
     bottom, left to right wraparound on the screen.
     ROWCRS and COLCRS define the cursor location for the next
     element to be read from or written to in the main screen segment
     of the display. For the text window cursor, values in locations 656
     to 667 ($290 to $29B) are exchanged with the current values in
     locations 84 to 95 ($54 to $5F), and location 123 ($7B) is set to 255
     ($FF) to indicate the swap has taken place. ROWCRS and
     COLCRS are also used in the DRAW and FILL functions to
     contain the values of the endpoint of the line being drawn. The
     color of the line is kept in location 763 ($2FB). These values are
     loaded into locations 96 to 98 ($60 to $62) so that ROWCRS and
     COLCRS may be altered during the operation.
     BASIC's LOCATE statement not only examines the screen, but
     also moves the cursor one position to the right at the next PRINT
     or PUT statement. It does this by updating locations 84 and 85,
     above. You can override the cursor advance by saving the
     contents of the screen before the LOCATE command, then
     restoring them after the LOCATE. Try:
     100  REM: THE SCREEN MUST HAVE BEEN 0
         PENED FOR READ OR READ/WRITE PREV
         IOUSLY
     110  LOOK = PEEK(84): SEE = PEEK(85)
     120  LOCATE X,Y,THIS
     130  POKE 84, LOOK: POKE 65, SEE
     Note that CHR$(253) is a non-printing character---the bell--
     and doesn't affect the cursor position.
     See COMPUTE!, August 198l, for an example of using COLCRS
     for dynamic data restore and updating with the screen editor and
     the IOCBs.
87          	57          	DINDEX
 
-      Display mode/current screen mode. Labelled CRMODE by (*M).
     DINDEX contains the number obtained from the low order four
     bits of most recent open AUX1 byte. It can be used to fool the OS
     into thinking you are in a different GRAPHICS mode by
     POKEing DINDEX with a number from zero to 11. POKE with
     seven after you have entered GRAPHICS mode eight, and it will
     give you a split screen with mode seven on top and mode eight
     below. However, in order to use both halves of the screen, you
     will have to modify location 89 (below) to point to the area of the
     screen you wish to DRAW in. (See Your Atan 400/800, pp. 280 -
     283.)
     Watch for the cursor out-of-range errors (number 141) when
     changing GRAPHICS modes in this manner and either PRINTing
     or DRAWing to the new mode screen. POKE 87 with the BASIC
     mode number, not the ANTIC mode number.
     Did you know you can use PLOT and DRAWTO in GR.0? Try
     this:
     10   GR.0 
     20   PLOT 0,0: DRAWTO 10,10: DRAWTO 0
        ,10
     30   DRAWTO 39,0: DRAWTO 20,23: DRAWT
        O 0,20
     40   GOTO 40
     You can also set the text window for PRINT and PLOT modes by
     POKEing 87 with the graphics mode for the window. Then you
     must POKE the address of the top left corner of the text window
     into 88 and 89 ($58, $59). The screen mode of the text window is
     stored at location 659 ($293).
     You may have already discovered that you cannot call up the
     GTIA modes from a direct command. Like the + 16 GRAPHICS
     modes, they can only be called up during a program, and the
     screen display will be reset to GR.0 on the first INPUT or PRINT
     (not PRINT#6) statement executed in these modes.
     Since this location only takes BASIC modes, you can't POKE it
     with the other ANTIC modes such as "E", the famous "seven-and-
     a-half" mode which offers higher resolution than seven and a four
     color display (used in Datasoft's Micropainter program). If you're
     not drawing to the screen, simply using it for display purposes,
     you can always go into the Display List and change the
     instructions there. But if you try to draw to the screen, you risk an
     out-of-bounds error (error number 141).
     See Creative Computing, March 1982, for an excellent look at
     mode 7.5. The short subroutine below can be used to change the
     Display List to GR.7.5:
     1000  GRAPHICS 8+16: DLIST = PEEK(560)
          ) + PEEK(561) * 256:POKE DLIST +
           3,78
     1010  FOR CHANGE = DLIST + 6 TO DLIST
           + 204: IF PEEK(CHANGE) = 15 THE
          N POKE CHANGE,14
     1020  IF PEEK (CHANGE) = 79 THEN POKE
          CHANGE,78: NEXT CHANGE
     1030  POKE 87,7:RETURN
     
     DOWNLOAD MODE75.BAS
     (Actually, 15 ($F) is the DL number for the maximum memory
     mode; it also indicates modes eight through eleven. The DL's for
     these modes are identical.) Fourteen is the ANTIC E mode;
     GR.7.5 This program merely changes GR.8 to mode E in the
     Display List. The value 79 is 64 + 15; mode eight screen with BIT
     6 set for a Load Memory Scan (LMS) instruction (see the DL
     information in locations 560, 561; $230, $231). It does not check
     for other DL bits.
     You can also POKE 87 with the GTIA values (nine to eleven). To
     get a pseudo-text window in GTIA modes, POKE the mode
     number here and then POKE 623 with 64 for mode nine, 128 for
     mode ten, and 192 for mode eleven, then POKE 703 with four, in
     program mode. (In command mode, you will be returned to
     GR.0.) You won't be able to read the text in the window, but you
     will be able to write to it. However, to get a true text window,
     you'll need to use a Display List Interrupt (see COMPUTE!,
     September 1982). If you don't have the GTIA chip, it is still
     possible to simulate those GRAPHICS modes by using DINDEX
     with changes to the Display List Interrupt. See COMPUTE!, July
     1981, for an example of simulating GR.10.
88,89          	58,59          	SAVMSC
 
-      The lowest address of the screen memory, corresponding to the
     upper left corner of the screen (where the value at this address
     will be displayed). The upper left corner of the text window is
     stored at locations 660, 661 ($294, $295).
     You can verify this for yourself by:
     WINDOW = PEEK(88) + PEEK(89) * 256: POKE WINDOW,33
     This will put the letter "A" in the upper left corner in GR.0, 1 and
     2. In other GRAPHICS modes, it will print a colored block or
     bar. To see this effect, try:
     5   REM FIRST CLEAR SCREEN
     10  GRAPHICS Z: IF Z > 59 THEN END
     15  SCREEN = PEEK (88) + PEEK (89) *
        256
     20  FOR N = 0 TO 255: POKE SCREEN + N
        ,N
     25  NEXT N: FOR N = 1 TO 300: NEXT N:
          Z = Z + 1
     30  GOTO 10
     
     DOWNLOAD SAVEMSC1.BAS
     You will notice that you get the Atari internal character code, not
     the ATASCII code. See also locations 560, 561 ($230, $231) and
     57344 ($E000).
     How do you find the entire screen RAM? First, look at the chart
     below and find your GRAPHICS mode. Then you multiply the
     number of rows-per-screen type by the number of bytes-per-line.
     This will tell you how many bytes each screen uses. Add this
     value, minus one, to the address specified by SAVMSC.
     However, if you subtract MEMTOP (locations 741, 742; $2E5,
     $2E6) from RAMTOP (106; $6A * 256 for the number of bytes),
     you will see that there is more memory reserved than just the
     screen area. The extra is taken up by the display list or the text
     window, or is simply not used (see the second chart below).
     Mode          0    1    2    3    4    5    6    7    8 9-12
     Rows
     Full         24   24   12   24   48   48   96   96  192  192
     Split        --   20   10   20   40   40   80   80  160  --
     Bytes per
     Line         40   20   20   10   10   20   20   40   40   40
     Columns
     per Line     40   20   20   40   80   80  160  160  320   80
     Memory (1)  993  513  261  273  537 1017 2025 3945 7900 7900
     Memory (2)
     Full        992  672  420  432  696 1176 2184 4200 8138 8138
     Split        --  674  424  434  694 1174 2174 4190 8112  --
     (1) According to the Atari BASIC Reference Manual, p.45; OS
     User's Manual, p.172, and Your Atari 400/800, p.360.
     (2) According to Your Atari 400/800, p.274, and Atari Microsoft
     Basic Manual, p.69. This is also the value you get when you
     subtract MEMTOP from RAMTOP (see above).
     For example, to POKE the entire screen RAM in GR.4, you
     would find the start address of the screen (PEEK(88) + PEEK(89)
     * 256), then use a FOR-NEXT loop to POKE all the locations
     specified above:
     10   GRAPHICS 4: SCRN = PEEK(88) + PE
        EK(89) * 256
     20   FOR LOOP = SCRN to SCRN + 479: R
        EM 48 ROWS * 10 BYTES - 1
     30   POKE LOOP,35: NEXT LOOP
     
     DOWNLOAD SAVEMSC2.BAS
     Why the minus one in the calculation? The first byte of the screen
     is the first byte in the loop. If we add the total size, we will go one
     byte past the end of the soreen, so we subtract one from the total.
     Here's how to arrive at the value for the total amount ot memory
     located for screen use, display list and Text window:
               Total memory allocation for the screen
                      Screen display       Display List
     -----------------------------------------------------------
          Text    unused  bytes  screen    unused  used
     GR  window   always  cond.   use      bytes   bytes   Total
     -----------------------------------------------------------
     0    ...      none   none    960      none      32      992
     1    160      none     80    400      none      34      674
     2    160      none     40    200      none      24      424
     3    160      none     40    200      none      34      434
     4    160      none     80    400      none      54      694
     5    160      none    160    800      none      54     1174
     6    160      none    320   1600      none      94     2174
     7    160      none    640   3200        96      94     4190
     8    160        16   1280   6400        80     176     8112
     The number of bytes from RAMTOP (location 106; $6A) is counted
     from the left text window column towards the total column.
     MEMTOP (741, 742; $2E5, $2E6) points to one byte below
     RAMTOP * 256 minus the number of bytes in the total column. If
     16 is added to the GRAPHICS mode (no text window), then the
     conditional unused bytes are added to the total. Then the bytes
     normally added for the text window become unused, and the
     Display List expands slightly. (See COMPUTE!, September 1981.)
     When you normally PRINT CHR$(125) (clear screen), Atari sends
     zeroes to the memory starting at locations 88 and 89. It continues to
     do this until it reaches one byte less than the contents of RAMTQP
     (location 106; $6A). Here is a potential source of conflict with your
     program, however: CHR$(125)--CLEAR SCREEN--and any
     GRAPHICS command actually continue to clear the first 64 ($40)
     bytes above RAMTOP!
     It would have no effect on BASIC since BASIC is a ROM
     cartridge. The OS Source Listing seems to indicate that it ends at
     RAMTOP, but Atari assumed that there would be nothing after
     RAMTOP, so no checks were provided. Don't reserve any data
     within 64 bytes of RAMTOP or else it will be eaten by the CLEAR
     SCREEN routine, or avoid using a CLEAR SCREEN or a
     GRAPHICS command. Scrolling the text window also clears 800
     bytes of memory above RAMTOP.
     You can use this to clear other areas of memory by POKEing the
     LSB and MSB of the area to be cleared into these locations. Your
     routine should always end on a $FF boundary (RAMTOP indicates
     the number of pages). Remember to POKE back the proper screen
     locations or use a GRAPHICS command immediately after doing
     so to set the screen right. Try this:
     10  BOTTOM = 30000: TOP = 36863: REM
        LOWEST AND HIGHEST ADDRESS TO CLEA
        R = $7530 & $8FFF
     20  RAMTOP = PEEK(106): POKE 106, INT
        (TOP + 1 / 256)
     30  TEST = INT(BOTTOM / 256): POKE89,
         TEST
     40  POKE 88. BOTTOM - 256 * TEST
     50  PRINT CHR$(125): POKE 106, RAMTOP
     60  GRAPHICS 0
     
     DOWNLOAD SAVEMSC3.BAS
     This will clear the specified memory area and update the address
     of screen memory. If you don't specify TOP, the CLEAR SCREEN
     will continue merrily cleaning out memory and, most likely, will
     cause your program to crash. Use it with caution.
     Here's a means to SAVE your current GR.7 screen display to disk
     using BASIC:
     1000  SCREEN = PEEK(88) + PEEK(89) *
          256
     1010  OPEN #2,8,0,"D:picturename"
     1020  MODE = PEEK(87): PUT #2, MODE:
          REM SAVE GR. MODE
     1030  FOR SCN = 0 TO 4: COL PEEK(70
          8 + SCN): PUT #2,COL: NEXT SCN:
          REM SAVE COLOR REGISTERS
     1040  FOR TV = SCREEN TO SCREEN + 319
          9:BYTE = PEEK(TV): PUT #2, BYTE:
          NEXT TV: CLOSE #2
          
     DOWNLOAD SAVEMSC4.BAS
     To use this with other screen modes, you will have to change the
     value of 3199 in line 1040 to suit your screen RAM (see the chart
     above). For example, GR.7 + 16 would require 3839 bytes (3840
     minus one). You can use the same routine with cassette by using
     device C:. To retrieve your picture, you use GET#2 and POKE 
     commands. You will, however, find both routines very slow. Using
     THE CIO routine at 58454 ($E456) and the IOCBs, try this machine
     language save routine:
     10  DIM ML$(10): B$(10): GR.8+16
     20  B$ = "your picture name":Q = PEEK
        (559)
     30  FOR N = 1 TO 6: READ BYTE: ML$(N,
        N) = CHR$(BYTE): NEXT N
     35  DATA 104,162,16,76,86,228
     36  REM PLA,LDX,$10,JMP $E456
     40  OPEN #1,4,0,B$
     50  POKE 849,1: POKE 850,7: POKE 852,
        PEEK(88): POKE 853,PEEK(89): POKE
        856,70: POKE 857,30: POKE 858,4
     55  REM THESE POKES SET UP THE IOCB
     60  POKE 559,0: REM TURN OFF THE SCRE
        EN TO SPEED THINGS UP
     70  X = USR(ADR(ML$)): CLOSE #1
     80  POKE 559,Q: REM TURN IT BACK ON A
        GAIN
        
     DOWNLOAD SAVEMSC5.BAS
     Note that there is no provision to SAVE the color registers in this
     program, so I suggest you have them SAVEd after you have
     SAVEd the picture. It will make it easier to retrieve them if they are
     at the end of the file. You will have to make suitable adjustments
     when SAVEing a picture in other than GR.8 + 16 -- such as
     changing the total amount of screen memory to be SAVEd, POKEd
     into 856 and 857. Also, you will need a line such as 1000 GOTO
     1000 to keep a GTIA or + 16 mode screen intact. See the Atari
     column in InfoAge Magazine, July 1982, for more on this idea. See
     location 54277 ($D405) for some ideas on scrolling the screen
     RAM.
------------------------------------------------------------------------
A SHORT DIGRESSION
There are two techniques used in this hook for calling a machine
language program from BASIC with the USR command. One method
is to POKE the values into a specific address -- say, page six -- and
use the starting address for the USR call, such as X = USR(1536). For
an example of this technique, see location 632 ($278).
The other technique, used above, is to make a string (ML$) out of the
routine by assigning to the elements of the string the decimal
equivalents of the machine language code by using a FOR-NEXT and
READ-DATA loop. To call this routine, you would use X =
USR(ADR(ML$)). This tells the Atari to call the machine language
routine located at the address where ML$ is stored. This address will
change with program size and memory use. The string method won't
be overwritten by another routine or data since it floats around safely
in memory. The address of the string itself is stored by the string/array
table at location 140 ($8C).
------------------------------------------------------------------------
90          	5A          	OLDROW
 
-      Previous graphics cursor row. Updated from location 84 ($54)
     before every operation. Used to determine the starting row for
     the DRAWTO and XIO 18 (FILL command).
91,92          	5B,5C          	OLDCOL
 
-      Previous graphics cursor column. Updated from locations 85 and
     86 ($55, $56) before every operation. These locations are used by
     the DRAWTO and XIO 18 (FILL) commands to determine the
     starting column of the DRAW or FILL
93          	5D          	OLDCHR
 
-      Retains the value of the character under the cursor used to
     restore that character when the cursor moves
94,95          	5E,5F          	OLDADR
 
-      Retains the memory location of the current cursor location. Used
     with location 93 (above) to restore the character under the cursor
     when the cursor moves
96          	60          	NEWROW
 
-      Point (row) to which DRAWTO and XIO 18 (FILL) will go.
97,98          	61,62          	NEWCOL
 
-      Point (column) to which DRAWTO and XIO 18 (FILL) will go.
     NEWROW and NEWCOL are initialized to the values in
     ROWCRS and COLCRS (84 to 86; $54 to $56) above, which
     represent the destination end point of the DRAW and FILL
     functions. This is done so that ROWCRS and COLCRS can be
     altered during these routines.
99          	63          	LOGCOL
 
-      Position of the cursor at the column in a logical line. A logical
     line can contain up to three physical lines, so LOGCOL can
     range between zero and 119. Used by the display handler.
  
100,101          	64,65          	ADRESS
 
-      Temporary storage used by the display handler for the Display
     List address, line buffer (583 to 622; $247 to $26E), new MEMTOP
     value after DL entry, row column address, DMASK value, data to
     the right of cursor, scroll, delete, the clear screen routine and for
     the screen address memory (locations 88, 89; $58, $59).
102,103          	66,67          	MLTTMP
 
-      Also called OPNTMP and TOADR; first byte used in OPEN as
     temporary storage. Also used by the display handler as
     temporary storage.
104,105          	68,69          	SAVADR
 
-      Also called FRMADR. Temporary storage, used with ADRESS
     above for the data under the cursor and in moving line data on
     the screen.
106          	6A          	RAMTOP
 
-      RAM size, defined by powerup as passed from TRAMSZ (location
     6), given in the total number of available pages (one page equals
     256 bytes, so PEEK(106) * 256 will tell you where the Atari thinks
     the last usable address --byte-- of RAM is). MEMIOP (741,
     742; $2E5. $2E6) may not extend below this value. In a 48K Atari,
     RAMTOP is initialized to 160 ($A0), which points to location
     40960 ($A000). The user's highest address will be one byte less
     than this value.
     This is initially the same value as in location 740. PEEK(740) / 4 or
     PEEK(106) / 4 gives the number of 1K blocks. You can fool the
     computer into thinking you have less memory than you actually
     have, thus reserving a relatively safe area for data (for your new
     character set or player/missile characters, for example) or
     machine language subroutines by:
     POKE(106), PEEK(106) - # of pages you want to reserve.
     The value here is the number of memory pages (256-byte blocks)
     present. This is useful to know when changing GR.7 and GR.8
     screen RAM. If you are reserving memory for PM graphics,
     POKE 54279, PEEK(106) - # of pages you are reserving before
     you actually POKE 106 with that value. To test to see if you have
     exceeded your memory by reserving too much memory space,
     you can use:
     10   SIZE = (PEEK(106) - # of pages)
        * 256
     20   IF SIZE < = PEEK(144) + PEEK(145
        ) * 256 THEN PRINT "TOO MUCH MEMOR
        Y USED"
     If you move RAMTOP to reserve memory, always issue a
     GRAPHICS command (even issuing one to the same GRAPHICS
     mode you are in will work) immediately so that the display list
     and data are moved beneath the new RAMTOP.
     You should note that a GRAPHICS command and a CLEAR
     command (or PRINT CHR$(125)) actually clear the first 64 bytes
     above RAMTOP (see location 88; $58 for further discussion).
     Scrolling the text window of a GRAPHICS mode clears up to 800
     ($320) bytes above RAMTOP (the text window scroll actually
     scrolls an entire GR.0 screen-worth of data, so the unseen 20
     lines * 40 bytes equals 800 bytes). PM graphics may be safe
     (unless you scroll the text window) since the first 384 or 768 bytes
     (double or single line resolution, respectively) are unused.
     However, you should take both of these effects into account when
     writing your programs.
     To discover the exact end of memory, use this routine (it's a tad
     slow):
     10  RAMTOP = 106: TOP = PEEK(RAMTOP)
     20  BYTE = TOP * 256: TEST = 255 - PE
        EK(BYTE): POKE BYTE,TEST
     30  IF PEEK(BYTE) = TEST THEN TOP = T
         OP +1: POKE BYTE, 255 - TEST
     40  GOTO 20
     50  PRINT "MEMORY ENDS AT "; BYTE
     One caution: BASIC cannot always handle setting up a display
     list and display memory for GRAPHICS 7 and GRAPHICS 8
     when you modify this location by less than 4K (16 pages; 4096
     bytes). Some bizarre results may occur if you use PEEK(106) - 8
     in these modes, for example. Use a minimum of 4K (PEEK(106) -
     16) to avoid trouble. This may explain why some people have
     difficulties with player/missile graphics in the hi-res (high
     resolution; GR.7 and GR.8) modes. See location 54279 ($D407).
     Another alternative to reserving memory in high RAM is to save
     an area below MEMLO, location 743 ($2E7: below your BASIC
     program). See also MEMTOP, locations 741, 742 ($2E5, $2E6).
107          	6B          	BUFCNT
 
-      Buffer count: the screen editor current logical line size counter.
108,109          	6C,6D          	BUFSTR
 
-      Editor low byte (AM). Display editor GETCH routine pointer
     (location 62867 for entry; $F593). Temporary storage; returns the
     character pointed to by BUFCNT above.
110          	6E          	BITMSK
 
-      Bit mask used in bit mapping routines by the OS display handler
     at locations 64235 to 64305 ($FAEB to $FB31). Also used as a
     display handler temporary storage register.
111          	6F          	SHFAMT
 
-      Pixel justification: the amount to shift the right justified pixel data
     on output or the amount to shift the input data to right justify it.
     Prior to the justification process, this value is always the same as
     that in 672 ($2A0).
112,113          	70,71          	ROWAC
 
-      ROWAC and COLAC (below) are both working accumulators for
     the control of row and column point plotting and the increment 
     and decrement functions.
114,115          	72,73          	COLAC
 
-      Controls column point plotting.
116,117          	74,75          	ENDPT
 
-      End point of the line to be drawn. Contains the larger value of
     either DELTAR or DELTAC (locations 118 and 119, below) to be
     used in conjunction with ROWAC/COLAC (locations 112 and
     114, above) to control the plotting of line points.
118          	76          	DELTAR
 
-      Delta row; contains the absolute value of NEWBOW (location 96;
     $60) minus ROWCRS (location 84; $54).
119,120          	77,78          	DELTAC
 
-      Delta column; contains the absolute value of NEWCOL (location
     97; $61) minus the value in COLCRS (location 85; $55). These
     delta register values, along with locations 121 and 122 below, are
     used to define the slope of the line to be drawn.
121          	79          	ROWINC
 
-      The row increment or decrement value (plus or minus one).
122          	7A          	COLINC
 
-      The column increment or decrement value (plus or minus one).
     ROWINC and COLINC control the direction of the line drawing
     routine. The values represent the signs derived from the value in
     NEWROW (location 96; $60) minus the value in ROWCRS
     (location 84; $54) and the value in NEWCOL (locations 97, 98;
     $61, $62) minus the value in COLCRS (locations 85, 86; $55,
     $56).
123          	7B          	SWPFLG
 
-      Split-screen cursor control. Equal to 255 ($FF) if the text window
     RAM and regular RAM are swapped; otherwise, it is equal to
     zero. In split-screen modes, the graphics cursor data and the text
     window data are frequently swapped in order to get the values
     associated with the area being accessed into the OS data base
     locations 84 to 95 ($54 to $5F). SWPFLG helps to keep track of
     which data set is in these locations.
124          	7C          	HOLDCH
 
-      A character value is moved here before the control and shift logic
     are processed for it.
125          	7D          	INSDAT
 
-      Temporary storage byte used by the display handler for the
     character under the cursor and end of line detection.
126,127          	7E,7F          	COUNTR
 
-      Starts out containing the larger value of either DELTAR (location
     118; $76) or DELTAC (location 119; $77). This is the number of
     iterations required to draw a line. As each point on a line is
     drawn, this value is decremented. When the byte equals zero, the
     line is complete (drawn).
---------------------------------------------------------------------
User and/or BASIC page zero RAM begins here. Locations 128 to 145
($80 to $91) are for BASIC program pointers; 146 to 202 ($92 to $CA)
are for miscellaneous BASIC RAM; 203 to 209 ($CB to $D1) are
unused by BASIC, and 210 to 255 ($D2 to $FF) are the floating point
routine work area. The Assembler Editor cartridge uses locations 128
to 176 ($80 to $B0) for its page zero RAM. Since the OS doesn't use this
area, you are free to use it in any non-BASIC or non-cartridge
environment. If you are using another language such as FORTH,
check that program's memory map to see if any conflict will occur.
See COMPUTE!'s First Book of Atari, pages 26 to 53, for a discussion
of Atari BASIC structure, especially that using locations 130 to 137
($82 to $89). Included in the tutorials are a memory analysis, a line
dump, and a renumber utility. See also De Re Atari, BYTE, February
1982, and the locations for the BASIC ROM 40960 to 49151 ($A000 to
$BFFF).
128,129          	80,81          	LOMEM
 
-      Pointer to BASIC's low memory (at the high end of OS RAM
     space). The first 256 bytes of the memory pointed to are the token
     output buffer, which is used by BASIC to convert BASIC
     statements into numeric representation (tokens; see locations
     136, 137; $88, $89). This value is loaded from MEMLO (locations
     743, 744; $2E7, $2E8) on initialization or the execution of a NEW
     command (not on RESET!). Remember to update this value when
     changing MEMLO to reserve space for drivers or buffers.
     When a BASIC SAVE is made, two blocks of information are
     written: the first block is the seven pointers from LOMEM to
     STARP (128 to 141; $80 to $8D). The value of LOMEM is
     subtracted from each of these two-byte pointers in the process, so
     the first two bytes written will both be zero. The second block
     contains the following: the variable name table, the variable
     value table, the tokenized program, and the immediate mode
     line.
     When a BASIC LOAD is made, BASIC adds the value at MEMLO
     (743, 744; $2E7, $2E8) to each of the two-byte pointers SAVEd as
     above. The pointers are placed back in page zero, and the values
     of RUNSTK (142, 143; $8E, $8F) and MEMTOP (144, 145; $90,
     $91) are set to the value in STARP. Then 256 bytes are reserved
     above the value in MEMLO for the token output buffer, and the
     program is read in immediately following this buffer.
     When you don't have DOS or any other application program
     using low memory loaded, LOMEM points to 1792 ($700). When
     DOS 2.0 is present, it points to 7420 ($1CFC). When you change
     your drive and data buffer defaults (see 1801, 1802; $709, $70A),
     you will raise or lower this figure by 128 bytes for each buffer
     added or deleted, respectively. When you boot up the RS-232
     handler, add another 1728 ($6C0) bytes used.
     LOMEM is also called ARGOPS by BASIC when used in
     expression evaluation. When BASIC encounters any kind of
     expression, it puts the immediate results into a stack. ARGOPS
     points to the same 256 byte area; for this operation it is reserved
     for both the argument and operator stack. It is also called
     OUTBUFF for another operation, pointing to the same 256 byte
     buffer as ARGOPS points to. Used by BASIC when checking a
     line for syntax and converting it to tokens. This buffer
     temporarily stores the tokens before moving them to the
     program. 
130,131          	82,83          	VNTP
 
-      Beginning address of the variable name table. Variable names
     are stored in the order input into your program, in ATASCII
     format. You can have up to 128 variable names. These are stored
     as tokens representing the variable number in the tokenized
     BASIC program, numbered from 128 to 255 ($80 to $FF).
     The table continues to store variable names, even those no longer
     used in your program and those used in direct mode entry. It is
     not cleared by SAVEing your program. LOADing a new program
     replaces the current VNT with the one it retrieves from the file.
     You must LIST the program to tape or disk to save your program
     without these unwanted variables from the table. LIST does not
     SAVE the variable name or variable value tables with your
     program. It stores the program in ATASCII, not tokenized form,
     and requires an ENTER command to retrieve it. You would use a
     NEW statement to clear the VNT in memory once you have
     LISTed your program.
     Each variable name is stored in the order it was entered, not the
     ATASCII order. With numeric (scalar) variables, the MSB is set
     on the last character in a name. With string variables, the last
     character is a "$" with the MSB (BIT 7) set. With array variables,
     the last character is a "(" with the MSB set. Setting the MSB turns
     the character into its inverse representation so it can be easily
     recognized.
     You can use variable names for GOSUB and GOTO routines,
     such as:
     10  CALCULATE = 1000
     .
     .
     100  GOSUB CALCULATE
     This can save a lot of bytes for a frequently called routine. But
     remember, each variable used for a GOSUB or GOTO address
     uses one of the 128 possible variable names. A disadvantage of
     using variable names for GOTO and GOSUB references is when
     you try to use a line renumbering program. Line renumbering
     programs will not change references to lines with variable
     names, only to lines with numbered references.
     Here's a small routine you can add to the start of your BASIC
     program (or the end if you change the line numbers) to print out
     the variable names used in your program. You call it up with a
     GOTO statement in direct mode:
     1   POKE 1664, PEEK(130): POKE 1665,
        PEEK (131)
     2   IF PEEK(1664) = PEEK(132) THEN IF
        PEEK(1665) = PEEK(133) THEN STOP
     3   PRINT CHR$(PEEK(PEEK(1664) + PEEK
       (1665) * 256)));
     4   IF PEEK(PEEK(1664) + PEEK(1665) *
        256)) > 127 THEN PRINT"";
     5   IF PEEK(1664) = 255 THEN POKE 166
       4, 0: POKE 1665, PEEK(1665) + 1: GO
       TO 2
     6   POKE 1664, PEEK(1664) + 1: GOTO 2
     
     DOWNLOAD VNTP.BAS
     See COMPUTE!, October 1981.
132,133          	84,85          	VNTD
 
-      Pointer to the ending address of the variable name table plus one
     byte. When fewer than 128 variables are present, it points to a
     dummy zero byte. When 128 variables are present, this points to
     the last byte of the last variable name, plus one.
     It is often useful to be able to list your program variables; using
     locations 130 to 133, you can do that by:
     10   VARI = PEEK(130) + PEEK(131) * 2
        56 :REM This gives you the start o
        f the table.
     20   FOR VARI = VARI TO PEEK(132) + P
        EEK(133) * 256 - 1: PRINT CHR$(PEE
        K(VARI) - 128 * PEEK(VARI > 127));
         CHR$(27 + 128 * PEEK(VARI) > 127)
        );:NEXT VARI
     25   REM this finds the end of the va
        ri able name table (remember table
        is end + 1). then PRINTs ASCII cha
        racters < 128
     30   NUM = 0: FOR VARI = PEEK(130) +
        PEEK(313) * 256 TO PEEK(132) + PEE
        K(131) * 256 - 1:NUM = NUM + (PEEK
        (VARI) < 127):NEXT VARI: PRINT NU
        M; "Variables in use"
        
     DOWNLOAD VNTD1.BAS
Or try this, for a possibly less opaque example of the same
routine:
     1000  NUM = 0: FOR LOOP = PEEK (130) +
           PEEK(131) * 256 TO PEEK(132) +
           PEEK(133) * 256 - 1
     1010  IF PEEK(LOOP) < 128 THEN PRINT
          CHR$(PEEK(LOOP));: GOTO 1030
     1020  PRINT CHR$(PEEK(LOOP) - 128): N
          UM - NUM + 1
     1030  NEXT LOOP: PRINT; PRINT NUM; "
          VARIABLES IN USE": END
          
     DOWNLOAD VNTD2.BAS
134,135          	86,87          	VVTP
 
-      Address for the variable value table. Eight bytes are allocated for
     each variable in the name table as follows:
     Byte              1         2     3  4     5     6    7      8
     Variable
     --------------------------------------------------------------
     Scalar           00     var #     six byte BCD constant
     Array;DIMed      65     var #     offset     first     second
         unDIMed      64               from       DIM + 1   DIM + 1
                                       STARP
     String;DIMed    129     var #     offset     length    DIM
          unDIMed    128               from
                                       STARP
     In scalar (undimensioned numeric) variables, bytes three to eight
     are the FP number; byte three is the exponent; byte four contains
     the least significant two decimal digits, and byte eight contains
     the most significant two decimal digits.
     In array variables, bytes five and six contain the size plus one of
     the first dimension of the array (DIM + 1; LSB/MSB), and bytes
     seven and eight contain the size plus one of the second dimension
     (the second DIM + 1; LSB/MSB).
     In string variables, bytes five and six contain the current length
     of the variable (LSB MSB), and bytes seven and eight contain the
     actual dimension (up to 32767). There is an undocumented
     BASIC statement, "COM," mentioned only in the BASIC
     Reference Manual's index, which executes exactly the same as
     the "DIM" statement (see Your Atari 400/800, p.346). Originally,
     it was to be used to implement "common" variables.
     In all cases, the first byte is always one of the number listed on the 
     chart above (you will seldom, if ever, see the undimensioned 
     values in a program). This number defines what type of variable 
     information will follow. The next byte, var # (variable number), is
     in the range from zero to 127. Offset is the number of bytes from
     the beginning of STARP at locations 140 and 141 ($8C, $8D).
     Since each variable is assigned eight bytes, you could find the
     values for each variable by:
     1000  VVTP = PEEK(134) + PEEK(135) *
          256: INPUT VAR: REM VARIABLE NUM
          BER
     1010  FOR LOOP = 0 TO 7: PRINT PEEK(V
          VTP + LOOP + 8 * VAR): NEXT LOOP
     where VAR is the variable number from zero to 127.
     If you wish to assign the same value to every element in a DIMed
     string variable use this simple technique:
     10   DIM TEST$(100)
     20   TEST$ = "*": REM or use TEST$(1)
     30   TEST$(100) = TEST$
     40   TEST$(2) = TEST$: PRINT TEST$
     By assigning the first, last and second variables in the array in
     that order, your Atari will then assign the same value to the rest of
     the array. Make sure you make the second and last elements
     equal to the string, not the character value (i.e don't use
     TEXT$(2) = "*").
     See De Re Atari for an example of SAVEing the six-byte BCD
     numbers to a disk file -- very useful when dealing with fixed
     record lengths.
136,137          	88,89          	STMTAB
 
-      The address of the statement table (which is the beginning of the
     user's BASIC program), containing all the tokenized lines of
     code plus the immediate mode lines entered by the user. Line
     numbers are stored as two-byte integers, and immediate mode
     lines are given the default value of line 32768 ($8000). The first
     two bytes of a tokenized line are the line number, and the next is
     a dummy byte reserved for the byte count (or offset) from the start
     of this line to the start of the next line.
     Following that is another count byte for the start of this line to the
     start of the next statement. These count values are set only when
     tokenization for the line and statement are complete.
     Tokenization takes place in a 256 byte ($100) buffer that resides at
     the end of the reserved OS RAM (pointed to by locations 128,
     129; $80, $81).
     To see the starting address of your BASIC line numbers use this
     routine:
     10   STMTAB = PEEK(136) + PEEK(137)*2
        56
     20   NUM = PEEK(STMTAB) + PEEK (STMTAB
        +1)*256
     30   IF NUM = 32768 THEN END
     40   PRINT"LINE NUMBER: ";NUM;" ADDRE
        SS: ";STMTAB
     50   STMTAB = STMTAB + PEEK(STMTAB+2)
     60   GOTO 20
     The August 1982 issue of ANTIC provided a useful program to
     delete a range of BASIC line numbers. The routine can be
     appended to your program and even be used to delete itself.
138,139          	8A,8B          	STMCUR
 
-      Current BASIC statement pointer, used to access the tokens
     being currently processed within a line of the statement table.
     When BASIC is awaiting input, this pointer is set to the
     beginning of the immediate mode (line 32768).
     Using the address of the variable name table, the length, and the
     current statement (locations 130 to 133, 138, 139), here is a way to
     protect your programs from being LISTed or LOADed: they can
     only be RUN! Remember, that restricts you too, so make sure you
     have SAVEd an unchanqed version before you do this:
     32000   FOR VARI = PEEK(130) + PEEK(1
           31) * 256 TO PEEK(132) + PEEK(1
           33) * 256:POKE VARI,155:NEXT VA
           RI
     32100   POKE PEEK(138) + PEEK(139) *
           256 + 2,0: SAVE "D:filename": N
           EW
     This will cause all variable names to be replaced with a RETURN
     character. Other characters may be used: simply change 155 for
     the appropriate ATASCII code for the character desired. Make
     sure that these are the last two lines of your program and that
     NEW is the last statement. CLOAD will not work, but a filename
     with C: will.
140,141          	8C,8D          	STARP
 
-      The address for the string and array table and a pointer to the end
     of your BASIC program. Arrays are stored as six-byte binary
     coded decimal numbers (BCD) while string characters use one
     bye each. The address of the strings in the table are the same as
     those returned by the BASIC ADR function. Always use this
     function under program control, since the addresses in the table
     change according to your program size. Try:
     10   DIM A$(10),B$(10)
     20   A$ = "*": A$(10) = A$: A$(2) = A
        $
     30   B$ = "&": B$(10) = B$: B$(2) = B
        $
     40   PRINT ADR(A$), ADR(B$)
     50   PRINT PEEK(140) + PEEK(141) * 25
        6: REM ADDRESS OF A$
     60   PRINT PEEK(140) + PEEK(141) * 25
        6 + 10: REM ADRESS OF A$ + 10 BYTE
        S = ADDRESS OF B$
     This table is expanded as each dimension is processed by
     BASIC, reducing available memory. A ten-element numeric
     array will require 60 bytes for storage. An array variable such as
     DIM A(100) will cost the program 600 bytes (100 * six per
     dimensioned number equals 600). On the other hand, a string
     array such as DIM A$(100) will only cost 100 bytes! It would save
     a lot of memory to write your arrays as strings and retrieve the
     array values using the VAL statement. For example:
     10   DIM A$(10): A$ = "1234567890"
     20   PRINT VAL(A$)
     30   PRINT VAL(A$(4,4))
     40   PRINT VAL(A$(3,3))+VAL(A$(8,9))
     See COMPUTE!, June 1982, for a discussion of STARP and
     VVTP. See De Re Atari for a means to SAVE the string/array area
     with your program.
142,143          	8E,8F          	RUNSTK
 
-      Address of the runtime stack which holds the GOSUB entries	
     (four bytes each) and the FOR-NEXT entries (16 bytes each). The
     POP command in BASIC affects this stack, pulling entries off it
     one at a time for each POP executed. The stack expands and
     contracts as necessary while the program is running.
     Each GOSUB entry consists of four bytes in this order: a zero to
     indicate a GOSUB, a two-byte integer line number on which the
     call occurred, and an offset into that line so the RETURN can
     come back and execute the next statement.
     Each FOR-NEXT entry contains 16 bytes in this order: first, the
     limit the counter variable can reach; second, the step or counter
     increment. These two are allocated six bytes each in BCD format
     (12 bytes total). The 13th byte is the counter variable number with
     the MSB set; the 14th and 15th are the line number and the 16th is
     the line offset to the FOR statement.
     RUNSTK is also called ENDSTAR; it is used by BASIC to point to
     the end of the string/array space pointed to by STARR above.
144,145          	90,91          	MEMTOP
 
-      Pointer to the top of BASIC memory, the end of the space the
     program takes up. There may still be space between this address
     and the display list, the size of which may be retrieved by the
     FRE(0) command (which actually subtracts the MEMTOP value
     that is at locations 741 and 742; $2E5, $2E6). Not to be confused
     with locations 741 and 742, which have the same name but are an
     OS variable. MEMTOP is also called TOPSTK; it points to the top
     of the stack space pointed to by RUNSTK above.
     When reserving memory using location 106 ($6A) and MEMTOP,
     here's a short error-trapping routine you can add:
     10   SIZE = (PEEK(106) - # of pages yo
        u are reserving) * 256
     20   IF SIZE < = PEEK(144) + PEEK(145
        ) * 256 THEN PRINT " PROGRAM TOO L
        ARGE": END
     Locations 146 to 202 ($92 to $CA) are reserved for use by the 8K
     BASIC ROM.
     Locations 176 to 207 ($B0 to $CF) are reserved by the Assembler
     Editor cartridge for the user's page zero use. The Assembler debug
     routine also reserves 30 bytes in page zero, scattered from location 164
     ($A4) to 255 ($FF), but they cannot be used outside the debug process.
     (See De Re Atari, Rev. 1, Appendix A for a list of these available
     bytes.)
186,187          	BA,BB          	STOPLN
 
-      The line where a program was stopped either due to an error or
     the use of the BREAK key, or a STOP or a TRAP statement
     occurred. You can use PEEK (186) + PEEK (187) * 256 in a
     GOTO or GOSUB statement.
195          	C3          	ERRSAVE
 
-      The number of the error code that caused the stop or the TRAP.
     You can use this location in a program in a line such as:
     10 IF PEEK(195) <> 144 THEN 100
201          	C9          	PTABW
 
-      This location specifies the number of columns between TAB
     stops. The first tab will beat PEEK(201). The default is ten. This is
     the value between items separated in a PRINT statement by com-
     mas -- such as PRINT AS, LOOP, C(12) -- not by the TAB key
     spacing.
     The minimum number of spaces between TABS is three. If you
     POKE 201,2, it will be treated as four spaces, and POKE 201,1 is
     treated as three spaces. POKE 201,0 will cause the system to
     hang when it encounters a PRINT statement with commas. To
     change the TAB key settings, see TABMAP (locations 675 to 689;
     $2A3 - $2B1). PTABW is not reset to the default value by pressing
     RESET or changing GRAPHICS modes (unlike TABMAP).
     PTABW works in all GRAPHICS modes, not merely in text
     modes. The size of the spaces between items depends on the pixel
     size in the GRAPHICS mode in use. For example, in GR.0, each
     space is one character wide, while in GR.8 each space is one-half
     color clock (one dot) wide.
203-207          	CB-CF          	....
 
-      Unused by either the BASIC or the Assembler cartridges.
208-209          	D0-D1          	....
 
-      Unused by BASIC. The only time I have seen any of these unused
     locations in use is in COMPUTE! (March 1982 and October
     1981), when they were used for user sort routines, and in ANTIC
     (June 1982), where they were used as flags in a graphic
     demonstration. The bytes from 203 to 209 ($CB to $D1) are the
     only page zero bytes uncontestably left free by BASIC.
210-211          	D2-D3          	....
 
-      Reserved for BASIC or other cartridge use.
Locations 212 to 255 ($D4 to $FF) are reserved for the floating point
package use. The FP routines are in ROM, from locations 55296 to
57393 ($D800 to $E031). These page zero locations may be used if the
FP package is not called by the user's program. However, do not use
any of these locations for an interrupt routine, since such routines
might occur during an FP routine called by BASIC, causing the
system to crash.
Floating Point uses a six-byte precision. The first byte of the Binary
Coded Decimal (BCD) number is the exponent (where if BIT 7 equals
zero, then the number is positive; if one, then it is negative). The next
five bytes are the mantissa. If only that were all there was to it. The
BCD format is rather complex and is best explained in chapter eight of
De Re Atari.
212-217          	D4-D9          	FR0
 
-      Floating point register zero; holds a six-byte internal form of the
     FP number. The value at locations 212 and 213 are used to return
     a two-byte hexadecimal value in the range of zero to 65536
     ($FFFF) to the BASIC program (low byte in 212, high byte in
     213). The floating point package, if used, requires all locations
     from 212 to 255. All six bytes of FR0 can be used by a machine
     language routine, provided FR0 isn't used and no FP functions
     are used by that routine. To use 16 bit values in FP, you would
     place the two bytes of the number into the least two bytes of FR0
     (212, 213; $D4, $D5), and then do a JSR to $D9AA (55722), which
     will convert the integer to its FP representation, leaving the result
     in FR0. To reverse this operation, do a JSR to $D9D2 (55762).
218-223          	DA-DF          	FRE
 
-      FP extra register (?)
224-229          	E0-E5          	FR1
 
-      Floating point register one; holds a six-byte internal form of the
     FP number as does FR0. The FP package frequently transfers
     data between these two registers and uses both for two-number
     arithmetic operations.
230-235          	E6-EB          	FR2
 
-      FP register two.
236          	EC          	FRX
 
-      FP spare register.
237          	ED          	EEXP
 
-      The value of E (the exponent).
238          	EE          	NSIGN
 
-      The sign of the FP number.
239          	EF          	ESIGN
 
-      The sign of the exponent.
240          	F0          	FCHRFLG
 
-      The first character flag.
241            Fl             DIGRT
     The number of digits to the right of the decimal.
242          	F2          	CIX
 
-      Character (current input) index. Used as an offset to the input
     text buffer pointed to by INBUFF below.
243,244          	F3,F4          	INBUFF
 
-      Input ASCII text buffer pointer; the user's program line input
     buffer, used in the translation of ATASCII code to FP values. The
     result output buffer is at locations 1408 to 1535 ($580 to $5FF).
245,246          	F5,F6          	ZTEMP1
 
-      Temporary register.
247,248          	F7,F8          	ZTEMP4
 
-      Temporary register.
249,250          	F9,FA          	ZTEMP3
 
-      Temporary register.
251          	FB          	RADFLG
 
-      Also called DEGFLG. When set to zero, all of the trigonometric
     functions are performed in radians; when set to six, they are done
     in degrees. BASIC's NEW command and RESET both restore
     RADFLG to radians.
252,253          	FC,FD          	FLPTR
 
-      Points to the user's FP number.
254,255          	FE,FF          	FPTR2
 
-      Pointer to the user's second FP number to be used in an
     operation.
     End of the page zero RAM.
---------------------------------------------------------------------------
PAGE ONE: THE STACK
Locations 256 to 511 ($100 to $1FF) are the stack area for the OS, DOS
and BASIC. This area is page one. Machine language JSR, PHA and
interrupts all cause data to be written to page one, and RTS, PLA and
RTI instructions all read data from page one. On powerup or RESET,
the stack pointer is initialized to point to location 511 ($1FF). The stack
then pushes downward with each entry to 256 ($100). In case of
overflow, the stack will wrap around from 256 back to 511 again.
---------------------------------------------------------------------------
PAGES TWO TO FOUR
Locations 512 to 1151 ($200 to $47F) are used by the OS for working
variables, tables and data buffers. In this area, locations 512 to 553
($200 to $229) are used for interrupt vectors, and locations 554 to 623
($22A to $26F) are for miscellaneous use. Much of pages two through
five cannot be used except by the OS unless specifically noted. A
number of bytes are marked as "spare", i.e., not in use currently. The
status of these bytes may change with an Atari upgrade, so their use is
not recommended.
There are two types of interrupts: Non-Maskable Interrupts (NMI)
processed by the ANTIC chip and Interrupt Requests (IRQ) processed
by the POKEY and the PIA chips. NMI's are for the VBLANK interrupts
(VBI's; 546 to 549, $222 to $225), display list interrupts (DLI) and
RESET key interrupts. They initiate the stage one and stage two
VBLANK procedures; usually vectored through an OS service routine,
they can be vectored to point to a user routine. IRQ's are for the timer
interrupts, peripheral and serial bus interrupts, BREAK and other key
interrupts, and 6502 BRK instruction interrupts. They can usually be
used to vector to user routines. See NMIST 54287 ($D40F) and IRQEN
53774 ($D20E) for more information. NMI interrupt vectors are marked
NMI; IRQ interrupt vectors are marked IRQ.
Refer to the chart below location 534 for a list of the interrupt vectors in
the new OS "B" version ROMs.
512,513          	200,201          	VDSLST
 
-      The vector for NMI Display List Interrupts (DLI): containing the
     address of the instructions to be executed during a DLI (DLI's are
     used to interrupt the processor flow for a few microseconds at the
     particular screen display line where the bit was set, allowing you
     to do another short routine such as music, changing graphics
     modes, etc.). The OS doesn't use DLI's; they must be user-
     enabled, written and vectored through here. The NMI status
     register at 54287 ($D40F) first tests to see if an interrupt was
     caused by a DLI and, if so, jumps through VDSLST to the routine
     written by the user. DLI's are disabled on powerup, but VBI's are
     enabled (see 546 to 549; $222 to $225).
     VDSLST is initialized to point to 59315 ($E7B3), which is merely
     an RTI instruction. To enable DLI's, you must first POKE 54286
     ($D40E) with 192 ($C0); otherwise, ANTIC will ignore your
     request. You then POKE 512 and 513 with the address (LSB/MSB)
     of the first assembly language routine to execute during the DLI.
     You must then set BIT 7 of the Display List instruction(s) where
     the DLI is to occur. You have only between 14 and 61 machine
     cycles available for your DLI, depending on your GRAPHICS
     mode. You must first push any 6502 registers onto the stack, and
     you must end your DLI with an RTI instruction. Because you are
     dealing with machine language for your DLI, you can POKE
     directly into the hardware registers you plan to change, rather
     than using the shadow registers that BASIC uses.
     There is, unfortunately, only one DLI vector address. If you use
     more than one DLI and they are to perform different activities,
     then changing the vectoring to point to a different routine must
     be done by the previous DLI's themselves.
     Another way to accomplish interrupts is during the VBLANK
     interval with a VBI. One small problem with using DLI's is that
     the keyboard "click" routine interferes with the DLI by throwing
     off the timing, since the click is provided by several calls to the
     WSYNC register at 54282 ($D40A). Chris Crawford discusses
     several solutions in De Re Atari, but the easiest of them is not to
     allow input from the keyboard! See Micro, December 1981,
     Creative Computing, July 1981 and December 1981.
     Here's a short example of a DLI. It will print the lower half of your
     text screen upside down:
     10   START = PEEK(560) + PEEK(561) *
        256: POKE START + 16,130
     20   PAGE = 1536: FOR PGM = PAGE TO P
        AGE + 7: READ BYTE: POKE PGM, BYTE
        : NEXT PGM
     30   DATA 72,169,4,141,1,212,104,64
     40   POKE 512,0: POKE 513,6: POKE 542
        86,192
     50   FOR TEST = 1 TO 240: PRINT"SEE "
        ;: NEXT TEST
     60   GOTO 60
     
     DOWNLOAD VDSLST.BAS
     Another example of a DLI changes the color of the bottom half of
     the screen. To use it, simply change the PAGE + 7 to PAGE + 10
     in the program above and replace line 30 with:
     30   DATA 72,169,222,141,10,212,141,2
        4,208,104,64
     Finally, delete lines 50 and 60. See also location 54282 ($D40A).
514,515          	202,203          	VPRCED
 
-      Serial (peripheral) proceed line vector, initialized to 59314
     ($E7B2), which is merely a PLA, RTI instruction sequence. It is
     used when an IRQ interrupt occurs due to the serial I/O bus
     proceed line which is available for peripheral use. According to
     De Re Atari, this interrupt is not used and points to a PLA, RTI
     instruction sequence. This interrupt is handled by the PIA chip
     and can be used to provide more control over external devices.
     See the OS Listing, page 33.
516,517          	204,205          	VINTER
 
-      Serial (peripheral) interrupt vector, initialized to 59314 ($E7B2).
     Used for the IRQ interrupt due to a serial bus I/O interrupt.
     According to De Re Atari, this interrupt is not used and points to
     a PLA, RTI sequence. This interrupt is processed by PIA. See the
     OS Listing, page 33.
518,519          	206,207          	VBREAK
 
-      Software break instruction vector for the 6502 BRK ($00)
     command (not the BREAK key, which is at location 17; $11),
     initialized to 59314 ($E7B2). This vector is normally used for
     setting break points in an assembly language debug operation.
     IRQ.
520,521          	208,209          	VKEYBD
 
-      POKEY keyboard interrupt vector, used for an interrupt
     generated when any keyboard key is pressed other than BREAK
     or the console buttons. Console buttons never generate an
     interrupt unless one is specifically user-written. VKEYBD can be
     used to process the key code before it undergoes conversion to
     ATASCII form. Initialized to 65470 ($FFBE) which is the OS
     keyboard IRQ routine.
522,523          	20A,20B          	VSERIN
 
-      POKEY serial I/O bus receive data ready interrupt vector,
     initialized to 60177 ($EB11), which is the OS code to place a byte
     from the serial input port into a buffer. Called INTRVEC by DOS,
     it is used as an interrupt vector location for an SIO patch. DOS
     changes this vector to 6691 ($1A23), the start of the DOS
     interrupt ready service routine. IRQ.
524,525          	20C,20D          	VSEROR
 
-      POKEY serial I/O transmit ready interrupt vector, initialized to
     60048 (EA90), which is the OS code to provide the next byte in a
     buffer to the serial output port. DOS changes this vector to 6630
     ($19E6), the start of the DOS output needed interrupt routine.
     IRQ.
526,527          	20E,20F          	VSEROC
 
-      POKEY serial bus transmit complete interrupt vector, initialized
     to 60113 ($EAD1), which sets a transmission done flag after the
     checksum byte is sent. IRQ.
     SIO uses the three last interrupts to control serial bus
     communication with the serial bus devices. During serial bus
     communication, all program execution is halted. The actual
     serial I/O is interrupt driven; POKEY waits and watches for a flag
     to be set when the requested I/O operation is completed. During
     this wait, POKEY is sending or receiving bits along the seriai
     bus. When the entire byte has been transmitted (or received), the
     output needed (VSEROR) or the input ready (VSERIN) IRQ is
     generated according to the direction of the data flow. This causes
     the next byte to be processed until the entire buffer has been sent
     or is full, and a flag for "transmission done" is set. At this point,
     SIO exits back to the calling routine. You can see that SIO wastes
     time waiting for POKEY to send or receive the information on the
     bus.
528,529          	210,211          	VTIMR1
 
-      POKEY timer one interrupt vector, initialized to 59314 ($E7B2),
     which is a PLA, RTI instruction sequence. Timer interrupts are
     established when the POKEY timer AUDF1 (53760; $D200)
     counts down to zero. Values in the AUDF registers are loaded
     into STIMER at 53769 ($D209). IRQ.
530,531          	212,213          	VTIMR2
 
-      POKEY timer two vector for AUDF2 (53762, $D202), initialized to
     59314 ($E7B2). IRQ.
532,533          	214,215          	VTIMR4
 
-      POKEY timer four vector for AUDF4 (53766, $D206), initialized
     to 59314 ($E7B2). This IRQ is only vectored in the "B" version of
     the OS ROMs.
534,535          	216,217          	VIMIRQ
 
-      The IRQ immediate vector (general). Initialized to 59126
     ($E6F6). JMP through here to determine cause of the IRQ
     interrupt. Note that with the new ("B") OS ROMs, there is a
     BREAK key interrupt vector at locations 566, 567 ($236, $237).
     See 53774 ($D20E) for more information on IRQ interrupts.
     The new "B" version OS ROMs change the vectors above as
     follows:
     VDSLST     59280 ($E790)
     VPRCED     59279 ($E78F)
     VINTER     59279 ($E78F)
     VBREAK     59279 ($E78F)
     VKEYBD     NO CHANGE
     VSERIN     60175 ($EB0F)
     VSEROR     NO CHANGE
     VSEROC     60111 ($EACF)
     VTIMR 1-4  59279 ($E78F)
     VIMIRQ     59142 ($E706)
     VVBLKI     59310 ($E7AE)
     VVBLKD     59653 ($E905)
---------------------------------------------------------------------------
The locations from 536 to 558 ($218 to $22E) are used for the system
software timers. Hardware timers are located in the POKEY chip and
use the AUDF registers. These timers count backwards every 1/60
second (stage one VBLANK) or 1/30 second (stage two VBLANK)
interval until they reach zero. If the VBLANK process is disabled or
intercepted, the timers will not be updated. See De Re Atari for
information regarding setting these timers in an assembly routine
using the SETVBV register (58460; $E45C). These locations are user-
accessible and can be made to count time for music duration, game
I/O, game clock and other functions.
Software timers are used for durations greater than one VBLANK
interval (1/60 second). For periods of shorter duration, use the
hardware registers.
536,537          	218,219          	CDTMV1
 
-      System timer one value. Counts backwards from 255. This SIO
     timer is decremented every stage one VBLANK. When it reaches
     zero, it sets a flag to jump (JSR) through the address stored in
     locations 550, 551 ($226, $227). Only the realtime clock
     (locations 18-20; $12-14), timer one, and the attract mode
     register (77; $4D) are updated when the VBLANK routine is cut
     short because time-critical code (location 66; $42 set to non-zero
     for critical code) is executed by the OS. Since the OS uses timer
     one for its I/O routines and for timing serial bus operations
     (setting it to different values for timeout routines), you should use
     another timer to avoid conflicts or interference with the operation
     of the system.
538,539          	21A,21B          	CDTMV2
 
-      System timer two. Decremented at the stage two VBLANK. Can
     be decremented every stage one VBLANK, subject to critical
     section test as defined by setting of CRITIC flag (location 66;
     $42). This timer may miss (skip) a count when time-critical code
     (CRITIC equals non-zero) is being executed. It performs a JSR
     through location 552, 553 ($228, $229) when the value counts
     down to zero.
540,541          	21C,21D          	CDTMV3
 
-      System timer three. Same as 538. Timers three, four, and five are
     stopped when the OS sets the CRITIC flag to non-zero as well.
     The OS uses timer three to OPEN the cassette recorder and to set
     the length of time to read and write tape headers. Any prior value
     in the register during this function will be lost.
542,543          	21E,21F          	CDTMV4
 
-      System timer four. Same as 538 ($21A).
544,545          	220,221          	CDTMV5
 
-      System timer five. Same as 538 ($21A). Timers three, four, and
     five all set flags at 554, 556 and 558 ($22A, $22C, $22E),
     respectively, when they decrement to zero.
546,547          	222,223          	VVBLKI
 
-      VBLANK immediate register. Normally jumps to the stage one
     VBLANK vector NMI interrupt processor at location 59345
     ($E7D1); in the new OS "B" ROMs; 59310, $E7AE). The NMI
     status register tests to see if the interrupt was due to a VBI (after
     testing for a DLI) and, if so, vectors through here to the VBI
     routine, which may be user-written. On powerup, VBI's are
     enabled and DLI's are disabled. See location 512; $200.
548,549          	224,225          	VVBLKD
 
-      VBLANK deferred register; system return from interrupt,
     initialized to 59710 ($E93E, in the new OS "B" ROMs; 59653;
     $E905), the exit for the VBLANK routine. NMI.
     These two VBLANK vectors point to interrupt routines that occur
     at the beginning of the VBLANK time interval. The stage one
     VBLANK routine is executed; then location 66 ($42) is tested for
     the time-critical nature of the interrupt and, if a critical code
     section has been interrupted, the stage two VBLANK routine is
     not executed with a JMP made through the immediate vector
     VVBLKI. If not critical, the deferred interrupt VVBLKD is used.
     Normally the VBLANK interrupt bits are enabled (BIT 6 at
     location 54286; $D40E is set to one). To disable them, clear BIT 6
     (set to zero).
     The normal seguence for VBLANK interrupt events is: after the
     OS test, JMP to the user immediate VBLANK interrupt routine
     through the vector at 546, 547 (above), then through SYSVBV at
     58463 ($E45F). This is directed by the OS through the VBLANK
     interrupt service routine at 59345 ($E7D1) and then on to the
     user-deferred VBLANK interrupt routine vectored at 548, 549. it
     then exits the VBLANK interrupt routine through 58466 ($E462)
     and an RTI instruction.
     If you are changing the VBLANK vectors during the interrupt
     routine, use the SETVBV routine at 58460 ($E45C). An
     immediate VBI has about 3800 machine cycles of time to use a
     deferred VBI has about 20,000 cycles. Since many of these cycles
     are executed while the electron beam is being drawn, it is
     suggested that you do not execute graphics routines in deferred
     VBI's. See the table of VBLANK processes at the end of the map
     area.
     if you create your own VBI's, terminate an immediate VBI with a
     JMP to 58463 ($E45F) and a deferred VBI with a JMP to 58466
     ($E462). To bypass the OS VBI routine at 59345 ($E7D1) entirely,
     terminate your immediate VBI with a JMP to 58466 ($E462).
     Here's an example of using a VBI to create a flashing cursor. It
     will also blink any text you display in inverse mode.
     10   FOR BLINK = 1664 TO 1680: READ B
        YTE: POKE BLINK, BYTE: NEXT BLINK
     20   POKE 548,128: POKE 549,6
     30   DATA 8,72,165,20,41,16,74,74,74,
        141
     40   DATA 243,2,104,40,76,62,233
     
     DOWNLOAD VVBLKD.BAS
     To restore the normal cursor and display, POKE 548,62 and
     POKE 549,233.
550,551          	226,227          	CDTMA1
 
-      System timer one jump address, initialized to 60400 ($EBF0).
     When locations 536, 537 ($218, $219) reach (count down to) zero,
     the OS vectors through here (jumps to the location specified by
     these two addresses). You can set your machine code routine
     address here for execution when timer one reaches (counts down
     to) zero. Your code should end with the RTS instruction.
     Problems may occur when timer values are set greater than 255,
     since the 6502 cannot manipulate 16-bit values directly (a
     number in the range of zero to 255 is an eight-bit value; if a value
     requires two bytes to store, such as a memory location, it is a
     16-bit value). Technically, a VBLANK interrupt could occur
     when one timer byte is being initialized and the other not yet set.
     To avoid this, keep timer values less than 255. See the Atari OS
     User's Manual, page 106, for details.
     Since the OS uses timer one, it is recommended that you use
     timer two instead, to avoid conflicts with the operation of the
     Atari. Initialized to 60396 ($EBEA) in the old ROMs, 60400
     ($EBF0) in the new ROMs. NMI
552,553          	228,229          	CDTMA2
 
-      System timer two jump address. Not used by the OS, available to
     user to enter the address of his or her own routine to JMP to when
     the timer two (538, 539; $21A, $21B) count reaches zero.
     Initialized to zero; the address must be user specified. NMI
554          	22A          	CDTMF3
 
-      System timer three flag, set when location 540, 541 ($21C, $21D)
     reaches zero. This register is also used by DOS as a timeout flag.
555          	22B          	SRTIMR
 
-      Software repeat timer, controlled by the IRQ device routine. It
     establishes the initial 1/2 second delay before a key will repeat.
     Stage two VBLANK establishes the 1/10 second repeat rate,
     decrements the timer and implements the auto repeat logic.
     Every time a key is pressed, STIMER is set to 48 ($30). Whenever
     SRTIMR is equal to zero and a key is being continuously pressed,
     the value of that key is continually stored in CH, location 764
     ($2FC).
556          	22C          	CDTMF4
 
-      System timer four flag. Set when location 542, 543 ($21E, $21F)
     counts down to zero.
557          	22D          	INTEMP
 
-      Temporary register used by the SETVBL routine at 58460
     ($E45C).
558          	22E          	CDTMF5
 
-      System timer five flag. Set when location 558, 559 ($22E, $22F)
     counts down to zero.
---------------------------------------------------------------------------
559          	22F          	SDMCTL
 
-      Direct Memory Access (DMA) enable. POKEing with zero allows
     you to turn off ANTIC and speed up processing by 30%. Of
     course, it also means the screen goes blank when ANTIC is
     turned off! This is useful to speed things up when you are doing a
     calculation that would take a long time. It is also handy to turn off
     the screen when loading a drawing, then turning it on when the
     screen is loaded so that it appears instantly, complete on the
     screen. To use it you must first PEEK(559) and save the result in
     order to return your screen to you. Then POKE 559,0 to turn off
     ANTIC. When you are ready to bring the screen back to life,
     POKE 559 with the number saved earlier.
     This location is the shadow register for 54272 ($D400), and the
     number you PEEKed above defines the playfield size, whether or
     not the missiles and players are enabled, and the player size
     resolution. To enable your options by using POKE 559, simply
     add up the values below to obtain the correct number to POKE
     into SDMCTL. Note that you must choose only one of the four
     playfield options appearing at the beginning of the list:
     Option                          Decimal   Bit
     No playfield                          0   0
     Narrow playfield                      1   0
     Standard playfield                    2   0,1
     Wide playfield                        3   0,1
     Enable missle DMA                     4   2
     Enable player DMA                     8   3
     Enable player and missile
       DMA                                12   2,3
     One line player resolution           16   4
     Enable instructions to fetch
       DMA                                32   5 (see below)
     Note that two-line player resolution is the default and that it is not
     necessary to add a value to 559 to obtain it. I have included the
     appropriate bits affected in the table above. The default is 34
     ($22).
     The playfield is the area of the TV screen you will use for display,
     text, and graphics. Narrow playfield is 128 color clocks (32
     characters wide in GR.0), standard playfield is 160 color clocks
     (40 characters), and wide playfield is 192 color clocks wide (48
     characters). A color clock is a physical measure of horizontal
     distance on the TV screen. There are a total of 228 color clocks on
     a line, but only some of these (usually 176 maximum) will be
     visible due to screen limitations. A pixel, on the other hand, is a
     logical unit which varies in size with the GRAPHICS mode. Due
     to the limitations of most TV sets, you will not be able to see all of
     the wide playfield unless you scroll into the offscreen portions.
     BIT 5 must be set to enable ANTIC operation; it enables DMA for
     fetching the display list instructions.
560,561          	230,231          	SDLSTL
 
-      Starting address of the display list. The display list is an
     instruction set to tell ANTIC where the screen data is and how to
     display it. These locations are the shadow for 54274 and 54275
     ($D402, $D403). You can also find the address of the DL by
     PEEKing one byte above the top of free memory:
     PRINT PEEK(741) + PEEK(742) * 256 + 1.
     However, 560 and 561 are more reliable pointers since custom
     DL's can be elsewhere in memory. Atari standard display lists
     simply instruct the ANTIC chip as to which types of mode lines to
     use for a screen and where the screen data may be found in
     memory. Normally, a DL is between 24 and 256 bytes long (most
     are less than 100 bytes, however), depending on your
     GRAPHICS mode (see location 88,89 for a chart of DL sizes and
     screen display use).
     By altering the DL, you can mix graphics modes on the same
     screen; enable fine scrolling; change the location of the screen
     data; and force interrupts (DLI's) in order to perform short
     machine language routines.
     DL bytes five and six are the addresses of the screen memory
     data, the same as in locations 88 and 89 ($58, $59). Bytes four,
     five, and six are the first Load Memory Scan (LMS) instruction.
     Byte four tells ANTIC what mode to use; the next two bytes are
     the location of the first byte of the screen RAM (LSB/MSB).
     Knowing this location allows you to write directly to the screen by
     using POKE commands (you POKE the internal character codes,
     not the ATASCII codes -- see the BASIC Reference Manual, p.
     55).
     For example, the program below will POKE the internal codes to
     the various screen modes. You can see not only how each screen
     mode handles the codes, but also roughly where the text window
     is in relation to the display screen (the 160 bytes below
     RAMTOP). Note that the GTIA modes have no text window. If
     you don't have the GTIA chip, your Atari will default to
     GRAPHICS 8, but with GTIA formatting.
     1   TRAP 10: GRAPHICS Z
     5   SCREEN = PEEK(560) + PEEK(561) *
       256
     6   TV = SCREEN + 4: TELE = SCREEN + 5
     8   DISPLAY = PEEK(TV) + PEEK(TELE) *
        256
     10  FOR N = 0 TO 255: POKE DISPLAY +
        N,N: NEXT N
     20  DISPLAY = DISPLAY + N
     30  IF DISPLAY > 40959 THEN Z = Z + 1
        : GOTO 1
     40  GOTO 10
     50  Z = Z + 1:IF Z > 60 THEN END
     60  GOTO 1
     Here's another short program which will allow you to examine the
     DL in any GRAPHICS mode:
     10  REM CLEAR SCREEN FIRST
     20  PRINT"ENTER GRAPHICS MODE": REM A
        DD 16 TO THE MODE TO SUPPRESS THE
        TEXT WINDOW
     30  INPUT A: GRAPHICS A
     40  DLIST = PEEK(560) + PEEIK(561) * 2
        56
     50  LOOK = PEEK(DLIST): PRINT LOOK;"
        ";
     60  IF LOOK <> 65 THEN DLIST = DLIST
        + 1: GOTO 50
     70  LPRINT PEEK(DLIST + 1);" ";PEEK(D
        LIST + 2)
     80  END
     The value 65 in the DL is the last instruction encountered. It tells
     ANTIC to jump to the address in the next two bytes to re-execute
     the DL, and wait for the next VBLANK. If you don't have a
     printer, change the LPRINT commands to PRINT and modify the
     routine to save the data in an array and PRINT it to the screen
     after (in GR.0).
     If you would like to examine the locations of the start of the
     Display List, screen, and text window, try:
     5   REM CLEAR SCREEN FIRST
     6   INPUT A: GRAPHICS A
     10  DIM DLIST$(10), SAVMSC$(10), TXT$
        (10)
     15  DLIST$ = "DLIST": SAVMSC$ = "SAVM
        SC": TXT$ = "TEXT"
     20  DLIST = PEEK(560) + PEEK(561) * 2
        56
     30  SAV = PEEK(88) + PEEK(89) * 256:
        TXT = PEEK(660) + PEEK(66l) * 256
     40  PRINT DLIST$;" "; DLIST,SAVMSC$;"
        ";SAV
     50  PRINT TXT$;" "; TEXT
     60  INPUT A: GRAPHICS A: GOTO 20
     Since an LMS is simply a map mode (graphics) or character
     mode (text) instruction with BIT six set, you can make any or all of
     these instructions into LMS instructions quite easily, pointing
     each line to a different RAM area if necessary. This is discussed
     in De Re Atari on implementing horizontal scrolling.
     DL's can be used to help generate some of the ANTIC screen
     modes that aren't supported by BASIC, such as 7.5 (ANTIC
     mode E) or ANTIC mode three, the lowercase with descenders
     mode (very interesting; ten scan lines in height which allow true
     descenders on lowercase letters).
     If you create your own custom DL, you POKE its address here.
     Hitting BESET or changing GRAPHICS modes will restore the
     OS DL address, however. The display list instruction is loaded
     into a special register called the Display Instruction Register (IR).
     which processes the three DL instructions (blank, jump, or
     display). It cannot be accessed directly by the programmer in
     either BASIC or machine language. A DL cannot cross a 1K
     boundary unless a jump instruction is used.
     There are only four display list instructions: blank line (uses BAK
     color), map mode, text mode, and jump. Text (character mode)
     instructions and map mode (graphics) instructions range from
     two to 15 ($2 to $F) and are the same as the ANTIC GRAPHICS
     modes. A DL instruction byte uses the following conventions
     (functions are enabled when the bit is set to one):
     Bit   Decimal   Function
     7       128     Display List Interrupt when set (enabled
                     equals one)
     6        64     Load Memory Scan. Next two bytes are the
                     LSB/MSB of the data to load.
     5        32     Enable vertical fine scrolling.
     4        16     Enable horizontal fine scrolling.
     3-0     8-1     Mode
                     0  0  1  0  Character
                       to        Modes
                     0  1  1  1
                     . . . . . . .
                     1  0  0  0  Map
                       to        Modes
                     1  1  1  1
     The above bits may be combined (i.e., DLI, scrolling and LMS
     together) if the user wishes.
     Special DL instructions (with decimal values):
     Blank 1 line  =  0   5 lines =  64
           2 lines = 16   6 lines =  80
           3 lines = 32   7 lines =  96
           4 lines = 48   8 lines = 112
     Jump instruction (JMP) = zero (three-byte instruction).
     Jump and wait for Vertical Blank (JVP) = 65 (three-byte
     instruction).
     Special instructions may be combined only with DL interrupt
     instructions.
     A Display List Interrupt is a special form of interrupt that takes
     place during the screen display when the ANTIC encounters a
     DL instruction with the interrupt BIT 7 set. See location 512
     ($200) for DLI information.
     Since DL's are too large a topic to cover properly in this manual,
     I suggest you look in the many magazines (i.e., Creative
     Computing, July 1981, August 1981; Micro, December 1981;
     Softside, #30 to 32, and BYTE, December 1981) for a more
     detailed explanation
562          	232          	SSKCTL
 
-      Serial port control register, shadow for 53775 ($D20F). Setting
     the bits in this register to one has the following effect:
     Bit    Decimal    Function
     0          1      Enable the keyboard debounce circuit.
     1          2      Enable the keyboard scanning circuit.
     2          4      The pot counter completes a read within two
                       scan lines instead of one frame time.
     3          8      Serial output transmitted as two-tone instead
                       of logic true/false (POKEY two-tone mode).
     4-6    16-64      Serial port mode control.
     7        128      Force break; serial output to zero.
     Initialized to 19 ($13) which sets bits zero, one and four.
563          	233          	SPARE
 
-      No OS use. See the note at location 651 regarding spare bytes.
564          	234          	LPENH
 
-      Light pen horizontal value shadow for 54284 ($D40C). Values
     range from zero to 227.
565          	235          	LPENV
 
-      Light pen vertical value: shadow for 54285 ($D40D). Value is the
     same as VCOUNT register for two-line resolution (see 54283;
     $D40B). Both light pen values are modified when the trigger is
     pressed (pulled low). The light pen positions are not the same as
     the normal screen row and column positions. There are 96
     vertical positions, numbered from 16 at the top to 111 at the
     bottom, each one equivalent to a scan line. Horizontal positions
     are marked in color clocks. There are 228 horizontal positions,
     numbered from 67 at the left. When the LPENH value reaches
     255, it is reset to zero and begins counting again by one to the
     rightmost edge, which has a value of seven.
     Obviously, because of the number of positions readable and the
     small size of each, a certain leeway must be given by the
     programmer when using light pen readouts on a program. At the
     time of this writing, Atari had not yet released its light pen onto
     the market, although other companies have.
566,567          	236,237          	BRKKY
 
-      BREAK key interrupt vector. This vector is available only with
     the version "B" OS ROMs, not the earlier version. You can use
     this vector to write your own BREAK key interrupt routine.
     Initialized to 59220 ($E754).
568,569          	238,239          	....
 
-      Two spare bytes.
570          	23A          	CDEVIC
 
-      Four-byte command frame buffer (CFB) address for a device --
     used by SIO while performing serial I/O, not for user access.
     CDEVIC is used for the SIO bus ID number The other three CFB
     bytes are:
571          	23B          	CCOMND
 
-      The SIO bus command code.
572          	23C          	CAUX1
 
-      Command auxiliary byte one, loaded from location 778 ($30A)
     by SIO.
573          	23D          	CAUX2
 
-      Command auxiliary byte two, loaded from location 779 ($30B) by
     SIO.
574          	23E          	TEMP
 
-      Temporary RAM register for SIO.
575          	23F          	ERRFLG
 
-      SIO error flag; any device error except the timeout error (time
     equals zero).
576          	240          	DFLAGS
 
-      Disk flags read from the first byte of the boot file (sector one) of
     the disk.
577          	241          	DBSECT
 
-      The number of disk boot sectors read from the first disk record.
578,579          	242,243          	BOOTAD
 
-      The address for where the disk boot loader will be put. The
     record just read will be moved to the address specified here,
     followed by the remaining records to be read. Normally, with
     DOS, this address is 1792 ($700), the value also stored
     temporarily in RAMLO at 4, 5. Address 62189 ($F2ED) is the OS
     disk boot routine entry point (DOBOOT).
580          	244          	COLDST
 
-      Coldstart flag. Zero is normal, if zero, then pressing RESET will
     not result in reboot. If POKEd with one (powerup in progress
     flag), the computer will reboot whenever the RESET key is
     pressed. Any non-zero number indicates the initial powerup
     routine is in progress.
If you create an AUTORUN.SYS file, it should end with an RTS
instruction. If not, it should POKE 580 with zero and POKE 9 with one.
You can turn any binary file that boots when loaded with DOS menu
selection "L" into an auto-boot file simply by renaming it
"AUTORUN.SYS". Be careful not to use the same name for any two
files on the same disk.
When this is combined with the disabling of the BREAK key discussed
in location 16 ($10) and the program protection scheme discussed in
location 138 ($8A), you have the means to protect your BASIC
software fairly effectively from being LISTed or examined, although
not from being copied.
581          	245          	....
 
-      Spare byte.
582          	246          	DSKTIM
 
-      Disk time-out register (the address of the OS worst case disk time-
     out). It is said by many sources to be set to 160 at initialization
     which represents a 171 second time-out, but my system shows a
     value of 224 on initialization. Timer values are 64 seconds for
     each 60 units of measurement expressed.
     It is updated after each disk status request to contain the value of
     the third byte of the status frame (location 748; $2EC). All disk
     operations have a seven second time-out (except FORMAT),
     established by the disk handler (you had noticed that irritating
     little delay, hadn't you?). The "sleeping disk syndrome" (the
     printer suffers from this malady as well) happens when your drive
     times out, or the timer value reaches zero. This has been cured
     by the new OS "B" version ROMs.
583-622          	247-26E          	LINBUF
 
-      Forty-byte character line buffer, used to temporarily buffer one
     physical line of text when the screen editor is moving screen
     data. The pointer to this buffer is stored in 100, 101 ($64, $65)
     during the routine.
623          	26F          	GPRIOR
 
-      Priority selection register, shadow for 53275 ($D01B). Priority
     options select which screen objects will be "in front" of others. It
     also enables you to use all four missiles as a fifth player and
     allows certain overlapping players to have different colors in the
     areas of overlap. You add your options up as in location 559,
     prior to POKEing the total into 623. In this case, choose only one
     of the four priorities stated at the beginning. BAK is the
     background or border. You can also use this location to select
     one of GTIA GRAPHICS modes nine, ten, or eleven.
     Priority options in order                      Decimal   Bit
     Player 0 - 3, playfield 0 - 3, BAK
         (background)                                   1      0
     Player 0 - 1, playfield 0 - 3, player 2 - 3,
       BAK                                              2      1
     Playfield 0 - 3, player 0 - 3, BAK                 4      2
     Playfield 0 - 1, player 0 - 3, playfield 2 -3,
       BAK                                              8      3
     Other options
     Four missiles = fifth player                      16      4
     Overlaps of players have 3rd color                32      5
     GRAPHICS 9  (GTIA mode)                           64      6
     GRAPHICS 10 (GTIA mode)                          128      7
     GRAPHICS 11 (GTIA mode)                          192     6, 7
     It is quite easy to set conflicting priorities for players and
     playfields. In such a case, areas where both overlap when a
     conflict occurs will turn black. The same happens if the overlap
     option is not chosen.
     With the color/overlap enable, you can get a multicolor player
     by combining players. The Atari performs a logical OR to colors
     of players 0/1 and 2/3 when they overlap. Only the 0/1, 2/3
     combinations are allowed; you will not get a third color when
     players 1 and 3 overlap, for example (you will get black instead).
     If player one is pink and player 0 is blue, the overlap is green. If
     you don't enable the overlap option, the area of overlap for all
     players will be black.
     In GTIA mode nine, you have 16 different luminances of the
     same hue. In BASIC, you would use SETCOLOR 4,HUE,0. To
     see an example of GTIA mode nine, try:
     10   GRAPHICS 9: SETCOLOR 4,9,0
     20   FOR LOOP = 1 TO 15: COLOR LOOP
     30   FOR LINE = 1 TO 2
     40   FOR TEST = 1 TO 25: PLOT 4 + TES
        T, LOOP + LINE +  SPACE: NEXT TEST
     45   NEXT LINE
     50   SPACE = SPACE + 4
     60   NEXT LOOP
     70   GOTO 70: REM WITHOUT THIS LINE,
        SCREEN WILL RETURN TO GR.0
        
     DOWNLOAD GTIA9.BAS
     In GTIA mode ten, you have all nine color registers available;
     hue and luminance may be set separately for each (it would
     otherwise allow 16 colors, but there are only nine registers). Try
     this to see:
     10   N = 0: GRAPHICS 10
     20   FOR Q = 1 TO 2
     30   FOR B = 0 TO 8: POKE 704 + B, N
        * 16 + A
     35   IF A > 15 THEN A = 0
     40   COLOR B
     45   A = A + 1: N = N + 1
     50   IF N > 15 THEN N = 0
     60   NEXT B
     65   TRAP 70: NEXT Q
     70   POP: N = N + 1: FOR Z = 1 TO 200
        : NEXT Z
     75   GOTO 30
     
     DOWNLOAD GTIA10.BAS
     GTIA mode eleven is similar to mode nine except that it allows 16
     different hues, all of the same luminance. In BASIC, use
     SETCOLOR 4,O,luminance. Try this for a GTIA mode eleven
     demonstration:
     10   GRAPHICS 11
     20   FOR LOOP = 0 TO 79: COLOR LOOP:
        PLOT LOOP,0: DRAWTO LOOP,191: NEXT
         LOOP
     30   GOTO 30
     
     DOWNLOAD GTIA11.BAS
     You can use these examples with the routine to rotate colors,
     described in the text preceding location 704. GTIA mode pixels
     are long and skinny; they have a four to one horizontal length to
     height ratio. This obviously isn't very good for drawing curves
     and circles!
     GTIA modes are cleared on the OPEN command. How can you
     tell if you have the GTIA chip? Try POKE 623,64. If you have the
     GTIA, the screen will go all black. If not, you don't have it. Here
     is a short routine, written by Craig Chamberlain and Sheldon
     Leemon for COMPUTE!, which allows an Atari to test itself for the
     presence of a CTIA or GTIA chip. The routine flashes the answer
     on the screen, hut can easily be modified so a program will
     "know" which chip is present so it can adapt itself accordingly:
     10 POKE 66,1:GRAPHICS 8:POKE 709,0:PO
        KE 710,0:POKE 66,0:POKE 623,64:P0K
        E 53248,42:POKE 5326l,3:PUT#6,1
     20 POKE 53278,0:FOR K=1 TO 300:NEXT K
        :GRAPHICS 18:POKE 53248,0:POSITION
         8,5:? #6;CHR$(71-PEEK(53252));"TI
        A"
     30 POKE 708,PEEK(20):GOTO 30
     
     DOWNLOAD CTIAGTIA.BAS
     How can you get the GTIA if you don't have one? Ask your local
     Atari service representative or dealer, or write directly to Atari in
     Sunnyvale, California.
     See the GTIA/CTIA introduction at location 53248 ($D000) for
     more discussion of the chip. See BYTE, May 1982, COMPUTE!,
     July through September 1982, and De Re Atari for more on the
     GTIA chip, and the GTIA Demonstration Diskette from the Atari
     Program Exchange (APX).
---------------------------------------------------------------------------
Locations 624 to 647 ($270 to $287) are used for game controllers:
paddle, joystick and lightpen values.
624          	270          	PADDL0
 
-      The value of paddle 0 (paddles are also called pots, short for
     potentiometer); PEEK 624 returns a number between zero and
     228 ($E4), increasing as the knob is turned counter-clockwise.
     When used to move a player or cursor (i.e., PLOT
     PADDLE(0),0), test your screen first. Many sets will not display
     locations less than 48 ($30) or greater than 208 ($D0), and in
     many GRAPHICS modes you will get an ERROR 141 -- cursor
     out of range. Paddles are paired in the controller jacks, so paddle
     0 and paddle 1 both use jack one. PADDL registers are shadows
     for POKEY locations 53760 to 53767 ($D200 to $D207).
625          	271          	PADDL1
 
-      This and the next six bytes are the same as 624, but for the other
     paddles.
626          	272          	PADDL2
 
- 
627          	273          	PADDL3
 
- 
628          	274          	PADDL4
 
- 
629          	275          	PADDL5
 
- 
630          	276          	PADDL6
 
- 
631          	277          	PADDL7
 
- 
632          	278          	STICK0
 
-      The value of joystick 0. STICK registers are shadow locations for
     PIA locations 54016 and 54017 ($D300, $D301). There are nine
     possible decimal values (representing 45 degree incrememts)
     read by each joystick register (using the STICKn command),
     depending on the position of the stick:
     Decimal                   Binary
               14                       1110
                |                         |
            10  | 6                 1010  | 0110
              \ |/                      \ |/
          11-- 15 ---7           1011-- 1111 --0111
              / |\                      / |\
             9  | 5                 1001  | 0101
                |                         |
               13                       1101
     15 (1111) equals stick in the upright (neutral) position.
     See Micro, December 1981,for an article on making a
     proportional joystick. For an example of a machine language
     joystick driver you can add to your BASIC program, see
     COMPUTE!, July 1981.
     One machine language joystick reader is listed below, based on
     an article in COMPUTE!, August 1981:
     1   GOSUB 1000
     10  LOOK = STICK(0)
     20  X = USR(1764,LOOK): Y = USR(1781,
         LOOK)
     30  ON X GOTO 120, 100, 110
     .
     .
     .
     100 REM YOUR MOVE LEFT ROUTINE HERE
     105 GOTO 10
     110 REM YOUR MOVE RIGHT ROUTINE HERE
     115 GOTO 10
     120 ON Y GOTO 150, 130, 140
     130 REM YOUR MOVE DOWN ROUTINE HERE
     135 GOTO 10
     140 REM YOUR MOVE UP ROUTINE HERE
     145 GOTO 10
     150 REM IF X <> 1 THEN NOTHING DOING.
          BRANCH TO YOUR OTHER ROUTINES OR
          TO 155
     155 GOTO 10
     .
     .
     .
     1000 FOR LOOP = 1764 TO 1790: READ BY
          TE: POKE LOOP, BYTE: NEXT LOOP
     1010 DATA 104,104,133,213,104,41,12,7
          4,74,73,2,24,105,1
     1020 DATA 133,212,96,104,104,133,213,
          104,41,3,76,237,6
     1030 RETURN
     
     DOWNLOAD STICK0.BAS
     See locations 88, 89 ($58, $59) for an example of a USR call using
     a string instead of a fixed memory location.
633          	279          	STICK1
 
-      This and the next two locations are the same as 632, but for the
     other joysticks. These four locations are also used to determine if
     a lightpen (PEN 0 - 3) switch is pressed.
634          	27A          	STICK2
 
- 
635          	27B          	STICK3
 
- 
636          	27C          	PTRIG0
 
-      Paddle trigger 0. Used to determine if the trigger or hutton on
     paddle 0 is pressed (zero is returned) or not (one is returned).
     Since these are the same lines as the joystick left/right switches,
     you can use PTRIG for horizontal movement. PTRIG(1) -
     PTRIG(0) returns -1 (left), 0 (center), + 1 (right). The next seven
     locations are for the other paddle buttons. PTRIG 0 - 3 are
     shadows for PIA register 54016 ($D300).
637          	27D          	PTRIG1
 
- 
638          	27E          	PTRIG2
 
- 
639          	27F          	PTRIG3
 
- 
640          	280          	PTRIG4
 
-      PTRIG 4-7 are shadows for PIA register 54017 ($D301).
641          	281          	PTRIG5
 
- 
642          	282          	PTRIG6
 
- 
643          	283          	PTRIG7
 
- 
644          	284          	STRIG0
 
-      Stick trigger 0. This and the next three locations perform the
     same function as the PTRIG locations except for the joysticks.
     Like PTBIG, zero is returned when the button is pressed; one is
     returned when it is not. STRIG registers are shadow registers for
     GTIA/CTIA locations 53264 to 53267 ($D010 to $D013).
645          	285          	STRIG1
 
- 
646          	286          	STRIG2
 
- 
647          	287          	STRIG3
 
- 
---------------------------------------------------------------------------
Locations 648 to 655 ($288 to $28F) are for miscellaneous OS use.
648          	288          	CSTAT
 
-      Cassette status register.
649          	289          	WMODE
 
-      Register to store either the read or the write mode for the cassette
     handler, depending on the operation: zero equals read, 128 ($80)
     equals write.
650          	28A          	BLIM
 
-      Cassette data record buffer size; contains the number of active
     data bytes in the cassette buffer for the record being read or
     written, at location 1021 ($3FD). Values range from zero to 128
     (cassette record size is 128; $80). The pointer to the byte being
     read or written is at 61 ($3D). The value of BLIM is drawn from
     the control bytes that precede every cassette record, as
     explained in location 1021.
651-655          	28B-28F          	....
 
-      Spare bytes. It is not recommended that you use the spare bytes
     for your own program use. In later upgrades of the OS, these
     bytes may be used, causing a conflict with your program. For
     example, the new OS ROMs use locations 652 and 653 ($28C,
     $28D) in the new IRQ interrupt handler routines. It is best to use a
     protected area of memory such as page six, locations 1536 to
     1791 ($600 to $6FF).
---------------------------------------------------------------------------
Locations 656 to 703 ($290 to $2BF) are used for the screen RAM
display handler (depending on GRAPHICS mode).
In split-screen mode, the text window is controlled by the screen editor
(E:), while the graphics region is controlled by the display handler
(S:), using two separate IOCB's. Two separate cursors are also
maintained. The display handler will set AUX1 of the IOCB to split-
screen option. Refer to the IOCB area, locations 832 to 959 ($340 to
$3BF). See COMPUTE!, February 1982, for a program to put GR.1
and GR.2 into the text window area. The text window uses 160 bytes of
RAM located just below RAMTOP (see location 106; $6A). See
location 88 ($58) for a chart of screen RAM use.
656          	290          	TXTROW
 
-      Text window cursor row; value ranges from zero to three (the text
     window has only four lines). TXTROW specifies where the next
     read or write in the text window will occur
657,658          	291,292          	TXTCOL
 
-      Text window cursor column; value ranges from zero to 39. Unless
     changed by the user, location 658 will always be zero (there are
     only 40 columns in the display, so the MSB will be zero). Since
     POSITION, PLOT, LOCATE and similar commands refer to the
     graphics cursor in the display area above the text window, you
     must use POKE statements to write to this area if PRINT
     statements are insufficient.
659          	293          	TINDEX
 
-      Contains the current split-screen text window GRAPHICS mode.
     It is the split-screen equivalent to DINDEX (location 87; $57) and
     is always equal to zero when location 128 ($7B) equals zero.
     Initialized to zero (which represents GR.0). You can alter the
     display list to change the text window into any GRAPHICS mode
     desired. If you do so, remember to change TINDEX to reflect that
     alteration.
660,661          	294,295          	TXTMSC
 
-      Address of the upper left corner of the text window. Split-screen
     equivalent of locations 88, 89 ($58, $59).
662-667          	296-29B          	TXTOLD
 
-      These locations contain the split-screen equivalents of OLDROW
     (90; $5A), OLDCOL (91, 92; $5B, $5C), OLDCHR (location 93,
     $5D) and OLDADR (locations 94, 95; $5E, $5F). They hold the
     split-screen cursor data.
668          	29C          	TMPX1
 
-      Temporary register, used by the display handler for the scroll
     loop count record.
669          	29D          	HOLD3
 
-      Temporary register.
670          	29E          	SUBTMP
 
-      Temporary storage.
671          	29F          	HOLD2
 
-      Temporary register.
672          	2A0          	DMASK
 
-      Pixel location mask. DMASK contains zeroes tor all bits which do
     not correspond to the specific pixel to be operated upon, and
     ones for bits which do correspond, according to the GRAPHICS
     mode in use, as follows:
     11111111  Modes 0, 1 and 2:   one pixel per screen display
                                   byte.
     11110000  Modes 9, 10 and 11: two pixels per byte.
     00001111
     11000000  Modes 3, 5 and 7:   four pixels per byte.
     00110000
     00001100
     00000011
     10000000  Modes 4, 6 and 8:   eight pixels per byte.
     01000000
     etc. to:
     00000001
     A pixel (short for picture cell or picture element) is a logical unit
     of video size which depends on the GRAPHICS mode in use for
     its dimensions. The smallest pixel is in GR.8 where it is only .5
     color clock wide and one scan line high. In GR.0 it is also only .5
     color clock wide, but it is eight scan lines high. Here is a chart of
     the pixel sizes for each mode:
                         Text Modes          Graphics modes
     GR. mode        0    1    2    3    4    5    6    7    8
     Scan lines
     per pixel       8    8   16    8    4    4    2    2    1
     Bits
     per pixel       1    1    1    2    1    2    1    2    1
     Color clocks
     per pixel      .5    1    1    4    2    2    1    1   .5
     Characters
     per line       40   20   20   --   --   --   --   --   --
     Pixels
     per width      --   --   --   40   80   80  160  160  320
     The number of pixels per screen width is based on the normal
     playfield screen. See location 559 ($22F) for information on
     playfield size.
673          	2A1          	TMPLBT
 
-      Temporary storage for the bit mask.
674          	2A2          	ESCFLG
 
-      Escape flag. Normally zero, it is set to 128 ($80) if the ESC key is
     pressed (on detection of the ESC character; 27, $1B). It is reset to
     zero following the output of the next character. To display
     ATASCII control codes without the use of an ESC character, set
     location 766 ($2FE) to a non-zero value.
675-689          	2A3-2B1          	TABMAP
 
-      Map of the TAB stop positions. There are 15 byte (120 bits) here,
     each bit corresponding to a column in a logical line. A one in any
     bit means the TAB is set; to clear all TABs simply POKE every
     location with zero. There are 120 TAB locations because there
     are three physical lines to one logical line in GRAPHICS mode
     zero, each consisting of 40 columns. Setting the TAB locations for
     one logical line means they will also be set for each subsequent
     logical line until changed. Each physical line in one logical line
     can have different TAB settings, however.
     To POKE TAB locations from BASIC, you must POKE in the
     number (i.e., set the bit) that corresponds to the location of the
     bit in the byte (there are five bytes in each line). For example:
     To set tabs at locations 5, 23, 27 and 32, first visualize the line as a
     string of zeros with a one at each desired tab setting:
               0000100000000000000000100010000100000000
     Then break it into groups of eight bits (one byte units). There are
     three bytes with ones (bits set), two with all zeros:
     00001000 =  8
     00000000 =  0
     00000010 =  2
     00100001 = 33
     00000000 =  0
     Converting these to decimal, we get the values listed at the right
     of each byte. These are the numbers you'd POKE into locations
     675 (the first byte) to 679 (the fifth byte on the line). On powerup
     or when you OPEN the display screen (S: or E:), each byte is
     given a value of one (i.e., 00000001) so that there are tab default
     tab stops at 7, 15, 23, etc., incrementing by eight to 119. Also,
     the leftmost screen edge is also a valid TAB stop (2, 42, and 82).
     In BASIC, these are set by the SET-TAB and CLR-TAB keys.
     TABMAP also works for the lines in the text display window in
     split-screen formats. TABMAP is reset to the default values on
     pressing RESET or changing GRAPHICS modes.
     See location 201 ($C9) about changing the TAB settings used
     when a PRINT statement encounters a comma.
690-693          	2B2-2B5          	LOGMAP
 
-      Logical line start bit map. These locations map the beginning
     physical line number for each logical line on the screen (initially
     24, for GR.0). Each bit in the first three bytes shows the start of a
     logical line if the bit equals one (three bytes equals eight bits *
     three equals 24 lines on the screen). The map format is as follows:
     Bit     7     6     5     4     3     2     1     0     Byte
     ------------------------------------------------------------
     Line    0     1     2     3     4     5     6     7      690
             8     9    10    11    12    13    14    15      691
            16    17    18    19    20    21    22    23      692
            --    --    --    --    --    --    --    --      693
     The last byte is ignored. The map bits are all set to one when the
     text screen is OPENed or CLEARed, when a GRAPHICS com-
     mand is issued or RESET is pressed. The map is updated as
     logical lines are entered, edited, or deleted.
694          	2B6          	INVFLG
 
-      Inverse character flag; zero is normal and the initialization value
     (i.e., normal ATASCII video codes have BIT 7 equals zero). You
     POKE INVFLG with 128 ($80) to get inverse characters (BIT 7
     equals one). This register is normally set by toggling the Atari
     logo key; however, it can be user-altered. The display handler
     XOR's the ATASCII codes with the value in INVFLG at all times.
     See location 702 ($2BE) below.
     INVFLG works to change the input, not the output. For example,
     if you have A$ = "HELLO", POKE 694, 128 will not change A$
     when you PRINT it to the screen. However, if you POKE 694, 128
     before an INPUT A$, the string will be entered as inverse.
695          	2B7          	FILFLG
 
-      Right fill flag for the DRAW command. If the current operation is
     a DRAW, then this register reads zero. If it is non-zero, the
     operation is a FILL.
696          	2B8          	TMPROW
 
-      Temporary register for row used by ROWCRS (location 84; $54).
697,698          	2B9,2BA          	TMPCOL
 
-      Temporary register for column used by COLCRS (locations 85,
     86; $55, $56).
699          	2BB          	SCRFLG
 
-      Scroll flag; set if a scroll occurs. It counts the number of physical
     lines minus one that were deleted from the top of the screen. This
     moves the entire screen up one physical line for each line
     scrolled off the top. Since a logical line has three physical lines,
     SCRFLG ranges from zero to two.
     Scrolling the text window is the equivalent to scrolling an entire
     GR.0 screen. An additional 20-line equivalent of bytes (800) is
     scrolled upwards in the memory below the text window address.
     This can play havoc with any data such as P/M graphics you have
     stored above RAMTOP
700          	2BC          	HOLD4
 
-      Temporary register used in the DRAW command only; used to
     save and restore the value in ATACHR (location 763; $2FB)
     during the FILL process.
701          	2BD          	HOLD5
 
-      Same as the above register.
702          	2BE          	SHFLOK
 
-      Flag for the shift and control keys. It returns zero for lowercase
     letters, 64 ($40) for all uppercase (called caps lock: uppercase is
     required for BASIC statements and is also the default mode on
     powerup). SHFLOK will set characters to all caps during your
     program if 64 is POKEd here. Returns the value 128 ($80;
     control-lock) when the CTRL key is pressed. Forced control-lock
     will cause all keys to output their control-code functions or
     graphics figures. Other values POKEd here may cause the
     system to crash. You can use this location with 694 ($2B6) above
     to convert all keyboard entries to uppercase, normal display by:
     10   OPEN #2,4,0,"K:"
     20   GET #2,A
     30   GOSUB 1000
     40   PRINT CHR$(A);: GOTO 20
     .
     .
     .
     1000 IF A = 155 THEN 1030: REM RETURN
           KEY
     1010 IF A > = 128 THEN A = A - 128: R
          EM RESTORE TO NORMAL DISPLAY
     1020 IF PEEK (702) = 0 AND A > 96 THEN
           A = A - 32: REM LOWERCASE TO UP
          PER
     1030 POKE 702,64: POKE 694,0
     1040 RETURN
     
     DOWNLOAD SHFLOK.BAS
703          	2BF          	BOTSCR
 
-      Flag for the number of text rows available for printing. 24 ($18) is
     normal for text mode GR.0; four for the text window, zero for all
     graphics modes. In all GRAPHICS modes except zero, if there is
     no text window then 703 will also read zero. The large-text
     displays in GR.1 and GR.2 are treated as graphics displays for
     this purpose. The display handler specifically checks for split-
     screen mode by looking for the variable 24 or four here. If it finds
     24 here, it assumes there is no text window; if not, it looks for the
     variable four.
     You can add a text window to GR.0 by POKEing here with four.
     The top portion (20 lines) of the screen will not scroll with the
     bottom. To write to the top part of the screen you will have to use
     the PRINT#6 statement as with modes one and two. One possible
     application of this would be to keep a fixed menu at the top of the
     screen while scrolling the bottom part, as done with the DOS
     menu.
---------------------------------------------------------------------------
Locations 704 to 712 ($2C0 to $2C8) are the color registers for players,
missiles, and playfields. These are the RAM shadow registers for
locations 53266 to 53274 ($D012 to $D01A). For the latter, you can use
the SETCOLOR command from BASIC. For all registers you can
POKE the desired color into the location by using this formula:
COLOR = HUE * 16 + LUMINANCE
It is possible to get more colors in GR.8 than the one (and a half) that
Atari says is possible by using a technique called artifacting. There is a
small example of artifacting shown at location 710 ($2C6). See De Re
Atari, Your Atari 400/800, Creative Computing, June 1981, and
COMPUTE!, May 1982.
Here are the 16 colors the Atari produces, along with their POKE
values for the color registers. The POKE values assume a luminance of
zero. Add the luminance value to the numbers to brighten the color.
The color registers ignore BIT 0; that's why there are no "odd" values
for luminance, just even values.
Color             Value         Color             Value
Black           0,      0	Medium blue     8,    128
Rust            1,     16       Dark blue       9,    144
Red-orange      2,     32       Blue-grey      10,    160
Dark orange     3,     48       Olive green    11,    176
Red             4,     64       Medium green   12,    192
Dk lavender     5,     80       Dark green     13,    208
Cobalt blue     6,     96       Orange-green   14,    224
Ultramarine     7,    112       Orange         15,    240
The bit use of the PCOLR and COLOR registers is as follows:
Bit     7  6  5  4  3  2  1  0
        --color--   luminance unused
Grey    0  0  0  0  0  0  0  Darkest
Rust    0  0  0  1  0  0  1
         etc. to:      etc. to:
Orange  1  1  1  1  1  1  1  Lightest
When you enable the color overlap at location 623 ($26F), ANTIC
performs a logical OR on the overlap areas. For example:
         01000010 Red, luminance two
    OR   10011010 Darkblue,luminance ten
         --------
Result = 10011010  Dark green, luminance ten
Here's a short machine language routine which will rotate the colors in
registers 705 to 712:
     10   DIM ROT$(30)
     20   FOR LOOP = 1 TO 27: READ BYTE: R
        OT$(LOOP,LOOP) = CHR$(BYTE): NEXT
        LOOP
     .
     .    PUT YOUR GRAPHICS ROUTINE HERE
     .
     100  CHANGE = USR(ADR(ROT$))
     105  FOR LOOP = 1 TO 200: NEXT LOOP:
         GOTO 100
     110  DATA 104,162,0,172,193,2,189,194
         ,2,157
     120  DATA 193,2,232,224,8,144,245,140
         ,200,2
     130  DATA  96,65,65,65,65,65,65
If you wish to rotate the colors in registers 704 to 711 instead, change
lines 110 and 120 to read as follows:
     110  DATA 104,162,0,172,192,2,189,193
         ,2,157
     120  DATA 192,2,232,224,8,144,245,140
         ,199,2
         
     DOWNLOAD BOTSCR.BAS
If you wish to include all of the registers 704 to 712 in the routine, make
the changes as above and change the eight in line 120 to nine and
restore the 199 to 200 in line 120. This routine works well with the
GTIA demos at location 623 ($26F).
For further detail, refer to your Atari BASIC Reference Manual, pp. 45 
-56, and the GTIA Demo Disk from APX.
704          	2C0          	PCOLR0
 
-      Color of player 0 and missile 0. Locations 704 to 707 are also
     called COLPM# in some sources. This is the shadow for 53266
     ($D012). In GTIA mode ten, 704 holds the background color
     (BAK; normally held by 712). You cannot use the SETCOLOR
     commands to change the PCOLR registers; color values must be
     POKEd into them.
705          	2C1          	PCOLR1
 
-      Color of player and missile 1. Shadow for 53267 ($D013).
706          	2C2          	PCOLR2
 
-      Color of player and missile 2. Shadow for 53268 ($D014).
707          	2C3          	PCOLR3
 
-      Color of player and missile 3. When the four missiles are
     combined to make a fifth player, it takes on the color in location
     711 (COLOR3). Shadow for 53269 ($D015).
708          	2C4          	COLOR0
 
-      Color register zero, color of playfield zero, controlled by the
     BASIC SETCOLOR0 command. In GRAPHICS 1 and
     GRAPHICS 2, this color is used for the uppercase letters.
     Shadow for 53270 ($D016). You can change the values in all of
     the COLOR registers from BASIC by using either the
     SETCOLOR command or a POKE.
709          	2C5          	COLOR1
 
-      The next four locations are the same as location 708 for the
     different playfields and SETCOLOB commands. In GR.1 and
     GR.2, this register stores the color for lowercase letters.
     COLOR1 is also used to store the luminance value of the color
     used in GR.0 and GR.8. Shadow for 53271 ($D017).
710          	2C6          	COLOR2
 
-      The same as above for playfield two; in GR.1 and GR.2, this
     register stores the color of the inverse uppercase letters. Shadow
     for 53272 ($D018). Used for the background color in GR.0 and
     GR.8. Both use COLOR1 for the luminance value.
     Despite the official limitations of color selection in GR.8, it is
     possible to generate additional colors by "artifacting", turning
     on specific pixels (.5 color clock each) on the screen. Taking
     advantage of the physical structure of the TV set itself, we
     selectively turn on vertical lines of pixels which all show the same
     color. For example:
     10   A = 40: B = 30: C = 70: D = 5: F
         = 20   GRAPHICS 8: POKE 87,7: P0K
        E 710,0: POKE 709,15: COLOR 1
     30   PLOT A,D: DRAWTO A,C: COLOR 2: P
        LOT F,D: DRAWTO F,C:
     40   PLOT A + 1,D: DRAWTO A + 1,C
     50   COLOR 3: PLOT B,D: DRAWTO B,C
     60   GOTO 60
     
     DOWNLOAD COLOR2.BAS
     A little experimentation with this will show you that the colors
     obtained depend on which pixels are turned on and how close
     together the pixel columns are. There are four "colors" you can
     obtain, as shown before. Pixels marked one are on; marked zero
     means they are off. Each pair of pixels is one color clock. Three
     color clocks are shown together for clarity:
     00:01:00 = color A     00:11:00 = color B
     00:10:00 = color C     00:01:10 = color D
     See BYTE, May 1982, De Re Atari, and Your Atari 400/800.
711          	2C7          	COLOR3
 
-      The same as the above but for playfield three. Also, the color for
     GR.1 and GR.2 inverse lowercase letters. Shadow for 53273
     ($D019).
712          	2C8          	COLOR4
 
-      The same as the above but for the background (BAK) and border
     color. Shadow for 53274 ($D01A). In GTIA mode ten, 704 stores
     the background color (BAK), while 712 becomes a normal color
     register.
     Here are the default (powerup) values for the COLOR registers
     (PCOL registers are all set to zero on powerup):
     Register      Color  =  Hue  Luminance
     708  (CO.0)     40       2       8
     709  (CO.1)    202      12      10
     710  (CO.2)    148       9       4
     711  (CO.3)     70       4       6
     712  (CO.4)      0       0       0
----------------------------------------------------------------------------
Locations 713 to 735 ($2C9 to $2DF) are spare bytes. Locations 736 to
767 ($2E0 to $2FF) are for miscellaneous use.
736-739          	2E0-2E3          	GLBABS
 
-      Global variables, or, four spare bytes for non DOS users. For
     DOS users they are used as below:
736-737          	2E0-2E1          	RUNAD
 
-      Used by DOS for the run address read from the disk sector one or
     from a binary file. Upon completion of any binary load, control
     will normally be passed back to the DOS menu. However, DOS
     can be forced to pass control to any specific address by storing
     that address here. If RUNAD is set to 40960 ($A000), then the left
     cartridge (BASIC if inserted) will be called when the program is
     booted.
     With DOS 1.0, if you POKE the address of your binary load file
     here, the file will be automatically run upon using the DOS
     Binary Load (selection L). Using DOS 1.0's append (/A) option
     when saving a binary file to disk, you can cause the load address
     POKEd here to be saved with the data. In DOS 2.0, you may
     specify the initialization and the run address with the program
     name when you save it to disk (i.e.,
     GAME.OBJ,2000,4FFF,4F00,4000). DOS 2.0 uses the /A option
     to merge files. In order to prevent your binary files from running
     automatically upon loading in DOS 2.0, use the /N appendage to
     the file name when loading the file.
     For users of CompuServe, there is an excellent little BASIC
     program (with machine language subroutines) to create autoboot
     files, chain machine language files with BASIC and to add an 850
     autoboot file in the Popular Electronics Magazine (PEM) access
     area. It is available free for downloading.
738-739          	2E2-2E3          	INITAD
 
-      Initialization address read from the disk. An autoboot file must
     load an address value into either RUNAD above or INITAD. The
     code pointed to by INITAD will be run as soon as that location is
     loaded. The code pointed to by RUNAD will be executed only
     after the entire load process has been completed. To return
     control to DOS after the execution of your program, end your
     code with an RTS instruction.
740          	2E4          	RAMSIZ
 
-      RAM size, high byte only; this is the number of pages that the top
     of RAM represents (one page equals 256 bytes). Since there can
     never be less than a whole page, it becomes practical to measure
     RAM in those page units. This is the same value as in RAMTOP,
     location 106 ($6A), passed here from TRAMSZ, location 6. Space
     saved by moving RAMSIZ or RAMTOP has the advantage of
     being above the display area. Initialized to 160 for a 48K Atari.
741,742          	2E5,2E6          	MEMTOP
 
-      Pointer to the top of free memory used by both BASIC (which
     calls it HIMEM) and the OS, passed here from TRAMSZ, location
     6 after powerup. This address is the highest free location in RAM
     for programs and data. The value is updated on powerup, when
     RESET is pressed, when you change GRAPHICS mode, or when
     a channel (IOCB) is OPENed to the display. The display list starts
     at the next byte above MEMTOP.
     The screen handler will only OPEN the S: device if no RAM is
     needed below this value (i.e. there is enough free RAM below
     here to accommodate the requested GRAPHICS mode change).
     Memory above this address is used for the display list and the
     screen display RAM. Also, if a screen mode change would
     extend the screen mode memory below APPMHI (locations 14,
     15: $E, $F), then the screen is set back for GR.0, MEMTOP is
     updated, and an error is returned to the user. Otherwise the
     mode change will take place and MEMTOP will be updated.
     Space saved by moving MEMTOP is below the display list. Be 
     careful not to overwrite it if you change GRAPHICS modes in
     mid-program. When using memory below MEMTOP for storage, 
     make sure to set APPMHI above your data to avoid having the
     screen data descend into it and destroy it.
743,744          	2E7,2E8          	MEMLO
 
-      Pointer to the bottom of free memory, initialized to 1792 ($700)
     and updated by the presence of DOS or any other low-memory
     application program. It is used by the OS; the BASIC pointer to
     the bottom of free memory is at locations 128, 129 ($80, $81). The
     value in MEMLO is never altered by the OS after powerup.
     This is the address of the first free location in RAM available for
     program use. Set after all FMS buffers have been allocated (see
     locations 1801 and 1802; $709 and $70A). The address of the last
     sector buffer is incremented by 128 (the buffer size in bytes) and
     the value placed in MEMLO. The value updates on powerup or
     when RESET is pressed. This value is passed back to locations 
     128, 129 ($80, $81) on the execution of the BASIC NEW
     command, but not RUN, LOAD or RESET.
     If you are reserving space for your own device driver(s) or
     reserving buffer space, you load your routine into the address
     specified by MEMLO, add the size of your routine to the MEMLO
     value, and POKE the new value plus one back into MEMLO.
     When you don't have DOS or any other application program
     using low-memory resident, MEMLO points to 1792 ($700. With
     DOS 2.0 present, MEMLO points to 7420 ($1CFC). If you change
     the buffer defaults mentioned earlier, you will raise or lower this
     latter value by 128 ($80) bytes for every buffer added or deleted,
     respectively. When you boot up the 850 Interface with or without
     disk, you add another 1728 ($6C0) bytes to the value in MEMLO.
     You can alter MEMLO to protect an area of memory below your
     program. This is an alternative to protecting an area above
     RAMTOP (location 106; $6A) and avoids the problem of the
     CLEAR SCREEN routine destroying data. However, unless you
     have created a MEM.SAV file, the data will be wiped out when
     you call DOS. To alter MEMLO, you start by POKEing WARMST
     (location 8) with zero, then doing a JMP to the BASIC cartridge
     entry point at 40960($A000) after defining your area to protect.
     For example, try this:
     10 DIM MEM$(24):PROTECT=700:REM NUMBE
        R OF BYTES TO CHANGE
     15 HIBYTE=INT(PROTECT/256):LOBYTE=PRO
        TECT-256*HIBYTE
     20 FOR N=1 TO 24:READ PRG:MEM$(N)=CHR
        $(PRG):NEXT N
     30 MEM$(6,6)=CHR$(LOBYTE):MEM$(14,14)
        =CHR$(HIBYTE)
     40 RESERVE=USR(ADR(MEM$))
     50 DATA 24,173,231,2,105,0,141,231,2,
        173,232,2,105
     60 DATA 0,141,232,2,169,0,133,8,76,0,
        160
        
     DOWNLOAD MEMLO.BAS
     You will find the address of your reserved memory by: PRINT
     PEEK(743) + PEEK(744) * 256 before you run the program. This
     program will wipe itself out when run. Altering MEMLO is the
     method used by both DOS and the RS-232 port driver in the 850
     Interface. See COMPUTE!, July 1981.
745          	2E9          	....
 
-      Spare byte.
746-749          	2EA-2ED          	DVSTAT
 
-      Four device status registers used by the I/O status operation as
     follows:
     746 ($2EA) is the device error status and the command status
     byte. If the operation is a disk I/O, then the status returned is that
     of the 1771 controller chip in your Atari disk drive. Bits set to one
     return the following error codes:
     Bit  Decimal  Error
     0       1     An invalid command frame was received (error).
     1       2     An invalid data frame was received.
     2       4     An output operation was unsuccessful.
     3       8     The disk is write-protected.
     4      16     The system is inactive (on standby).
     7      32     The peripheral controller is "intelligent" (has its
                   own microprocessor: the disk drive). All Atari
                   devices are intelligent except the cassette
                   recorder, so BIT 7 will normally be one when a
                   device is attached.
     747 ($2EB) is the device status byte. For the disk, it holds the
     value of the status register of the drive controller. For the 850
     Interface, it holds the status for DSR,CTS,CRX and RCV when
     concurrent I/O is not active (see the 850 Interface Manual). It also
     contains the AUX2 byte value from the previous operation (see
     the IOCB description at 832 to 959; $340 to $3AF).
     748 ($2EC) is the maximum device time-out value in seconds. A
     value of 60 here represents 64 seconds. This value is passed back
     to location 582 ($246) after every disk status request. Initialized to
     31.
     749 ($2ED) is used for number of bytes in output buffer. See 850
     Manual, p. 43.
     When concurrent I/O is active, the STATUS command returns
     the number of characters in the input buffer to locations 747 and
     748, and the number of characters in the output buffer to location
     749.
750,751          	2EE,2EF          	CBAUDL/H
 
-      Cassette baud rate low and high bytes. Initialized to 1484
     ($5CC), which represents a nominal 600 baud (bits per second).
     After baud rate calculations, these locations will contain POKEY
     values for the corrected baud rate. The baud rate is adjusted by
     SIO to account for motor variations, tape stretch, etc. The
     beginning of every cassette record contains a pattern of
     alternating off/on bits (zero/one) which are used solely for speed
     (baud) correction.
752          	2F0          	CRSINH
 
-      Cursor inhibit flag. Zero turns the cursor on; any other number
     turns the cursor off. A visible cursor is an inverse blank (space)
     character. Note that cursor visibility does not change until the
     next time the cursor moves (if changed during a program). If you
     wish to change the cursor status without altering the screen data,
     follow your CRSINH change with a cursor movement (i.e., up,
     down) sequence. This register is set to zero (cursor restored) on
     powerup, RESET, BREAK, or an OPEN command to either the
     display handler (S:) or screen editor (E:). See location 755 for
     another means to turn off the cursor.
753          	2F1          	KEYDEL
 
-      Key delay flag or key debounce counter; used to see if any key
     has been pressed. If a zero is returned, then no key has been
     pressed. If three is returned, then any key. It is decremented
     every stage two VBLANK (1/60 or 1/30th second) until it reaches
     zero. If any key is pressed while KEYDEL is greater than zero, it
     is ignored as "bounce." See COMPUTE!, December 1981, for a
     routine to change the keyboard delay to suit your own typing
     needs.
754          	2F2          	CH1
 
-      Prior keyboard character code (most recently read and
     accepted). This is the previous value passed from 764 ($2FC). If
     the value of the new key code equals the value in CH1, then the
     code is accepted only if a suitable key debounce delay has taken
     place since the prior value was accepted.
755          	2F3          	CHACT
 
-      Character Mode Register. Zero means normal inverse
     characters, one is blank inverse characters (inverse characters
     will be printed as blanks, i.e., invisible), two is normal
     characters, three is solid inverse characters. Four to seven is the
     same as zero to three, but prints the display upside down.
     This register also controls the transparency of the cursor. It is
     transparent with values two and six, opaque with values three
     and seven. The cursor is absent with values zero, one, four and
     five.
     Toggling BIT 0 on and off can be a handy way to produce a
     blinking effect for printed inverse characters (characters with
     ATASCII values greater than 128 -- those that have BIT 7 set).
     Shadow for 54273 ($D401). There is no visible cursor for the
     graphics mode output. CHACT is initialized to two.
     Here's an example of blinking text using this register:
     10 CHACT=755:REM USE INVERSE FOR WORD
        S BELOW
     15 PRINT "[THIS IS A TEST OF BLINKING ]
       [TEXT]"
     20 POKE CHACT,INT(RND(0)*4)
     30 FOR N=1 TO 100:NEXT N:GOTO 15
     See COMPUTE!, December 1981.
     Using a machine language routine and page six space, try:
     10 PAGE=1536:EXIT=1568
     20 FOR N=PAGE TO EXIT:READ BYTE:POKE
        N,BYTE:NEXT N
     30 PGM=USR(PAGE)
     40 PRINT "[THIS] IS A [TEST] OF [BLINKING]
        TEXT":REM MAKE SOME WORDS INVERSE
     50 GOTO 50
     60 DATA 104,169,17,141,40,2,169,6,141
        ,41
     70 DATA 2,169,30,141,26,2,98,173,243,
        2
     80 DATA 41,1,73,1,141,243,2,169,30,14
        1,26,2,96
        
     DOWNLOAD CHACT.BAS
     The blink frequency is set .5 second; to change it, change the
     30 in line 80 to any number from one (1/30 second) to 255 (eight
     .5 seconds). For another way to make the cursor visible or
     invisible, see locations 752 above.
756          	2F4          	CHBAS
 
-      Character Base Register, shadow for 54281 ($D409). The default
     (initialization value) is 224 ($E0) for uppercase characters and
     numbers; POKE CHBAS with 226 ($E2) to get the lowercase and
     the graphics characters in GR.1 and GR.2. In GR.0 you get the
     entire set displayed to the screen, but in GR.1 and GR.2, you
     must POKE 756 for the appropriate half-set to be displayed.
     How do you create an altered character set? First you must
     reserve an area in memory for your set (512 or 1024 bytes; look at
     location 106; $6A to see how). Then either you move the ROM set
     (or half set, if that's all you intend to change) into that area and
     alter the selected characters, or you fill up the space with bytes
     which make up your own set. Then you POKE 756 with the MSB
     of the location of your set so the computer knows where to find it.
     What does an altered character set look like? Each character is a
     block one byte wide by eight bytes high. You set the bits for the
     points on the screen you wish to be "on" when displayed. Here
     are two examples:
     one byte wide:
     00100000 = 32             #
     00010000 = 16              #
     00010000 = 16              #
     00010000 = 16              #
     00011110 = 30              ####
     00000010 =  2                 #
     00001100 = 12               ##
     00010000 = 16              #
     Hebrew letter Lamed
     one byte wide:
     10000001 = 129          #      #
     10011001 = 153          #  ##  #
     10111101 = 189          # #### #
     11111111 = 255          ########
     11111111 = 255          ########
     10111101 = 189          # #### #
     10011001 = 153          #  ##  #
     10000001 = 129          #      #
     Tie-fighter
     You can turn these characters into DATA statements to be POKEd
     into your reserved area by using the values for the bytes as in the
     above examples. To change the ROM set once it is moved, you
     look at the internal code (see the BASIC Reference Manual, p.
     55) and find the value of the letter you want to replace--such as
     the letter A--code 33. Multiply this by eight bytes for each code
     number from the start of the set (33 * eight equals 264). You then
     replace the eight bytes used by the letter A, using a FOR-NEXT
     loop with the values for your own character. For example, add
     these lines to the machine language found a few pages further on:
     1000 FOR LOOP=1 TO 4:READ CHAR:SET=CH
          ACT+CHAR*8
     1010 FOR TIME=0 TO 7:READ BYTE:POKE S
          ET+TIME,BYTE: NEXT TIME
     1020 NEXT LOOP
     1030 DATA 33,0,120,124,22,22,124,120,
          0
     1040 DATA 34,0,126,82,82,82,108,0,0
     1050 DATA 35,56,84,254,238,254,68,56,
          0
     1060 DATA 36,100,84,76,0,48,72,72,48
     2000 END
     RUN it and type the letters A to D.
     Why 224 and 226? Translated to hex, these values are $E0 and
     $E2, respectively. These are the high bytes (MSB) for the location
     of the character set stored in ROM: $E000 (57344) is the address
     for the start of the set (which begins with punctuation, numbers
     and uppercase letters), and $E200 (57856), for the second half of
     the ROM set, lowercase and graphic control characters (both
     start on page boundaries). The ROM set uses the internal order
     given on page 55 of your BASIC Reference Manual, not the
     ATASCII order. See also location 57344 ($E000).
     You will notice that using the PRINT#6 command will show you
     that your characters have more than one color available to them
     in GR.1 and GR.2. Try PRINTing lowercase or inverse
     characters when you are using the uppercase set. This effect can
     be very useful in creating colorful text pages. Uppercase letters,
     numbers, and special characters use color register zero (location
     708; $2C4 - orange) for normal display, and color register two
     (710; $2C6 - blue) for inverse display. Lowercase letters use
     register one (709; $2C5 - aqua) for normal display and register
     three (711; $2C7 - pink) for inverse. See COMPUTE!, December
     1981, page 98, for a discussion of using the CTRL keys with letter
     keys to get different color effects.
     One problem with POKEing 756 with 226 is that there is no blank
     space character in the second set: you get a screen full of hearts.
     You have two choices: you can change the color of register zero
     to the same as the background and lose those characters which
     use register zero--the control characters--but get your blanks
     (and you still have registers one, two and three left). Or you can
     redefine your own set with a blank character in it. The latter is
     obviously more work. See "Ask The Readers," COMPUTE!, July
     1982.
     It is seldom mentioned in the manuals, but you cannot set 756 to
     225 ($El) or any other odd number. Doing so will only give you
     screen garbage. The page number 756 points to must be evenly
     divisible by two.
     When you create your own character set and store it in memory,
     you need to reserve at least 1K for a full character set (1024 bytes
     --$400 or four pages), and you must begin on a page boundary.
     In hex these are the numbers ending with $XX00 such as $C000
     or $600 because you store the pointer to your set here in 756; it
     can only hold the MSB of the address and assumes that the LSB is
     always zero--or rather a page boundary. You can reserve
     memory by:
     POKE 106,PEEK(106)-4 (or any multiple of four)
     And do a GRAPHICS command immediately after to have your
     new memory value accepted by the computer. If you are using
     only one half of the entire set, for GR.1 or GR.2, you need only
     reserve 512 bytes, and it may begin on a .5K boundary (like
     $E200; these are hexadecimal memory locations that end in
     $X200). If you plan to switch to different character sets, you will
     need to reserve the full 1K or more, according to the number of
     different character sets you need to display. RAM for half-K sets
     can be reserved by:
     POKE 106,PEEK(106)-2 (or a multiple of two)
     The location for your set will then begin at PEEK(106)*256.
     Because BASIC cannot always handle setting up a display list for
     GR.7 and GR.8 when you modify location 106 by less than 4K (16
     pages), you may find you must use PEEK(106)-16. See location
     88,89 ($58,$59) and 54279 ($D407) for information regarding
     screen use and reserving memory.
     Make sure you don't have your character set overlap with your
     player/missile graphics. Be very careful when using altered
     character sets in high memory. Changing GRAPHICS modes, a
     CLEAR command, or scrolling the text window all clear memory
     past the screen display. When you scroll the text window, you
     don't simply scroll the four lines; you actually scroll a full 24 (20
     additional lines * 40 bytes equals 800 bytes scrolled past
     memory)! This messes up the memory past the window display
     address, so position your character sets below all possible
     interference (or don't scroll or clear the screen).
     You can create and store as many character sets as your memory
     will allow. You switch back and forth between them and the ROM
     set by simply POKEing the MSB of the address into 756. Of
     course, you can display only one set at a time unless you use an
     altered display list and DLI to call up other sets. There are no
     restrictions outside of memory requirements on using altered
     character sets with P/M graphics as long as the areas reserved for
     them do not overlap.
     A GRAPHICS command such as GR.0, RESET or a DOS call
     restores the character set pointer to the ROM location, so you
     must always POKE it again with the correct location of your new
     set after any such command. A useful place to store these sets is
     one page after the end of RAM, assuming you've gone back to
     location 106 ($6A) and subtracted the correct number of pages
     from the value it holds (by POKE 106,PEEK(106) minus the
     number of pages to be reserved; see above). Then you can reset
     the character set location by simply using POKE
     756,PEEK(106)+1 (the plus one simply makes sure you start at
     the first byte of your set).
     A full character set requires 1024 bytes (1K: four pages) be
     reserved for it. Why? Because there are 128 characters, each
     represented by eight bytes, so 128 * eight equals 1024. If you are
     using a graphics mode that uses only half the character set, you
     need only reserve 512 bytes (64 * eight equals 512). Remember to
     begin either one on a page boundary (1K boundary for full sets or
     .5K for half sets). By switching back and forth between two
     character sets, you could create the illusion of animation.
     Many magazines have published good utilities to aid in the
     design of altered character sets, such as the January 1982
     Creative Computing, and SuperFont in COMPUTE!, January
     1982. I suggest that you examine The Next Step from Online,
     Instedit from APX, or FontEdit from the Code Works for very
     useful set generators. One potentially useful way to alter just a
     few of the characters is to duplicate the block of memory which
     holds the ROM set by moving it byte by byte into RAM. A BASIC
     FOR-NEXT loop can accomplish this, although it's very slow. For
     example:
     5 CH=57344
     10 START=PEEK(106)-4:PLACE=START*256:
        POKE 106,PEEK(106)-5:GRAPHICS 0: RE
        M RESERVE EXTRA IN CASE OF SCREEN
        CLEAR
     20 FOR LOOP=0 TO 1023:POKE PLACE+LOOP
        ,PEEK(CH+LOOP):NEXT LOOP:REM MOVE
        THE ROM SET
     30 POKE 756,PLACE/256:REM TELL ANTIC
        WHERE CHSET IS
     Here's a machine language routine to move the set:
     10 DIM BYTE$(80)
     15 REM MEM-1 TO PROTECT SET FROM CLEA
        R SCREEN DESTRUCTION (SEE LOC.88)
     20 MEM=PEEK(106)-4:POKE 106,MEM-1: CHA
        CT=MEM*256:GRAPHICS 0
     30 FOR LOOP=1 TO 32:READ PGM:BYTE$(LO
        OP,LOOP)=CHR$(PGM):NEXT LOOP
     40 DATA 104,104,133,213,104,133,212
     50 DATA 104,133,215,104,133,214,162
     60 DATA 4,160,0,177,212,145,214
     70 DATA 200,208,249,230,213,230,215
     80 DATA 202,208,240,96
     90 Z=USR(ADR(BYTE$),224*256,CHACT)
     .
     . ADD YOUR OWN ALTERATION PROGRAM OR
     THE EARLIER EXAMPLE HERE
     .
     .
     1500 POKE MEM-1,0:POKE 756,MEM
     If you have Microsoft BASIC or BASIC A+, you can do this very
     easily with the MOVE command!
     Remember, when altering the ROM set, that the characters aren't
     in ATASCII order; rather they are in their own internal order.
     Your own set will have to follow this order if you wish to have the
     characters correlate to the keyboard and the ATASCII values.
     See page 55 of your BASIC Reference Manual for a listing of the
     internal order. Creative Computing, January 1982, had a good
     article on character sets, as well as a useful method of
     transferring the ROM set to RAM using string manipulation. See
     also "Using Text Plot for Animated Games" in COMPUTE!, April
     1982, for an example of using character sets for animated
     graphics.
757-761          	2F5-2F9          	....
 
-      Spare bytes.
762          	2FA          	CHAR
 
-      Internal code value for the most recent character read or written
     (internal code for the value in ATACHR below). This register is
     difficult to use with PEEK statements since it returns the most
     recent character; most often the cursor value (128, $80 for a
     visible, zero for an invisible cursor).