6502_EhBASIC_V2.22/bugsnquirks.txt

178 lines
7.2 KiB
Plaintext
Raw Normal View History

2017-01-26 13:24:30 +00:00
EhBASIC 2.22 has a few bugs and quirks that you should know about.
2016-12-21 18:50:41 +00:00
1. The interrupt system is severely broken.
When an IRQ occurs and IRQ_vec is called in min_mon.asm the interrupt is only
registered with IRQbase but the interrupt source is not serviced nor is the
interrupt disable bit set at RTI. As a consequence the interrupt is immediately
called again and again and IRQbase is trashed until the interrupt is serviced
by the ON IRQ handler in basic.
The problem is discussed in http://forum.6502.org/viewtopic.php?f=5&t=2411
How I solved the problem for my emulator:
https://github.com/Klaus2m5/AVR_emulated_6502_4SBC/tree/master/EhBASIC
However, you should keep in mind that the interrupt service capacity in EhBASIC
is very limited. In a 2MHz system more than 100 interrupts per second or
interrupts requiring less than 10ms service time should be handled in machine
language. The numbers are worse if the interrupt handler gets more complex.
Of course, a hybrid solution is always possible. You could service the interrupt
in machine language and flag an interrupt to basic only after a buffer is
filled/emptied or a count is reached.
2017-01-05 10:11:26 +00:00
2016-12-21 18:50:41 +00:00
2. String handling when the string is in the input buffer.
When a string is entered via the input buffer (Ibuffs - Ibuffe) in Ehbasic it
is transient because it gets overwritten by the next input. In this case it
needs to be copied to the string area. In all other cases the string remains in
2017-01-05 10:11:26 +00:00
place and only a pointer needs to be set to the string location.
2016-12-21 18:50:41 +00:00
There is a bug in EhBASIC to determine where the string is.
LAB_20DC
2017-01-05 10:11:26 +00:00
STX Sendh ; save string end high byte
LDA ssptr_h ; get string start high byte
CMP #>Ram_base ; compare with start of program memory
BCS LAB_RTST ; branch if not in utility area
2016-12-21 18:50:41 +00:00
This does not work, if RAM_base is below the input buffer or EhBASIC itself is
below RAM_base. The fix requires the input buffer not to cross a page boundary:
LAB_20DC
STX Sendh ; save string end high byte
LDA ssptr_h ; get string start high byte
2017-01-05 10:11:26 +00:00
; *** begin RAM above code / Ibuff above EhBASIC patch ***
2016-12-21 18:50:41 +00:00
; *** replace
; CMP #>Ram_base ; compare with start of program memory
; BCS LAB_RTST ; branch if not in utility area
; *** with
CMP #>Ibuffs ; compare with location of input buffer page
BNE LAB_RTST ; branch if not in utility area
2017-01-05 10:11:26 +00:00
; *** end RAM above code / Ibuff above EhBASIC patch ***
2016-12-21 18:50:41 +00:00
3. Output of some functions limited to integers is negative.
This is not a bug but documented behavior.
Affected functions FRE(), SADD(), VARPTR(), DEEK()
If you want to use FRE() with large RAM you must write:
? FRE(0)-(FRE(0)<0)*$10000
If you really want to deviate from the beaten path, you can add a routine to
convert unsigned integers and jump to it from the functions that you want to
respond with an unsigned number. It replaces LAB_AYFC for these functions.
; save and convert unsigned integer AY to FAC1
LAB_UAYFC
LSR Dtypef ; clear data type flag, $FF=string, $00=numeric
STA FAC1_1 ; save FAC1 mantissa1
STY FAC1_2 ; save FAC1 mantissa2
LDX #$90 ; set exponent=2^16 (integer)
SEC ; always positive
JMP LAB_STFA ; set exp=X, clear FAC1_3, normalise and return
You cannot apply this routine to operators which also use LAB_AYFC (=, OR, AND
EOR <<, >>) as they require signed integers. The value -1 is asigned to a
comparison evaluating as TRUE. Therefore logical operators must be able to
evaluate -1 correctly.
2017-01-05 10:11:26 +00:00
4. Use of decimal mode and invalid BCD
There is only one place in EhBASIC where decimal mode is used. HEX$() uses
invalid BCD to convert a number to a hexadecimal string. Some processors do not
support decimal mode and emulators most of the time will not support invalid
BCD (nibbles in the range of $A - $F).
LAB_AL2X
CMP #$0A ; set carry for +1 if >9
ADC #'0' ; add ASCII "0"
STA (str_pl),Y ; save to temp string
DEY ; decrement counter
RTS
A patch is available to disable use of decimal mode in EhBASIC.
LAB_AL2X
CMP #$0A ; set carry for +1 if >9
; *** begin disable decimal mode patch ***
; *** insert
BCC LAB_AL20 ; skip adjust if <= 9
ADC #$06 ; adjust for A to F
LAB_AL20
; *** end disable decimal mode patch ***
ADC #'0' ; add ASCII "0"
STA (str_pl),Y ; save to temp string
DEY ; decrement counter
RTS
At the same time you must disable SED & CLD at the HEX$() function.
LAB_HEXS
CPX #$07 ; max + 1
BCS BinFErr ; exit if too big ( > or = )
STX TempB ; save # of characters
LDA #$06 ; need 6 bytes for string
JSR LAB_MSSP ; make string space A bytes long
LDY #$05 ; set string index
; *** disable decimal mode patch - comment next line ***
; SED ; need decimal mode for nibble convert
LDA nums_3 ; get lowest byte
JSR LAB_A2HX ; convert A to ASCII hex byte and output
LDA nums_2 ; get middle byte
JSR LAB_A2HX ; convert A to ASCII hex byte and output
LDA nums_1 ; get highest byte
JSR LAB_A2HX ; convert A to ASCII hex byte and output
; *** disable decimal mode patch - comment next line ***
; CLD ; back to binary
5. Ibuffs located at $xx00
If the input buffer is located at the beginning of a page then any direct
statement (RUN, LIST, ...) is read from Ibuffs-$100 resulting in unexpected
behavior of EhBASIC.
A patch is available from Daryl Rictor. I took the freedom to add conditional
assembly.
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
; *** begin patch for when Ibuffs is $xx00 - Daryl Rictor ***
; *** insert
.IF Ibuffs&$FF==0
LDA Bpntrl ; test for $00
BNE LAB_142P ; not $00
DEC Bpntrh ; allow for increment when $xx00
LAB_142P
.ENDIF
; *** end patch for when Ibuffs is $xx00 - Daryl Rictor ***
; end of patch
DEC Bpntrl ; allow for increment
RTS
The conditional in the patch abover requires Ibuffs to be known at path 1 during
assembly. The standard definition of Ibuffs does not satisfy this requirement.
We need to replace it like below:
; Ibuffs can now be anywhere in RAM, ensure that the max length is < $80,
; the input buffer must not cross a page boundary and must not overlap with
; program RAM pages!
;Ibuffs = IRQ_vec+$14
Ibuffs = VEC_SV+$16
; start of input buffer after IRQ/NMI code
Ibuffe = Ibuffs+$47; end of input buffer