Word wrap revisited…

  1. 2015/1/5 Update: Jim’s v3 code has been fixed.

In the “CoCo Community”, Jim Gerrie is well-known for his prolific BASIC programs. He and his son have cranked out an endless assortment of games over the years for both the Radio Shack Color Computer and the MC-10. Since the MC-10 also started out as a 4K computer, he has long been since writing programs to fit in such little memory. He is the first one to submit programs to the 1980 4K CoCo Programming Challenge I am hosting.

After he saw my word wrap article and its follow-up with updated code, he was kind enough to share a simple word wrap routine that he uses. His looks like this:

...
1 C1=1:CC=WD
2 FORCC=CC TOC1+2STEP-1:IFMID$(M$,CC,1)<>""ANDMID$(M$,CC,1)<>" "THENNEXT
3 PRINTMID$(M$,C1,CC-C1):C1=CC+1:CC=C1+(WD-1):IFC1<=LEN(M$)THEN2
4 RETURN
...

FOUR lines compressed of code. Since he works with low-memory BASIC so often, he demonstrates plenty of the optimizing techniques I mentioned earlier and some I didn’t mention. Not only does he number his program by 1s, he also places the subroutine at the start of the program. Every time you GOTO or GOSUB, Color BASIC will either search forward (if the line number you are going to is higher than the one you are currently on), or start at the TOP of your program and search forward. This means if you had something like this:

100 REM A REALLY BIG PROGRAM
...
150 GOSUB 1000
...
995 END
1000 REM MY SUBROUTINE
1010 PRINT "HELLO!"
1020 RETURN

…when you called “GOSUB 1000” from line 150, BASIC would then have to scan forward until it finds line 1000. If you have hundreds of lines of BASIC code, this is a big waste of CPU time.

However, if you placed that routine at the start of the program (and had a line at the beginning to jump past it), every time you called the routine it would find it much quicker:

19 GOTO 100
20 REM MY SUBROUTINE
30 PRINT "HELLO!"
40 RETURN
100 REM A REALLY BIG PROGRAM
...
150 GOSUB 20
...
995 END

Keep in mind, there are always tradeoffs. GOTO works the same way, and ant complex BASIC program is usually full of GOTOs. Every GOTO has to do the same scanning (forward, or starting at the top) to find the routine. This means each GOTO to an earlier line number now has to scan past all your subroutine lines every time you GOTO. For the fastest code, you need to take in to consideration what happens more often — GOSUBing to functions, or GOTOs to higher line numbers.

As to how significant the time savings can be, I plan to write another article in the near future with some simple benchmarks.

Here is Jim’s complete program, which uses my WRAPTEST code to process the same strings:

0 CLEAR200:DIMC1,CC,M$:GOTO10
1 C1=1:CC=WD
2 FORCC=CC TOC1+2STEP-1:IFMID$(M$,CC,1)<>""ANDMID$(M$,CC,1)<>" "THENNEXT
3 PRINTMID$(M$,C1,CC-C1):C1=CC+1:CC=C1+(WD-1):IFC1<=LEN(M$)THEN2
4 RETURN
10 CLS
30 INPUT"SCREEN WIDTH [32]";WD
40 IF WD=0 THEN WD=32
50 INPUT"UPPERCASE ([0]=NO, 1=YES)";UC
60 TIMER=0:TM=TIMER
70 PRINT "SHORT STRING:"
80 M$="This should not need to wrap.":GOSUB 1
90 PRINT "LONG STRING:"
100 M$="This is a string we want to word wrap. I wonder if I can make something that will wrap like I think it should?":GOSUB 1
110 PRINT "WORD > WIDTH:"
120 M$="123456789012345678901234567890123 THAT WAS TOO LONG TO FIT BUT THIS IS EVEN LONGER ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234 SO THERE.":GOSUB 1
130 PRINT"TIME TAKEN:"TIMER-TM
140 END
Jim Gerrie's CoCo tiny and fast word-wrap routine.
Jim Gerrie’s tiny and fast word-wrap routine for CoCo BASIC.

His routine is small and fast. It does not implement UC uppercase conversion, does not use the last character of the line, and has issues with words longer than the line length — but just look at the code size and speed savings! This is a great, efficient approach when you can control the output. As long as you aren’t displaying “supercalifragilisticexpialidocious” it works great.

However, Jim seems up to the challenge, and he made some small changes to allow his wrap routine to handle words longer than the screen width. Again, just four lines of code:

0 CLS:CLEAR255:DIMCC,C1,C2,M$:GOTO10
1 C1=1:CC=WD+1
2 CC=CC-1:ON-(MID$(M$,CC,1)<>""ANDMID$(M$,CC,1)<>" "ANDCC>C1)GOTO2:C2=CC-C1:IFCC=C1 THENC2=31:CC=C1+WD-2
3 PRINTMID$(M$,C1,C2):C1=CC+1:CC=C1+WD:ON-(C1<=LEN(M$))GOTO2:RETURN
10 CLS
30 INPUT"SCREEN WIDTH [32]";WD
40 IF WD=0 THEN WD=32
50 INPUT"UPPERCASE ([0]=NO, 1=YES)";UC
60 TIMER=0:TM=TIMER
70 PRINT "SHORT STRING:"
80 M$="This should not need to wrap.":GOSUB 1
90 PRINT "LONG STRING:"
100 M$="This is a string we want to word wrap. I wonder if I can make something that will wrap like I think it should?":GOSUB 1
110 PRINT "WORD > WIDTH:"
120 M$="123456789012345678901234567890123 THAT WAS TOO LONG TO FIT BUT THIS IS EVEN LONGER "
121 M$=M$+"ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234 SO THERE.":GOSUB 1
130 PRINT"TIME TAKEN:"TIMER-TM
140 END
Jim Gerrie's third version.
Jim Gerrie’s (v3) tiny and fast word-wrap routine for CoCo BASIC.

His new version, while still not using the last character of a line, now will break up words like supercalifragilisticexpialidocious. Because, you know, you have words like that in your text adventures all the time. And speaking of text adventures, he sent in this link to an archive of text adventures including many Jim (and his son) wrote. For many years he was using his original word wrap routine just fine (since he controlled the output) so all his additions are really just un-needed hoops to jump through for my abusing text case :)

Thanks, Jim, for sharing this with us! If anyone else wants to take a shot at it, feel free to send me a .DSK or .CAS image of your version. I have been using the XRoar emulator to do this testing (and take screen shots) on my Mac, and XRoar is also available for Windows, Linux and other systems.

Until next time, I hope things will be…

OK

…with you!

One thought on “Word wrap revisited…

  1. Pingback: A tale of two word wrap routines | Sub-Etha Software

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.