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

Commodore ML Saver

Buck Childress

This short, useful program saves any machine language program directly from memory into a disk or tape file. It works on any Commodore 64 or 128 (in 64 mode).

There are many useful machine language (ML) utilities available in public domain collections, on computer bulletin boards, and in publications like COMPUTE!. The most common way to place an ML program in memory is with a BASIC loader—a BASIC routine which READs the necessary values from DATA statements and POKEs them into memory. That method is fine for short ML programs, but can involve quite a delay when the ML program is long. It takes time, first of all, to load the BASIC loader. Then there's another wait while it POKEs everything into memory.

A much faster technique is to load the ML from disk or tape directly into memory. The only problem is making the tape or disk file. Machine language monitors such as Supermon can save any ML program directly from memory. But if you don't have a monitor, or don't know how to use one, that's not a viable option, either.

A Better Way

"ML Saver" is a short BASIC utility that can save any machine language program on disk or tape directly from where it resides in memory. After you type in and save ML Saver, load and run the program that creates the ML code you want to save. Make a note of the starting and ending addresses. If the ML is POKEd into memory with a FOR-NEXT loop, these addresses usually appear in the loop itself. For instance, if the loop is FOR J = 49152 to 51000:READ Q:POKE J,Q:NEXT then you know the starting address is 49152 and the ending address is 51000. Now check the SYS address used to activate the program. This is usually the same as the starting address (for example, SYS 49152), but some programs are activated by jumping to an address somewhere in the middle of the code.

Once you have this information, you're ready to load and run ML Saver. The program asks you for the name you want to save the ML program under: Enter any name up to eight characters in length (extra characters are ignored). After you've supplied the name, enter D to save to disk or T for tape. Then enter the starting and ending addresses you wrote down earlier. ML Saver proceeds to save the ML code.

After the file has been created, you can load it with LOAD"filename",8,1 for disk or LOAD"filename",1,1 for tape (of course, you should replace filename with the filename you used when saving the program). Then SYS to the correct address to activate the program. To do this under program control, put the following statements at the beginning of your program:

10 IF J = l THEN 30
20 J = 1:LOAD"filename",8,l
30 REM PROGRAM CONTINUES HERE

When you run a program containing these lines, the variable J equals 0, so the computer falls through the IF test in line 10 and performs line 20. This line sets J to a nonzero value and loads the ML. After the load is complete, the computer automatically reruns the program beginning at line 10, but does not erase previously established variables. This time around, J equals 1, so the computer skips line 20 and proceeds with line 10.

Commodore ML Saver

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

FE 10 INPUT"{CLR}{DOWN}PROGRAM NAME";PN$ : IFLEN(PN$)>8THENPN$ = LEFT$ (PN$, 8)
JC 40 FORJ = 1TOLEN(PN$) : POKE2039 + J, ASC(MID$(PN$, J, l)) :NEXTJ
AM 50 PRINT"{DOWN}{RVS}D{OFF}I SK OR (RVS}T{OFF}APE? ";
GH 60 GETA$:IFA$=""THEN60
HC 70 IFA$="D"THENDEVICE=8:GOT 0100
EC 80 IFA$="T"THENDEVICE=1:GOT 0100
FH 90 GOTO60
EC 100 PRINTA$:POKE780,15:POKE 781,DEVICE:POKE782, 255:SYS65466
DB 110 POKE780,LEN(PN$):POKE78 1, 248:POKE782,7:SYS65469
FK 120 INPUT"[DOWN]BEGINNING A DDRESS";BA
XA 130 HI=INT(BA/256):LO=BA-(H I*256)
MS 140 POKE251,LO:POKE252,HI
PP 150 INPUT"{DOWN}ENDING ADDRESS";EA
SJ 160 HI=INT(EA/256):LO=EA-(H I*256)+l
PF 170 POKE780,251:POKE7, 81,LO:POKE782,HI
RF 180 PRINT" {DOWN JSAVING ML VERSION OF ";PN$
KX 190 SYS65496: END