Sunday, April 8, 2012

Microsoft BASIC for the Replica 1


At this site is source code that can generate the first eight known versions of Microsoft BASIC for the
6502. It was generated by disassembling the ROMs, organizing and commenting the code, and figuring out the differences between the various versions.

I made some patches so I can run it on a Replica 1. You need the assembler from the CC65 tools  to build it.

If you want a more complete version of Apple BASIC, see Applesoft Lite.

I chose to use Ohio Scientific (OSI) BASIC since it has the fewest external dependencies. It also happens to be the BASIC I used on my first computer.

All the code is here. To get OSI BASIC running on the Replica 1, extract the source code, apply the
patch REPLICA1-PATCHES-FOR-OSI.patch, and build it, e.g. on a Linux system:

mkdir msbasic
cd msbasic
unzip ../msbasic.zip
patch -p1 < ../REPLICA1-PATCHES-FOR-OSI.patch 
./make.sh

The patch defaults to linking at address $A000, the address of an EEPROM on the Replica 1 Multi I/O board. It builds the "small" version of BASIC which fits in the 8K EEPROM.

The start address is $BD0D which is determined by looking at msbasic.lst and seeing that the address of COLD_START is $0007 from the start of the INIT section, and adding it to the address of the INIT section in osi.map, which is $BD06 ($BD06 + $0007 = $BD0D).

To use the patched make.sh file to generate the Woz monitor file to download to the Replica 1 you'll need my bintomon program. Upload the file tmp/osi.mon to the Replica 1. Then start it (e.g. "BD0DR"). You will see the following:




MEMORY SIZE? 
TERMINAL WIDTH? 40


 31999 BYTES FREE


OSI 6502 BASIC VERSION 1.0 REV 3.2
COPYRIGHT 1977 BY MICROSOFT CO.


OK




In the above I hit Enter in response to the memory size prompt, which will use all available memory. I entered 40 for the terminal width.

There is a well-known Easter egg in Microsoft BASIC which varies slightly across versions. In the OSI version if you enter "A" in response to the memory size question it will display the author of the
code:




MEMORY SIZE? A


WRITTEN BY RICHARD W. WEILAND.


MEMORY SIZE? 





If you don't have an EEPROM and Multi I/O board, you can run MS BASIC out of RAM.  Change the file osi.cfg so that the line specifying the start address of the ROM is, say, $6000 instead of $A00 for the EEPROM, e.g.

BASROM:         start = $6000, size = $2000, fill = no, file = %O;

Change the line in make.sh that runs bintomon to specify the start address of 0x6000.  When running in RAM, don't let if default to use all memory or it will overwrite itself.  In this example you can use 24000 to leave room for the 8K of BASIC at the top of memory.  You should have about 23K of memory available for BASIC programs.

To port it to the Replica 1, I made the following changes (for details, see the patch):

  • The MONRDKEY routine to read from the keyboard was pointed to the Woz mon location $FFEB.
  • The routines MONRDKEY (read key from keyboard) and LOAD and SAVE were implemented in the file osi_extra.s. LOAD and SAVE are no-ops and do nothing,
  • The file extra.s needed to include osi_extra.s when building for OSI.
  • The version of CC68K I used did not recognize the C-style comments, so I had to remove them from some source files.
  • I patched the build script make.sh to only build the OSI version and to call the bintomon program to generate the Woz mon download file.
  • I also added options to make.sh to generate an assembler listing file and link map file so you can determine the right start addresses.
  • The osi.cfg file was modified for the size of EEPROM.
  • The file osi_iscntc.s has code to check for the Control-C key being pressed. This was modified to work with the Replica 1. Control-C interrupts a running program. On the Replica 1 it works with a keyboard through the serial port but I found it did not work with a PS/2 keyboard because the Propeller code does not seem to pass this key code to the Replica 1.

This version is the "small" version of BASIC which fits in 8K and supports 6 digit precision for floating point math. You can build the 9 digit precision version by changing the file defines_osi.s to comment out the line "CONFIG_SMALL := 1". It no longer fits in 8K so you need to link it a lower address, e.g. $5000 if using RAM.

The OSI version of MS BASIC has a nasty bug with garbage collection of strings not working correctly.  If you use arrays of strings eventually your program would try to free up space by garbage collecting old strings and lock up the machine. This was fixed in later versions of BASIC.

A sample program which illustrates the floating point sine function is below.  It calculates points on a sine curve to be used in my experiment using the 6522 VIA as a digital to analog converter. Here is the program:

 10 REM CALCULATE DATA POINTS FOR SINE WAVE
 20 PI = 3.14159265
 30 PRINT "SAMPLE VALUE ROUNDED"
 40 FOR S = 0 TO 15
 50 V = 7.5*SIN(2*PI * S/16) + 15/2
 60 PRINT S;V;INT(V+0.5)
 70 NEXT S
 80 END

The output for the "small" version of BASIC with 6 digit floating point precision is the following:

SAMPLE VALUE ROUNDED
 0  7.5  8 
 1  10.3701  10 
 2  12.8033  13 
 3  14.4291  14 
 4  15  15 
 5  14.4291  14 
 6  12.8033  13 
 7  10.3701  10 
 8  7.5  8 
 9  4.62988  5 
 10  2.1967  2 
 11  .570904  1 
 12  0  0 
 13  .570902  1 
 14  2.1967  2 
 15  4.62987  5 

And the output for 9 digit floating point is:

SAMPLE VALUE ROUNDED
 0  7.5  8 
 1  10.3701257  10 
 2  12.8033009  13 
 3  14.4290965  14 
 4  15  15 
 5  14.4290965  14 
 6  12.8033009  13 
 7  10.3701258  10 
 8  7.50000003  8 
 9  4.62987429  5 
 10  2.19669917  2 
 11  .570903519  1 
 12  1.11758709E-08  0 
 13  .57090348  1 
 14  2.1966991  2 
 15  4.62987421  5 

With more effort you could port the other versions of MS BASIC to the Replica 1, including Applesoft. I may do this in future.

No comments: