VIC machine language programmers: here's one of the most valuable tools there is for working in machine language. Thirty-four commands are at your disposal including single-step, hex conversion, search, EPROM routines, and a relocator. If you aren't yet working with machine language, the instructions for entering and using this program are easy to follow and you might want to add it to your library for later use. Micromon might even lead you into the intriguing and often quite useful world of the machine's own language. As presented, this program takes up 4K of memory from $4000 (16384 decimal) to $4FFF (20479), but there are instructions for locating it elsewhere in RAM memory.
I could not resist F. Arthur Cochrane's suggestion in the January 1982 COMPUTE! about modifying the PET Micromon for VIC use and publishing the results. The VIC Micromon presented here is the product of several months of use and revision of an initial modified version completed in April 1982.
The initial modifications involved redefining Micromon's workspace from the PET tape buffer at $27A to the VIC tape buffer at $33C. The VIC tape buffer was redefined to $375, and the Micromon Load and Save commands rewritten to read and write absolute memory images to cassette tape. A Verify command was added as well.
Other modifications included redefining locations used by Micromon in the BASIC and kernal storage areas from the PET to the VIC equivalents. The address of the decimal output routine used by the conversion commands was changed to the VIC routine at $DDCD. Because the VIC IRQ vector is at $314, rather than at a zero page location such as $90 for the PET, the single instruction interrupt time had to be increased to compensate for the absolute store instructions used. Two of these instructions are used in setting the IRQ vector when rolling out of Micromon for the Walk and Quick trace commands. Also, hardware differences required changes to the interrupt timer addresses. Originally at $E848 and $E849 for the PET, these were redefined as $9128 and $9129 for the VIC.
Micromon uses an IRQ service routine to provide forward and reverse scrolling for the Hex conversion, Memory dump, and Disassembly commands. Because VIC's screen readily relocates and has a unique format of 23 lines by 22 columns, most of the scrolling code in the IRQ service routine had to be rewritten.
Solving Early Problems
I had previously built a 16K memory board for operation in the $2000 to $5FFF address space of the VIC. So, along with the modifications already mentioned, the programming for the initial VIC Micromon included a relocation from $1000 to $4000. The code was entered as two separate 2K blocks on my VIC using a BASIC Hex Editor and subsequently programmed onto two 2716 EPROMs with a programmer I had built to operate off the VIC USER I/O port. An extension of the BASIC Hex Editor provided the EPROM programming control.
Once installed on my VIC at $4000, VIC Micromon was accessed by a SYS16384 from BASIC. Each Micromon command was exercised for proper operation. I had difficulty returning to BASIC with the E and X commands, as well as stack interference in executing test programs with the G, W, and Q commands. I solved these problems by changing the stack area used by VIC Micromon to the bottom half of the $100 page. This was done by setting the stack pointer to $7F rather than $FF in the command input section of VIC Micromon.
The New locater command would work only once in the word mode when the command was invoked several times consecutively. A flag at $28C for PET Micromon and $34E for VIC Micromon differentiates between the instruction mode and the word mode in the New locater command. The problem is due to the flag being used also as an offset index to check absolute addresses. The flag was being incremented without being cleared on each consecutive New locater command in word mode. This was fixed by inserting code in the command input section of VIC Micromon to always clear $34E prior to execution of any command.
The Assembler command would not properly assemble branch instructions which had branch offsets of $7E and $7F. This problem resulted from a simple plus/minus range check prior to adjusting the offset value by -2. The fix for VIC Micromon is given here as an inline patch for PET Micromon users. The PET Micromon code from $1525 to $1538 was rewritten to use a value of $82 for a range check. The resulting code, which is one byte longer, was accommodated by replacing the branch and jump instructions at $150E to $1512 with two NOPs and a branch. The code at $1513 to $1524 was moved down one location to be at $1512 to $1523, and the branch instructions originally at $1519 and $1520 had their offsets adjusted up by one.
F. Arthur Cochrane presented an extra set of commands implemented on about an additional 1K module called Micromon Plus. Of the commands in Micromon Plus, I felt that the Print switcher and PROM programmer commands would be desirable in VIC Micromon. However, instead of creating an extra module above the existing 4K of the initial VIC Micromon, I decided that, with some code crunching, the Print switcher and PROM programmer commands could be contained within an enhanced 4K VIC Micromon. Since there are many printers available with a RS-232 interface, the enhanced VIC Micromon Print switcher command would support the RS-232 interface on the VIC User I/O port rather than the VIC serial port interface. Also, since I already had an EPROM programmer working off the User I/O port, the enhanced VIC Micromon PROM programmer command would support my programmer rather than one on the IEEE bus.
Code crunching consisted of code optimization and code removal while keeping function and structure. The table of internal Micromon addresses used to set up and check interrupt vectors was removed. While the table helped in any relocation of Micromon, I felt that direct changes of vector address values were relatively easy and well worth the program area saved. VIC Micromon has six locations with interrupt vector values that must be changed when VIC Micromon is relocated. The checks for the different versions of PET BASIC were removed as well. It didn't make sense to have universality in some parts of VIC Micromon when a good part was applicable only to the VIC.
The VIC has two levels of indirection for the input and output to device routines. The first level is the use of PET compatible addresses for the jump vectors at the end of the 8K kernal ROM. The second level of indirection is the use of an indirect jump table in RAM which allows the user to redefine the vectors. Because of this, I felt that the use of I/O jump vectors at the beginning of Micromon was unnecessary.
Besides the four ROM routines mentioned by F. Arthur Cochrane (input character, output a character, load a program, and save a program), there were other ROM routines, such as get from keyboard ($FFE4) and close I/P and O/P channels ($FFCC), used by PET Micromon. For VIC Micromon these were expanded to about 20 ROM routines, since I chose to use VIC kernal routines when possible. For example, the test for STOP key code at location $18AE of the PET Micromon was replaced with a call to the test STOP key routine at $FFE1 in the VIC kernal ROM.
Altogether, the code crunching resulted in over 250 bytes freed. This allowed me to add the Print switcher and EPROM commands along with a few handy ones which did not require much code to implement. Following is a detailed description of VIC Micromon commands with a different format or function from similar commands in PET Micromon and of new commands in VIC Micromon.
VIC Micromon Instructions
Initialize Memory And Screen Pointers
.1 1000 1E00 1E
Define low memory as $1000 and high memory as $1E00 regardless of the memory present. The screen is defined to start at the $1E page of memory. The screen memory should always be on an even page within the range of $1000 to $1E00. Odd page values result in incorrect setup and operation of the VIC display. Although 3K of RAM can be added at $400 to $FFF, this memory is not accessible for use as screen memory.
Memory pages at $000 and $200 are accessible, but are not usable since they are used for BASIC and kernal storage, working buffers, and stack area. If the screen page is within the low to high memory range specified, there can be usage conflict of the screen memory pages. If the "I" command is used and exit is made to BASIC, the NEW command must be invoked in the BASIC environment to clean up the memory pointers used by BASIC.
Jump To Micromon Subroutine
The subroutine at $2000 is called while remaining in the VIC Micromon environment. The assembly language subroutine should exit by using a RTS instruction, which causes a return to the command input section of VIC Micromon. The machine image as shown by the Register display command is not used, nor is it disturbed when the subroutine returns to VIC Micromon.
.L 2000 "TEST FILE" 01
Search for and, if found, load into memory the data file on device # 1 named TEST FILE. If the name is not specified, the first file found is loaded. The data is loaded into memory starting at location $2000. The last address loaded is determined by the length of the binary data file. If the device number is not specified, it defaults to device # 1, which is the VIC cassette tape. The original memory addresses and name of the last file read can be inspected by doing a Memory display of the tape buffer which is at $375 for VIC Micromon.
If the output is to the screen, then switch the output to the RS-232 channel (device # 2). If the output is not to the screen, restore the output to the screen with the RS-232 channel left active until the RS-232 output buffer is drained. Note that opening the RS-232 channel grabs 512 bytes for I/O buffering from the top of memory.
Regardless of the output, clear the RS-232 channel and set output to the screen.
If the output is to the screen, set CC into the RS-232 command register at location $294 and BB into the RS-232 control register at location $293. Output is then switched to the RS-232 channel. This command is invalid if output is not currently to the screen.
Command Register Format
Control Register Format
.S 2000 3000 "TEST FILE" 01
Save memory from $2000 up to, but not including, $3000 onto device # 1, which is the VIC cassette tape. If the device number is not specified, it defaults to device # 1. The name TEST FILE is placed in the file header for the file saved.
.V 2000 "TEST FILE" 01
Search for and verify, if found, the data file on device #1 named "TEST FILE." If the name is not specified, the first file found is verified. The data is verified by reading the file and comparing it to the data in memory starting at location $2000. If not specified, the device defaults to device #1. If there is a mismatch, the message ERROR is outputted to the screen at the end of the file verification.
Command End Tone
Enable the command end tone. A continuous tone will be generated at the end of execution of the next command. The tone can be turned off but still be enabled by just hitting the carriage return. No tone is generated if there is a syntax error while inputting the next command.
Disable the command end tone.
.π 2800 2FFF 00
Program the 2716 type EPROM via the EPROM programmer on the VIC User I/O port with data read from memory starting at location $2800 and ending at location $2FFF. The last input parameter specifies in hex the starting 256 byte page offset on the EPROM. If the low order byte of the starting memory address is zero and the offset is zero, then the programming starts with the first byte of the EPROM. For example, to program only the last byte of the 2K EPROM with a data byte from location $2FFF in memory, the command would be:
.π 2FFF 2FFF 07
During programming, a compare of EPROM to memory is done for each data byte just after it is written to the EPROM. Any mismatch due to failure to program the EPROM results in output to the screen of the mismatched memory location. If programming must be terminated early, just hit the STOP key. No other means should be used to abort EPROM programming. A warm restart or power down while programming can damage the EPROM.
.£ 2999 27FF 00
Load memory starting at location $2000 and ending at location $27FF with data read from the EPROM via the EPROM programmer on the VIC User I/O port. The last input parameter specifies in hex the starting 256 byte page offset on the EPROM. If the low order byte of the starting memory address is zero and the offset is zero, then the reading starts with the first byte of the EPROM. For example, to read only the last byte of the 2K EPROM and compare that with the data byte in memory at location $37FF, the command would be:
.£ 10FF 10FF 07
During memory load, a compare of EPROM to memory is done for each data byte just after it is written to memory. Any mismatch because of failure to write the memory with data from the EPROM results in output to the screen of the mismatched memory location. The STOP key can be used to terminate the command early.
.=3000 37FF 00
Compare memory starting at location $3000 and ending at location $37FF with data read from the EPROM via the EPROM programmer on the VIC User I/O port. The last input parameter specifies in hex the starting 256 byte page offset on the EPROM. If the low order byte of the starting memory address is zero and the offset is zero, then the reading starts with the first byte of the EPROM. For example, to read only the last byte of the 2K EPROM and compare that with the data byte in memory at location $37FF, the command would be:
.=37FF 37FF 07
Any mismatch between the EPROM and corresponding memory data results in output to the screen of the mismatched memory location. The STOP key can be used to terminate the command early.
Table 2: Commands for VIC Micromon
Of the set of commands available on the PET version of Micromon, only two were removed in the conversion to the VIC. These were the K (Kill Micromon) and Z (change character sets) commands. The K command is not necessary since the VIC doesn't have the TIM monitor. The function of the Z command, which is to change character sets, is already provided for on the VIC by pressing the VIC shift and Commodore keys at the same time. The rest of the commands described by F. Arthur Cochrane for the PET Micromon (see COMPUTE!, January 1982, p. 160) all apply identically to the commands for VIC Micromon, with the exception of the LOAD and SAVE commands, which have different formats.
VIC Micromon is always entered from VIC BASIC by a SYS 16384 when it resides at $4000 to $4FFF. Either the E (Exit VIC Micromon) or the X (Exit to BASIC) command would be used to exit VIC Micromon and return to the BASIC environment. The difference between these two commands is that the X command leaves the VIC Micromon vectors in the IRQ and BRK interrupt vector locations while in the BASIC environment. Also, the tape buffer is left defined as beginning at $375. Thus, certain IRQ interrupt conditions such as the moving of the cursor to the top or bottom of the screen with output from a D, M, or $ command displayed will cause scrolling and reentry into VIC Micromon. Also, if a BRK instruction is executed, VIC Micromon will be reentered via its BRK interrupt handler.
The E command restores the IRQ and BRK interrupt vectors and resets the tape buffer pointer to a value of $33C prior to exit to the VIC BASIC environment. Thus all active linkages and vectors to VIC Micromon are removed, and the VIC behaves as if VIC Micromon never existed. In particular, the E command should be used to exit VIC Micromon when the normal VIC cassette tape LOAD, SAVE, and VERIFY commands are to be used in the BASIC environment. Otherwise, invalid results are likely to occur with some tape operations.
Both the E and X commands expect the stack pointer value (as shown for SP by the Register display command) to be the same as when VIC Micromon was first entered via the BASIC SYS command. If the value of SP or the part of the stack pointed to by SP is overwritten, such as by the execution of faulty code, a clean exit to BASIC by the E and X commands is unlikely. However, both the E and X commands do check if BASIC has been initialized, and if not, exit to BASIC is via an indirect jump to the address given at location $C000. The address given in location $C000 is $E378, which is the entry to initialize BASIC. In this case, the value of SP and the contents of the stack aren't important. Once in BASIC and regardless of how the exit from VIC Micromon was made, any subsequent access to VIC Micromon at $4000 is always by a SYS16384.
VIC Micromon as given here is located from $4000 to $4FFF. It can be relocated to any 256 byte page boundary by making the changes, as shown in the following example, which relocate VIC Micromon from $4000 to $6000.
The example begins with VIC Micromon at $4000 and ends with a relocated VIC Micromon in RAM at $6000 as well as the original at $4000.
.T 4000 4FFF 6000 .N 6000 6003 2000 4000 4FFF .N 6012 6E6D 2000 4000 4FFF .N 6FB5 6FFE 2000 4000 4FFF W
In order to access the relocated VIC Micromon at $6000, exit using the E command and then from BASIC use SYS24576.
Cartridge And Checksum
The VIC-20 treats cartridge programs located at $A000 in a special way. On power-up, a test is made for the existence of the $A000 cartridge program, and if one exists, an indirect jump is made to the address specified at location $A000. This jump is made after the stack pointer is initialized, but before anything else is done. Because kernal initialization has not occurred, any cartridge program using kernal I/O routines must do kernal initialization before using those routines.
VIC Micromon as presented here has the kernal initialization calls built in so that it can easily be relocated and used as a cartridge program at $A000. Besides making the changes to relocate it to $A000, the only additional changes are to the first four bytes of VIC Micromon.
Power-up with VIC Micromon installed as a cartridge at $A000 will result in immediate entry into VIC Micromon. Because BASIC is not initialized when the E or X command is used after power-up, the exit to BASIC will be via an indirect jump to the address given in location $C000, which is the entry to initialization of BASIC. Once in BASIC, subsequent access of VIC Micromon at $A000 must be made to location $A012, which is done via a SYS40978.
There is one last point, or rather one last byte, in VIC Micromon which is not used for anything other than to make the 4K byte checksum of VIC Micromon come out to a rounded up page value. For example, the VIC Micromon from $4000 to $4FFF has a data byte value of $E6 at location $4FFF that results in a checksum of $BF00. This provides an easy way to verify the integrity of VIC Micromon without having to memorize or look up a checksum.
Three Notes On VIC Micromon
Using the VIC Micromon tape commands L, S, and V on a VIC-20 with 3K of RAM installed at $400 to $FFF will result in overwrite of $400 to $438 with file header characters (blanks). This is due to the tape buffer being relocated to $375 while in VIC Micromon from the normal $33C. The normal VIC cassette commands will work properly and not overwrite this area when you EXIT from VIC Micromon. This is because VIC Micromon restores the tape buffer pointer value to $33C when an EXIT is done. This problem does not occur if the 3K RAM at $400 to $FFF is not installed.
If the I (Initialize memory and screen pointers) command was used in VIC Micromon and you EXIT, then the RUN/STOP plus RESTORE should be used in addition to the NEW command to clean up the BASIC environment.
Any binary image saved on cassette tape with the VIC Micromon "S" command can be loaded in the normal VIC-20 BASIC environment by using the command: LOAD" ", 1, 1 which looks for the next program on tape and LOADs it into the same part of memory that it came from (see page 9 of VIC-20 Programmer's Reference Guide).
There's a good amount of typing to do to enter the VIC Micromon program. Use the following BASIC program (after you've SAVEd a copy of your efforts) to locate any errors you might have made.
Program 3: VIC Micromon Checksum
10 DATA 12915, 16867, 15061, 13732, 14507, 13829, 13801, 12813, 15027, 13920 20 DATA 14355, 11977, 11877, 13583, 11338, 15173, 12337, 14852, 14051, 15723 30 DATA 13442, 14047, 14746, 15059, 13134, 15848, 15858, 17856, 13327, 8655 40 DATA 12171, 10231 100 Q = 16384 110 FOR BLOCK = 1 TO 32 120 FOR BYTE = 0 TO 127 130 X = PEEK (Q + BYTE) : CK = CK + X 140 NEXT BYTE 150 READSUM 160 IF SUM < > CK THEN PRINT " ERROR IN BLOCK #" : GOTO 170 175 PRINT " BLOCK"BLOCK" IS CORRECT " 170 CK = 0 : Q = Q + 128 180 NEXT BLOCK