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