Author's Preface

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 the reader is familiar enough with his or her 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; refer to your BASIC manual. 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: PRINT PEEK (708) 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 eight-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: MSB = INT (BYTE/256):LSB = BYTE - MSB * 256 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 binary math 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 SFF (255 in deci- mal), 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 discussing 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 between 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 for the reader 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 freguently 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 returned--for example, NOT ((3 + 4) >= 6) results in zero. See COMPUTE!, May 1981 for a machine language routine to allow you to perform Boolean bit logic using a USR call from BASIC. 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. I also suggest that if the reader doesn't already have one, he or she obtain a program to translate hex to decimal and decimal to hex (possibly even one with binary translations as well). The ROM cartridge from Eastern House Software, Monkey Wrench, is useful for this purpose. Perhaps the easiest to use is the TI Programmer calculator from Texas Instruments. The examples in this book were all written using Atari 8K BASIC. They are intended to demonstrate the use or the effect of a particular memory location. They are not intended as the best examples of BASIC programming; they were written for simplicity, not sophistication. As a final note, any question or doubt as to either a particular location or explanation has been noted. It can't hurt to play around yourself, POKEing in the memory to see what other effects you can discover. If you find something I didn't, good! Please write and let me know. 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, hut 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 of 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 FORTH, Pascal, LISP, or 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. If you want to stay with a high-level language, I suggest you learn FORTH. It has some of the speed of machine language code with the ease of "higher level language" programming. 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, and PUSH have very different meanings in computerese.


Example: 912-927 390-39F IOCB5

The main memory map shows you the decimal and then the hexadecimal location, the label (assigned by Atari and used by OS, DOS or DUP routines), and then comments and description. The label has no real function; it is merely a mnemonic convenience. Readers are referred to Stan Kelly-Bootle's delightful book, The Devil's DP Dictionary (McGraw-Hill Ryerson, 1981), for a full definition of the word "label". The following abbreviations are also noted in the comments: (R) Read (W) Write Sometimes the functions are different in a particular location, so each is noted. (D:) Disk Drive (F:) Screen Editor (S:) Display (K:) Keyboard (P:) Printer (C:) Cassette (R:) RS-232 interface. (Don't confuse this with (R) for Read.) The context should be obvious. (number) e.g. (708) Shadow Register. This is a RAM register which corresponds to a ROM register in one of the special Atari chips such as GTIA or POKEY. The shadow location is the address you use to PEEK and POKE values. These shadow locations are polled by the hardware addresses 30 times a second at every stage two VBLANK interval, and the values used are transferred to the hardware locations for use. In order to effect any "permanent" change to the hardware location, you have to use the shadow register in BASIC (of course, every change is negated when you turn the machine off!). Only machine language is fast enough to use the hardware addresses directly. For example, location 54273 is for character control. It polls location 755 to see if the screen characters are to be normal, inverse, or upside- down. To change the characters, you POKE location 755--the shadow --not 54273. If you POKE 54273, you will get the desired effect--for 1/60 of a second! As mentioned above, you can use the hardware addresses directly in machine language, but not in BASIC. It's just too slow. Sometimes, where most appropriate, a hexadecimal number will be displayed and the decimal number put in parentheses. The context should be obvious concerning which is a shadow or a decimal number. (* letter) refers to a source in the case of a conflicting location or explanation. See the source below. ($number) refers to a hexadecimal (also called hex) number (i.e.: $D40E). I also refer to "pages" in memory. Pages are sections of 256 bytes ($100) of memory which end with 00 (i.e.: $E200, $C000, $600). Four pages ($400) equals 1024 bytes or 1K (kilobyte) of memory.


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 hit 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 hits 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 semi- colons and commas suppress the End-Of-Line character (EOL). DCB: Device Control Block, used 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 DOSSYS that controls all disk I/O. The latest edition of DOS is called DOS 2.OS (S for single density). DUP: Disk Utilities Package. The software loaded from disk file DUPSYS 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. The OS resides in the 10K front cartridge slot under the hood in your Atari 800. It's not visible in the 400 without taking the cover apart (not recommended). The OS is the same for both the 400 and 800. There are two versions of the OS currently in circulation: the older "A" ROMs and the newer "B" ROMs, released around January 1982. The new OS is almost identical to the old OS except that it corrects a few bugs and changes some addresses. Not all of your old software will run with the new OS. The differences between the two are better explained in Appendix Four. 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 SIO. The actual operating system itself is the portion of the OS ROM which handles the I/O. PMG, PM Graphics: Player/missile 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 random, 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 returns 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.


Letters in brackets are used in this guide to identify the source. (*M) Master Memory Map Ver. 2, Santa Cruz Educational Software, 1981. A memory guide by the same people who brought us the TRICKY TUTORIAL series. The latter are both tutorials and applications utilities. The map does contain some annoying errata. (*Y) Your Atari Computer, by Lon Poole with Martin McNiff & Steven Cook, Osborne/McGraw-Hill, 1982. The best guide to date on general use of the Atari. Very highly recommended (*C) COMPUTE!'s First Book of Atari, by the Editors of COMPUTE! Magazine, Small System Services Inc., 1981. A good collection of early articles that appeared in the magazine. At the time of this writing, COMPUTE!'s Second Book of Atari had just been released. It is therefore not used as a reference source here, but it is a must for serious programmers. It contains a wealth of information on an enormous range of topics, including advanced graphics, forced- read modes, page flipping, Atari BASIC and many valuable utilities. It should be a staple in most Atari owners' libraries. (*I) Inside Atari DOS, compiled by Bill Wilkinson, published by COMPUTE! Books, Small System Services, Inc., 1982. An explanation and copyrighted source code for the FMS portion of DOS 2.0. Atari BASIC: Learning by Using, by Thomas Rowley, Hofhacker Press, 1981. A lot of information packed into a surprisingly good little book. The following publications are all from Atari, Inc. I recommend them to all truly interested in understanding their Atari computers: (*D): De Re Atari: an arcane, but indispensable reference to the Atari's operations and come of its most impressive aspects, by Chris Crawford et al. Serialized in BYTE magazine, late 1981 to mid 1982. Earlier editions have some errata, so make sure you obtain the latest edition. (*O) Operating System User's Manual and (*H) Hardware Manual. The famous "technical manuals" pair. Indispensable for serious users, albeit heavy going and not generally very professional in their presentation of material. (*8) 850 Interface Module Operator's Manual. The 850 manual gives many examples in BASIC of how to use the RS232 serial interface ports for both printer control and telecommunications. A very good terminal program called Jonesterm, in BASIC with machine language subroutines, is in the public domain and is available on many electronic bulletin board systems, including CompuServe. Modem users will find many useful programs available in CompuServe. (*L) Operating Systems Listing and (*U) Disk Utilities Listings are the commented, copyrighted source code listings for the OS and the DUP.SYS portion of DOS. (*B) Atari BASIC Reference Manual. (*S) Disk Operating System II Reference Manual. (*A) Atari Microsoft BA SIO Instruction Manual. Microsoft BASIC makes excellent use of PEEKs and POKEs to accomplish many tasks. It also has many powerful commands not available in the 8K BASIC.


ANTIC Magazine had an extensive memory map, written by James Capparell, which continued over a number of issues. When it was used as a source, I labelled these references with (AM). It has a few minor errata in it. I found a number of other magazine articles useful, particularly those in COMPUTE! and Creative Computing. I also found Softside, BYTE, ANALOG and Micro magazines to be useful in the preparation of this book. These are all referred to throughout the book by month or issue. We owe a vote of thanks to the folks at Atari who published the technical manuals and the source listings of the operating system and the DOS. We owe another vote of thanks to Bill Wilkinson, of Optimized Systems Software Inc., who created the DUP portion of DOS and decided to publish the source code in his Inside Atari DOS. No other computer manufacturer has, to my knowledge, ever provided users with such in-depth material or the details of its own operating systems. Without it, none of this would have been possible: a lot of the information here was gleaned from those sources. This book is arranged in four sections: a numerical listing of the main Atari memory locations, their labels and their use; a general map diagram to show how the memory is broken down; an appendix of utility material with charts and tables, and an index/cross-reference guide. There is an awful lot of information contained here; tedious as it might appear, I suggest that you read this manual through at least once. Some of the information which is not clear in one area may be elaborated on and made clearer in another area. Wherever another location is referred to in one description, you should turn to the reference and read it after you have read through the first location. You should also refer to the locations used in any sample program. The more familiar you are with the memory, the more you will get out of your Atari. When you read the description in any memory location, make sure you refer to either the shadow or the hardware register mentioned for more information.



On powerup (when you turn on the computer) the Atari OS performs a number of functions, some of which are noted as defaults in the memory locations to follow. Among these functions are: Determine the highest RAM address and clear all RAM to zeroes (except locations zero to 15; $0 to $F). Erase and format the device table. S:, E:, K:, P:, C: handlers, SIO, CIO and interrupt processor are all initialized. Set the screen to GRAPHICS mode zero, 24 lines by 40 columns; set screen margins. Initialize the cartridge(s) if present; test for the B (right), then for the A (left) cartridge. Check the cartridge slots for disk boot instructions and, if they are present, boot disk. Transfer control to the cartridge or booted program. Initialize the RAM interrupt vectors at 512 to 548 ($200 to $224). Store zero in the following hardware registers: 53248 to 53503, 53760 to 54527 ($D000 - $D0FF, $D200 - $D4FF). The START key flag is tested and, if set (the START key is held down), CKEY (74; $4A) requests a cassette boot HATABS (794; $31A) is initialized to point to the ROM-resident device handlers. IOCB zero is OPENed to device E:. Coldstart (powerup) essentially wipes the computer clean and should only be used for such. It's rather drastic.


When the RESET key is pushed, the OS performs some of the same functions as in powerup as well as some unique functions, including: Set the warmstart flag (location 8) to true (255; $FF). Clear the OS portion of RAM from locations 16 to 127 ($10 - $7F) and 512 to 1023 ($200- $3FF). Reset all RAM interrupt vectors. Reformat the device handler table (HATABS); added vectors are lost. Re-initialize the cartridge(s). Return to GRAPHICS mode zero. Transfer control to the cartridge or hooted program. Restore the default values in RAM. Note that a RESET does not wipe RAM, but leaves it intact. Usually your program and variables will be secure when you press RESET. This is considerably less drastic than powerup as above. There are two vectors for initialization so that these processes may be user initiated: 58484 ($E474) for RESET and 58487 ($E477) for powerup. See the OS User's Manual, pages 109 to 112, and De Re Atari for a flowchart of the process.

Return to Table of Contents | Previous Chapter | Next Chapter