From 662ba6460aa305dec1933830f7fae0f342b37a7c Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Thu, 6 Dec 2018 01:26:38 +0100 Subject: [PATCH] random number stuff --- prog8lib/c64lib.p8 | 7 ++-- prog8lib/c64utils.p8 | 59 ++++++++++++++++++++++++++ prog8lib/mathlib.p8 | 30 +++++++++++++- prog8lib/prog8lib.p8 | 98 ++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 187 insertions(+), 7 deletions(-) diff --git a/prog8lib/c64lib.p8 b/prog8lib/c64lib.p8 index 2c3e8636c..403fb9ab5 100644 --- a/prog8lib/c64lib.p8 +++ b/prog8lib/c64lib.p8 @@ -141,7 +141,7 @@ asmsub GIVAYF (lo: ubyte @ Y, hi: ubyte @ A) -> clobbers(A,X,Y) -> () = $b391 asmsub FREADUY (unsigned: ubyte @ Y) -> clobbers(A,X,Y) -> () = $b3a2 ; 8 bit unsigned Y -> float in fac1 asmsub FREADSA (signed: ubyte @ A) -> clobbers(A,X,Y) -> () = $bc3c ; 8 bit signed A -> float in fac1 asmsub FREADSTR (length: ubyte @ A) -> clobbers(A,X,Y) -> () = $b7b5 ; str -> fac1, $22/23 must point to string, A=string length -asmsub FPRINTLN () -> clobbers(A,X,Y) -> () = $aabc ; print string of fac1, on one line (= with newline) +asmsub FPRINTLN () -> clobbers(A,X,Y) -> () = $aabc ; print string of fac1, on one line (= with newline) (consider FOUT + STROUT as well) asmsub FOUT () -> clobbers(X) -> (uword @ AY) = $bddd ; fac1 -> string, address returned in AY ($0100) asmsub FADDH () -> clobbers(A,X,Y) -> () = $b849 ; fac1 += 0.5, for rounding- call this before INT @@ -169,8 +169,8 @@ asmsub ABS () -> clobbers() -> () = $bc58 ; fac1 = ABS(fac1) asmsub SQR () -> clobbers(A,X,Y) -> () = $bf71 ; fac1 = SQRT(fac1) asmsub EXP () -> clobbers(A,X,Y) -> () = $bfed ; fac1 = EXP(fac1) (e ** fac1) asmsub NEGOP () -> clobbers(A) -> () = $bfb4 ; switch the sign of fac1 -asmsub RND () -> clobbers(A,X,Y) -> () = $e097 ; fac1 = RND() (tip: use RNDA instead) -asmsub RNDA (acc: ubyte @ A) -> clobbers(A,X,Y) -> () = $e09a ; fac1 = RND(A) +asmsub RND () -> clobbers(A,X,Y) -> () = $e097 ; fac1 = RND() (tip: use RNDA instead) pseudo random number generator +asmsub RNDA (acc: ubyte @ A) -> clobbers(A,X,Y) -> () = $e09a ; fac1 = RND(A) pseudo random number generator asmsub COS () -> clobbers(A,X,Y) -> () = $e264 ; fac1 = COS(fac1) asmsub SIN () -> clobbers(A,X,Y) -> () = $e26b ; fac1 = SIN(fac1) asmsub TAN () -> clobbers(A,X,Y) -> () = $e2b4 ; fac1 = TAN(fac1) @@ -189,6 +189,7 @@ asmsub HOMECRSR () -> clobbers(A,X,Y) -> () = $E566 ; cursor to top left of sc ; ---- C64 kernal routines ---- +asmsub STROUT (strptr: uword @ AY) -> clobbers(A, X, Y) -> () = $AB1E ; print null-terminated string (a bit slow, see if you can use c64scr.print_string instead) asmsub IRQDFRT () -> clobbers(A,X,Y) -> () = $EA31 ; default IRQ routine asmsub IRQDFEND () -> clobbers(A,X,Y) -> () = $EA81 ; default IRQ end/cleanup asmsub CINT () -> clobbers(A,X,Y) -> () = $FF81 ; (alias: SCINIT) initialize screen editor and video chip diff --git a/prog8lib/c64utils.p8 b/prog8lib/c64utils.p8 index 74a828541..e8a712cd1 100644 --- a/prog8lib/c64utils.p8 +++ b/prog8lib/c64utils.p8 @@ -21,6 +21,7 @@ asmsub init_system () -> clobbers(A,X,Y) -> () { ; All three registers set to 0, status flags cleared. %asm {{ sei + jsr determine_start_rnd_seed cld lda #%00101111 sta $00 @@ -41,6 +42,18 @@ asmsub init_system () -> clobbers(A,X,Y) -> () { clv cli rts + +determine_start_rnd_seed + lda c64.TIME_HI + adc c64.TIME_MID + adc c64.TIME_LO + ldy c64.RASTER + sta start_rnd_seed + sty start_rnd_seed+1 + rts + +start_rnd_seed .word $2c9e + }} } @@ -356,6 +369,52 @@ asmsub float_sub_SW1_from_XY (mflt: uword @ XY) -> clobbers(A,X,Y) -> () { }} } +sub print_float (value: float) { + ; ---- prints the floating point value (without a newline) using basic rom routines. + ; clobbers no registers. + %asm {{ + pha + tya + pha + txa + pha + lda #print_float_value + jsr c64.MOVFM ; load float into fac1 + jsr c64.FOUT ; fac1 to string in A/Y + jsr c64.STROUT ; print string in A/Y + pla + tax + pla + tay + pla + rts + }} +} + +sub print_float_ln (value: float) { + ; ---- prints the floating point value (with a newline at the end) using basic rom routines + ; clobbers no registers. + %asm {{ + pha + tya + pha + txa + pha + lda #print_float_ln_value + jsr c64.MOVFM ; load float into fac1 + jsr c64.FPRINTLN ; print fac1 with newline + pla + tax + pla + tay + pla + rts + }} + +} + } ; ------ end of block c64flt diff --git a/prog8lib/mathlib.p8 b/prog8lib/mathlib.p8 index 2cb1ba6b1..4e6a5458c 100644 --- a/prog8lib/mathlib.p8 +++ b/prog8lib/mathlib.p8 @@ -171,6 +171,34 @@ remainder = SCRATCH_ZP1 }} } +asmsub randseed (seed: uword @ AY) -> clobbers() -> () { + ; ---- reset the random seeds for the byte and word random generators + ; default starting values are: A=$2c Y=$9e + %asm {{ + sta randword._seed + sty randword._seed+1 + tya + clc + sbc #100 + sta randbyte._seed + rts + }} +} + +asmsub randseedr () -> clobbers() -> () { + ; ---- initializes the byte and word random generators with the 'random' seed + ; that was stored when the program started. This can be used if you don't + ; want your program to use the same random number sequence every time it is loaded or runs. + %asm {{ + lda c64utils.start_rnd_seed + ldy c64utils.start_rnd_seed+1 + jsr math.randseed + ora #$80 ; make negative + jsr c64.RNDA ; reseed the float rng using the (negative) number in A + rts + }} +} + asmsub randbyte () -> clobbers() -> (ubyte @ A) { ; ---- 8-bit pseudo random number generator into A @@ -185,7 +213,7 @@ asmsub randbyte () -> clobbers() -> (ubyte @ A) { + sta _seed rts - _seed .byte $3a +_seed .byte $3a _magic .byte $1d _magiceors .byte $1d, $2b, $2d, $4d, $5f, $63, $65, $69 .byte $71, $87, $8d, $a9, $c3, $cf, $e7, $f5 diff --git a/prog8lib/prog8lib.p8 b/prog8lib/prog8lib.p8 index c3e98fc8a..303a41269 100644 --- a/prog8lib/prog8lib.p8 +++ b/prog8lib/prog8lib.p8 @@ -11,6 +11,8 @@ memory ubyte SCRATCH_ZP2 = $03 ; scratch register #2 in ZP memory uword SCRATCH_ZPWORD1 = $fb ; scratch word in ZP ($fb/$fc) memory uword SCRATCH_ZPWORD2 = $fd ; scratch word in ZP ($fd/$fe) + const uword ESTACK_LO = $ce00 + const uword ESTACK_HI = $cf00 %asm {{ @@ -28,7 +30,7 @@ ror2_word -; @todo: stubs for now +; @todo: implement stubs! ; @todo: move float operations to their own library (only included when floats are enabled) ub2float @@ -44,12 +46,57 @@ w2float rts push_float + ; ---- push mflpt5 in A/Y onto stack + ; (taking 3 stack positions = 6 bytes of which 1 is padding) + sta SCRATCH_ZPWORD1 + sty SCRATCH_ZPWORD1+1 + ldy #0 + lda SCRATCH_ZPWORD1,y + sta ESTACK_LO,x + iny + lda SCRATCH_ZPWORD1,y + sta ESTACK_HI,x + dex + iny + lda SCRATCH_ZPWORD1,y + sta ESTACK_LO,x + iny + lda SCRATCH_ZPWORD1,y + sta ESTACK_HI,x + dex + iny + lda SCRATCH_ZPWORD1,y + sta ESTACK_LO,x + dex rts + push_float_from_indexed_var rts -pop_var_float +pop_float + ; ---- pops mflpt5 from stack to memory A/Y @TODO CHECK ORDER OF POPS + ; (frees 3 stack positions = 6 bytes of which 1 is padding) + sta SCRATCH_ZPWORD1 + sty SCRATCH_ZPWORD1+1 + ldy #4 + inx + lda ESTACK_LO,x + sta SCRATCH_ZPWORD1,y + dey + inx + lda ESTACK_LO,x + sta SCRATCH_ZPWORD1,y + dey + lda ESTACK_HI,x + sta SCRATCH_ZPWORD1,y + dey + inx + lda ESTACK_LO,x + sta SCRATCH_ZPWORD1,y + lda ESTACK_HI,x + dey + sta SCRATCH_ZPWORD1,y rts pop_float_to_indexed_var @@ -59,6 +106,25 @@ pop_mem_float rts copy_float + ; -- copies the 5 bytes of the mflt value pointed to by SCRATCH_ZPWORD1, + ; into the 5 bytes pointed to by A/Y. Clobbers Y. + sta SCRATCH_ZPWORD2 + sty SCRATCH_ZPWORD2+1 + ldy #0 + lda SCRATCH_ZPWORD1,y + sta SCRATCH_ZPWORD2,y + iny + lda SCRATCH_ZPWORD1,y + sta SCRATCH_ZPWORD2,y + iny + lda SCRATCH_ZPWORD1,y + sta SCRATCH_ZPWORD2,y + iny + lda SCRATCH_ZPWORD1,y + sta SCRATCH_ZPWORD2,y + iny + lda SCRATCH_ZPWORD1,y + sta SCRATCH_ZPWORD2,y rts inc_var_f @@ -243,12 +309,38 @@ func_any rts func_all rts + func_rnd + ; -- put a random ubyte on the estack + jsr math.randbyte + sta ESTACK_LO,x + dex rts + func_rndw + ; -- put a random uword on the estack + jsr math.randword + sta ESTACK_LO,x + tya + sta ESTACK_HI,x + dex rts + func_rndf - rts + ; -- put a random floating point value on the stack + stx SCRATCH_ZP1 + lda #39 + jsr c64.RNDA ; rng into fac1 + ldx #<_rndf_rnum5 + ldy #>_rndf_rnum5 + jsr c64.FTOMEMXY ; fac1 to mem X/Y + ldx SCRATCH_ZP1 + lda #<_rndf_rnum5 + ldy #>_rndf_rnum5 + jmp push_float +_rndf_rnum5 .fill 5 + + func_wrd rts func_uwrd