Managing Memory: VIC And Atari
Charles Brannon, Editorial Assistant
Properly handling and allocating memory can be quite a challenge. This article, for the VIC and Atari, reveals some of the tricks used to successfully manage your computer's memory.
Programmers often wrangle with limitations and possibilities involving their computer's memory. For one thing, there never seems to be enough of it. If you have a 48K machine, you may never come close to filling it with a BASIC program. But when you start allocating RAM for graphics, or use your 48K for VisiCalc or a word processor, you need all you can get, and then some.
Where Did It Go?
A confusing problem is the discrepancy between memory installed and what you get from PRINT FRE(0). The 5K VIC has 3583 bytes free; the 48K Atari has less than 38K available for BASIC (this varies if you use DOS, or if the RS-232 handler is installed). Where did the missing memory go?
You've probably heard of the operating system (OS). It is a series of machine language programs in your computer's ROM that handle such mundane but vital functions as keyboard input, screen display, cassette and disk input/output, and interpreting BASIC code. The OS resides in permanent ROM memory, so it's not included in your RAM memory size. But since it is a program like any other, it needs some RAM for variables and buffers. The OS uses about 1K of low memory (starting from zero) and varying amounts of high memory for screen display.
For example, the Atari GRAPHICS 0 text screen uses 960 bytes, the VIC's combination text/color map screen uses 1012 bytes. So, on the VIC-20, 5K less 2K gives about 3K. 48K - 2K = 46K on the Atari. Using the BASIC cartridge disables another 8K on the Atari (if you have 48K, since a cartridge "maps" into the same memory range as upper RAM), so we get the approximate figure of 38K. Extensions to the OS, such as the DOS (Disk Operating System), gobble up from 4-9K of memory. And adding software-based languages, such as Atari Microsoft BASIC or BASIC A +, can use from 16-26K more! Whatever's left is yours to use for BASIC programming, variables, arrays, strings, and graphics.
Using graphics consumes even more memory. A full character set on the Atari uses 1024 bytes; a full set on the VIC uses 2048 bytes of memory. A full set is required for a VIC-20 hi-res screen. Atari's super hi-resolution screen (and the 16-color GTIA modes) uses almost 8K of RAM. Player/missile graphics uses at least 2K.
And if that weren't enough, the computer can make life even harder for programmers. The VIC and Atari won't use just any block of RAM you've generously set aside — they're too choosy for that. The graphics chips in the Atari frequently require that the memory be on a 1K, 2K, or 4K boundary (explained later). VIC's requirements are similar.
In addition, the memory we reserve must be protected. Unless we say otherwise, BASIC will probably encroach upon our block of memory. We'll have to lower the "top-of-memory" pointer that tells BASIC or the OS how much memory it has. In effect, we'll fool the computer and reserve some "high memory" for our own purposes. Even this can cause problems, however, and we'll try to document them. Sometimes it's safer to use low memory (discussed later).
Let's start with screen memory. This is the area where the text you see on the screen is stored. It can also hold the information required for a high-resolution, multicolor display. Many programmers use POKE, rather than PRINT, to place information directly on the screen. For example, if you enter POKE 7680,1 on a 5K VIC, or POKE 40000,33 on a 48K Atari, an A will appear at the upper left-hand corner of the screen. Using these same POKEs on an expanded VIC or 16K Atari won't work. This is because the screen memory "moves around," depending on the amount of memory installed.
Screen Memory: Atari
The Atari likes to keep its screen at the very top of memory, so that it's side by side with ROM. That way, the screen can be erased with a massive series of zeros. Because of the way the screen clear code is written, it overshoots the end of screen memory. With the screen tucked up next to ROM, it won't matter. ROM is safe from these extra POKEs. But if you have relocated the Atari screen, memory just past the end of screen memory won't be safe. Clearing the screen can erase 64 bytes past the top of screen memory. Scrolling the text window can clear up to 800 bytes.Screen clears too much:
Screen clears too much:
One solution is to reserve more memory than you need, and position your character set or P/M graphics higher up. You might be able to prevent the screen from scrolling or clearing. To reserve memory, just POKE a new value into RAMTOP (location 106) and re-execute a GRAPHICS statement. For example:
POKE 106, PEEK(106)-4:GRAPHICS 0
reserves four pages (1K) of high memory. The GRAPHICS command moves the screen and display list below RAMTOP. Everything above RAMTOP is yours. It will not be altered except as noted above. RAMTOP will be restored only by system reset.
You can find out the new address of screen memory with:
SCREEN will contain the proper address for any memory size. So instead of POKEing directly to locations 40000-40959 on a 48K Atari, use the above code and POKE SCREEN instead. This permits your program to run on any Atari, and the code is even more readable.
Screen Memory: VIC
Text screen memory is at location 7680 on a 5K VIC. This changes when you add memory. To obtain the correct text screen address on any VIC, use:
Color memory (normally at 38400) is determined with:
Now if you want to manually move the screen, things get more complicated. One use of multiple screens is page flipping, where you use two or more views of an object and show them in sequence to provide animation. See Jim Butter-field's "Alternate Screens," in COMPUTE!'s First Book of VIC, We've reprinted his dual screen program at the end of this article. Press the F1 key to switch screens.
More Moving Memory
Other areas of memory also change with various memory sizes. Most Atari programs are stored at the same location in low memory, but if you boot DOS, the LOMEMory pointer is bumped up, and BASIC starts higher up (at about $2000). You can determine the start of BASIC on any Atari with:
The VIC is notorious for moving BASIC. On a PET/CBM, BASIC always starts at $0401 (decimal 1025). 5K VICs start at $1001 (decimal 4097). Add 3K of memory (8K total), and it's just like the PET — decimal 1025. But add 8K to a 5K VIC (13K total), and the start of BASIC moves again, this time to 4609 decimal. You can eliminate all the guesswork with:
This information is useful if you're trying to load a VIC program into a PET.
Character Sets: Atari
A character set must be located on a 512 byte boundary. You can even use pages four to six, subject to interference by floating point routines. (Pages are blocks of 256 bytes, starting at location zero. Thus, page zero would be the addresses from 0-255.) The easiest way is to simply "step back" from the top of RAM, without altering RAMTOP. If you place it behind the display list, but well above BASIC, it will be safe. Large BASIC programs, however, can encroach upon your reserved area. And if you change graphics modes, you must step back past the largest mode used.
The step size has to be a multiple of four for a full 1024-byte character set. You need to step back four pages to get past the screen in modes 0,1,2,3,4 and 5, and then four more to hold your character set, for a total of eight. GRAPHICS 6 would require 12, GRAPHICS 7 would require 20, and you would need to step back a whopping 36 pages to fit your character set beneath a GRAPHICS 8 display.
A statement like:
CHSET = (PEEK(106) - 8) * 256
is most often used. CHSET will hold the starting address where you should POKE your character set, or copy from ROM character set at 57344.
Character Sets: VIC
You have to lower high memory on the VIC to protect a custom character set from BASIC'S string storage. The high memory pointer is at location 56. For a small character set, you need to protect two 256-byte pages at the top of memory. POKE 56,PEEK(56)-2 protects the RAM. You also have to change BASIC'S string pointer. Use these lines:
X = PEEK(56) - 2 : POKE52, X : POKE56, X : POKE51, PEEK(55) : CLR CS * 256 * PEEK (52) + PEEK(5l)
You have to execute CLR to reset BASIC'S pointers after you lower high memory. Find the character set area as CS. (Use POKE 36868,255 to tell VIC where the new character set is.) This technique doesn't work on expanded VICs. Instead, you can store a full character set at locations 4096 to 7615 on an expanded VIC if you execute the following series of POKEs:
POKE 52, 22 : POKE 56, 22 : CLR : POKE 36869, 240
To use these POKEs with an 8K expander, you'll have to relocate the start of BASIC as well:
POKE 44, 32 : POKE 8192, 0 : NEW
Naturally, the latter code cannot be within a main program. You'll also have to relocate the screen:
POKE 36866, 150 : POKE 648, 30 : PRINT CHR$(147);
This will set the screen memory to location 7680, just like an unexpanded VIC.
Player/Missile Graphics On Atari
There are two types of P/M graphics: single and double line resolution. Single line resolution requires 2K of RAM: 256 bytes for each player (4 × 256 = 1K), 256 bytes for the missiles, and 768 unused bytes. Single line resolution, which has the vertical "fineness" of GRAPHICS 8 pixels, must start its memory on a 2K boundary (divisible by eight pages).
Double-line resolution, where two bytes are displayed for every byte in the shorter 128-byte player area, uses only 1K. 128 bytes are used for each player, 128 for the missiles, and 384 bytes are wasted. We've reprinted at the end of this article the memory table that pictorially represents this layout. You can easily store a small character set, machine language, or player shapes in the unused area.
If you lower RAMTOP, you have to subtract eight for single-line resolution, and four for double line. If you must fit large GRAPHICS screens (greater than seven) below RAMTOP, you must be sure to lower RAMTOP in 4K blocks. You can also just step back past the existing screen display (without touching RAMTOP). You must step back a multiple of four pages for double line resolution, and a multiple of eight pages for single-line.
To be safe, step back eight pages (or 16 for single-line) from modes 0-6. Go back 16 pages for double / 24 pages for single resolution in GRAPHICS 7, and 36/40 pages for GRAPHICS 8. The same problems apply as with character sets: lowering RAMTOP can cause up to 800 bytes of your protected area to be erased.
An Alternative: Use LOMEM
Let's take a look at another technique for reserving memory on an Atari. Various utilities and extensions (such as large machine language programs) frequently load in at low memory. For example, DOS loads in at $0700. To protect itself, DOS bumps up the low memory pointer to the end of DOS, where BASIC programs will then be stored. You can do the same trick to protect your own area of memory. Pick any point after about $1F00 to store your machine language, character sets, or P/M graphics. Address $2000 is perfect – it's on a 1K, 2K, and 4K boundary.
Before using the low RAM, it must be protected by changing LOMEM, $02E7. After you change LOMEM, you have to re-initialize the machine, so any program in memory will be lost. The best solution is to use a two-part program. Let the first part protect low memory, and then run the second part. For example, let's say you want to protect 2K of memory from $2000. The last byte in the 2K range will be $27FF. To place $2800, the new low memory value into LOMEM, use:
POKE 743, 0 : POKE 744, 40 : POKE 8, 0 : A = USR(40960)
POKEing 0 into WARMST ($08) tells the OS to reinitialize, and jumping to address 40960 ($A000) re-executes the cartridge (BASIC). The memory below $2800 is safe from any interference.
Someday, computers will have unlimited RAM. We already see low-cost 64K and high-end 896K microcomputers. Even languages will likely grow larger, becoming faster and easier to use. There are already languages available for the VIC and Atari that ease the hassle of memory allocation, such as BASIC A + for Atari, with its built-in P/M graphics commands, and the Super Expander for the VIC, which adds easy high-resolution commands such as CIRCLE and PAINT (adding 3K of RAM as a bonus!). But if you're interested in doing it yourself (and you have to in machine language), I hope these suggestions help.
Page Flipping for VIC
100 REMDUAL SCREEN JIM BUTTERFIELD 110 POKE56,28 : CLR 120 DIML%(23) 130 GOSUB400 : PRINTCHR$(147) : GOSUB400 140 Z$ = CHR$(133) 200 GETX$ : IFX$ = Z$ THEN GOSUB 400 210 PRINTX$; : GOTO 200 400 REM SWITCH 410 S = PEEK(648) 420 IFS = 28 THENS = 30 : T = 150 : GOTO 500 430 IFS = 30 THENS = 28 : T = 22 : GOTO 500 440 STOP : REMARK: ERROR 500 POKE648,S : POKE36866,T 510 FOR J = 0 TO 23 520 V = PEEK(J + 217) : POKEJ + 217,L%(J): 530 L%(J) = V 540 NEXTJ 550 PRINT : RETURN
Memory Allocation for P/M GraphicsPMBASE must be on 1K boundary for double-line resolution, 2K boundary for single-line resolution.