Classic Computer Magazine Archive ANTIC VOL. 8, NO. 4 / AUGUST 1989

Mapping the Atari


Antic brings back the classic 8-bit reference book.

Serialization by Ian Chadwick

Ian Chadwick's "Mapping The Atari" has been one of the core references for Atari 8-bit programmers since the first edition was published in 1983. The book is set up as a comprehensive guide to the memory locations in the Atari 130XE, 65XE, 800XL, 600XL, 1200XL, 800 and 400. But it is much more than that. It is a virtual encyclopedia of indispensible information about the inner workings of the Atari.

This invaluable sourcebook essentially is out of print today, although a few copies of "Mapping The Atari" can still be found in the publisher's warehouse and occasionally at specialty computer stores. Therefore, it is with great satisfaction that Antic announces we are beginning an exclusive serialization of key excerpts from the revised second edition of Chadwick's book. This opening segment provides a useful overview of the material that will be covered in upcoming issues.

What exactly is a memory map? It is a guide to the memory locations in your computer. A memory location is one of 65536 storage places called bytes in which a number is stored. Each of these bytes holds a number for programs, data, color, sound, system operation, or is empty (i.e, has a zero in it), waiting for you to fill it with your own program.

Each byte is composed of eight bits, each of which can be either a one (on) or a zero (off). The alterable area of memory you use for your programs is called the Random Access Memory (RAM), while the area used by the Atari to run things is called the Read Only Memory (ROM). Although some of the memory locations in the special Atari chips were designed to be written to like the RAM, the rest of the ROM, including the Operating System ROM, cannot be altered by you since it contains routines such as the floating point mathematics package and the input/output routines.

I hope that you are familiar enough with your Atari to understand some of these rudimentary uses of a memory map. It is not the scope of this manual to fully explain how to use PEEK and POKE statements. Briefly, however, PEEK allows you to look at the value stored in any one memory location. If you want that value to be printed to the screen, you must preface the PEEK statement with a PRINT statement such as:


If you haven't changed your color registers, this will return the number 40 to your screen. All bytes in the Atari can hold a number between zero and 255. POKE allows you to place a value into a byte, such as:

POKE 755,4

By doing this you will have turned your text upside down! You can return it to normal by:

POKE 755,2

Similarly, POKE 710,80 will turn your screen dark purple! As with PEEK, POKE can only involve numbers between zero and 255. You will not be able to POKE into most of the ROM locations since the numbers in many of them are "hard-wired," "burned" into the chip, and cannot be changed in this manner.

So how does the Atari (or other 8-bit microcomputers, for that matter) store a number larger than 255? By breaking it down into two parts; the Most Significant Byte (MSB), which is the number divided by 256 and rounded down to the nearest whole number, and the Least Significant Byte (LSB), which is the original number minus the MSB. The Atari knows to multiply the MSB by 256 and add the LSB to get the number. For example, the number 45290 is stored as two parts: 234 (LSB) and 176 (MSB). 176 times 256 equals 45056, plus 234 equals 45290.


The Atari uses the convention of storing addresses in the LSB/MSB manner in memory (i.e, the smaller part is in the first memory location). For example, locations 88 and 89 store the lowest address of the screen memory. Let's say the numbers found there are 22 and 56, respectively. To get the decimal address, you take the MSB (stored in 89) and multiply it by 256, then you add it to the LSB at 88. In our case that's 56 * 256 equals 14336, plus 22 equals 14358. This is the address of the upper left corner of the screen. A simple way to do this in BASIC is:

BYTE = PEEK(88) + PEEK(89) * 256

The reverse (to break up a decimal location into MSB and LSB) is done by:


This process is easier for assembly language programmers who use hexadecimal numbers, since the right two digits are always the LSB and the two left of them are the MSB. For example:

$D016 (hexadecimal for 53270) equals 16 (LSB) and D0 (MSB)

$16 equals 22 in decimal, and $D0 equals 208 decimal. Multiply the MSB by 256 and add 22 and you get 53270. Throughout the map portion of this book I have provided both decimal and hexadecimal numbers together for ease of reference. In 8K BASIC you can use decimal numbers only with POKE, and PEEK will return only decimal values to you.

Hexadecimal is a base 16 used instead of the normal base ten system because it is more suited to the eight-bit structure of the computer. So, when we say 2175 in decimal, what we really mean is:

10000  1000  100  10  1        
    0     2    1   7  5

In hex, the same number is $87F. That breaks down to:

4096    256    16    1
   0      8     7    F   

Rather than multiply each next step up by ten, we multiply by 16. Okay, but where do we get "F" from? Well, if base ten has the numbers zero to nine, base 16 will have to have some letters added to the end to make up for the extra numbers:

  Decimal 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15  
  Hex     0 1 2 3 4 5 6 7 8 9  A  B  C  D  E  F  

So $F equals 15 in decimal. Now here's how it all relates to and bits:

Each byte can be broken up into two parts (nybbles), like this 0000 0000

If each nybble is considered a separate number, in decimal, the value of each would range from zero to 15, or zero to $F. Aha! So if all the bits in each group are on (one, or set), then you have:

1111     1111   Binary
  15       15   Decimal
   F        F   HEX

You join the two hex numbers together and you get $FF (255 in decimal), the largest number a byte can hold. So you can see how we translate bytes from binary to hex, by translating each nybble. For example:

1001    1101     Binary
   9      13     Decimal
   9       D     Hex

$9D equals nine times 16 plus 13, or 157 in decimal.

0100     0110    Binary
   4        6    Decimal
   4        6    Hex

$46 equals four times 16 plus six, or 70 in decimal.

1111   1010    Binary  
  15     10    Decimal
   F      A    Hex

$FA equals 15 times 16 plus ten, or 250 in decimal.

Obviously, it is easier to do this with a translation program or a calculator!

Since I will often be discuss setting bits and explaining a small amount of bit architecture, you should be aware of the simple procedures by which you can turn on and off specific bits in any location (that is, how to manipulate one of the eight individual bits within a byte). Each byte is a collection of eight bits: numbers are represented by turning on the particular bits that add up to the number stored in that byte. Bits can be either zero (0 equals off) or one (1 equals on, or SET). The bits are numbered zero to seven and represent the following decimal numbers:

Bit      7   6   5   4  3  2  1  0
Value  128  64  32  16  8  4  2  1

The relationship belween the bits and the powers of two should be obvious. Adding up all the numbers (all the bits are set) gives us 255. So each byte can hold a number between zero (no bits are set) and 255 (all bits are set).

Sometimes instead of zero, no bits set is intended to mean 256. That will be noted in the relevant locations. So how do you set a bit? Simple: POKE it with the appropriate number. For example, to set Bit 5, POKE the location with 32. To set Bits 7, 5 and 4, add up their values, 128 + 32 + 16, and POKE the location with the total:176.

Sometimes you need to set a bit without changing other bits already set, so you:

POKE number, PEEK (number) + decimal value for the bit to be set.(i.e., POKE 50418, PEEK(50418) + 32)

To turn off a bit, instead of adding the value you would subtract it with POKE number, PEEK (number), minus the decimal value for the bit to be turned off. Binary math is simple and easy to learn; if you don't understand it now, you should do further reading on machine language before attempting any serious use of this guide.


It is useful to know how to perform Boolean logic on bits. There are three functions used in assembly code for bit manipulation in this manner: AND, OR and EOR (exclusive OR). Each requires you to use two numbers, the one being acted upon and the one used to perform the function. Here is a brief explanation of how these logical functions work:

AND is usually used as a mask--to zero out unwanted bits. You compare two binary numbers using AND; if both bits in the same location are one, then the result is one. If either bit is zero, then the result is zero. For example:

          51 = 00110011
AND       15 = 00001111
Result                  = 00000011 = 3

OR is frequently used to force setting of a bit. If either bit in the original or the mask is one, then the result is one. For example:

           65 = 01000001
OR        128 = 10000000
Result        = 11000001 = 193

In this case, 65 is the ATASCII "A". By ORing it with 128, we get 193, the ATASCII inverse "A".

EOR "flips" bits in the original if the mask has a one in the same location. For example:

           193 = 11000001
EOR        128 = 10000000
Result         = 01000001 = 65

In this case, we have returned the inverse "A" to the normal ATASCII value. An EOR with 255 (all ones) will produce the complement of the number:

            171 = 10101011
EOR         255 = 11111111
Result          = 01010100 = 84

   In brief:
 Original:       Mask:        AND:        OR:         EOR:
 0               0            0           0           0
 0               1            0           1           1
 1               0            0           1           1
 1               1            1           1           0

Atari BASIC supports AND, OR and NOT; NOT is the logical complement where NOT1 equals zero and NOT0 equals one. If the expression is true, you get a zero; if NOT true, a one is retumed--for example NOT ((3 + 4) > = 6) results in zero.

In general, I have attempted to avoid using 6502 assembly language mnemonics, but have included them where I felt their use described the action to be taken better than a lengthy explanation. Most common are JMP (jump to location), JSR (jump to subroutine), RTS (return from subroutine), and RTI (return from interrupt). Readers should be minimally familiar with machine language in order to understand any machine language subroutines used here.

You can't hurt the machine by POKEing about in memory, although you may crash any program in memory, so SAVE your program first. Usually you can salvage it by pushing [RESET], but you may have to turn off the machine and reboot on occasion. You can learn a lot about your machine by simply playing around with it.


The majority the information here concerns language-independent locations and can be used regardless of the language you use for your programming. When the location is language-dependent, such as the BASIC or DOS areas, I have noted it in the proper section. You may exert the same control over your Atari in whatever language you chose. You will obviously have to change the commands PEEK and POKE to the proper commands of your language.

BASIC is a good language to start with: you can use it to learn programming, to explore your computer, to experiment with, and to have fun with. However, when you are ready to go on, you will have to learn a more efficient, faster language if you really want to make the best use of your Atari. Many people choose 6502 machine language because of its speed.

Computer languages, whichever you use, are quite exact in their meaning, especially compared to English. Consider that in English, a fat chance and a slim chance both mean the same thing. Yet POKE, PUT, an PUSH have very different meanings in computerese.


ANTIC, CTIA AND GTIA, PIA, POKEY: Special Atari chips controlling the 400/800's graphics, color and screen resolution controller jacks and. sound, respectively. Located in ROM, locations 53248 to 54783. ANTIC also processes the Non-Maskable Interrupts and POKEY processes the Interrupt Requests. These chips, along with the 6502 microprocessor which runs the rest of the Atari, are housed inside your computer, protected by the metal shielding underneath the plastic cover.

BIT, BYTE: A bit is the smallest size division of memory in your computer. It is so small that it can hold only one value in it: off (zero) or on (one). Eight bits together form a byte; this is the size of the memory locations discussed in this book. You will sometimes hear programmers talk about a half-byte called a "nybble."

CIO: Central Input/Output routines located in ROM. Controls Input/Output Control Block operations. Briefly, CIO handles the data input and output through the device driver(s) (also known as device handlers), then passes control to those drivers. It's a single interface with which to access all peripherals in a device-independent manner (i.e., uniform handling of data with no regard to the device being accessed). As an example: writing data to a disk file is treated in an identical manner as writing data to the screen; commas insert blanks between elements and both semicolons and commas suppress the End-Of-Line charracter (EOL).

DCB: Device Control Block, by Serial Input/Output.

DL: Display List. This is a set of instructions which tell the ANTIC chip where to find the screen display data and how that data is to be placed on the TV screen.

DLI: Display List Interrupt. A DLI causes the display to stop processing to temporarily run a user-written routine.

DOS: Disk Operating System. The software loaded from disk file DOS.SYS that controls all disk I/O. The latest edition of DOS is called DOS 2.0S (S for single density).

DUP: Disk Utilities Package. The software loaded from disk file DUP.SYS that handles the DOS menu functions such as Copy.

FMS: (or sometimes DFMS): File Management System portion of DOS; a dedicated device driver that controls all I/O operations for device "D:".

FP: Floating Point mathematical package in ROM.

I/O: Input/Output.

IOCB: Input/Output Control Block. Area of RAM (locations 832 to 959) used by CIO to define operations to devices such as the disk drive (D:), printer (P:), screen display (S:), keyboard (K:) and screen editor (E:). ZIOCB is the page zero IOCB.

IRQ: Interrupt Request used for serial port communication, peripheral devices, timing and keyboard input. IRQ's are processed by the POKEY chip.

NMI: Non-Maskable Interrupt; used for video display and RESET. NMIs are processed by the ANTIC chip.

OS: operating system. The resident system that runs the Atari.

Although people often refer to the entire ROM area as the OS, this is not correct. The OS ROM is that portion of memory which holds the floating point package, the Atari character set, the device handlers, and both CIO and SIG. The actual operating system itself is the portion of the OS ROM which handles the I/O.

PMG, PM Graphics: Player/missle graphics. Players and missiles are special moveable, user-defined, colored screen objects. They are often used for games, animation, or special cursors. PM graphics are unique in that you can establish the manner (priority) in which they interact with the rest of the screen display and each other.

RAM: Random Access Memory. All memory below the OS area (0 to 49151) which is used for storage, programs, buffers, cartridges, DOS, IOCB, shadow registers, and registers for the special Atari chips. Random Access means you can get to and from these locations at randem, not that they store information randomly!

ROM: Read Only Memory. That part of high memory (locations 49152 to 65535) in which the special hardware chips and the OS reside. ROM is also used to describe cartridge memory such as the 8K BASIC ROM, which cannot be user-altered (the cartridge ROM supersedes the RAM). You cannot alter most of the ROM, although some of the locations in the special Atari chips may be temporarily set to a new value.

With both RAM and ROM, we refer to areas with lesser values as being in "low" memory and locations with larger values as being in "high" memory.

SIO: Serial Input/Output routines located in ROM. Controls serial operations including the 850 interface (R:) and cassette recorder (C:). Briefly, SIO controls the Atari peripherals as per the request placed in its Device Control Block (DCB) by the proper device driver. It is also accessed by FMS for data transfer.

VBI: VBLANK interrupt. A VBI is an interrupt that occurs during the VBLANK interval, causing the computer to jump to a user-specified location to process a short user-written routine during the VBLANK process.

VBLANK: Vertical Blank. The interval between the time the TV electron beam turns off after reaching the bottom right corner of the screen and retums to the top left corner and turns back on again. This small time period may be used by machine language programmers for short routines without interrupting the display by writing a VBI (above). There are two VBLANK stages. Stage one is performed every VBLANK cycle (1/60 second). Stage two is performed either every 1/30 second or every 1/60 second when it doesn't interrupt time-critical code being executed. See the end of the memory map for the processes executed in each stage.

Copyright 1983 and 1985, COMPUTE! publications, Inc.

$16.95, COMPUTEI Books, P.O. Box 5406, Greensboro, North Carolina 27403
(919) 275-9809.

Ian Chadwick is a Toronto-based freelance writer.

A Graphics Memory Map

This diagram is not to scale; it is merely meant to give you a visual idea of the structure of the Atari memory. The numbers on the right are the memory pointers: these locations point to the addresses shown. The numbers on the left are the actual locations in memory.


The bottom of the BASIC RAM depends on whether or not you have DOS files loaded in. Without DOS, LOMEM should be 1792, with DOS 7420. If you increase or decrease the number of disk and sector buffers by modifying DOS, this value will change again. See locations 743, 744 and 1801, 1802.

The size and location of the variable, string and array tables depend on the program use and size. The more variables and arrays, the larger the memory the tables use.

The size and address of the Display List and screen memory depend on the GRAPHICS mode in use.

The first 256 bytes pointed to by LOMEM are the token output buffer. The actual BASIC program starts at the address pointed to by VNTP.

Atari Timing Values

clock frequency = 1.79 MHz
1 machine cycle = 0.558 microseconds
1 frame = 1/60 second
scan lines = 262/frame
color clocks = 228/scan line
color clocks = 2/machine cycle
machine cycles = 29868/frame
machine cycles = 114/scan line

VBLANK time = 7980 machine cycles or less, depending on GRAPHICS mode. The shortest 6502 instruction requires two cycles; during that time the electron beam moves four color clocks.

Horizontal blank time:

Wide playfield  18 machine cycles
playfield       34 machine cycles
playfield       50 machine cycles

   Location Contents Pointers
65535 _____



58533 _____

58367 _____


57343 _____

55295 _____




53247 _____

49151 _____

40959 _____

Size and
vary with



32767 _____


Size and
vary with




1791 ______

Top of memory ______________________
Operating System ROM

Device handler routines
Serial Input/Output (SIO) utilities
Interrupt handler

Central Input/Output (CIO) utilities

Operating System vectors_______________
Initial RAM vectors on powerup
JMP vectors

ROM Character set ____________________

Floating Point ROM package

I/O chips____________________________




Unused 4K ROM block ________________

or Left cartridge (A) ___________________

Top of BASIC RAM or

Right cartridge (B) ROM if present
(Atari 800 only)

Text window screen RAM
40800 for GR. 0

Bottom of screen RAM
40000 for GR. 0

Display List:
39968 for GR. 0


User-program RAM ___________________

The amount of RAM can be ascertained by:

Bottom varies: see note below
Depends on buffer area allocated.

RAM used by DOS and File System Manager

Stack for FOR-NEXT & GOSUB

String & array table &
end of BASIC program
BASIC program

Statement table:
Beginning of BASIC program
Variable variable table

VNTP + 1

Variable name table

BASIC bottom of memory

Sector buffer
Drive & sector buffer
DOS vector
DUP.SYS start
VTOC buffer
DOS initialization
or BASIC RAM without
DOS resident
DUP.SYS beginning

RAM used by OS and cartridge.
(to bottom of RAM)

Page six RAM


794-831 HATABS

512,513 VDSLST
514-527 Vectors


756 CHBAS ______________________


755 CH1
564-565 LPEN
560-561 SDLSTL
636-639 PTRIG#
632-635 STICK#
624-631 PADDL#

704-707 PCOLR#
708-712 COLOR#
644-647 STRIG#




60,661 TXTMSC

88,89 SAVMSC

560,561 SDLSTL

741, 742 MEMTOP


144,145 MEMTOP
142,143 RUNSTK
14,15 APPMHI

140,141 STRAP

136,137 STMTAB

134,135 VVTP

132,133 VNTD

130,131 VNTP

743,744 MEMLO
128,129 LOMRM

4921,4937 SABUFL/H
4905,4913 DBUFA1/H
10,11 DOSVEC

12,13 DOSINI
(743,744 MEMLO)
(128,129 LOMEM)

1535 _____________________________


RAM used by BASIC______________
(to bottom of RAM)

Floating Point RAM








Operating System RAM

Cassette buffer

Printer buffer



BASIC zero page RAM

Floating Point pg. 0

Assembler Cart. pg. 0

OS page zero RAM

Zero page IOCB

Bottom of memory