From db18f631485eea0b1e7d6c8cf853ff4a281c2aba Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Thu, 27 May 2021 17:12:46 -0400 Subject: cash_dirty, change random seeding, now 9006 bytes --- rand.s | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) (limited to 'rand.s') diff --git a/rand.s b/rand.s index 6efcabd..f1b2c72 100644 --- a/rand.s +++ b/rand.s @@ -1,6 +1,5 @@ .export _randl, _rand1to3 - .import _rand ; .export _randb, _randi, _randl ; .export _rand1in5 ; .export _randbit @@ -37,6 +36,109 @@ _rand1to3: ldx #0 ; now A is 1..3, but we have to force X to 0... rts +;;; This rand() function copied from cc65-2.19's libsrc/common/rand.s +;;; and modified for my nefarious purposes. +;;; srand() is not present (we don't use it). +; +; Random number generator +; +; Written and donated by Sidney Cadot - sidney@ch.twi.tudelft.nl +; 2016-11-07, modified by Brad Smith +; 2019-10-07, modified by Lewis "LRFLEW" Fox +; +; May be distributed with the cc65 runtime using the same license. +; +; +; int rand (void); +; void srand (unsigned seed); +; +; Uses 4-byte state. +; Multiplier must be 1 (mod 4) +; Added value must be 1 (mod 2) +; This guarantees max. period (2**32) +; The lowest bits have poor entropy and +; exhibit easily detectable patterns, so +; only the upper bits 16-22 and 24-31 of the +; 4-byte state are returned. +; +; The best 8 bits, 24-31 are returned in the +; low byte A to provide the best entropy in the +; most commonly used part of the return value. +; +; Uses the following LCG values for ax + c (mod m) +; a = $01010101 +; c = $B3B3B3B3 +; m = $100000000 (32-bit truncation) +; +; The multiplier was carefully chosen such that it can +; be computed with 3 adc instructions, and the increment +; was chosen to have the same value in each byte to allow +; the addition to be performed in conjunction with the +; multiplication, adding only 1 additional adc instruction. +; + + .export _rand, _randseed, _randseedl, _randseedh, _initrand, _addrandbits + +.bss + +; The seed. Not ANSI C compliant: we default to 0 rather than 1. +_randseedl: +_randseed: .res 4 +_randseedh = _randseed+2 + +.code + +_rand: clc + lda _randseed+0 + adc #$B3 + sta _randseed+0 + adc _randseed+1 + sta _randseed+1 + adc _randseed+2 + sta _randseed+2 + and #$7f ; Suppress sign bit (make it positive) + tax + lda _randseed+2 + adc _randseed+3 + sta _randseed+3 + rts ; return bit (16-22,24-31) in (X,A) + +; Initially the seed comes from sequential reads of POKEY's random +; register. It never returns 0 so we're guaranteed to have a usable +; seed. +_initrand: + ldx #3 +@l: + lda RANDOM + sta _randseed,x + dex + bpl @l + rts + +; Caller passes us a user keystroke as ATASCII, in A. We take bits 0 +; to 2, wait that many scanlines, get a random number from POKEY, and +; EOR it into the _randseed byte pointed to by the low 2 bits of the +; frame counter (RTCLOK+2). +; Note that agetc() is still calling rand() on odd frames while all +; this is going on. +_addrandbits: + and #$07 + tax +@l1: + sta WSYNC + dex + bpl @l1 + lda RTCLOK+2 + and #$03 + tax + lda RANDOM +@e: + eor _randseed,x + beq @e ; if the result is 0, undo the eor. + sta _randseed,x + rts + + ;;; rest of file is commented out ; RANDOM is the POKEY LFSR read address. According to the POKEY data -- cgit v1.2.3