Showing posts with label Tandy. Show all posts
Showing posts with label Tandy. 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 

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, September 3, 2022

Programming Tandy/Radio Shack's MC-10 in Assembly Language

 What you were probably looking for is here:

https://joels-programming-fun.blogspot.com/2022/08/trs-mc-10-assembly-lang-pt1-vtl-2.html

This is where that rant originally resided, but the URL and the content didn't quite match, so I moved it. 

I will probably add links for more assembly language information for the MC-10 here later.

Sunday, August 28, 2022

Tandy/Radio Shack MC-10 Assembly Language, pt 1 -- Getting VTL-2 (Very Tiny Language) Running

Tandy/Radio Shack MC-10 Microcomputer
photo by Simon South, from Wikimedia,
licensed under GNU Free Documentation License

(This is part 4 of the VTL series.) 

The MC-10 is a very stripped-down computer based on the 6801 microprocessor and the 6847 video display generator that Tandy/Radio Shack produced in 1983, a couple of years too late and priced too high to compete in its target market, against the Commodore VIC-20 and the Timex/Sinclair ZX81. 

Yes, if Radio Shack management had recognized the market , they could have released essentially the same computer in 1981, maybe with a non-Microsoft BASIC. I think it would have been very competitive in 1981.

Part of the reason I find it interesting is that it is similar to Motorola's Micro Chroma 68 prototyping kit, which was my first computer back in 1981.

Anyway, I have been working over the last several weeks, on adding functionality to my assembler for the 6800/6801, asm68c, so that it can produce the .c10 format file that the MC-10 can read. That is in itself worth a post, but not now. My purpose in doing so was to make it possible to install VTL-2 (Very Tiny Language) and fig-Forth on the MC-10.

In order to get  either running on the MC-10, I need to arrange to get input from the keyboard and output to the display. In fact, pretty much anything you want to do beyond graphics is going to pretty much have you using the keyboard and the display.

Output to the raw display in assembler is actually not all that hard, and input from the raw keyboard is not particularly impossible, but especially the keyboard would require writing and debugging a lot of code. If the BASIC ROM provides routines I can use I might as well use them at this level of work.

Writing a simple set of BIOS class routines can be a project for a hypothetical 'nother day. Others have done something along this line, providing a more capable BASIC interpreter that doesn't get in the way of high resolution (for the 6847 controller) graphics and such.

I remembered that someone had posted information on using the BASIC ROM routines in the MC-10 group Facebook group, so I went hunting and found a disassembly file of the BASIC ROM that Simon Jonassen had posted, mc10.txt. And then Greg Dionne told me about a full assembly listing that is also available, MC10_ROM.txt.

In these files, I found a list of useful hooks into the ROM just under the interrupt vectors, starting at address $FFDC. The first two hooks are

FFDC | F8 83    POLCAT  fdb  KEYIN   ; read keyboard
FFDE | F9 C6    CHROUT  fdb  PUTCHR  ; console out

But that's not enough information to be confident I can use them.

You can go to the labels KEYIN and PUTCHR in the listing and find more complete descriptions. For PUTCHR, you find this (plus a bit more):

* Send character in ACCA to the current output device.

Likewise, for the KEYIN routine, you find this:

* Poll the keyboard for a key-down transition.
* Return ASCII/control code in ACCA or 0 if no key-down transitions.

It looks straightforward, but I have found there are often a lot of hidden assumptions behind such routines. It's usually wisest to test them with simple code before you go trying to wrap whole parsers and interpreters around them. 

And I was, for some reason, a little suspicious of the POLCAT routine -- too suspicious, maybe.

And that's the subject of this post.

My first attempt was pretty simple. Scan the keyboard, output the result, wait a while so I have time to see the results, repeat. Except that I put in code that adapted it to my source for VTL-2, which wants to use the B accumulator to get the characters in and out instead of the A accumulator:

*	INPUT ONE CHAR INTO B ACCUMULATOR
INCH	PSHA
	PSHX
	LDX	INCHV
	JSR	0,X
	PULX
	TAB
	PULA
	RTS
*
*	OUTPUT ONE CHAR 
OUTCH	PSHA
	PSHX
	LDX	OUTCHV
	TBA
	JSR	0,X
	PULX
	PULA
	RTS

Then I ran out of time. (I'm working on this in the evenings and on the weekends). 

And when I came back I had forgotten that the B accumulator shims were in there. 

Wasted a whole evening "discovering" that the BASIC ROM was actually using the B accumulator, in contradiction to all claims and appearances! And started planning this post to explain how I discovered this pseudo-fact. (Bleaugh!)

I suppose I could retrace my steps in those "discoveries". Outside of the fact that I was ignoring the shims that were right in front of my nose, I was actually using useful debugging techniques. But since the whole process was based on false assumptions, that would be confusing. And somebody might end up thinking those pseudo-facts were facts. So I won't. 

Instead, in this post, I'll walk through the tests as I should have done them. Or at least a few of the steps.

(And, again, I ran out of time. Too many distractions. I hope I can remember what I was doing next time I pick this up.)

Okay, so I tried this, somewhere along the line:

	OPT	6801
	ORG	$4C00

* MC-10 BASIC ROM vectors
POLCATV	EQU	$FFDC	; Scan keyboard	
CHROUTV	EQU	$FFDE	; Write char to screen


TEST	LDX	POLCATV
	JSR	0,X	; scan
	TSTA		; 0 means no key pressed
	BEQ	TEST	; That's going to play Hobb with CTL-@.
	LDX	CHROUTV
	JSR	0,X	; print to screen and advance
*	CLRB
*	CLRA
*LOOOP	SUBD	#1	; wait a sizeable fraction of a second
*	BNE	LOOOP
	BRA	TEST	; get more
*
	ORG TEST    

You'll notice that I also tried a wait loop, which is now commented out. Without the wait loop, it sits there and waits for me to hit a key and then outputs it at the current location on the screen. 

With a little more code and testing, I was able to convince myself that it does what the programmer who wrote the comments considered polling (although it isn't what I consider polling) and I figured out how to work the interface:

* MC-10 BASIC ROM vectors
INCHV	EQU	$FFDC	; Scan keyboard	
OUTCHV	EQU	$FFDE	; Write char to screen
*
*	RECEIVER POLLING
POLCAT	PSHA
	PSHX
	LDX	INCHV	; at any rate, don't wait.
	JSR	0,X	; 
	TAB		; MC-10 ROM says NUL is not input.
	SEC
	BNE	POLCATR	; Don't wait.
	CLC
POLCATR	PULX
	PULA
	RTS
*POLCAT	LDAB	ACIACS
*	ASRB
*	RTS
*
*	INPUT ONE CHAR INTO B ACCUMULATOR
INCH	BSR	POLCAT
	INC	$400F	; DBG
	BCC	INCH	; Wait here.
	INC	$4010	; DBG
	STAB	$4011	; DBG
	RTS
*
*	OUTPUT ONE CHAR 
OUTCH	PSHA
	PSHX
	LDX	OUTCHV
	TBA
	JSR	0,X
	PULX
	PULA
	RTS

But when I tried to load VTL-2 with this (CLOADM), BASIC gave me I/O errors. And I noticed that the output object was relatively huge. 

And I remembered that the ORG and the RMBs that set up the direct page variables will cause the .c10 file to include object where there is no memory on the MC-10 -- in the range from $0100 to $4000. Trying to CLOADM binary code where there is no memory will cause I/O errors from BASIC. 

So I decided, as a quick fix, to change the direct page declarations to EQUs instead of RMBs:

* 	ORG	$C0	; Move this according to your environment's needs.
DPBASE	EQU	$C0	; Change this to move the registers.
* PARSET	RMB	2	; Instead of SAVE0 in TERM/NXTRM
PARSET	EQU	DPBASE+2
* CVTSUM	RMB	2	; Instead of SAVE1 in CBLOOP
CVTSUM	EQU	PARSET+2
* MLDVCT	EQU	CVTSUM	; Instead of SAVE1 in mul/div (1 byte only)
MLDVCT	EQU	CVTSUM
* DIVQUO	RMB	2	; Instead of SAVE2 in DIV
DIVQUO	EQU	MLDVCT+2
* MPLIER	EQU	DIVQUO	; Instead of SAVE2 in MULTIP
MPLIER	EQU	DIVQUO
* EVALPT	RMB	2	; Instead of SAVE3
EVALPT	EQU	MPLIER+2
* CNVPTR	RMB	2	; Instead of SAVE4
CNVPTR	EQU	EVALPT+2
* VARADR	RMB	2	; Instead of SAVE6
VARADR	EQU	CNVPTR+2
* OPRLIN	RMB	2	; Instead of SAVE7
OPRLIN	EQU	VARADR+2
* EDTLIN	RMB	2	; Instead of SAVE8
EDTLIN	EQU	OPRLIN+2
* INSPTR	RMB	2	; Instead of SAVE10 (maybe? Will some VTL programs want it back?)
INSPTR	EQU	EDTLIN+2
* SAVLIN	RMB	2	; Instead of SAVE11
SAVLIN	EQU	INSPTR+2
* SRC	RMB	2	; For copy routine
SRC	EQU	SAVLIN+2
* DST	RMB	2	; ditto
DST	EQU	SRC+2
STKMRK	EQU	DST+2	; to restore the stack on each pass.
DPALLOC	EQU	STKMRK+2	; total storage declared in the direct page

That's a little tiresome work, adding the previous label plus two in place of all the RMBs, but it does the job.

(I think I'm going to regret doing it this way, later.)

That loaded, but then when I tried to EXEC it, it just went away and didn't come back.

After some thought, I decided to use the BASIC stack instead of making a private stack for VTL-2. I'll need to check that it really is enough stack, but I thought that was the first thing to try, and that's what the second-to-last line there defining STKMRK is for. (Okay, that's two steps in one I'm showing.) 

The interpreter wants to reset the stack each time through, so it needs something to reset the stack to, and that is why I'll save the BASIC stack position to STKMRK on entry from the COLD label.

And that worked well enough to give me a cursor. But what I typed at the keyboard did not show on the screen. 

So I added some debugging assembly language equivalent of POKEs to the screen. With the right debugging output to screen 

(see the source of a later step at https://osdn.net/users/reiisi/pastebin/8573, the lines with DBG in the comments),

I was able to see that the commands were actually going in, and that they were being recognized, because I was able to get good output from typing 

?=*

even though the command itself did not show on the screen. And that quickly led to recognizing that the MC-10 does not echo what you type until after BASIC parses it. So I needed to decide where to add code to echo the input. The EXORsim code simply assumes that INCH will echo for me, so I decided to follow that approach and just add an output JSR in the INCH routine. Should work.

Let's publish this rant-in-progress to my blog while I see if it works.

And, it did. 

Okay, now the echo works. And I added what I thought would store the stack pointer in the Z variable so I could examine it, but I did it like this:

START
*	LDS	#STACK	; re-initialize at beginning of each evaluate
	LDS	STKMRK	; from mark instead of constant
	STS	VARS+25 ; DBG so we can get a look at the stack pointer BASIC gives us.

That should have been VARS+25*2. So, instead of in Z, it shows up spread across L and M, which is an eye-crosser to read. That's easy to fix. And I should remove the other DBG lines before I forget.

Now I can see where the stack is when BASIC passes control to VTL-2.

Why should I worry?

The last byte assembled by the above source is at $4F67. The end of memory for a 4K MC-10 is $4FFF. I think that should be enough space between the code and what BASIC is using at the end of RAM, but putting that stack pointer somewhere I can see it helps me figure if it really is enough.

But checking the memory bounds variables shows that my memory probe code is not working right. & is set right, but * ends up with the probe having not run at all. Still, if I overwrite the * variable with 19456 ($4C00), I can enter a simple program, list it, and run it.

Hmm. It looks like I have the branch upside down in the probe somehow. How did I have that working before? Did I? 

[Sort of. But, yes, the test is upside down. I am embarrassed. More below when I get it fixed. It's lousy, still having to work a day job instead of devoting full time to playing games like this.]

Somewhat of success, but I think that's all I have time for tonight. (What day was this?)

Picking this back up on the 3rd of September, I'll give you the summary version of what happened with the probe test that was upside down. Yes, this is embarrassing.

You know how I got all enthusiastic about the improved CPX in my explanation of the software differences between the 6800 and the 6801? Well, when I was adapting Joe H. Allen's simulator, I forgot to make sure the carry flag got set in the CPX emulation routine when running as a 6801. Probably also failed to set the other flags right. So, in my initial successful code for EXORsim running a 6801 core, I had the test inverted.

So I had to go back and fix that in EXORsim6801, and test it a little, and move things around a bit in my blogs and OSDN stuff, and that's where I've been for three weeks or however long it took.

I should describe how to get this stuff running on the Xroar MC-10 emulator at this point, I think. Get the source from the pastebuffer in my OSDN pages:

https://osdn.net/users/reiisi/pastebin/8607 (But see notes for 20220904 and 20220911 below.)

Assemble with the switch to output the .c10 file. The command line

asm68c -l2 -c10 VTL_6801_mc10.asm

should give you the listing to the screen so you can check for errors. Or you can redirect the listing to a file 

asm68c -l2 -c10 VTL_6801_mc10.asm > VTL_6801_mc10.list

and pull the listing file up in a text editor. 

Run Xroar with the command line

xroar -machine mc10

You may need to add some to the configuration file to get that to work, I don't remember. (I put an ampersand on the end to tell the bash shell to run it concurrently with the terminal session, so I don't have to open another terminal.)

Selecting the tool menu will allow you to select keyboard translation, which I need (with my Japanese keyboard), and, more importantly, open up the tape control:

Click the insert button in the tape control dialogue and select the file VTL_6801_mc10.c10 (assuming you've given the assembler file the same name as I show above).

Now click the emulator window to make it active again, and type in the CLOADM command.

Go back to the tape control dialogue and hit the play button, and the MC-10 emulator should load the virtual tape for something like twenty virtual seconds (virtual seconds! Goes by very quickly, less than a real second.) and then tell you it got it. Below the file name, type in the EXEC command with no start address.

I'm not sure whether the CLOADM command in the stock MC-10 BASIC allows specifying a load address. Nor am I sure whether the EXEC command allows specifying an execute address. But the lowest ORG directive in the assembler file sets the load address for the C10 file. And the ORG directive at the end of the assembler file sets the starting address in the S-record output, with the C10 output setting the same starting address. So you don't need to tell BASIC where to load or where to execute.

Anyway, entering the EXEC command should give you an OK prompt and a cursor without a cursor, and you may think nothing happened until you try typing something. 

[202209111413 add:]

No cursor in the source I have up. Adding a cursor is pretty simple if you look through the listing of BASIC A flashing cursor takes a little more thought and effort. I'll leave that as an exercise for the reader, since I want to move ahead to the 6809 transliteration.

[202209111413 add end.]

VTL doesn't give many error messages, it mostly just doesn't do anything it doesn't understand. So if you type "ZZ" and hit enter, rather than a cryptic BASIC error message, you just get another OK and more cursor:


Test it by typing in a math expression, like 

?= 1+1*2

The ?= is like BASIC's PRINT comman. But you'll quickly notice that VTL's calculator parsing is not the algebraic infix you learned in school and get from BASIC. When you need to alter the left-to-right parsing, use parenthesis:

?= 1+(1*2)

The ampersand variable & tells you where in memory your program will get stored. It's kind of the bottom of currently available memory. (Kind of.) 

The asterisk variable * tells you what the highest available address for VTL programs is. (The way I've set it up, it's the byte before the VTL interpreter itself starts.)

Both the & and the * are supposed to be set by hand in the original VTL-2, but I had to move so much around that it just made more sense to have the interpreter probe and set them for you.

I did check whether it should run in a 4K MC-10.

xroar -machine mc10 -ram 4K &

With that, VTL-2 returns these values for the beginning and end of the programming area, and I ended up putting the BASIC stack pointer marker in the semicolon variable:

  • ?=&
    17416
  • ?=*
    19455
  • ?=;
    20375

That's 

  • $4408 begining of VTL programming area
  • $4BFF end of VTL programming area
  • $4F97 BASIC stack mark

The last address assembled in the code as it stands now is $4F67. So you have $4F98-$4F68 or $30 (decimal 48) bytes of stack space before the stack overwrites the return from OUTCH, and VTL crashes. That should be enough, especially for programs that fit in the very small programming area.

It's plenty to run a short test program:

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

If you want to give VTL-2 more room to work, you can set the ORG before COLD to the highest address your memory configuration allows, about one or two kilobytes less than your end of memory. And that should be the only thing you have to change, if I did my job right in the source.

Uh, yeah. The object image for VTL is less than a kilobyte. Just so you know. Just so you're prepared for the limits.

This is not thoroughly tested, and has some known problems -- like random number generation is not quite functional.

[202209041331: add (more embarrassment!)]

I made a bad optimization to the random function in the above, and in the EXORciser versions. Don't know how I missed this one, either. Blame it on my age?

At the label AR2 in the source code, I falsely corrected, without thinking, the addition of the low byte to the high, and vice-versa. My false correction looks like this:

AR2	STD	0,X	; STORE NEW VALUE
	ADDD	QUITE	; RANDOMIZER
	STD	QUITE
	RTS

Looks reasonable, right? As long as you ignore the comment about randomizer?

Well, here's what it looked like in the original 6800 code:

AR2	STAA	0,X	; STORE NEW VALUE
	STAB	1,X
	ADDB	QUITE	; RANDOMIZER
	ADCA	QUITE+1
	STAA	QUITE
	STAB	QUITE+1
	RTS

 See what was going on? 

Well, I probably should fix the pastebuffer, but OSDN won't let me today. Maybe I have too many. But I don't want to publish this code in a repository without some explicit permission from the authors. Anyway, the fix I recommend is below, with a couple of lines of code to detect lack of initialization and semi-auto initialize it:

AR2	STD	0,X	; STORE NEW VALUE
	BNE	AR2RND	; Initialize/don't get stuck on zero.
	INCB		; Keep it known cheap.
*	ADDD	QUITE	; RANDOMIZER	; NO! Don't do this.
AR2RND	ADDB	QUITE	; RANDOMIZER	; Adding the low byte to the high byte
	ADCA	QUITE+1	;		; is cheap but intentional.
	STD	QUITE
	RTS

Just search the code for "RANDOMIZER", cut the bad code out, and paste in the fix. Or, better yet, edit it with your own, improved random function.

Initialization -- yeah, this is another place where the original code left initialization out to keep the code tiny.

[202209041331: add end]

[2022091112291333: add] 

While transliterating for the 6809, I discovered that I missed some more opportunities to optimize for the 6801.

If you look for the label 

SUBTR    SUBD    0,X

you'll notice that, in the 6800 source, it was a very short routine to subtract whatever X pointed to from D. Every call to SUBTR can be replaced with the actual body of the subroutine in the 6801 source, with no increase of code size. You can search for BSR SUBTR and JSR SUBTR and replace each with SUBD 0,X. (I don't think there will be any JSR SUBTR, but if there are, you can replace that, two, for a byte of code saved.)

Really wish I had more time after work to focus on this stuff.

[2022091112291333: add end]

[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/

[JMR202210011737: add end]