Many owners of the new Commodore 64 will have access to a large number of programs written originally for the PET computer. It is natural for these people to ask "What is involved in converting these programs so that they will run on the 64?". This article will attempt to detail some of the steps involved and hopefully make the conversion somewhat easier. I will only be discussing conversions involving 2.0 and 4.0 ROM PETs. Those interested in converting programs from 1.0 ROM PETs should be able to make the additional changes necessary.
In many cases, a PET program will run immediately on a 64. In some cases, a few minor changes will make the program workable. In a few cases, major surgery will be required, and in some instances, unless you are heavily into machine language, the conversion will be impossible. The type of conversion required will depend on the makeup of the original program.
As I said above, some programs will run immediately on the 64. These programs will be written entirely in BASIC and will not make use of the commands POKE, PEEK, WAIT, SYS, and USR. The easiest way to determine if a program falls in this category is to simply load the program into the 64 and run it. If it works, great. Otherwise read on.
Note: All BASIC programs for the PET will load into the 64 correctly. This may seem surprising since a PET program is stored in memory starting at location 1025 while 64 programs normally start at 2049. Such loads are successful because of a relocation feature incorporated into the Commodore 64 (and also the VIC 20) computer. These computers will automatically load a program at the START OF BASIC (wherever that happens to be), unless told to do otherwise (see your manual to see how to tell it to do otherwise).
I should point out that I have had some difficulty loading programs that were saved on a PET with 1.0 ROMS. Such programs do list but the first line is usually mangled. This can be fixed up by deleting that first line and retyping it or by a few simple POKEs.
The Simplest Conversion
Of the programs that do require conversion, the simplest to fix are the ones that do not use the SYS or USR commands. They may use the POKE, PEEK or WAIT commands, but these can usually be fixed up by changing an appropriate address and possibly a corresponding numeric value.
For example, POKE 59468,14 is a command frequently found in PET programs to convert the screen display to lower case. If this command is executed on the 64, nothing drastic will happen but lower case is definitely not displayed. The correct command on the 64 is POKE 53272,23. Thus part of the conversion process will be to locate all POKE 59468,14 statements in the program and change them to POKE 53272,23. Similarly, all POKE 59468,12 statements will have to be changed to POKE 53272,21 (This converts the screen display to upper case and graphics).
The majority of 'fixes' can be achieved in this manner:
i) Find the address on the PET that is causing a problem,
ii) Find the corresponding address on the 64.
iii) Make all changes involving that address.
What is needed then is a list of addresses for the PET that can cause problems and a list of the corresponding addresses for the 64.
Actually, with a little more work, we can even do better. Ideally, a program should be able to run on any machine— PET with 2.0 ROMS, PET with 4.0 ROMS, and the Commodore 64.
This can be achieved for the upper/lower case conversion above in the following way.
Assume first that the program is running on a PET. Somehow have the computer execute the following commands:
3000 TEXT = 59468: REM Address to be poked for upper/lower case 3010 UC = 12: REM Value to be poked for upper case 3020 LC = 14: REM Value to be poked for lower case
On the other hand, if the program is running on a 64, have it execute the following:
3100 TEXT = 53272 3110 UC = 21 3120 LC = 23
Now change all POKE 59468,12 statements to POKE TEXT,UC and all POKE 59468,14 statements to POKE TEXT,LC. After these changes are made, the correct case will be displayed regardless of which computer the program is running on. If all other problem addresses can be fixed up in this manner, then we are well on our way to converting the program to work on all three computers.
Which Computer are You?
The first task then is to somehow identify what type of computer a program is running on.
There already is a standard technique for identifying whether a PET has 2.0 ROMS or 4.0 ROMS; namely,
110 IF PEEK (50003) = 160 THEN ... : REM 4.0 ROMS 120 IF PEEK (50003) = 1 THEN ... : REM 2.0 ROMS
PEEKing location 50003 on a 64 will usually yield a zero. I say 'usually' because 50003 is a RAM location on the 64 and is normally unused. However, machine language routines can be placed in that area and so you cannot be 100% sure what location 50003 will contain. The sequence below will set around this problem and will identify the type of computer correctly without destroying any machine code already there.
100 X = PEEK (50003): POKE 50003,0: Y = PEEK (50003) 110 IF Y = 160 THEN COMPS = "4.0":REM 4.0 ROMS 120 IF Y = 1 THEN COMPS = "2.0":REM 2.0 ROMS 130 IF Y = THEN POKE 50003,X :COMP$ = "64": REM COMMODORE 64
The statement POKE 50003,0 in line 100 has absolutely no effect on 2.0 PETS or 4.0 PETS since location 50003 is in ROM. On the 64 however, it puts a zero into that RAM location. Notice that the original value in location 50003 is saved by the statement X = PEEK(50003) and restored again in line 130 if the computer is identified as being a 64. Note the use of the variable COMPS to identify the type of computer just in case it is needed again later in the program.
Now the conversion process should be clear. It should include the following:
1) At the beginning of the program, jump to a subroutine that identifies the type of computer that the program is currently running on.
2) In that subroutine, initialize a set of standard variables (such as TEXT, LC, UC, etc.) to the correct values for that computer.
3) Change all references to numerical addresses or values to the corresponding standard variables.
Here is a sample initialization routine.
10 GOSUB 60000 20 REM MAIN PROGRAM60000 X = PEEK(50003):POKE 50003,0:Y = PEEK(50003) 60010 REM INITIALIZE VARIABLES COMMON TO 2.0 & 4.0 PETS 60020 TEXT = 59468:UC = 12:LC = 14:SCREEN = 32768:HIV = 144 60030 NUMCH AR = I58:KEY = 151 :NOKEY = 255 60040 IF Y<> 1 THEN 60100 60050 REM INITIALIZE VARIABLES PECULIAR TO 2,0 PETS 60060 COMPS = "2.0":EN A = 46:DIS = 49 60070 RETURN
60100 IF Y <> 160 THEN 60200 60110 REM INITIALIZE VARIABLES PECULIAR TO 4.0 PETS 60120 COMPS = "4.0":EN A = 85:DIS = 88 60130 RETURN 60200 IF Y <> THEN 60300 60210 REM INITIALIZE VARIABLES PECULIAR TO THE 64
60220 COMP$ = "64":TEXT = 53272:UC = 21 :LC = 23:SCREEN = 1024:HIV = 788 60230 NUMCHAR = 198:KEY =203:NOKEY = 64:ENA = 49:DIS = 52 60240 POKE 50003,X:RETURN 60300 PRINT "I DON'T RECOGNIZE THIS COMPUTERLAND
The variables SCREEN, NUMCHAR, etc. will be explained shortly.
More Problem Areas
Upper/lower case conversion is certainly not the only problem area. Another potential one is the screen.
1. The Screen
On the PET the screen is found in memory locations 32768-33767. On the 64, it is found in locations 1024-2023.
If all output to the screen is obtained through the use of PRINT statements, then absolutely no problem will arise. If however, the output is POKEd to the screen, then changes will be required.
These changes are best achieved by assigning a value to the base address of the screen and then using an appropriate offset from that base.
For example the base address of the screen on the PET is 32768 while on the 64 it is 1024. Therefore, the first thing to do is to assign values to the standard variable SCREEN as follows:
SCREEN = 32768 if on a PET
SCREEN = 1024 if on a COMMODORE 64
i) Poking a single value onto the screen.
A statement of the form
POKE 32956,61
on a PET has to be changed as follows:
First, calculate the offset.
Offset = 32956-32768 = 188
Then, change POKE 32956,61 to
POKE SCREEN + 188,61
The resulting statement will work on either a PET or a 64 (assuming SCREEN has been properly initialized).
Notice that the 61 does not have to be changed as these values are the same for both PETS and the 64
ii) Poking with a loop.
The following is a typical PET routine that POKES a border of 'reversed diamonds' around the screen.
100 FOR I = 32768 TO 32807 : POKE I, 218 : NEXT 110 FOR I = 32847 TO 33767 STEP 40 : POKE I,218 : NEXT 120 FOR I = 33766 TO 33328 STEP - 1 : POKE I,218 :NEXT 130 FOR I = 33688 TO 32768 STEP - 40 : POKE I,218 : NEXT
This can be changed to work on both PETS and 64 by changing each screen address as above.
100 FOR I = SCREEN TO SCREEN + 39 : POKE I,218: NEXT 110 FOR I = SCREEN + 79 TO SCREEN + 999 STEP 40: POKE I,218: NEXT 120 FOR I = SCREEN 4- 998 TO SCREEN + 990 STEP - 1 : POKE I,218 : NEXT 130 FOR I = SCREEN + 920 TO SCREEN STEP - 40 : POKE I,218: NEXT
Or better yet
100 FOR 1 = TO 39 : POKE SCREEN + I,218 : NEXT 110 FOR I = 1 TO 24 : POKE SCREEN + 39 + I*40,218 : NEXT 120 FOR I = 38 TO STEP - 1 : POKE SCREEN + 960 + I,218 : NEXT 130 FOR I = 23 TO 1 STEP - 1 : POKE SCREEN + I*40,218 : NEXT
2. Clearing the Keyboard Buffer
The PET is able to retain up to ten keystrokes in a buffer, enabling you touch typists to type as fast as you can without losing any keystrokes. This can sometimes add extra unwanted characters to the beginning of an input, so a common technique in PET programming is to clear the keyboard buffer before each input is requested. This can be accomplished in a couple of ways.
100 FOR I = 1 TO 10 : GET A$ : NEXT
or
100 POKE 158,0
The first method will work as is on the 64. The second method must be changed.
On 2.0 and 4.0 PETS, location 158 always contains the number of characters in the keyboard buffer. On the 64 this value is stored in location 198. Thus if we assign values to the standard variable NUMCHAR as follows:
NUMCHAR = 158 if on a PET
NUMCHAR = 198 if on a 64
and change all references to POKE 158,0 to POKE NUMCHAR, 0, then the resulting statement will work on both computers.
3. Pausing Until any Key is Pressed
Here again two techniques are commonly used.
100 GET A$ : IF AS = "" THEN 100
is certainly the simplest and will work on both computers.
100 POKE 158,0 : WAIT 158,1 : POKE 158,0
is another technique and will have to be changed to
100 POKE NUMCHAR,O : WAIT NUMCHAR,l : POKENUMCHAR,0
4. Which Key is Pressed
A common technique used on the PET, especially in games, is to PEEK at location 151 to see if a key is being pressed and if so which one. Depending on which key is pressed a certain action is performed. This technique is frequently used in games that use the numeric keypad as a joystick. A sample sequence might be
500 X = PEEK(151)510 IF X =255 THEN 1000 : REM NO KEYPRESS 520 IF X = 18 THEN 2000 : REM 2 KEY IS PRESSED 530 IF X = 50 THEN 3000 : REM 8 KEY IS PRESSED
etc.
The conversion here is a little more complicated but is still possible. First, we need to know that location 151 on the PET corresponds to location 203 on the 64. Then assign the following values to the standard variable KEY:
KEY = 151 if on a PET
KEY = 203 if on a 64
Replacing line 500 with
500 X = PEEK(KEY)
gives us a start with the conversion.
Another problem occurs with the values stored in location 151 (or 203) when a key is not being pressed. Location 151 on the PET contains 255 while location 203 on the 64 contains 64. This time we will use the standard variable NOKEY and initialize it as follows:
NOKEY = 255 if on a PET
NOKEY = 64 if on a 64
Line 510 is then replaced with
510 IF X = NOKEY THEN 1000
There are two problems associated with the other keys. First, location 151 will contain a certain value on the 2,0 machines, the same value on the Skinny 40 (i.e. the 9 inch screen) machines, but a different value on the Fat 40 machines. There is no standard way, that I am aware of, for distinguishing between a Skinny 40 and a Fat 40 machines. But PEEKing at location 57344 will do as well as any other. On a Skinny 40 you will get a value of 169 while on a Fat 40 you will get a value of 76.
The easiest way to see what value is stored in location 151 is to run the following program segment and press any key that you wish to test.
100 KEY = 151 : REM KEY = 203 ON THE 64 110 PRINT PEEK(KEY) : GOTO 110
The second problem arises from the fact that the 64 does not have a numeric keypad and using the numbers 2,4,6, and 8 to simulate a joystick is unacceptable. It would be much better to use the keys 1,J,K, and M or some other suitably arranged set of keys.
My suggestion for getting around this is to first settle on the keys that you wish to use on each machine (they don't have to be the same). Find the values corresponding to these keys by running the short program above and store these values in corresponding standard variables which I like to designate Kl, K2, K3, etc. (for KEY1, KEY2, KEY3, etc.) Then lines 520 and 530 can be replaced by the following:
520 IF X = Kl THEN 2000 530 IF X = K2 THEN 3000
etc.
5. Disabling the Stop Key
The stop key on the PET can be disabled by altering the
Hardware Interrupt Vector. For example.
POKE 144,49 for 2.0 PETS
POKE 144,88 for 4.0 PETS
will disable the stop key (and the time clock as well).
The corresponding command on the 64 is
POKE 788,52
To enable the stop key again
POKE 144,46 for 2.0 PETS
POKE 144,85 for 4.0 PETS
and POKE 788,49 for the 64
These can be replaced by
POKE HIV.DIS
to disable the stop key
and
POKE HIV,ENA
to enable the stop key after appropriately initializing the variables HIV, DIS, and ENA. On the 64, the program can still be stopped by pressing the RUN/STOP and RESTORE keys simultaneously, but this will prevent stoppage of a program due to accidentally pressing the STOP key.
A good question to ask is "How do you know what value is to be stored in these locations?". The PET program actually tells you the location to POKE as well as the value, but the value to be POKED on the 64 is usually different (c.f. disabling the stop key above or converting to upper/lower case). A memory map will tell you what location to POKE on the 64, but it will not tell you what value to POKE it with. A good start is to PEEK that location from direct mode and make note of the value. Do this for all three machines and it will tell you the 'normal' state of that location. For example, PEEKing location 144 on 2.0 PETS and 4.0 PETS yields 46 and 85 respectively. PEEKing at 788 on the 64 yields 49. Observing that the value to disable the slop key on the 2.0 & 4.0 PETS are each three more than the 'normal' value, a good start to finding the correct value on the 64 is to add 3 to the 'normal' value of 49, obtaining 52. This process will work for more than 90% of the problem values. It is that last 5-10% (hat makes the conversion challenging.
It would be impossible to list all problem locations and their 'fixes' here (I will list what 1 feel are the more common ones below). Instead I have attempted to give you a feeling for how the conversion should proceed. The proper tools that are required are the excellent memory maps (both zero page and ROM routines) published for all three computers in COMPUTE! by Jim Butterfield. Another excellent source is the book Programming the PET/CBM by Raeto Collin West and 1 am sure there are others.
A Couple of Cautions
1. The PET and the 64 only recognize the first two letters of a variable name. When converting a program you must make certain that the variables already present in the program do not conflict with the standard variables suggested above. If there is a conflict, change whichever you feel is easier.
2. If a program is to be used both on a PET and a 64, then the changes should be made on and saved with a PET computer. The reason for this is that a program saved on a 64 will not load properly on a PET, due to the lack of a relocation feature in the PET (But see below).
If the changes are made on a PET, then a utility such as BASIC AID or POWER will be invaluable since you can type in such things as
FlNDPOKE
and all lines that contain a POKE statement will be listed, making it easier for you to make the necessary changes and to make certain that you have found all of them.
Similarly you can type in
FINDSC
to see if there are any variables in the program that will conflict with the standard variable SCREEN.
Programs That Contain SYS or USR Commands
These programs will require that you be somewhat familiar with machine language in order for you to be able to make the necessary conversions. Such changes are beyond the scope of this article. However, let me say that these M/L routines themselves fall into a number of categories.
1) The routine works on the 64 as is. (Few routines will likely fall in this category)
2) The routine will work with a simple address change. (These are frequently ROM routines such as the routine for resetting the entire stack)
3) The routine will work with some minor changes. An example here could be a routine to reverse a portion of the screen. Chances are the only changes necessary would be for the location that determines the base address of the screen. However, if parameters are passed in the calling statement, then the location of certain ROM routines (such as checking for a comma) might have to be changed as well.
4) The routine will require major surgery before it will work. A program like BASIC AID or MICROMON would fall into this category. Such programs should be left to the experienced users.
Other areas that may require major changes are those programs that make use of the BASIC 4.0 disk commands. Some of these can be fixed up easily, but some are extremely difficult (e.g., those that make use of Relative Record files).
Programs that make use of CB2 sound will still run on the 64, but no sound will be produced. The POKEs that the PET uses to produce these sounds will POKE into the ROMS of the 64 and hence do no harm. Once you are familiar with the sound process on the 64, here is a good place to make use of the variable COMPS. For example, suppose lines 1000-1030 in the PET program are used to produce the sound. Leave these lines exactly as they are and add a similar routine for producing sound on the 64 beginning with
1031 IF COMPS < > "64" THEN 1040
Your sound routine can be placed in lines 1032-1039 and the rest of the program should proceed as normal.
Loading Programs Saved on the 64 Into the PET
As mentioned above, programs saved on the 64 do not load properly into a PET. It is not a difficult procedure to correct this shortcoming however. Here are the steps.
1 . Type in a dummy line into the PET.
0 REM
will do.
2. Type in POKE 2048,0
3. LOAD in the program that was saved on the 64 as you normally would.
4. Type in POKE 1025,1 : POKE 1026,8
You should now be able to LIST the program including the dummy line that you typed in initially. Delete this line by typing in < RETURN >. The process is now complete. You can save the program to cassette or disk. The next time that you load it into your PET, it will load normally. If you are using a disk, you will notice that the program is 3 blocks longer than the original even though it is the same program. The reason for this is that the Start of Variables pointer did not get changed properly. An experienced programmer can set into the monitor and make the necessary changes without too much difficulty, but the program will operate correctly without making this change.
Some of the More Common Problem Locations
2.0 PET | 4.0 PET | 64 | Suggested Name | Description |
40-41 | 40-41 | 43-44 | SBAS | Start of BASIC text |
42-43 | 42-43 | 45-46 | SVAR | Start of variables |
44-45 | 44-45 | 47-48 | SARR | Start of arrays |
46-47 | 46-47 | 49-50 | EARR | End of arrays |
52-53 | 52-53 | 55-56 | TMEM | Top of memory |
144-145 | 144-145 | 788-789 | HIV | Hardware Interrupt Vector |
151 | 151 | 203 | KEY | Which key is pressed |
158 | 158 | 198 | NUMCHAR | Number of characters in keyboard buffer |
159 | 159 | 199 | RVS | Screen reverse flag |
167 | 167 | 204 | CRSR | Flag for flashing cursor in GET statements |
196 | 196 | 209 | SLO | Pointer to screen line |
197 | 197 | 210 | SHI | (low/high format) |
198 | 198 | 211 | CH | Horizontal position of cursor |
216 | 216 | 214 | CV | Vertical position of cursor |
623 | 623 | 631 | BUFF | Start of keyboard buffer |
634 | 634 | - |
|
Start of first cassette buffer |
826 | 826 | 828 | CAS | Start of second cassette buffer |
32768 | 32768 | 1024 | SCREEN | Start of screen memory |
59468 | 59468 | 53272 | TEXT | Poke location for upper/lower case |
64721 | 64790 | 64738 |
|
Simulates power on reset |
|
|
|
Special Values |
|
12 | 12 | 21 | UC | Upper case |
14 | 14 | 23 | LC | Lower case |
255 | 255 | 64 | NOKEY | No key is pressed |
46 | 85 | 49 | ENA | Enable stop key |
49 | 88 | 52 | DIS | Disable stop key |
(Written for the Canadian Commodore Educational Group)
ref: Commodore Microcomputer Magazine, Issue 22, March 1983, pp. 41-46
Garry Kiziak
01.03.1983
Keywords: Commodore PET, Commodore 64, Software, Conversion