Wednesday, 9 January 2013

Getting Speed Out of MC-10 Microsoft Basic

Over the past few years I've slowly learned about, or stumbled my way to, a bunch of techniques for getting a lot of speed out of the Microsoft basic that comes with the MC-10.

The main GOSUB routines are usually grouped in the 1-19 line range.  I can't remember who originally taught me to do this or whether I figured it out on my own somehow, but it was Neil Morrison on the MC-10 yahoo forum who drove the point home when he commented:

> One of the most important things is to put all of the GOSUB and GOTO destinations in the first lines of the > program. You can actually put a jump to the end of the program, DIM variables there,
> and then jump to where you start.
>
> When you use a GOSUB or GOTO the program will begin at the first line and check every line of the
> program until it hits the line number used. You want to make that search time as short as you can.
>
> So IIRC, your program reads like
>
> 0 GOTO 2000
> 10 RETURN
> 20 RETURN
> 30 RETURN
> ...
> 100 ' Program start
> ...
> 2000 A=1:B=3:C=7.5 .....
> ...
> 2100 GOTO 100
>
> All tricks we used at the time.
>
> Neil

I also started to use a main FOR/NEXT loop usually occuring around line 20 instead of GOTOs.  And when I use FOR/NEXTs, I leave off the variable designation for the NEXT command (i.e. NEXT A), since this is unnecessary and simply slows down the interpreter.  By structing my programs using FOR/NEXT loops instead of GOTOs, and using ON/GOSUB/GOTO statements instead IF/THENs, and by packing lines as tightly as possible (which can be done completely on the MC-10 up to 128 characters length and almost completely in Coco Basic up to 256 characters in length), I have managed to get quite a turn of speed out of old un-compiled Basic.

I also, generally use memory heavily by doing as many of the repetitive calculations at initialization as possible and then store the results in arrays. This often means a long start-up delay for a program, but much faster game play when things finally get going.  In attempting to create a fast "side scroller" game like my RAIDER this was critical.  It calculates all the ups and downs for the random cavern generation before each round and then saves these in an array, so that when the screen is printing the scrolling cavern all it has to do is use MID to print the current 32 character long strings with one character less, and then plot the new part of the cavern on the left side of the screen.
If I'm manipulating strings, I would always try to CLEAR as much memory as possible to cut down on the garbage collection delays. The MC-10 boots allocating only  about 100 bytes of string space, but using the CLEAR command you can designate more. An individual string variable can be assigned a string up to 255 characters in length, regardless of what the manual says. However, since you can only input program lines that are 127 lines long you can't directly assign strings greater than 127 (or even less, since you must also include a line number and the assignment A$="). It can be larger if you generate a string some other way, say by constructing it from data read from data statements. However, if you are concatenating a lot of strings (A$=A$+B$) you must clear enough extra memory to allow the MC-10 to do all the concatenations. That is A$=A$+B$ requires that you have extra space allocated for A$ so that the MC-10 can store it and then store it again but with B$ added. The MC-10 will then "garbage collect" the space of the original version of A$ and clean up the string space behind the scene to allow that space to be used again by other string variables. I guess you could say you need to clear enough space for all string "handling" rather than just all the strings you intend to use. However, as Mechacoco (Darren) from the Yahoo group also notes:
Strings which are only assigned simple literal values within a program line do not require any string space. Neither do variables which are assigned as an exact copy of another. For example, the following will work:
10 CLEAR 0
20 A$ = "HELLO WORLD"
30 B$ = A$
40 PRINT B$

...but this will produce an ?OS ERROR in line 40:
10 CLEAR 0
20 A$ ="HELLO"
30 B$ = " WORLD"
40 C$ = A$+B$
For this to work, you would need to CLEAR at least 11 bytes for string space.
- Darren
Managing string space so that the MC-10 had the maximum space for doing its garbage collection was critical for a program like my attempt at a 3D first person tank shooter game like KURSK, which is always cobbling together your current view (from string arrays) in any of the four possible directions you can turn your turret:
It's been an intriguing challenge refining these techniques, which I have mostly gleaned from the comments of helpful folks on Yahoo, or from around the Net over the years.  One technique that has been especially helpful was described very well by J Diffendaffer on the Yahoo forum
Yeah, the variables go into the list in the order you create them and placing the most used ones first means they get found faster.  I believe this was covered in the book 'BASIC Faster and Better'. There is a PDF version online somewhere.
All my programs now use DIM to not only declare arrays, but all variables that will be used in the program.  What's most important is to put the most used variables first, since the variable names have to be searched through in a list ordered in terms of either when they are first declared in an initial DIM statement or first used by in the program.  So variables used intensely in the main loop (usually lines 20-30) should come first in the DIM statement.

I have almost completely stopped using IF statements except for non-critical mundane tasks like opening screens and menus.  Instead of IF, I use an ON/GOTO/GOSUB structures like this:

10 ON1-(A>B)GOTO20:REM ** PATH FOLLOWED IF TRUE **
20  ** THE PATH FOLLOWED IF FALSE **

A structure like this allows for much tighter packing of lines and just seems to work a lot faster than IF.  Since every space and new line of program must also be dealt with by the interpreter, getting rid of them is very helpful for increasing speed, and since the MC-10 doesn't have an ELSE statement, every IF statement effectively must hog its own line, so the above technique is a very useful one.  There are other ways of also using the pre-calculated arrays mentioned about more easily in such ON/GOTO and ON/GOSUB statements.  When I use an ON/GOSUB statement I also generally use multiple RETURNs to leap back directly into the main FOR/NEXT loop after that statement, rather than GOTOing to a single RETURN. In other words any RETURN is the same as any other, so I also generally have a line like 1 RETURN at the top of the program for use as a "null" option for any of my ON/GOSUB statements and their lists of subroutines.

Screenshots of most of the games I have created using these techniques can be found at:
https://github.com/jggames

Word Wrapping and Web Crawling for Code


As I worked on programming projects to create the programs I had wanted as a kid for my MC-10, I realized that there was a large amount of Basic code available on the Net from which to work. I began to search for sites that archived old code which might be suitable for conversion to MC-10 Basic. I discovered that many of the magazines I had drooled over as kid, were available as scanned PDFs.  Sometimes these PDFs had also been converted to text, or could be, by using OCR software. This was not always perfect, but it did help reduce some of the typing involved. It's faster to correct each line (while consulting a printout of the original) than re-typing a whole program (although this is what we did when I was a kid). I also discovered that there was a large number of programs available on the Net already in text format. I found that the best way to find such programs was to do a search using two unique Basic language words like GOTO and GOSUB (which don't appear in properly spelled ordinary English), and some desired program "theme" word such as FIRE or ATTACK or DUNGEON or MAP, or SPACE, etc. Using this method I came across large numbers of "classic" 8-bit game programs.  Most of them were essentially text based programs, but sometimes I could jazz them up using the colourful VDG graphic characters.  New Poker was one of my programs that emerged in this way.  It was taken from a text based David Ahl Basic listing, which used full text descriptions to describe your hand.  I added a routine that printed the cards "graphically."  By using a black background for the card, I could create simple representations of the suit symbols.  However, this necessitated also printing reverse video numbers.  Unlike the poker program I had created as a kid (which I simply called POKER).

David Ahl's original listing didn't format the screen in any way, the cards could end up being being printed on different rows of the screen.  But in Coco basic you must use poke to put the reverse versions of numbers on the screen, so I needed a way to know where the cursor was and to print/poke the appropriate reverse character for the card suit/number wherever the card got printed.  Fellow MC-10ers on the Yahoo group provided the relevant peek locations for finding out the current location of the print cursor.

P1=(PEEK(17024)AND1)*256+PEEK(17025):POKEMC+P1-1,PEEK(MC+P1-1)-64:RETURN


The Coco equivalent uses the peek locations 136 and 137.  Using this location you can simply peek the value the location you want to "reverse" and poke that peek value -64.  It provided a simple way to get full reverse video messages for all the character set, instead of just the alpha characters.

Another problem I had to overcome converting listings like those of David Ahl, is that they often printed long detailed messages.  These messages usually assumed at least a 40 character screen, if not an 80 character screen.  For the oldest classic programs, like Ahl's poker, it was assumed that information would simply scroll up off the top of the screen.  This was OK but I needed a way to deal with long messages so I decided to work out a simple word wrap algorithm that I could use to replace all print commands.  I had tried various forms of doing this in other program conversions I had done, such as GARGOYLE CASTLE,
which read each character until it passed a certain threshold, when it would start looking for a space character, at which point it would split the line.  These character based wrap routines were slow.  They spit out lines like an old three hundred baud terminal program.  Finally I came up with a simple and fast routine that used the MID command:

0 CLEAR500:DIMCC,ZZ,M$,I$:GOTO5
1 ZZ=1:CC=32:FORCC=CCTOZZSTEP-1:I$=MID$(M$,CC,1):IFI$<"!"THEN?MID$(M$,ZZ,CC-ZZ):ZZ=CC+1:CC=ZZ+32:IFI$=""THENCC=.
2 CC=CC+(CC>255)*(CC-255):NEXT:M$="":RETURN

5 REM PROGRAM START
6 INPUT M$:GOSUB1:GOTO6

Once I had this routine, converting some of the basic text based adventures I had wanted to play as kid on my MC-10 were easy, such as ASMOVIAN, which I remember seeing in an old Atari book  and games for the TRS-80 model 3 that my mother used to bring home from school (she was a primary teacher) on weekends, such as Ray Sato's SABOTAGE:
You can also see the use of my reverse video routine being used for the message at the bottom of the screen.  Here are just a few of the sites for archaic code that I've found:
basichome Commodore.ca Gallery Magazines Compute! Magazine - 44 to 90 Gorilla download (Arcade action game) index if-archive-games-source-basic Ira Goldklang's TRS-80 Revived Site Documentation - Books Quite BASIC — Trebuchet Game Steven's ZX81 Computer Tandy 1000 Basic Programs TI-92 BASIC Games - ticalc.org trek iii.4 - Google Search TRS-80 Color Computer Software Repository - -coco-Documents-Books- World Of Dragon WP List Shareware Add-ins Directory JSBasic The Nascom Home Page Index of /if-archive/games/source/basic TRS-80 Model III Emulator Commodore - Magazines - Input General retrogaming websites • Retroaction The *HUMONGOUS* CP/M Software Archives Index of /cpmarchives/trs80/Software/Model 1/S TRS-80 Color Computer Software Repository Brutal Deluxe Software BASIC Gamer - Issue #1 The Game Creators Forum - 20 Liners - [DBPro] Grail Of The Gods ... 18 line Rogue-Like Dungeon Crawler Sync Commands - DarkBASIC Professional Help Wiki Other platforms and computers Software (Dragon, TRS-80, CPC, BBC, PC, Coleco Vision etc..) Index of /pcsig08 Dragon 32 Games by Abacus - Provided by Dragon 32 Universe Dragon 32 Games by Argus Press - Provided by Dragon 32 Universe labs » mclelun Pipe Dream Flash Game » mclelun 


Port of "Switchbox" from the Atari 520 ST to the Coco and MC-10

I used to remember reading computer magazines in the mid 80s.  I mostly read the ones available in my high school library, such as Compute! or Creative Computing.  Although they had the occasional article on the Color Computer (but obviously never the failed MC-10), they were for the most part Commodore, Atari and Apple focused, with some growing emphasis on the PC.  This meant that TRS-kids like me where left on the outside looking in at the vast cornucopia of type-in software made available in these magazines for these other machines.  I couldn't afford a subscription to Rainbow or Color Computer magazine of Hot Coco (except on the rare trip to the Mall magazine shop, when I happened to have enough).  So I remember gazing at all the amazing games and wondering (and sometimes trying to figure out) how they could possibly be converted to my little MC-10 (and its little 32X16 screen vs the more standard 40X24 screens of the other machines).

I recall being particularly intrigued by a game called "Switchbox."  It basically recreated on the screen something like one of those funny Japanese metal-ball-drop game machines, but for two players.  It was in Compute! magazine in the March 1986 edition: https://archive.org/details/1986-03-compute-magazine

I suspect there was simply something inherently intriguing to my young mind about the complexity of all the "switches"--like the allure of taking apart an old alarm clock.  The richness of the display and the complexity of the interactions were very attractive.  I think I might have tried to make a conversion then, but if I did, it didn't survive the interim to today (unlike some of my other software which I hope also to discuss here).  However, in the past few years I have been programming some of the projects I dreamt of then and have built a lot more competence in programming in Basic.  One things I have learned about is the similarity between TRS-80 basic and other more Microsoft compatible versions of basic for the PC and other later home computers.  So when I finally got around to digging up the old article on "Switchbox" in Compute! this last summer (2012),  I was pleased to note there was a PC version:


However, as I examined the code I realized that due to the PC having a 25 row screen, it was going to be especially difficult to cut the game down to fit the size of a Coco/MC-10 screen.  I was about to put the project aside when I noticed the Atari 520 ST version:


Because it was one of the first "windowed" machines, and because it still was used primarily with a TV, most games were still made for its 40 column 24 high res screen mode.  But because it was "windowed" it also lost areas of that screen to the ever present top menu bar and window borders.  Because of this, I realized when I counted, that its switchbox had been pared down to a smaller number of rows of switches, which might be able to fit on a 32 by 16 screen!  Its version of basic was very advanced and well structured, but essentially Microsoft-like, so I only had to do a little digging to figure out the few distinct commands (eg. GOTOXY) and convert the bulk of the core logic for managing the switches.  Then all I had to do was come up with a way of representing these using the block graphics of the Motorola VDG, instead of using the line graphic features of the Atari 520ST.  Here's what I came up with:


You'll notice that the ST and the Coco/MC-10 version share the same four rows of switches, versus the 5 rows in the PC version.  Of course I had to come up with my own system of sounds for the dropping balls, as the STs sound commands far exceed those of the simple SOUND statement of the MC-10.  I think they came out quite nicely, but you might disagree.  Please try the game for yourself.  The MC-10 version can be downloaded as part of the ZIP file of all my games or you can download the coco version on the JGGAMES5.DSK virtual Coco disk at:
https://github.com/jggames

And so, at least in terms of this Compute! game, I'm no longer simply someone looking in from the outside...

Tuesday, 8 January 2013

Pipe Frenzy


Pipe Frenzy
 
Well I'm starting a new programming project and a new blog at the same time.  My new programing project is a Basic language version of the classic 8-bit game "Pipe Frenzy" to be created on my TRS-80 MC-10 computer.  The graphic above is a preliminary sketch of the work grid, cursor and some of the pipe shapes.  The idea for this project comes from the site http://www.mclelun.com/blog/2012/04/pipe-dream-flash-game/ McLelun has created his own flash version of the classic "Pipe Frenzy" (AKA "Pipe Dream) genera.  It's lots of fun!

So why create a new version for the TRS-80 MC-10?  Well, that's just what I do.  I like trying to re-create classic 8-bit video games (and other software) for the MC-10 only using its very limited resources.  It's just a little more capable than a Sinclair ZX81.  It has a few extra-capabilities compared to that classic introductory computer (colour, sound) but on the whole it is about the same limited level.  When I was a kid, the MC-10 was the machine that introduced me to computing.  At that time in the early 80s you had to be prepared to write, or at least type-in, programs in order to have any software at all.  This was especially true of the MC-10, which came only at the very end of the Sinclair ultra-cheap-introductory-computer trend (and the great RAM drought of the early 80s), so that by the time it was introduced people had moved on to slightly more capable 8-bit machines like the Commodore 64, Atari 800, TRS-80 Color computer, Ti99, which had full keyboards and more memory. etc.  So the MC-10 was left an orphan in terms of a user base, and as a result, had an EXTREMELY limited amount of professional software created for.  This meant that the small number of people who had bought one, like me, were left largely to our own devices, in terms of software...so I took up Basic programming.  Some of my projects I kept over the years, and when I had my MC-10 returned to me by an uncle who had carefully kept it after I had passed it on to my cousins (I had moved on to a bigger and better Tandy 1000) I dusted it off (and my old software too), and got back to the business of Basic programing as an adult hobby.

Now I'm a part of the vast, and apparently growing number of people who have "retro-computing" as a pastime.

I plan to use this blog to describe my current projects and some of my past projects and share some of the things I've learned about programming the MC-10 (and its older brother the Tandy Coco).  Over time I have learned a bunch of techniques for squeezing a substantial amount of speed out of the Microsoft Basic that came standard with the MC-10.  This has been an necessity because 1) I don't know machine language and have little interest in learning it, and 2) there are no basic compilers for the MC-10 like those developed for more popular machines, such as the ZX81.

So this blog will be dedicated to the MC-10 (and also to the Coco, which I also owned for a short time when I was a teenager) and their versions of standard interpreted (non-extended) Basic.  If you are interest in these topics please drop by and see what we (my son Charlie now shares an interest in my hobby) have been up to.