EhBASIC bug Ibuffs location

Bug in EhBASIC 2.22 Daryl Rictor et al (from a discusson on 6502.org)

The following works:

; Ibuffs can now be anywhere in RAM, ensure that the max length is $80
IRQ_vec   = VEC_SV+2      ; IRQ code vector
Ibuffs      = IRQ_vec+$14

Whereas the following doesn’t:

; Ibuffs can now be anywhere in RAM, ensure that the max length is $80
Ibuffs      = $0400
Ibuffe      = Ibuffs + $47    ; end of input buffer

Of course be careful to make sure that Ram_base is quite faraway from Ibuffs.

So, Ibuffs can be anywhere in RAM that’s not $0400??
Any reason $0400 is magical?
Nope. $0400 is an example. $0500 gives you the same result: negative.
As long as Ibuffs is in the same page as ccflag and friends, it works. And ccflag can be at $0400.

Now, if you reference Ibuffs in relation to IRQ_vec (copy it over from min_mon.asm), then things work.
Perhaps someone somewhere made some assumptions of the page where Ibuffs need to be e.g. be in the same page as ccflag and friends etc.

The other problem is what I’ve already observed: the EhBASIC binary has to be located in memory higher than Ram_base and Ram_top. Otherwise strange things happen.

With Ibuffs set to $0400 AND Ram_base set to $0500, I did a Cold start and entered this line – 10 PRINT “HELLO WORLD”

I examined the memory at Ram_base and found that the stored line was formatted correctly. However, when I typed LIST, all I got back was HELLO WORLD, as if I had typed RUN. Typing RUN also returned HELLO WORLD. When I ran the SYS command (my added command to return me to my Monitor), it just ignored it and returned to the BASIC input prompt.

Next, I changed Ibuffs to $0401 and reassembled. This time, everything performed as it should.

Next, I set Ram_base to $0600 with Ibuffs set to $0400 and entered the same line. This time, LIST returned nothing. Examining memory at $0600, the stored line is there and is correct. RUN and SYS also return nothing.

Finally, I set Ram_base to $0600 and Ibuffs to $0401 and all worked as it should.
I think I found the problem… and it would explain the issue with Ibuffs and Ram_base being 1 page apart too.

This piece of code is the problem:

LAB_142A
   INY            ; increment pointer
   INY            ; increment pointer (makes it next line pointer high byte)
   STA Ibuffs,Y   ; save [EOL] (marks [EOT] in immediate mode)
   INY            ; adjust for line copy
   INY            ; adjust for line copy
   INY            ; adjust for line copy
   DEC Bpntrl     ; allow for increment (change if buffer starts at $xxFF)
   RTS

Previously in the code, Bpntrl gets set to Ibuffs. When the DEC instruction gets executed, Bpntrl get set to $FF. Later in the code, we have this:

LAB_15F6
   JSR   LAB_IGBY     ; increment and scan memory

LAB_15F9
   JSR   LAB_15FF   

The routine LAB_IGBY is located in zero page (to increase speed). it looks like this:

LAB_2CEE
   INC   Bpntrl        ; increment BASIC execute pointer low byte
   BNE   LAB_2CF4      ; branch if no carry
               ; else
   INC   Bpntrh       ; increment BASIC execute pointer high byte

; page 0 initialisation table from $C2
; scan memory

LAB_2CF4
   LDA   $FFFF         ; get byte to scan (addr set by call routine)
   CMP   #TK_ELSE      ; compare with the token for ELSE
   BEQ   LAB_2D05      ; exit if ELSE, not numeric, carry set

   CMP   #':'          ; compare with ":"
   BCS   LAB_2D05      ; exit if >= ":", not numeric, carry set

   CMP   #' '          ; compare with " "
   BEQ   LAB_2CEE      ; if " " go do next

   SEC                 ; set carry for SBC
   SBC   #'0'          ; subtract "0"
   SEC                 ; set carry for SBC
   SBC   #$D0          ; subtract -"0"
                       ; clear carry if byte = "0"-"9"
LAB_2D05
   RTS

The code at LAB_2CEE will INC Bpntrl, which becomes $00 and then INC’s Bpntrh to $05. Now this pointer is pointing to the wrong page. And depending upon what is stored there, different things will happen.

This note is incorrect:

   DEC   Bpntrl      ; allow for increment (change if buffer starts at $xxFF)

It should read (change if buffer starts at $xx00).

My fix would be to add this:

LAB_142A
   INY            ; increment pointer
   INY            ; increment pointer (makes it next line pointer high byte)
   STA Ibuffs,Y   ; save [EOL] (marks [EOT] in immediate mode)
   INY            ; adjust for line copy
   INY            ; adjust for line copy
   INY            ; adjust for line copy

; add patch for when Ibuffs is $xx00 - Daryl Rictor
   LDA  Bpntrl    ; test for $00
   BNE  LAB_142P  ; not $00
   DEC   Bpntrh   ; allow for increment when $xx00
LAB_142P
; end of patch
   DEC   Bpntrl    ; allow for increment
   RTS

I have tested this fix and it worked for me.

Daryl