Classic Computer Magazine Archive COMPUTE! ISSUE 70 / MARCH 1986 / PAGE 93

MultiMemory

For Commodore 64 And Apple

Patrick Parrish, Programming Supervisor

This short utility partitions free memory so several BASIC programs can be loaded into your computer at once. Among other things, it's a great aid during program development—you can keep a couple of BASIC programming utilities at hand as you work, or test alternate versions of new routines before adding them to your main program. The Apple version works on all Apple II series computers with either DOS 3.3 or ProDOS.

The idea of partitioning memory into several modules which can contain separate programs is not new—Charles Brannon relied on BASIC pointers to split the PET into four 8K blocks with "Quadra-Pet" (COMPUTE!, June 1981), and Feeman Ng later partitioned the 64 into three 12K blocks with "Triple 64" (COMPUTEI's GAZETTE, April 1985). Much like these earlier programs, "MultiMemory" divides free memory in your Commodore 64 or Apple into independent workspaces. Three partitions are set up in the 64, and four in the Apple. As before, you can load different BASIC programs into the computer at once. These could be utilities, applications, or games. And, once again, you can save and load programs from any of these areas without affecting the others.

But MultiMemory goes one step further. Not only are the BASIC programs in each module protected from one another, but the variables generated by each are protected as well. Any program can change a variable's value without affecting identically named variables that may exist in other partitions. That means there's even less chance of conflict between the programs, allowing you more flexibility when using MultiMemory.

Entering MultiMemory

The BASIC languages in the 64 and Apple were both written by Microsoft, Inc. and thus share numerous similarities. Nowhere is this more clearly seen than in a section of memory called zero page (locations 0–255), where many BASIC pointers are stored. If you compare detailed memory maps for these computers, you'll find that many zero-page pointers, though located at slightly different addresses, are the same on these two machines. MultiMemory takes advantage of this by using identical zero-page pointers in the 64 (locations 43–56) and in the Apple (locations 103–116) to split up free memory. As a result, the 64 and Apple versions of MultiMemory are alike in many ways.

Whether you have a 64 or an Apple II series computer, MultiMemory is entered in the same fashion. Both versions contain short machine language routines entered by a BASIC loader. Carefully type Program 1 for the 64 or Program 2 for the Apple and save a copy to disk or tape before running it for the first time.

When you run MultiMemory, line 100 sets the top of BASIC memory for the first partition. This is memory location 16384 (64*256) on the 64 and location 8192 on the Apple (we'll see why later).

Line 110 POKEs the machine language routine in lines 150–330 into a safe place in memory. On the 64, it's placed at the top of BASIC RAM (40769) just below BASIC ROM (40960). On the Apple, it resides at location 38251 just below DOS (38400). These areas are relatively safe from memory conflicts.

Line 120 checks to see if the machine language data has been correctly typed. Lines 130 and 140 place zeros in three sequential locations at the start of each memory module. The first zero is required to indicate the start of BASIC. The second and third zeros NEW each memory module. Finally, the NEW command in line 140 clears the BASIC loader from memory and leaves us in module 1.

Three Or Four Computers

To access any module on the 64, type SYS 40769 and press RETURN. The cursor will disappear. Now, pick a work area by typing 1, 2, or 3. For a test, let's choose partition number 2. A tone sounds as the partition number is displayed on the screen. That's all it takes to switch modules.

If you're using an Apple, type CALL 38251 and press RETURN. Choose among work areas 1 to 4. Again, for a test, specify number 2. A tone sounds, the partition number is displayed, and we're ready to program.

When you type LIST, you'll see that module 2 is empty. Now type PRINT FRE(0) to determine how much memory is available in this module. The 64 should show about 16K free, and the Apple about 8K. On either machine, there is plenty of room for a short BASIC program and its variables. To see that both a program and its variables remain intact within a particular module, let's enter and run a program in module 2 and then do the same in module 1.

While in module 2, type and run this program:

10 REM EXAMPLE 2
20 A$="MODULE #2"
30 FOR I=1 TO 20:NEXT I

After running this program, type PRINT A$,I and press RETURN. You should see this:

MODULE #2 21

Save this program to disk or tape with the filename "P2."

Now let's go to another module. Before we do this, list the program in module 2 so that it's at the bottom of the screen. Now type SYS 40769 on the 64 or CALL 38251 on the Apple and choose module 1.

Independent Variables

After entering module 1, type LIST to prove that our first program has been left behind in module 2. Again, if you wish, type PRINT FRE(0) to determine the amount memory available in this module. The 64 should show about 14K and the Apple approximately 6K.

Program "P2" should still be on the screen. Even though it was listed in module 1, it remains visible if you switch partitions without clearing the screen. This makes it possible to copy program lines from one module to another with the screen editor. Simply use the screen editing keys to cursor up to line 10. Change the 2 in this line to a 1 and hit RETURN to enter this line in memory (Apple users must cursor to the end of the line before pressing RETURN, of course). Line 10 is now copied into memory in module 1 without disturbing line 10 in module 2.

If the BASIC screen prompts do not obscure the other program lines, you can copy them to module 1 in the same manner. At any rate, lines 20 and 30 should read:

20 A$="MODULE #1"
30 FOR I=1 TO 10:NEXT I

As you did before, run the program and then type PRINT A$,I. The result is:

MODULE #1		11

Save this program on disk or tape as "P1."

Now, go back to module 2 with SYS 40769 or CALL 38251 and type LIST. You should see program "P2" on the screen unchanged. Print the values for A$ and I. You'll see they still have the values they had when we left module 2.

Applications

As you can imagine, this process can be very valuable if you're writing and debugging your own programs. Suppose you're writing a program in module 1 and you need a subroutine from a BASIC program you have on disk. Maybe you aren't sure which disk the program is on. On the 64, normally you'd have to save the program currently in memory before looking at the disk directory, because the directory overwrites the BASIC workspace. (On the Apple, this wouldn't be a problem, since the disk catalog is not loaded into the BASIC workspace.)

With MultiMemory, you can nimbly jump to another module, load the directory there to find the program you need, and then load it into that module or the third module, leaving the directory intact. And, once you've found the subroutine you need from your earlier program, you can list it on the screen, shift back to the first partition, and copy the lines by RETURNing over them.

Now suppose that some bug in your program keeps the subroutine from working as you expected. Since variables retain their values within each program module, you can test each routine separately, compare the resulting variables, and make changes to your working version where needed.

With all this jumping from module to module, you might loose track of which partition you're in. To find out, you can type PRINT PEEK(40914) on the 64 or PRINT PEEK(38339) on the Apple.

In addition to aiding program development, MultiMemory can be used to hold a few BASIC programs that can be run individually. For instance, you might have a series of BASIC programs that, in sequence, manipulate data stored on disk. The first program could read in the data, manipulate it, and then write the results back to disk. In turn, a second or third program (or on the Apple, even a fourth) stored in the other workspaces could do the same. Or you could designate one BASIC workspace for data storage, much like a RAM disk.

Before undertaking any sophisticated programming applications with MultiMemory, however, you should consider how it works and keep in mind a few restrictions on its use.

Memory Ceilings

As mentioned earlier, MultiMemory uses a series of BASIC pointers in zero page to set up each workspace. The values required by these pointers for each module are stored in a lookup table at the end of the program. Whenever you SYS or CALL MultiMemory, it stores the current zero-page values in positions within this table which correspond to the current module. The program then waits for you to specify the next module.

When you pick a module, MultiMemory reads the zero-page pointer values for the module and places them in their proper zero page locations. The pointers transferred are the starting addresses for the location of the BASIC program, the array and nonarray variables, the string variables, and the top of BASIC memory.

The barriers separating the partitions were selected to keep MultiMemory compatible with most programs. On the 64, the first module runs from memory locations 2048–16383; the second, from 16384–32767; and the third, from 32768–40768. Partitions are placed on 16K boundaries because the 64's VIC-II chip can address only one 16K block at a time. The VIC-II chip is responsible for handling the 64's video display—such things as sprite shapes, screen memory, and character data.

On the Apple, the first module runs from memory locations 2048–8191; the second, from 8192–16383; the third, from 16384–27317; and the fourth, from 27318–38250.

Note that the location of module 2 coincides with the Apple's first high-resolution graphics page. That means any programs which use the hires graphics page should be loaded into another module. And, of course, any programs loaded into module 2 will likely be erased if a program in another module uses the hires page.

Program 1: MultiMemory For Commodore 64

For instructions on entering this listing, please refer to "The New Automatic Proofreader for Commodore" in this issue of COMPUTE!.

XA 100 POKE56, 64 : CLR
CR 110 FORI = 40769TO40959 : READA : POKEI, A : X = X + A : NEXT
DH 120 IFX<>22456THENPRINT"ERROR IN DATA STATEMENTS." : STOP
KA 130 POKE16384, 0 : POKE16385, 0 : POKE16386, 0
RA 140 POKE32768, 0 : POKE32769, 0 : POKE32770, 0 : NEW
JD 150 DATA 174, 210, 159, 189, 210, 159, 170, 160, 0, 185
QJ 160 DATA 43, 0, 157, 214, 159, 232, 200, 192, 14, 208
SG 170 DATA 244, 32, 228, 255, 41, 15, 240, 249, 201, 4
BA 180 DATA 176, 245, 72, 72, 169, 35, 32, 210, 255, 104
QR 190 DATA 24, 105, 48, 32, 210, 255, 169, 13, 32, 210
BG 200 DATA 255, 32, 143, 159, 104, 170, 142, 210, 159, 189
CF 210 DATA 210, 159, 170, 160, 0, 189, 214, 159, 153, 43
CR 220 DATA 0, 232, 200, 192, 14, 208, 244, 96, 169, 0
HS 230 DATA 168, 153, 0, 212, 200,192, 25, 144, 248, 169
PX 240 DATA 15, 141, 24, 212, 169,10, 141, 5, 212, 169
PK 250 DATA 84, 141, 15, 212, 169, 39, 141, 1, 212, 169
MQ 260 DATA 20, 141, 4, 212, 169, 21, 141, 4, 212, 162
RA 270 DATA 0, 134, 251, 160, 0, 200, 208, 253, 232, 208
XD 280 DATA 250, 230, 251, 165, 251, 201, 4, 208, 242, 169
DD 290 DATA 0, 141, 4, 212, 96, 1, 0, 14, 28, 1
HJ 300 DATA 8, 3, 8, 3, 8, 3, 8, 0, 64, 0
JK 310 DATA 64, 0, 64, 1, 64, 3, 64, 3, 64, 3
GE 320 DATA 64, 0, 128, 0, 128, 0, 128, 1, 128, 3
DR 330 DATA 128, 3, 128, 3, 128, 65, 159, 65, 159, 65, 159

Program 2: MultiMemory For Apple

For instructions on entering this listing, please refer to "COMPUTE!'s Guide to Typing In Programs" in this issue of COMPUTE!.

B6 100 HIMEM : 8192
B3 110 FOR I = 38251 TO 38399 : READ A : POKE I, A:X = X + A : NEXT
6B 120 IF X < > 16739 THEN PRINT "ERROR IN DATA STATEMENTS." : STOP
5F 130 POKE 8192, 0 : POKE 8193, 0 : POKE 8194, 0
B6 140 POKE 16384, 0 : POKE 16385,0 : POKE 16386, 0 :
       POKE 27318, 0 : POKE 27319, 0 : POKE27320, 0 : NEW
B3 150 DATA 174, 195, 149, 189, 195, 149, 170, 160
C6 160 DATA 0, 185, 103, 0, 157, 200, 149, 232
2F 170 DATA 200, 192, 14, 208, 244, 173, 0, 192
52 180 DATA 201, 128, 144, 249, 141, 16, 192, 170
A0 190 DATA 41, 15, 240, 241, 201, 5, 176, 237
14 200 DATA 72, 32, 58, 255, 169, 163, 32, 237
C0 210 DATA 253, 138, 32, 237, 253, 32, 142, 253
BB 220 DATA 104, 170, 142, 195, 149, 189, 195, 149
31 230 DATA 170, 160, 0, 189, 200, 149, 153, 103
49 240 DATA 0, 232, 200, 192, 14, 208, 244, 165
C7 250 DATA 105, 133, 175, 165, 106,133, 176, 96
70 260 DATA 1, 0, 14, 28, 42, 1, 8, 3
2F 270 DATA 8, 3, 8, 3, 8, 0, 32, 0
47 280 DATA 32, 0, 32, 1, 32, 3, 32, 3
6E 290 DATA 32, 3, 32, 0, 64, 0, 64, 0
0l 300 DATA 64, 1, 64, 3, 64, 3, 64, 3
BE 310 DATA 64, 182, 106, 182, 106, 182, 106, 183
50 320 DATA 106, 185, 106, 185, 106,185, 106, 107
09 330 DATA 149, 107, 149, 107, 149