Article 154499 of comp.sys.apple2: Newsgroups: comp.sys.apple2,comp.emulators.apple2 Subject: Re: And now, from the author of the DOS Disk post, a post that actually relates to this newsgroup. From: dempson@actrix.gen.nz (David Empson) Date: Sun, 14 Nov 1999 01:07:53 +1300 Message-ID: <1e18fih.qho731vo48pqN%dempson@actrix.gen.nz> References: <1e17yeq.16d8k6h1ff8ugwN%dempson@actrix.gen.nz> Organization: Empsoft User-Agent: MacSOUP/2.4.2 NNTP-Posting-Host: 202.49.157.176 X-Original-NNTP-Posting-Host: 202.49.157.176 X-Trace: 14 Nov 1999 01:07:29 NZST, 202.49.157.176 Lines: 172 Path: news1.icaen!news.uiowa.edu!news.physics.uiowa.edu!hammer.uoregon.edu!logbridge.uoregon.edu!newsfeed.berkeley.edu!news-stock.gip.net!news.gsl.net!gip.net!news.iprolink.co.nz!news.actrix.gen.nz!dempson Xref: news1.icaen comp.sys.apple2:154499 comp.emulators.apple2:17903 Jon Bettencourt wrote: > No. This COM is of type $FA. Ah, so it is just usurping the file type which is reserved for an Integer BASIC program. > In article <1e17yeq.16d8k6h1ff8ugwN%dempson@actrix.gen.nz>, > dempson@actrix.gen.nz (David Empson) wrote: > > > For example, there was a series of articles published in "The > > Sourceror's Apprentice" many years ago, which described a cyclic > > shift/XOR-based random number generator. It generates 8-bit random > > numbers from a 32-bit seed variable, and has a repeat period of 2^32-1 > > (4194962795). The seed can be any value except zero, and could be > > derived from memory locations $4E and $4F, which are incremented > > continuously while the system is waiting for a keypress (with the > > standard monitor routines, as used by GET and INPUT from BASIC). > > I don't want to have it wait until a keypress. The point is that you don't need to wait for a keypress again - as long as the computer has waited for a keypress at any point since it last booted, then these two locations contain a random number which is dependent on the speed of the computer and how long the user waited before pressing each key (cumulative). > Might there be any memory location that is always changing that I > can use as a random number? Nope. Some I/O locations might produce something which is slightly random, but I wouldn't recommend trying it. In the IIgs you can access the horizontal scan position and use that as a semi-random seed (but only if the amount of time from the last reset is somewhat unpredictable). Another option is to use a real time clock, if there is one, since it should always produce a different value. No matter where your initial value comes from, it should only be used as a seed for the pseudo-random number generator. You can't expect to get more than one "random" number out of any of the above sources, unless you can somehow depend on unpredictable external activity, e.g. the actions of the user. OK, I've found the article. It was published in The Sourceror's Apprentice, Volume 1 Number 4 (April 1989). The article was called "Random Bytes", and was written by Robert C Moore of the Applied Physics Laboratory at the John Hopkins University in Laurel, Maryland. The article covers two designs for shift and exclusive OR random number generators. I'll use the simpler one here, which has a shorter period of 2^25-1 (33554431). To use this routine you need a four bytes to hold a the random number seed. I'll use memory locations $3C1 through $3C4 for the random number working variable. The variable is stored in little-endian order (low order byte first). After each call to the RANDOM routine, the new random 8-bit number can be taken from the first byte of the variable (at $03CC). If you need a random number larger than 8 bits, it is necessary to call the RANDOM routine once for each 8-bit result. Don't try to use the values stored in the second, third or fourth byte of the variable. Before this routine can be used, the random number variable must be seeded from an appropriate source, with a 25-bit to 32-bit value which can be anything except zero. (You will always get the same sequence of results if you use the same seed value each time.) If you can only provide a shorter seed value (e.g. 16 bits), then it is a good idea to "kick start" the random number generator by generating several random numbers before you start to use the result (otherwise you are likely to get several zero bytes for the first few "random" numbers). Here is the random number routine in source form: R1 EQU $03CC R2 EQU $03CD R3 EQU $03CE R4 EQU $03CF RANDOM ROR R4 ; Bit 25 to carry LDA R3 ; Shift left 8 bits STA R4 LDA R2 STA R3 LDA R1 STA R2 LDA R4 ; Get original bits 17-24 ROR ; Now bits 18-25 in ACC ROL R1 ; R1 holds bits 1-7 EOR R1 ; Seven bits at once ROR R4 ; Shift right by one bit ROR R3 ROR R2 ROR STA R1 RTS Here is a routine to seed the random number generator with a reasonable initial value: INITRAND LDA $4E ; Seed the random number generator STA R1 ; based on delay between keypresses STA R3 LDA $4F STA R2 STA R4 LDX #$20 ; Generate a few random numbers INITLOOP JSR RANDOM ; to kick things off DEX BNE INITLOOP RTS Now to wrap this in a "fill the hi-res graphics screen" routine: NOISEGEN JSR INITRAND ; Seed the random number generator LDA #$00 STA $3C ; Borrow monitor variables for a pointer LDA #$20 STA $3D LDY #$00 ; Initialize the offset LDX #$20 ; and the page count FILLLOOP JSR RANDOM STA ($3C),Y INY BNE FILLLOOP INC $3D DEX BNE FILLLOOP RTS Converting this to machine code, I'll put the NOISEGEN routine at $0300, the INITRAND routine at $0320, and the RANDOM routine at $0340. Here are the monitor commands necessary to enter this program into memory: 0300:20 20 03 A9 00 85 3C A9 20 85 3D A0 00 A2 20 20 0310:40 03 91 3C C8 D0 F8 E6 3D CA D0 F3 60 EA EA EA 0320:A5 4E 8D C1 03 8D C3 03 A5 4F 8D C2 03 8D C4 03 0330:A2 20 20 40 03 CA D0 FA 60 EA EA EA EA EA EA EA 0340:6E C4 03 AD C3 03 8D C4 03 AD C2 03 8D C3 03 AD 0350:C1 03 8D C2 03 AD C4 03 6A 2E C1 03 4D C1 03 6E 0360:C4 03 6E C3 03 6E C2 03 6A 8D C1 03 60 If you want to save the whole thing, use: BSAVE NOISEGEN,A$300,L$6D I've tried it out on my IIgs, and it seems to work fine. With the system set to Normal speed (1 MHz), it takes about 1 second to fill the screen, which is somewhat slower than the clear screen routine, but not enough to worry about. It looks pretty random to me. Note that if you want to do this again (getting a different pattern), you should avoid calling INITRAND more than once. You can use CALL 800 to call the INITRAND routine directly, then use CALL 771 for each random fill. If you only need to use it once, just CALL 768. -- David Empson dempson@actrix.gen.nz Snail mail: P O Box 27-103, Wellington, New Zealand