Porting ehbasic to the Apple ][

A forum for users of EhBASIC (Enhanced BASIC), a portable BASIC interpreter for 6502 microcomputers written by Lee Davison.
leeeeee
In Memoriam
Posts: 347
Joined: 30 Aug 2002
Location: UK
Contact:

Post by leeeeee »

Quote:
I went to your website and downloaded the source but it looked the same to me, is there a more recent version somewhere? (this says 07/14/03)
Should be Ver 1.10 which is the last version I uploaded. The version I'm working on is 1.14 and a bit but that may get held up because I'm also re-writing the entire value/function/variable get section as well as some other tweaks which will be Ver 2.xx. This ties in with the 68k version of EhBASIC which is at 2.21.
Quote:
However that paper on combined Tausworthe generators says:

"recurrences based on polynomials with too few non-zero coefficients are known to have important statistical defects" (and gives references)
I try to remember this ..
Quote:
Anyone attempting to generate random numbers by deterministic means is, of course, living in a state of sin." - John Von Neumann
There is no such thing as a deterministic random number generator, any aparent randomness is caused purely by the limits of your perception. Someday, somewhere, whatever you write will fail some randomness test.

The reason I used the PRNG generator I did was it fulfilled my two most pressing needs at the time, it's fast - about 40x faster than the standard method, and it's spectrally flat with a reasonable cycle time.
Quote:
So you probably want a more complex polynomial any way

My impression (but I'm no expert) is that a 32 bit prng is way too short to be much good (which is why he (Pierre L'Ecuyer) combines them)
I'm planning on sticking with the 32bit shift type PRNG but probably with 15 or 17 shifts and a scatter array. This costs in speed and size but experiments so far are encouraging.
Quote:
(and if it were me doing it, it would be by guess and by golly, so I'd test the shit out of it ;) )
Trouble with that is the code would never see light of day as there's always something more to do.

Lee.
bogax
Posts: 250
Joined: 18 Nov 2003

Post by bogax »

leeeeee wrote:
Quote:
Anyone attempting to generate random numbers by deterministic means is, of course, living in a state of sin." - John Von Neumann
There is no such thing as a deterministic random number generator, any aparent randomness is caused purely by the limits of your perception. Someday, somewhere, whatever you write will fail some randomness test.
every body knows that ;)
Quote:
The reason I used the PRNG generator I did was it fulfilled my two most pressing needs at the time, it's fast - about 40x faster than the standard method, and it's spectrally flat with a reasonable cycle time.
hmm, what's the standard method?
Quote:
I'm planning on sticking with the 32bit shift type PRNG but probably with 15 or 17 shifts and a scatter array. This costs in speed and size but experiments so far are encouraging.
I understand this to mean that you're going to run through 15 or 17 cycles of the
LFSR each time the RND function is called and then combine the result with some random
constants (maybe XOR the result with a number from an array of random numbers, indexed
by the lower four bits of the result, or something like that)

working on that assumption..

First, the problem with using an LFSR with only 32 bits is that each value occurs only
once per cycle, so it's more like playing with a shuffled deck of cards (with the problem of
card counting) than it is like rolling dice. Of course, if you never expect to use anything
near the full 32 bits, it can appear more like rolling dice. But sounds like your going to
go to some pains to make sure things are shuffled up reasonably well.
You can achieve some of that just by using a more "complex" polynomial.
Using every nth value from the LFSR should shuffle things up some but it
won't increase the cycle length and using every 15th or 17th will decrease the cycle length
and throw away most of your possible values (2^32-1, the maximal cycle length for
a 32 bit LFSR, is divisible by both 15 and 17)
For about the same cost as another cycle or two of a single LFSR you could run another LFSR
combine them and both shuffle things up some more and increase the cycle length

I'm not trying to talk you into anything, I'm just pointing out that you can probably get
better effect for less cost than what you're going to do (if I understand that correctly)

I'd be curious how you derive and apply your scatter array, if you'd care to
elucidate
User avatar
dclxvi
Posts: 362
Joined: 11 Mar 2004

Post by dclxvi »

bogax wrote:
Using every nth value from the LFSR should shuffle things up some but it
won't increase the cycle length and using every 15th or 17th will decrease the cycle length
and throw away most of your possible values (2^32-1, the maximal cycle length for
a 32 bit LFSR, is divisible by both 15 and 17)
For a K-bit generator, where bit J is the other feedback bit (i.e. you shift in bit K-1 XOR bit J), you can make a generator that has a maximal sequence length of 2^K. In a 2^K-1 length right shift generator, the value after 0000...0001 is 1000...0000. The idea for the 2^K length generator is to insert the all-zero state (0000...0000) in between these two. This is done as follows:

Let P = NOT (bit 0 OR bit 1 OR bit 2 OR ... OR bit K-3 OR bit K-2)

Then shift in bit K-1 XOR bit J XOR P which is the same as bit K-1 XOR (bit J OR bit P), since bit J is 0 when P is 1. The actual implementation would probably be:

If P=0, then shift in bit K-1 XOR bit J
If P=1, then shift in bit K-1 XOR 1

A (K-1)-bit NOR "gate" is easy to do in software, but there is a speed penalty. One advantage is that you don't have to reject the all-zero state. For example in a K=31 right shift generator, you can use: (note that in this case, bit 0 is the leftmost bit, not the rightmost)

Code: Select all

LDA BITS_30_TO_24
AND #$FC          ; use AND #$3F for a left shift generator
ORA BITS_23_TO_16
ORA BITS_15_TO_7
ORA BITS_7_TO_0
then the Z flag is clear (BNE branches) when P=0, and set (BEQ branches) when P=1.

In fact, the formula for P is the same even for cases where there are more than two feedback bits (such as K=32).
bogax wrote:
For about the same cost as another cycle or two of a single LFSR you could run another LFSR
combine them and both shuffle things up some more and increase the cycle length
With the 2^K-1 length generator, using every Nth number (i.e. N shifts) will not necessarily take N times longer (speed-wise) than a single shift (as it would if you were using a single shift inside a loop). For a K=31 and J=27 right shift generator (i.e. the current EhBASIC generator):

Code: Select all

N=0 (i.e. the bits of the old seed):

    abcdefgh ijklmnop ABCDEFGH IJKLMNO

N=1 (i.e. the new seed after 1 right shift):

    Oabcdefg hijklmno pABCDEFG HIJKLMN
XOR L

N=2:

    NOabcdef ghijklmn opABCDEF GHIJKLM
XOR KL

N=5:

    KLMNOabc defghijk lmnopABC DEFGHIJ
XOR HIJKL

N=28:

    defghijk lmnopABC DEFGHIJK LMNOabc
XOR abcdefgh ijklmnop ABCDEFGH IJKL

N=29:

    cdefghij klmnopAB CDEFGHIJ KLMNOab
XOR Oabcdefg hijklmno pABCDEFG HIJKL
XOR L
Obviously N=1 will be the fastest. In the N=5 case, by getting everything aligned first, only a single XOR is needed. The shifting (and XOR-ing of bits within a byte) can be sped up with tables. Any N <= J+1 will not be that much slower than N=5, and even N > J+1 doesn't make things that much worse.

The fastest N=1 routine I've come up with takes 29 (clock) cycles, assuming the seed is stored on the zero page. I think an N=5 routine can be written in only 101 cycles, which I think can be cut down to 60 cycles with only 4 pages of tables. As you may have guessed, I've written a couple of N=5 routines, but I haven't tested them, so the cycle count for working routines may be different by +/- a few cycles.
usotsuki
Posts: 70
Joined: 23 Dec 2002

Post by usotsuki »

"Thread Necromancy!"

A while ago I did a couple rough ports of EHBASIC 2.09 to the Apple, and I just managed a third which uses the monitor more directly.

This leaves me, actually, where all I need to do is actually implement LOAD and SAVE (and fix some bugs in my setup which cause undesirable behavior when errors occur in DOS 3.3) and it will be truly complete.

I gave it a fixed load address and removed the Memory Size prompt. It loads just about as high as I can safely load it without stepping on 48K DOS ($6800-$8FFF). Some pointers are moved around and the ^C check is temporarily disabled because I'm using FPBASIC-style blocking GET rather than C64-style.

The vectors and input buffer sit at $9000, and do not interfere with e.g., dropping into the monitor. DOS now knows how to do a warm boot into EHBASIC, and Reset does a warm restart of DOS followed by an immediate dump back into EHBASIC.

For the sake of the older machines in the ][ line, all messages are capitalized.

Free space is 24K - 1 byte.

A temporary workaround for the lack of LOAD and SAVE uses ?chr$(4), DEEK and DOKE, thus -

PRINT CHR$(4); "BSAVE filename, A"; DEEK($79); ",L"; DEEK($7B)-DEEK($79)

PRINT CHR$(4); "BLOAD filename, A"; DEEK($79): DOKE $7B, DEEK($79)+DEEK($AA60)

Naturally all of this is DOS 3.3-specific.

-uso.
leeeeee
In Memoriam
Posts: 347
Joined: 30 Aug 2002
Location: UK
Contact:

Post by leeeeee »

The Apple ][ is one of the most frequent can-you-port-EhBASIC-to-X requests that I get. As I haven't had an apple system for a looooong time I've had to say no, now all I need to do is send them to you. 8^)=

It's also good to see features that I implemented, like DEEK, DOKE and hex values, being put to use. What better affirmation of the usefulness of a feature is there than it actually being used?

Good work.

Lee.
usotsuki
Posts: 70
Joined: 23 Dec 2002

Post by usotsuki »

DOKE/DEEK is the most obviously useful function :)

I have an Apple //e, though it's collecting dust atm as I do most of my dev work with an old Apple //e emulator. Not perfect but more than adequate for the job.

I can put the disk image with my current copy on my site or something for now, though LOAD and SAVE are broken in my port and there's a couple other tweaks I could stand to make for compatibility...

edit: http://usotsuki.info/ehiigs.png
- this is my current port of EHBasic running on an emulated Apple IIgs (65C816).

http://usotsuki.info/EHBasic%20II%20090101.dsk.gz
- this is the disk image of the current working copy running on DOS 3.3, the HELLO and APPLESOFT files are there to work around a bug I can't find that makes it break unless it is activated from a program.

CALL $9D84 exits to the BASIC it was run from. CALL 36768 or CALL -28768 will reinitialize EHBASIC. The code is resident from $6800-$9100 and the vectors/buffers lie above it. DOS is located from ca. $9D00-$FFFF. There is 24K minus one byte available for code.

...and with a little hacking I could prolly get an additional 12K.
usotsuki
Posts: 70
Joined: 23 Dec 2002

Post by usotsuki »

I'm working on this again, scrapped my port and started over. With PDOS RDOS code I am hoping to be able to actually load and save stuff.

For familiarity's sake I patched a couple fpbasic-isms in (home, pr#, in#, vtab, htab) and a "bye" command. It runs on ProDOS 8 now (instead of DOS 3.3), sitting at the 32K location which should give the PDOS RDOS code enough breathing space. Even Ctrl-C is functional now.

http://usotsuki.hoshinet.org/EHBasic%20II%20100129.zip contains the working project.

Thinking about it, with the extended commands, functions don't work right (!) but everything else does. ATM I have two files, EHBASIC.SYSTEM and EHBASICN.SYSTEM. The latter works correctly. The former has the added commands but does not work correctly (I'd like to figure this out).

EDIT: Disregard the last comment, I'm a doof. I replaced the .ZIP with a fixed version (although the fpbasic/intbasic style HLIN and VLIN use comma instead of AT).
usotsuki
Posts: 70
Joined: 23 Dec 2002

Post by usotsuki »

Until I fix the LOAD/SAVE issue, which I think boils down to a difference between how Microsoft BASIC and EHBASIC store strings, this is probably going to be my final "alpha" of an Apple ][ port.

http://usotsuki.hoshinet.org/EHBasic%20II%20100130.zip

The LOAD/SAVE issue (I should probably bring this up in a different subforum, since it really has very little to do with EHBASIC) is the big showstopper. I'd like to also implement, at least, CAT, PREFIX, LOCK, UNLOCK, RENAME and DELETE, to have most of the capability of BASIC.SYSTEM built into it. - This is specific to the Apple ][ port.
usotsuki
Posts: 70
Joined: 23 Dec 2002

Post by usotsuki »

*sigh*

I rewrote part of the LOAD/SAVE handler I'm attaching to ehbasic and it seems not to be doing the right thing here...

Code: Select all

getinstr: jsr LAB_EVST
          tax
          beq jsyner
          lda #$00
          sta namebuf+1, x
          tay
@1:       lda (ut1_pl), y
          sta namebuf, y
          iny
          dex
          bne @1
          rts
What I'm trying to do here is this: this code is called by both LOAD and SAVE, and is supposed to copy a string argument to namebuf, with a null-terminator.

What it ends up copying is the "Ready" prompt, so obviously I'm not doing it right. :/ ("jsyner" is a label containing "jmp LAB_SNER")
usotsuki
Posts: 70
Joined: 23 Dec 2002

Post by usotsuki »

I've gotten past that hurdle and my current issues with the port are now no longer related to EHBASIC itself. I'll continue to combat my own stupidity on the Apple boards/groups and report here if I get anywhere.
User avatar
8BIT
Posts: 1787
Joined: 30 Aug 2002
Location: Sacramento, CA
Contact:

Post by 8BIT »

usotsuki,

I am posting my SAVE command code here with the hope it may help you. On my SBC-3, the DOS expects a save file command to be stores at $0200, starting with the command "SF" followed by the path and file name, a comma, the hex start address, another comma, and then the hex end address. My system uses the / as the folder seperator. EHBASIC will tokenize that, changing it the a $b9. You'll see the test for that below. I also discovered that EHBASIC complained about the command line parameters, i.e. "SAVE DIR/FILENAME.BAS". What I did to fix that was to erase the input buffer as I read it. You may or may not have similar issues. The subroutine "pscan" reads through the EHBASIC program until it finds the end.

Here's a link to my EHBASIC source code on my website, it has more details and all the support files. The file basldsv.asm contains the load and save routines. Hope this gets you going again.

http://sbc.rictor.org/download/EhBASIC.zip

Daryl

Code: Select all

psave		ldx	#$00
		lda	ibuffs+1
		stz	ibuffs+1	; this fixes syntax error in ehbasic
		bne	psave15
		rts
psave1		lda	ibuffs+1,x
		stz	ibuffs+1,x	; this fixes syntax error in ehbasic
		beq	psave3
psave15		cmp	#$b9
		bne	psave2
		lda	#"/"
psave2		sta	$202,x
		inx
		cpx	#$46       ; length of ibuffs
		bne	psave1
		rts			; entry too long, abort
psave3		lda	#","
		sta	$202,x
		inx
		phx
		jsr	pscan		; Find end of program
		plx
		lda	smemh
		jsr	ToHex
		lda	smeml
		jsr	ToHex
		lda	#","
		sta	$202,x
		inx
		lda	itemph
		jsr	ToHex
		lda	itempl
		jsr	ToHex
		lda	#$00
		sta	$202,x
		jsr	SaveF		; save file to IDE (in DiskOS)
		rts
usotsuki
Posts: 70
Joined: 23 Dec 2002

Post by usotsuki »

The error was...buffer page alignment. *faults* (It works now, I got the pointer from a comp.sys.apple2 regular.)

I'm currently trying to add some touches to it. The missing elements I want to get into the wedge by the time I call it gold, right now, are BLOAD/BSAVE, CAT/CATALOG, CREATE, and possibly BRUN and an extension to RUN. CAT will be the trickiest of these.
Post Reply