Classic Computer Magazine Archive COMPUTE! ISSUE 67 / DECEMBER 1985 / PAGE 10

Making ML Loaders

Please give me a Commodore program that turns a machine language program into BASIC lines like the listings for your "MLX" machine language entry utility. I want something that looks like this:

49152: 169, 091, 133, 170, 169, 200, 092

Darwin Clay

We frequently get letters from readers who want to generate MLX-style listings for their own machine language (ML) programs. However, while it's occasionally useful to convert an ML program into BASIC, there is no practical reason to list it in MLX format. An MLX listing is not a program—the only thing you can do with it is create a machine language program by running MLX and typing in the listing. Since you already have the ML program, that would be a fruitless exercise. What you seem to need is a BASIC loader: a BASIC routine that creates a machine language program by reading values from DATA statements and POKEing them into the correct memory locations. BASIC loaders can be added as subroutines to other BASIC programs.

Here are two short programs that construct loaders, using the dynamic keyboard technique to write the necessary DATA statements. The first program creates a loader from an ML program that's already in memory. Enter the starting and ending addresses of the ML program, followed by the beginning line number for the DATA statements (don't use lines 1–8). When the blinking cursor reappears, your BASIC loader is in memory, ready to be saved. The last line of the loader READs the DATA statements and POKEs the correct values into memory. Be sure to save this program before running it: Lines 1–8 erase themselves after the loader is complete.

Since this method uses string operations, it disrupts the contents of the highest memory addresses used by BASIC (just under location 40960 on the 64). That may cause problems if you're trying to make a loader for an ML program that resides in the same area. The solution is to lower the top of BASIC pointer: To protect a 2K area at the top of BASIC, type the statement POKE 56, PEEK(56)–8: CLR and press RETURN.

1 INPUT "START ADDRESS" ; AD : INPUT
"END ADDRESS" ;E : INPUT "FIRST
LINE NUMBER" ;L : SA = AD 	: rem 98
2 PRINT "{CLR}"L" DATA "; 	: rem 123
3 PRINTMID$(STR $ (PEEK (AD)), 2);
: NUM = NUM + 1 : IFAD < ETHE N7	:rem 216
4 IF NUM > 16 THEN PRINT ","; : GOTO 3	:rem 99
5 PRINT"{HOME} {2 DOWN} L = "L" {LEFT} + 1 : AD = "AD" {LEFT} : E = "E"
{LEFT} : SA = "SA" {LEFT} : GOTO 2"	: rem 182
6 POKE 198, 5 : POKE 631, 19 : POKE 632, 13 : POKE 633, 13 : END	: rem 59
7 PRINT "{HOME} {2 DOWN} "L + 1" FOR J = "SA"TO" AD-1" {LEFT} : READ Q : POKE J, Q : NEXT" : FOR J = 1TO8 : PRINT
J : NEXT	:rem 100
8 POKE 631, 19 : POKE 198, 12 : FOR J = 0 TO 10 : POKE 632 + J, 13 : NEXT : END	:rem 160

In some cases you may not know the ending address of the ML program, or it may be inconvenient to have the ML in memory while you're making a loader. With only slight modifications, this program can make a loader for an ML program stored on disk. First, in line 7 replace the statement FOR J = 1TO8 with FOR J = 0TO8. Then replace lines 1, 3, 5, and 8 with the lines shown here. This routine works like the first example, but gets the ML data from disk rather than memory. Again, remember to save the program before running it for the first time.

0 INPUT "FILENAME"; F$ : INPUT "FIRST LINE NUMBER";L : OPEN 2, 8,
2, "0 : " + F $ + ",P,R"	:rem 48
1 GET # 2, LO $ : GET # 2, HI $ : SA = ASC (L O$ + CHR$ (0)) + ASC (HIS + CHR$ (0)) * 256 : AD = SA	:rem 76
3 GET # 2, X $ : PRINT MID $ (STR $ (ASC( X $ + CHR $ (0))), 2); : NUM = NUM + 1 : A D = AD + 1 : IFST < > 0 THEN 7	:rem 142
5 PRINT "{HOME} {2 DOWN}L = "L" {LEFT} + 1 : AD = "AD" {LEFT} : SA = "S A" {LEFT}: POKE 152, 1 : GOTO 2"
:rem 50
8 POKE 631, 19 : POKE 198, 12 : FOR J = 0 TO 10 : POKE 632 + J, 13 : NEXT : OPEN l5,  8, 15 : CLOSE 15 : END  :rem 126