Showing posts with label Color Computer. Show all posts
Showing posts with label Color Computer. Show all posts

Sunday, April 26, 2026

Which Is More Compact on the Tandy Color Computer -- Machine Code or BASIC?

A perennial question on one of the Tandy/Radio Shack Color Computer FaceBook groups:

Is machine code or BASIC more compact?

The answer is not simple, so I'm going to blog it.

The first question is, which BASIC?

BASIC compilers convert the BASIC program source to machine code (or assembly language, which is pretty much functionally equivalent to machine code). So comparing the compactness of BASIC compilers to machine code is basically just analyzing the ability of the compiler to produce efficient code.

Some BASIC interpreters directly interpret from the program text. This tends not to be very compact, since you're the program is just the text stored. But it may well be more compact than the machine code produced by a simplistic compiler or a programmer who isn't very fluent in the processor and its machine/assembly language.

Other BASIC interpreters parse the source text and compile it to high-level byte codes defined by the interpreter, storing the stream of byte codes, usually with the comments. Whether the stored byte-code stream is compact or not depends to a large extent on how well the byte code is designed.

Compared to most CPU machine codes, the byte-code streams can be rather compact.

But the comments that get stored with the byte-code streams can result in a stored program that is not compact. In fact, the better the comments, the fatter the stored program.

But there's more! (heh)

The 6809 in the Tandy/Radio Shack Color Computer has a very advanced machine code which is essentially equivalent in expressiveness to a well-designed byte code.

So 6809 machine code tends to be compact.

Aaaand the BASIC interpreter in the Color Computer is one of Microsoft's. Microsoft developed a method of mechanically projecting their 8080 BASIC on other CPU architectures, which resulted in quickly done implementations that basically ignored many of the special features of other processors and wasted a lot of code and cycles emulating the BASIC run-time that Bill and Paul hacked together for the 8080.

So, even though the BASIC in the Color Computer is a byte-code interpreter, it's not necessarily all that compact. 

So the general conclusion is that you really don't want to ask the question. Just learn both as tools.

But, there's MORE!

The Color Computer does not have a separate BIOS like the IBM PC 5150 does.

It has some routines that can be used more-or-less independently of BASIC, specifically the Input Character and Output Character routines. If you have DOS Extended Basic plugged in (via the floppy controller cartridge), the disk input and output routines can also be used, with some care, somewhat independently from BASIC.

That's code that you don't have to write yourself, and it (usually) exists in ROM in the Color Computers 1 & 2, and doesn't take up space in RAM.

That's not compact code, but it might save space.

If you are willing to let BASIC do a lot of the lifting, you can mix machine language code with BASIC code by reserving space for it via BASIC commands and reading the machine language code in from data statements, or reading the machine language parts in from disk or tape.

If you don't co-exist with BASIC, you have to write your own fundamental (especially, I/O) routines and include them with your programs -- unless you target the OS-9/6809 operating system (or the community rewrite of OS-9/6809, NitrOS-9), or Flex09, or one of the other operating systems available for the 6809.

And all the code you write yourself takes up space.

Really, targeting OS-9/6809 is probably the better idea, but I don't want to take the time to take that topic up in this post.

Bits of stuff you may want to know relative to this question, BASIC takes up 8K to 24K in the upper half of the 6809's 64K address space in the Color Computers 1 & 2. Your BASIC program and your machine code will have to share the lower 32K, or as much as is physically installed -- except for in the 64K mode, which I will explain a little bit after explaining what I just said.

  • Color BASIC lives in 8K of ROM inside the computer, in the upper half of the address space -- so it can boot the computer up on power on. Color BASIC is the boot ROM.

  • Extended Color BASIC (ECB) is obtained by adding an 8K extension ROM internally. (Or, in some later models that come with ECB installed, there is only one 16K ROM.) The 8K of ECB extensions exist just below the boot ROM.

  • Disk Extended Color BASIC (DECB) adds another 8K of ROM in the controller ROMpack, as I mentioned above. The ROM for DECB, when the floppy disk controller pack is installed, exists just above the boot ROM.

It looks like this:

(Double apologies for having incorrect order in the description above and an incorrect table here for the first couple of hours live, and till having the positions of the ROMs swapped above and below, for the first week this was live. The described position of the interrupt vectors in the boot ROM was also 8K too low. Guess I've been working too hard.) 

65504~65535reserved, and interrupt vectors
65280~65503I/O, control
57344~65279(gap)
49152~57343DECB ROM (if present)
40960~49151Color BASIC/Boot/interrupt code
32768~40959ECB (if present)
0~32767RAM

(For those wondering, the addressing circuitry ghosts the top 32 bytes of the boot ROM {from 49120 to 49151} up 16K {up to 65504 to 65535} so that the vectors in the ROM that starts at 40960 can be read in response to interrupts.) 

The boot process points the video controller somewhere in the RAM, and 512 bytes (one quarter kilobyte) is used for the video buffer (text mode). BASIC reserves some of the RAM for strings and variables and some for storing code, does some other initialization, and shows you the copyright notice and OK prompt.

You can check how much physical RAM is installed by using the BASIC PRINT command, printing the value of the MEM pseudo-variable right after power-on:

PRINT MEM

What it should show you for various sizes of physical RAM installed:

  • 4K RAM: PRINT MEM shows less than 4K, around 2K after boot, in Color BASIC only. ECB and DECB will not boot in 4K of RAM.

  • 16K RAM: PRINT MEM shows between 4K and 16K, close to 16K for Color BASIC, a bit more than 8K for ECB, and a bit more than 6K for DECB.

  • 32K RAM: PRINT MEM shows between 16K and 32K, close to 31K for Color BASIC, a bit over 24K for ECB, and a bit over 22K for DECB. 

These reservations of RAM can be adjusted by BASIC commands in your program (or just at the keyboard, when you're testing things).

Use the FILES command to adjust the number of file buffers.

Use the CLEAR command to specify how much string variable/space you want, and what you want BASIC to respect as the top of RAM. For instance, if you want 2000 bytes for variables and strings, and you want to put your machine language routines at 30000 and above, use

CLEAR 2000, 30000

(That's assuming you have 32K RAM or more.)

PRINT MEM after that, and you should get just over 18K, which BASIC will use to store the program in.

(I think that's the way it worked.)

Now, if you want to leave BASIC completely behind, using your own I/O routines and all, you don't really have to care how much memory BASIC thinks is left over. You only have to pay attention to where the video buffer is. But then you have to include your own I/O routines with the code, and they do take space (and time to write).

(But you also need to pay attention to the interrupt time operations of the machine.) 

You can get information on how to determine where the video buffer is and such from EDTASM+ or DISK EDTASM manuals and other sources.

Now, I mentioned the 64K RAM mode. You can install 64K of RAM in a Color Computer 1 or 2 (with some physical modifications on the mainboard, instructions are available in various places if yours doesn't have the expansions already installed). But Microsoft's BASIC will only use 32K of it.

How you get access to the full 64K is to use OS-9/6809 -- or NitrOS-9. And leave Microsoft BASIC behind. 

:)

Or, you can load a (machine language) routine to hit the Page Switch bit to map the physically high half of RAM low, copy the ROMs to the RAM, flip the page switch back so that the code from the ROMs is in place for the next interrupt, and you're in business, running the ROM code out of RAM.

Unfortunately, Microsoft BASIC still doesn't want to let you set the limit to BASIC above (a hundred bytes or so below) 32K. But you do end up with some RAM in the upper half that can be used for machine code.

There are patches, modified BASICs and 3rd party BASICs that let you get around the 32K limit, finding them is an exercise for the reader.

Then there is the Color Computer 3. The smallest RAM configuration for the Color Computer 3 is 128K. That's bigger than the 6809 can address by itself, of course. The Color Computer 3 has a replacement for the SAM (and VDG) called the GIME, which provides the means of bank switching the RAM around in 8K chunks, and that's how it can access more memory.

The Color Computer 3 boots from the ROMs, copies the ROM to RAM, and still leaves you with only 32K for BASIC. Except that the new version of BASIC provides for wider text screens, higher resolutions, and more colors, managing the video memory for you. All of this uses the expanded memory, and leaves the conventional memory available for your program. So it's definitely worth the upgrade.

On the other hand, OS-9/6809 level 2 or NitrOS-9 will take care of the bank switching for you, if you use that, letting you use more of the expanded RAM space for your own code. 

Other OSses that will take advantage of the banks switching for you -- I believe UniFlex can, and Fuzix should be able to, as well. 

Or you can write your own, for fun. :) 

I really should do a more complete version of this post, I suppose, with diagrams and coding examples, and an explanation of how to run OS-9 and NitrOS-9 and maybe some of the others, but I really don't feel like I can afford the time this week or next. I have to take care of some government paperwork.

So, the conclusion --

If you are needing to squeeze functionality into a tight space, the question isn't really machine code vs. BASIC. 

It's figuring out what you want to do with which -- and the fun in doing that is why you are doing retro in the first place, isn't it?

And then when you've had fun with the BASIC environment, figuring out when you want to leave it behind for a more complete OS, and which path forward. 

Monday, September 19, 2022

VTL-2 part 5, Transliterating to 6809

 

Tandy/Radio Shack TRS-80 Color Computer 1
16K Color Computer 1
by Wikimedia contributor Bilby,
licensed under CC BY 3.0
via Wikimedia Commons

Well, the transliteration of the MC-10 version of VTL-2 in 6801 assembler to 6809 assembler on the Tandy Color Computer actually went pretty quickly once I made time, using the relationships between the 6800/6801 assembly language and runtime and the 6809 assembly language and runtime that I describe in my post on the software differences between the three CPUs. 

But then I found myself using the assembly language equivalent of poking telltales to the screen to figure out where I'd fallen asleep at the wheel.

There was only one place, really, where I had inverted the transfer from B to A in the character output routine, or was it from A to B in the keyboard input? Something like that.

And it handled basic expressions, but wandered off in the ether any time I tried to type in a program. After going back over the transliteration with a fine-toothed comb and finding nothing (and falling asleep doing it) for several days in a row, then using more telltales to the screen to pinpoint where it was dying, I decided to look back in the commented disassembly of Color Computer extended BASIC. 

It was only a matter of a half an hour to finding the problem.

Color Computer BASIC uses a number of variables in the direct page. 

I had dodged a few of the variables down around $C0 by starting the direct page variables at $D0. But there is a variable at $E2 used by the IRQ handler routine as a counter, and by starting there I was using $E2 as the SAVLIN variable, which is essentially the most used variable during program editing.

But $00E2 is the place where the CoCo BASIC IRQ response return was counting screen refresh interrupts (60 times a second).

So I moved everything down to start at $C4, just after the PIA mask variable, and the variable list ended right before $E2. 

So I didn't have to move any variables, and I didn't have to optimize the copy routines to be sensible and use X and Y together instead of X and the SRC and DEST variables in the DP.

And I can type in the test program I've been using:

10 A=0 20 A=A+1 30 ?=A 40 ?="" 50 #=(A<11)*20 60 ?="DONE"

and list it by typing 

0 

and hitting Enter. And I can run it by typing 

#=1 

and hitting Enter.

The source code is at https://osdn.net/users/reiisi/pastebin/8705. Copy or download it from there. 

If you want to assemble it to run in 32K, fix the ORG before COLD. It needs less than 1K of RAM for the code. With another 1K to the end of RAM for the BASIC stack it borrows and as a buffer between BASIC and VTL-2, set the ORG at 2K  before the end of RAM.

You'll need LWTools to assemble it -- either download it or use mercurial or git to clone it, then compile it and copy the executables into your preferred place for user-local executables. 

Then use the following command line or something similar to assemble the source:

lwasm --list --symbols -f decb -o VTL_6809_coco_translit.bin VTL_6809_coco_translit.asm

This will give you a .bin file that XRoar can load from XRoar's File menu. (Sometime I'll put a screenshots here. Until then, refer to the MC-10 post.) 

Run XRoar with the command line with

xroar -machine coco -ram 16k &

for a 16K RAM Color Computer configuration. It will look a lot like what I show of XRoar running the MC-10 emulation in the MC-10 post.

If you load it from the .bin file, you'll need to type

EXEC &h3800

at the BASIC prompt to get VTL-2 running after loading it.

Another way to load it is to convert it to a .cas format and load it from the Tape Control dialog, as I described for the MC-10. You can convert the .bin file to a .cas file with a command like 

bin2cas.pl -o VTL-2.CAS -C -l 0x3800 -e 0x3800 VTL_6809_coco_translit.bin

To get the bin2cas.pl tool, look for it under CAS Tools on the the dragon page on 6809.org: 

https://www.6809.org.uk/dragon/
If you specify the load and execute addresses in the bin2cas command line as above, you'll need to type 

CLOAD
EXEC

at the Color Computer BASIC prompt.

You should be able to modify this source code to run on other 6809 computers with a little thought, especially if you walk through my posts on getting the 6800 and 6801 source running on the MC-10 and on EXORsim.

You should also find some interesting challenges left for the interested reader, such as modifying it to use the Y register in the edit routines, and to work with the DP moved out of BASIC's working area. Such things as that.

I think I'm off to other interesting projects now.

(Maybe. Not sure whether I want to go back and see if I can get fig-Forth running right on the 6809 first or whether I want to try my hand at writing my own VTL source, or a VTL-like language of my own design, etc. Or go back to trying to work on novels for a while. I probably need to get XRoar set up for GNU-debugging before anything else.)

[JMR202209231810: add]

I have written up a post on VTL expressions, here: https://joels-programming-fun.blogspot.com/2022/09/short-description-vtl-2-expressions-very-tiny-language-p1.html , which will help in testing and otherwise making use of the language. I should also shortly have a post up introducing programming in VTL-2.

JMR202209231810: add end]

[JMR202210011737: add]

I now have my work on VTL-2 up in a private repository:

https://osdn.net/users/reiisi/pf/nsvtl/wiki/FrontPage

There is a downloadable version of VTL-2 for the Tandy MC-10 (6801) in the stock 4K RAM configuration in there, with source, executable as a .c10 file, and assembly listing for reference. Look for it in the directory mc10:

https://osdn.net/users/reiisi/pf/nsvtl/files/

I haven't wrapped it up for the Color Computer yet, expect that later. But you can see the latest source I'm working on for the Color Computer in the source tree:

https://osdn.net/users/reiisi/pf/nsvtl/scm/tree/master/

[JMR202210011737: add end]

 

Saturday, April 20, 2019

Q&D Prime Sieve in Color Computer BASIC?

Okay. So the post on writing a C program to check the time required to count N primes wasn't my best offering on the subject of primes.

This will be even more bizarre, although closer in spirit to the post in the Vintage {computers | microprocessors | microcontrollers } FB group on a Fortran program for counting primes.

Let's count primes less than 256 in Tandy/Radio Shack Extended Color Computer BASIC!





1 REM A PROGRAM TO COUNT PRIMES IN COLOR COMPUTER BASIC
2 REM JOEL MATTHEW REES, APRIL 2019, AMAGASAKI, JAPAN
3 REM COPYRIGHT 2019, JOEL MATTHEW REES
4 REM MAY BE FREELY USED FOR NON-COMMERCIAL PURPOSES.
10 MAX=25520 DIM PRIMES(MAX)
30 FINAL = MAX/2
40 PRIMES(0)=0
50 PRIMES(1)=0
60 FOR I=2 TO MAX: PRIMES(I)=1: NEXT
70 FOR I=2 TO FINAL
80 FOR J=I+I TO MAX STEP I
90 PRIMES(J)=0
100 NEXT J
110 NEXT I
115 COUNT=0
120 FOR I=0 TO MAX
130 PRINT I;" IS ";
140 IF PRIMES(I)=0 THEN PRINT "NOT "; ELSE COUNT=COUNT+1
150 PRINT "PRIME."
160 NEXT I
170 PRINT COUNT;" PRIMES LESS THAN "; MAX; "."



(This is essentially the same algorithm as in this post on a small sieve, which also points to some implementations of the same in Ada and Forth.)

(You can download this as a file on my OSDN Japan account, here. I was not successful in using imgtool to put it back in a DECB disk, however.)

And let's see how long it takes. (Counting seconds in my head.)


Constructing the sieve itself takes about ten seconds, printing the sieve (Not very meaningful when the list mostly ends up scrolling off the screen.) takes another nine.

54 primes less than 255. Yep. That other program says the same.

255 numbers in 10 seconds is about 25 numbers per second, average, although average here does not mean what it seems to mean.

Now this program is very easy to modify to count the first thousand or more primes up to something like 15,000 on a 32K Coco.

First, check your RAM:

    PRINT MEM


 If it says something over 22,000, there should be plenty of room. Let's try 8,192, a nice round number. Edit line 10:

    EDIT 10
    10 MAX=8192
    RUN



Woops!

Byte arrays in BASIC aren't done that way. In fact, they aren't hardly done at all. We would have to go get BASIC09 to do byte arrays in a BASIC on the Color Computer, I think. (Or we could do it in BIF. Or assembler.)

(Would be faster. Maybe I need an excuse to fire up OS-9. Not Mac OS-9, Microware OS-9, which well predated the Macintosh itself. Tandy/Radio Shack missed serious opportunies on that. Tandy's stupid mistake of not letting the company's products compete with each other, as if there were only one prize to be won. Making money linear is the best way to lose. Put down the mike, I know, I know.)

Let's try again with only 1,024.


About 45 seconds to calculate the sieve, and another 35 to scroll the list off the screen. 


Says 172 primes less than 1024. That checks with that other program, too.

Checking 1024 numbers in 45 seconds averages 1024/45 numbers per second, or about 23 per second, which seems nearly linear to the earlier time.

And it looks like we have some memory left. In fact, it looks like our array only costs about 4 bytes per integer, which means we should easily be able to get away with 4,096. And time may be linear.


But I'm going to use the clock instead of counting for more than 3 minutes.

Expect, if the time is no better than linear, something like 4096/23, or 178 seconds, about three minutes.

Executing it. Yep. About three minutes to calculate.

Why should the time be nearly linear? The print loop is just a single loop, not nested, no branching. That makes sense.

But the sieve itself is nested, scanning the array and blocking out non-primes once for each prime it sees. But, first, the scan is only from the prime's double, skipping by the prime, so the later loops become really quick. And the loop ignores scanning on the non-primes, because those have all been picked up by the first loops. So the scans really don't take nearly as much time as we might think.

The scans after initialization will be half the count of the initialization, then a third, then a fifth, then a seventh, ...

Printing takes a rather long time. But that's always true. Almost three minutes to print the count.


564 primes less than 4,096. Check that? Yep. That other program agrees.

If we could extrapolate to 100,000,000 (which we can't, at least not this way), we would expect the Color Computer to take (100000000/23)/(60*60*24) days, or about 50 days. But the Color Computer would need about 500 megabytes of RAM, quite possible on modern desktop computers with multiple gigabytes of RAM, but not on the Color Computer.

Maybe a sieve array that big could be simulated on hard disk, but that would incur more time costs.

Left over memory with just 4,096 entries -- 1,850. If we want to do more on a Coco, we need a more sophisticated method.

Also, since the list scrolls off the screen, it would make sense to, instead of printing the list, write a loop that would allow the user to type in a beginning and ending number and list primes between the two numbers.

Those are left as exercises for the reader, for now. (There is a way to check whether a number is prime after this program ends. Do you know how?)