Supermon64
Jim Butterfield, Associate Editor
Supermon64 is your gateway to machine language programming on the Commodore 64. Supermon, inseveral versions, has been popular over the years as a major programming tool for Commodore users. With this adaptation for the 64, a good book on 6502 programming, and patience, you can learn to write programs or subroutines which are capable of running at extraordinary speeds. You can learn machine language programming.
Supermon64 itself is in machine language, but you can type it in without knowing what it means. Using the Tiny Peeker/Poker (Program 1), or via the built-in monitor of a PET, type it in and SAVE it. The fastest way to check for errors is to type in Program 3 on a regular PET (or use the portioning techniques described in the article to make room for the checksum program the same way you made room for the Tiny Peeker). Then load Supermon64 into the PET. It will come in above your BASIC. Then RUN the checksum and it will report the location of any errors.
The easiest way to type in Supermon64 is by using a monitor. Unfortunately, you won't have a monitor until Supermon64 is typed in. This leads to a chicken-and-egg situation. It's no good my suggesting that you should borrow a friend's Supermon64 to type this in; if he's got it, you can just make a copy and save a lot of work. There's gotta be another way.
The Commodore 64 has lots of memory. We can waste some of it to create an easy method which will allow us to enter this program. Maybe we'll even learn something along the way.
You may have noticed that when you power up the 64, it tells you that you have 38911 bytes free. For the moment, I'm not going to tell you what happened to the rest of the 64K (it's there, but BASIC won't use it). The baffling thing is that if you ask the machine to PRINT FRE(0), it will tell you that it has -26627 bytes free. Don't be confused: this is a bug and you can get the right number by adding 65536. Whip out your trusty calculator, do the addition, and do you get 38911? Of course not, but it's close enough (another story for another time).
Now: we're going to trim some memory away from the computer, so as to give ourselves space to stage Supermon64. First, we must prepare the new space so that it will be able to hold a BASIC program. Type POKE 8192,0 and the space is ready. Next, we are going to move BASIC to this new area. Type POKE 44,32 followed by NEW and the deed is done. At this point we seem to have a perfectly normal Commodore 64 machine. Everything will work as before. But, if you ask PRINT FRE(0) you'll find that your free space has dropped to 32765 bytes. We have sectioned off the space where we will plant Supermon64. [You can use this same technique, then type in Program 3 and run the checksum on your program — Ed.]
Now we are ready for a simple input program. Enter the following:
Program 1. Tiny Peeker/Poker.
100 PRINT "TINY PEEKER/POKER" 110 X$ = "*" : INPUT X$ : IF X$ = "*" THEN END 120 GOSUB 500 130 IF E GOTO 280 140 A = V 150 IF J>LEN(X$) GOTO 300 160 FOR I = 0 TO 7 170 P = J : GOSUB 550 180 C(I) = V 190 IF E GOTO 280 200 NEXT I 210 T = 0 220 FOR I = 0 TO 7 230 POKE A + I, C(I) 240 T = T + C(I) 250 NEXT I 260 PRINT "CHECKSUM = ";T 270 GOTO 110 280 PRINT MID$(X$, 1, J);"??" : GOTO 110 300 T = 0 310 FOR I = 0 TO 7 320 V = PEEK(A + I) 330 T = T + V 340 V = V/16 350 PRINT " "; 360 FOR J = 1 TO 2 370 V% = V 380 V = (V - V%)*16 390 IF V%>9 THEN V% = V% + 7 400 PRINT CHR$(V% + 48); 410 NEXT J 420 NEXT I 430 PRINT "/";T 440 GOTO 110 500 P = 1 510 L=4 520 GOTO 600 550 P=J 560 L=2 600 E=0 610 V=0 620 FOR J=P TO LEN(X$) 630 X=ASC(MID$(X$, J)) 640 IF X=32 THEN NEXT J 650 IF J>LEN(X$) GOTO 790 660 P=J 670 FOR J=P TO LEN(X$) 680 X=ASC(MID$(X$, J)) 690 IF X<>32 THEN NEXT J 700 IF J-P<>L GOTO 790 710 FOR K=P TO J-1 720 X=ASC(MID$(X$, K)) 730 IF X < 58 THEN X=X-48 740 IF X>64 THEN X=X-55 750 IF X<0 OR X>15 GOTO 790 760 V=V*16+X 770 NEXT K 780 RETURN 790 E=-1 800 RETURN
This program is a very tiny monitor. It will allow you to enter information into memory, eight bytes at a time. To do this: wait for the question mark, and then type in monitor-format the address and contents:
? 0800 00 1A 08 64 00 99 22 93
The program will return a checksum value to you, which you can use to insure that you have entered the information correctly. To view memory, type in only the address: the contents will be displayed.
Completing The Job
When you have finished entering all that data, you can make Supermon64 happen quite easily. Three last POKE commmands and a CLR:
POKE 44,8 POKE 45,232 POKE 46,17 CLR
You have Supermon64. Save it with a conventional BASIC SAVE before you do anything else.
Now you may RUN it — and learn how to use it.
Supermon64 Summary
Commodore Monitor Instructions:
G GO RUN L LOAD FROM TAPE OR DISK M MEMORY DISPLAY R REGISTER DISPLAY S SAVE TO TAPE OR DISK X EXIT TO BASIC
Supermon64 Additional Instructions:
A SIMPLE ASSEMBLER D DISASSEMBLER F FILL MEMORY H HUNT MEMORY P PRINTING DISASSEMBLER T TRANSFER MEMORY
• Simple assembler
.A 2000 LDA #$12 .A 2002 STA $8000,X .A 2005 (RETURN)
In the above example the user started assembly at 2000 hex. The first instruction was load a register with immediate 12 hex. In the second line the user did not need to type the A and address. The simple assembler prompts with the next address. To exit the assembler type a return after the address prompt. Syntax is the same as the disassembler output.
• Disassembler
.D 2000 (SCREEN CLEARS) 2000 A9 12 LDA #$12 2002 9D 00 80 STA $8000,X 2005 AA TAX 2006 AA TAX
(Full page of instructions)
Disassembles 22 instructions starting at 2000 hex. The three bytes following the address may be modified. Use the CRSR keys to move to and modify the bytes. Hit return and the bytes in memory will be changed. Supermon64 will then disassemble that page again.
• Printing disassembler
.P 2000,2040 2000 A9 12 LDA #$12 TAX 2002 9D 00 80 STA $8000,X 2005 AA TAX .... 203F A2 00 LDX #$00
To engage printer, set up beforehand:
OPEN 4,4:CMD4
• Fill memory
.F 1000 1100 FF
Fills the memory from 1000 hex to 1100 hex with the byte FF hex.
• Go run
.G
Go to the address in the PC register display and begin RUN code. All the registers will be replaced with the displayed values.
.G 1000
Go to address 1000 hex and begin running code.
• Hunt memory
.H C000 D000 ‘READ
Hunt through memory from C000 hex to D000 hex for the ASCII string read and print the address where it is found. A maximum of 32 characters may be used.
.H C000 D000 20 D2 FF
Hunt memory from C000 hex to D000 hex for the sequence of bytes 20 D2 FF and print the address. A maximum of 32 bytes may be used.
• Load
.L
Load any program from cassette #1.
.L "RAM TEST"
Load from cassette #1 the program named RAM TEST.
.L "RAM TEST", 08
Load from disk (device 8) the program named RAM TEST. This command leaves BASIC pointers unchanged.
• Memory display
.M 0000 0080 . 0000 00 01 02 03 04 05 06 07 . 0008 08 09 0A 0B 0C 0D 0E 0F
Display memory from 0000 hex to 0080 hex. The bytes following the .: can be altered by typing over them, then typing a return.
• Register display
.R PC IRQ SR AC XR YR SP 0000 E62E 01 02 03 04 05
Displays the register values saved when Supermon64 was entered. The values may be changed with the edit followed by a return.
• Save
.S "PROGRAM NAME", 01, 0800, 0C80
SAVE to cassette #1 memory from 0800 hex up to but not including 0C80 hex and name it PROGRAM NAME.
.S "0 : PROGRAM NAME", 08, 1200, 1F50
SAVE to disk drive #0 memory from 1200 hex up to but not including 1F50 hex and name it PROGRAM NAME.
• Transfer memory
.T 1000 1100 5000
Transfer memory in the range 1000 hex to 1100 hex and start storing it at address 5000 hex.
• Exit to BASIC
.X
Return to BASIC ready mode. The stack value SAVEd when entered will be restored. Care should be taken that this value is the same as when the monitor was entered. A CLR in BASIC will fix any stack problems.
Program 3. Supermon64 Checksum.
100 REM SUPERMON64 CHECKSUM PROGRAM 110 DATA 10170, 13676, 15404, 14997, 15136, 16221, 16696, 12816, 16228, 14554 120 DATA14677, 15039, 14551, 15104, 15522, 16414, 15914, 8958, 11945 : S = 2048 130 FOR B = 1 TO 19 : READ X : FOR I = STOS + 128 : N = PEEK(I) : Y = Y + N 140 NEXT I : IF Y <> XTHENPRINT "ERROR IN BLOCK #" B : GOTO 160 150 PRINT "BLOCK #"B" IS CORRECT" 160 S = I : Y = 0 : NEXT B : REM CHECK LAST SHORT BLOCK BY HAND