Okay, maybe I should have said I wasn't PLANNING to build a more usable Apple II EhBASIC port. Here are a few of the sugeestions I've sucessfully incorporated:
1. Change all CR ($0D) LF ($0A) sequences to CR, in things like the Ready message, the sign-on message, etc. You could also change the A2_IN routine to print nothing when it sees an $0A, but then you wouldn't be able to print LFs with a PRINT CHR$(10) when you wanted to.
There are CRLF sequences ($0d,$0a) in the following messages: (remove the $0a from these sequences)
a. LAB_SMSG (line 7676)
b. LAB_BMSG (line 8483)
c. LAB_RMSG (line 8486) contains 2 CRLF sequences
d. LAB_IMSG (line 8488)
e. LAB_REDO (line 8489)
2. Move everything on Page 2 (Ibuffs, ccflag, etc.) to page 3 so that you can drop into the monitor with a CALL $FF69 and return to EhBASIC with 0G
a. change Ibuffs to $0323 (line 27)
b. change ccflag to $0300 (line 407)
3. Comment out the all of the Memory Size prompting and just use Ram_top for this parameter.
a. comment out lines 478-523 (JSR LAB_CRLF to LAB_2DB6)
b. comment out lines 526-527 (the CPY #(>Ram_base+1) and BCC LAB_GMEM instructions)
c. changed last entry of StrTab (line 7669) to Ram_top
d. comment out lines 7672-7673 (the LAB_MSZM message)
5. Add a halting key input vector to allow a cursor to be displayed (which, like the Ctrl-C vector, could simply default to the current behavior). For example, the LAB_1359 loop would be replaced with a JSR V_IN_HALT.
7. Write a custom line input routine which allows ESC sequences, allows the right-arrow to retype, clears to the end of the line when return is pressed, allows the line to be cancelled or cleared (restarted), and displays any control characters entered in inverse (black-on-white) text so that they can be easily spotted.
This only adds the ESC sequences, right-arrow retyping, and clearing to the end of the line when return is pressed.
a. changed JSR V_INPT at LAB_1359 to JSR A2_INH (line 944)
b. commented out the BCC LAB_1359 instruction (line 945)
c. commented out the BEQ LAB_1359 instruction (line 947)
d. inserted the following A2_INH code
A2_INH STY $3E ; save Y (just in case)
JSR $FD35 ; display cursor, wait for keypress, allow ESC sequences
CMP #$8D ; check for return key
JSR $FC9C ; clear to end of line if return
A2_INH1 CMP #$95 ; check for right arrow key
LDA ($28),Y ; retype (40 columns only)
A2_INH2 EOR #$80
LDY $3E ; restore Y
8. Write a custom Ctrl-C handler. The default Control-C handler calls the A2_IN routine which doesn't allow Control-S to reach the output routines, so listings and other scrolling text can't easily be paused.
This Ctrl-C handler does not check interrupts, so if you use them, replace the RTS with a JMP LAB_FBA2.
a. change the Ctrl-C check vector in PG2_TABS to A2_CC (line 7605)
b. insert the following A2_CC code
A2_CC LDA $C000 ; read key press
CMP #$83 ; check for Ctrl-C
RTS ; if not, leave it be
A2_CC1 STA $C010 ; clear keyboard strobe
JMP LAB_163B ; handle ctrl-C
Did you tell me about the undocumented feature in FOR?
Yes, but it was quite a while ago, and I only mentioned that I thought there would be a problem. The problem occurs when the 3 FAC1 mantissa bytes of the number after the TO keyword are $FF and the FAC rounding byte is $80 to $FF. What happens is that the sign bit is incorporated into the MSB of the FAC1 before the rounding byte is rounded into the FAC1. Each of the following behaves as you would expect:
FOR Z=1 TO 16777215: ? Z: NEXT
FOR Z=1 TO 16777216: ? Z: NEXT
A=16777215+.5: FOR Z=1 TO A: ? Z: NEXT
...but to see the U.F. (undocumented feature) in all its glory:
FOR Z=1 TO 16777215+.5: ? Z: NEXT
10. Replace the current pseudo-random sequencer with a linear congruential random number generator.
I've been working on that. For any integer number range that fits in 0 to 2^n-1 taking the nth value does help as there are 2^n possible results. I'm also trying using this in combination with small a (256 byte) scattering array so that the sequence is still the maximal length.
I've got a linear congruential RNG written and tested. It includes a routine that allows you to plug it into the USR function of EhBASIC. The USR function takes the same argument as the RND function so you can just replace RND with USR in your programs. The heart of the generator is a function called RAND which performs the 32-bit calculation seed = a * seed + c. There are three versions of RAND: a fast version using tables, a short (in terms of number of bytes) version, and a middle version (slightly longer than the short version, but between the other two versions in terms of speed). The multiplier can easily be changed in the first two versions. A JSR RAND in the fast version takes only 94 cycles but uses 4 pages of tables. You can even squeeze two more cycles out of it by using 6 pages of tables.
There are two other functions which are not needed by EhBASIC: RANDOM and URANDOM. RANDOM generates a random number between 0 and arg-1 inclusive. URANDOM does the same, but produces a perfectly uniform distribution. In other words, the sequence length is 2^32 and if you pass RANDOM a number between 0 and 5, some numbers will be a teensy bit (a very teensy bit) more likely than others, since 2^32 is not a multiple of 6. URANDOM makes each possibility equally likely. There are versions of both functions for 8 and 16-bit arguments. All that is left to do is to stop writing long-winded forum posts, document the use of all these functions, and send it to Mike.
In terms of the pseudo-random sequencer, taking every Nth value does help, but fiddling with the randomness of a generator tends to make it worse. Of course, linear congruential generators aren't perfect either. Here is a program that illustrates the limitations of the EhBASIC RNG (with the shift code fixed). Note that as written it uses every 5th random number.
130 K=K-1: DIM X(K)
140 DIM G(15,15): FOR X=0 TO 15: FOR Y=0 TO 15: G(X,Y)=46: NEXT: NEXT
150 FOR I=0 TO $8000:FOR J=0 TO $10000
160 FOR A=1 TO C
170 FOR B=0 TO K: FOR Z=1 TO N: X(B)=RND(0): NEXT: NEXT
180 FOR B=0 TO K: FOR Z=1 TO N: Y=RND(0): NEXT: G(X(B)*16,Y*16)=88: NEXT
190 FOR X=0 TO 15: FOR Y=0 TO 15: ? CHR$(G(X,Y));: NEXT: ?: NEXT: ?
The program attempts to fill a 16 x 16 square. Using only every Nth random number, it generates K x-coordinates, then K y-coordinates, and "plots" them. Every C iterations, it displays the grid. When K=1, the following values of N also fail: N=1, N=2, N=3, N=31. Makes some interesting patterns though, doesn't it?