Friday, October 14, 2022

Part 1g: fixing Tiny BASIC and creating the relocated ROMs

It turns out that I'm not the only one who has had the problem with the odd extra characters at the start of each line. Others who have built clones of the ETA-3400 or even those with original units connected up to a PC serial port have seen this odd behavior. While the problem is not evident in the Fantom II monitor, it is certainly annoying in Tiny BASIC.

Apparently the problems come from the terminal program using 8 bit data while the Fantom II monitor only uses the first 7 bits. Unfortunately Tiny BASIC gets upset with all 8 bits and this causes the 8th bit to be displayed as some other character in VT100 mode. This can be fixed in some cases by changing the settings in the terminal application. However I'm using a dedicated VT100 clone and I am unable to change the data to 7 bits, at least in my current firmware.

I should point out that the original ETA-3400 was meant to be connected to a Heathkit H19 serial terminal, and I'm using a VT100 clone. However others are also using VT100 terminal applications on their PCs so it's fixable.

What I had to do was clip off the 8th bit by patching Tiny BASIC output routine as follows:

Original code:

*------------------------------------------------------------------------------
                         * emit a character in A
                         *-----------------------------------------------------
2098 7c 00 bf        emit_char:     inc     column_cnt   * advance to column 1
209b 2b 0a                          bmi     loc_5A7      * if at column 128, stop emit
209d df ba                          stx     X_save       * save X
209f 37                             pshb                 * save B
20a0 bd 1c 09                       jsr     OUT_V        * emit character
20a3 33                             pulb                 * restore B
20a4 de ba                          ldx     X_save       * restore X
20a6 39                             rts                  * done

Patched code:

*------------------------------------------------------------------------------
                         * emit a character in A
                         *-----------------------------------------------------
                        ; alternate routine for VT-100 terminal
2098   7c 00 bf      emit_char:     inc     column_cnt   ;* advance to column 1
209b   2b 0a                        bmi     loc_5A7      ;* if at column 128, stop emit
209d   36                           psha     ;* save char
209e   84 7f                        anda #%01111111      ;* clear bit 7
20a0   bd 1c 09                     jsr     OUT_V        ;* emit character
20a3   32                           pula                 ;* restore char
20a4   01                           nop          ;fill to maintain original monitor
20a5   01                        nop     
20a6   39                           rts                  ;* done

I'm not saving the x-reg before jsr OUT_V because it isn't used in OUT_V anyway. that saved me enough bytes to squeeze in the instruction to mask out the 8th bit. Also on entry to the routine a-reg and b-reg are the same. Since the b-reg is also not used in OUT_V then we can just use the a-reg and save extra bytes. The 8th bit is only masked to send to the output routine, then it's restored to what it was originally, which might have it's 8th bit set. I have to fill the remaining code with nop's so the next instruction at $20a7 stays in the same location.

this is the OUT_V routine:

                        * print a character in A to output device
1c09 7e 18 65           OUT_V:          jmp    Mon_Write_Char

And the Mon_Write_Char routine is in the Fantom II monitor section of the code. There is no jsr to Mon_Write_Char because it has one at the end one instead. This saves bytes.

There are other patches needed when the ROMs are relocated to high memory, but the patch we've just done fixes the 8 bit random character issue.

I typed in a few Tiny BASIC programs to make sure everything is working and it seems to be OK. Pretty quickly though I want to type in a bigger program and since I have no tape interface I have no way to save and reload programs. Typing in even a small program becomes tedious pretty quickly.

Now I build the tape interface on another pre-ethed pcb from Jaycar and add it to the PIA. 

It looks very ugly but it's just temporary until I get things working, then I can get some pcb's made.


On the left hand end is two RCA sockets for cassette input and output.

The cassette port mainly consists of the comparator and several resistors and capacitors. There is two output levels to choose from, 500mV and 50mV. I just use a fly-lead to pick which level I want since I don't know which one will work with my cassette.

And since I don't have any working cassette drives, I have been waiting to see if my Digital mp3 cassette voice recorder will do the job. It's a whopping 2GB. Each file is saved separately and they can be transferred by USB to a PC as an .mp3 file.


A compact and reliable Digital .mp3 recorder. One of those airport adapters plugged into the top so a 3.5mm stereo lead can be plugged in to those RCA terminals on the cassette port.

I wasn't sure how well this would work. Would the .mp3 compression ruin the audio recording and not read back correctly. The only way to find out is to try it.

Tiny BASIC has a LOAD and SAVE command which is used to read and write BASIC programs to/from cassette. It's pretty slow, but better than nothing. I SAVE my first short test program to cassette and then LOAD it back.

When it saves it does about 5-10 seconds of leader tone so that when it is read back it can sync and then watch out for the first bit.

Tiny BASIC stores it's programs starting at $100 and fills upwards until the top of RAM which is $0FFF normally giving us just under 4K to store BASIC programs.

What I didn't realise at first is that it also saves the first $100 (256) bytes with each BASIC program and this will come back to bite me later.

I got a Lunar Lander game up and running from one supplied from a member of the ET-3400 groups.io and I also created my own Drunk Crossing a Bridge simulator that I rewrote from memory as a teenager. This was just a simple program that used the random number generator to plot a track down a scrolling screen, and if the drunk hit the sides of the bridge he fell off the bridge into the water. When the program starts you choose the width of the bridge. The length is somewhat random and partly depends on the width you select.

Getting bored with that I wanted to write a Star Trek game, but I knew that 4K was not going to cut it. So I next relocate the Fantom II monitor and Tiny BASIC into high memory. At first I was going to just patch the ROM manually. That was before I realised there was about 200 patches to do, so then I used the A68 Assembler to create a relocated version of Tiny BASIC. I have Greg Simmons from the ET3400 group to thank for the disassembled Tiny BASIC listing which he created for the low memory version of Tiny BASIC. This made my job a lot easier.

Thinking ahead

In the relocated version I have moved the Fantom II monitor to sit at $F400..$FBFF instead of $1400..$1BFF, and that's so it sits directly under the ET-3400 monitor at $FC00..$FFFF. I then relocated Tiny BASIC to fit below that at $EC00..F3FF. This is for two reasons. First it's easier to remember the starting address if you already knew the low memory entry points. ie D 1400 becomes D F400 top start the Fantom monitor, and G 1C00 becomes G EC00, so you are only changing the first hex digit. The second reason was so that a larger BASIC or other interpreter could fit below the monitor, just in case there wasn't enough room for Tiny BASIC and what ever else you wanted to fit in 11K of ROM. The PIA is relocated to $C200, just above the existing keypad and 7-segment display. That may change later, but it seems like a good choice for now leaving room for future expansion space at $C300, $C400 and up to $C7FF, leaving $C800 for possible ROM expansion.

There is now more patches required to run the code at that address. After assembly I still had to break it up into blocks and store them in a specific sequence in the EPROM using the table I described previously before burning the EPROM.

In the Fantom II monitor the main changes were to the PIA address which was at $1000 and now sat at $C200. It was a simple matter of searching for 10 00 in the source listing or search for the word TERM which was used to describe the PIA port address in the source file.

I also had to change the way the monitor determined it's highest memory address. In the original source code it started at the PIA TERM address of $1000 then tested each address below that until it found memory that could be written to and read back correctly. So normally this would test $0FFF and it would pass, so it assigned the highest memory address as $0FFF.

Under the remapped scheme this may not work since the PIA is now at $C200. If it starts at $C1FF and works down it will be writing to and reading back from the hex keypad and 7-segment display locations potentially causing havoc.

Instead I insert a patch so that it starts at $BFFF then works down from that.

Original code. 

;6821 PIA abbreviations:
; DDR x = Data Direction Register x
; DR x = Data Register x
; CR x = Control Register x
;note: DR x and DDR x use the sasme address in the PIA, CR x controls which register is in use.
1400 0f                 MAIN    SEI
1401 ce 10 00                   LDX     #TERM ;reload TERMINAL PIA adrs, IN CASE of IRREGULAR ENTRY
1404 6f 01                      CLR     1,X ;set port A Control Register bit 2=0 so we can setup DDR A  
1406 6f 03                      CLR     3,X ;set port B Control Register bit 2=0 so we can setup DDR B
;setup serial terminal Data Direction Register:
1408 86 01                      LDAA    #%00000001 ;0 = input, 1 = output
140a a7 00                      STAA    0,X ;setup DDR A PA1..PA7 as inputs, PA0 as output
;setup cassette port Data Direction Register:
140c 86 7f                      LDAA    #%01111111 ;0 = input, 1 = output
140e a7 02                      STAA    2,X ;setup DDR B PA7 as input, PA0..PA6 as output
1410 c6 04                      LDAB    #%00000100 ;bit 2 is used to set whether DR or DDR is in use
1412 e7 01                      STAB    1,X ;set port A Control Register bit 2=1 so we can use DR A 
1414 e7 03                      STAB    3,X ;set port B Control Register bit 2=1 so we can use DR B
1416 a7 00                      STAA    0,X ;IDLE MARKING!! sets PA0 Tx data to low output
;bit 2=1 is ignored by DR A because it's an input
                        *       NOW FIND MEMORY EXTENT
                        
1418 09                 MAIN1   DEX
1419 a6 00                      LDAA    0,X ;read RAM into a-reg
141b 63 00                      COM     0,X ;invert bits in RAM
141d 43                         COMA ;invert a-reg
141e a1 00                      CMPA    0,X ;is it still same after inverting both
1420 26 f6                      BNE     MAIN1 ;if not go down to next address
1422 63 00                      COM     0,X             ;RESTORE GOOD BYTE

After initialising the PIA starting at $1400 it falls through to $1418 where the x-reg then contains the PIA TERM address of $1000. It then starts testing for RAM.

Patched code in high memory:

;---------------------patch------------------------
F400 7e fb 58                   JMP     $FB58 ;patched for relocated PIA
;option for 48K RAM
;----------------------------------------------------
F403 ce c0 00                   LDX     $C000 ;top of 48K RAM +1 for ETA-3400X
F406 01                         NOP                
;fill old code with NOPs...
F407 01                         NOP
F408 01                         NOP
F409 01                         NOP
F40A 01                         NOP
F40B 01                         NOP
F40C 01                         NOP
F40D 01                         NOP
F40E 01                         NOP
F40F 01                         NOP
F410 01                         NOP
F411 01                         NOP
F412 01                         NOP
F413 01                         NOP
F414 01                         NOP
F415 01                         NOP
F416 01                         NOP
F417 01                         NOP

and at $FB58 there is space for some patches:

;--------------------------------------     ;patch for relocated PIA to $C200
fb58 0f                 MAIN    SEI
fb59 ce c2 00                   LDX     #TERM           ;TERMINAL PIA, IN CASE IRREGULAR ENTRY,
fb5c 6f 01                      CLR     1,X             ;set CRA to select DDRA
fb5e 6f 03                      CLR     3,X ;set CRB to select DDRB
fb60 86 01                      LDAA    #1
fb62 a7 00                      STAA    0,X ;setup DDRA: PA0 as output, PA1..PA7 as inputs 
fb64 86 7f                      LDAA    #%01111111B ;(0 = input, 1 = output)
fb66 a7 02                      STAA    2,X ;setup DDRB: PB0..PB6 as outputs, PB7 as input
fb68 c6 04                      LDAB    #4 ;now set both ports as Data registers
fb6a e7 01                      STAB    1,X ;set CRA to select DRA
fb6c e7 03                      STAB    3,X ;set CRB to select DRB
fb6e a7 00                      STAA    0,X             ;IDLE MARKING!!, set PA0 to high ?
;ie a-reg bit 0 still high from adrs $fb64
fb70 7e F4 03                   JMP     $F403 ;rts equivalent without using stack

There wasn't enough room to fit in an extra instruction between $F400 and $F418, so instead I jump out to $FB58 where there is unused ROM space and squeeze the extra code there. On return to $F403 the x-reg is set to $C000 so it starts its RAM test below that instead. Not the best coding and it could be improved or shortened.

A few other sections of Tiny BASIC have to be changed. The following equates are changed:

f8e1                 Mon_Read_Char   equ    $F8E1 ;{changed for Fantom monitor at $F400}
f865                 Mon_Write_Char  equ    $F865 ;{changed for Fantom monitor at $F400}
fb1f                 Mon_Test_Break  equ    $FB1F ;{changed for Fantom monitor at $F400}
                        ;* The ETA-3400 Tiny Basic ROM has additional hooks
fa80                 Mon_FTOP        equ    $FA80       ;Find top of RAM {changed for Fantom monitor at $F400}
f400                 Mon_Cold        equ    $F400       ;Monitor cold start {changed for Fantom monitor at $F400}
fb2d                 Mon_Load        equ    $FB2D       ;Monitor load from tape {changed for Fantom monitor at 
$F400}
fb38                 Mon_Save        equ    $FB38       ;Monitor save to tape {changed for Fantom monitor at 
$F400}
f618                 Mon_OUTIS       equ    $F618       ;Monitor write zero-terminated string {changed for Fantom monitor at $F400}

That's the majority of the patches done. There was one other patch to remove the leading characters on each line but I seem to have lost it at the moment.

So with the Fantom II monitor and Tiny BASIC up and running in high memory I now have a 48K space to play with. And I can probably complete the pcb layout and order some boards.

What to do with all that space next...

No comments:

Post a Comment

Part 2o: The future of the ETA-3400X

You can find all the work I've done on the ETA-3400X and 8K ALTAIR 680 BASIC, except for the ETA-3400X Gerber files, on the ET-3400 grou...