mirror of
https://github.com/irmen/prog8.git
synced 2024-11-20 03:32:05 +00:00
rnd()/rndf() routines can now be seeded with new rndseed()/rndseedf() routines. fixes #80
This commit is contained in:
parent
733c17ad3a
commit
ec5adffdc2
@ -56,7 +56,7 @@ romsub $af4b = ROUND() clobbers(A,X,Y) ; round fac1
|
||||
romsub $af4e = ABS() clobbers(A,X,Y) ; fac1 = ABS(fac1)
|
||||
romsub $af51 = SIGN() clobbers(X,Y) -> ubyte @ A ; SIGN(fac1) to A, $ff, $0, $1 for negative, zero, positive
|
||||
romsub $af54 = FCOMP(uword mflpt @ AY) clobbers(X,Y) -> ubyte @ A ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than
|
||||
romsub $af57 = RND_0() clobbers(A,X,Y) ; fac1 = RND(fac1) float random number generator NOTE: special cx16 setup required, use RND() stub instead!!
|
||||
romsub $af57 = RND_0() clobbers(A,X,Y) ; fac1 = RND(fac1) float random number generator
|
||||
romsub $af5a = CONUPK(uword mflpt @ AY) clobbers(A,X,Y) ; load mflpt value from memory in A/Y into fac2
|
||||
romsub $af5d = ROMUPK(uword mflpt @ AY) clobbers(A,X,Y) ; load mflpt value from memory in current bank in A/Y into fac2
|
||||
romsub $af60 = MOVFRM(uword mflpt @ AY) clobbers(A,X,Y) ; load mflpt value from memory in A/Y into fac1 (use MOVFM instead)
|
||||
@ -151,6 +151,32 @@ asmsub FREADUY (ubyte value @Y) {
|
||||
|
||||
&uword AYINT_facmo = $66 ; $66/$67 contain result of AYINT
|
||||
|
||||
sub rndf() -> float {
|
||||
%asm {{
|
||||
stx P8ZP_SCRATCH_REG
|
||||
lda #1
|
||||
jsr RND_0
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub rndseedf(ubyte s1 @A, ubyte s2 @X, ubyte s3 @Y) clobbers(X) {
|
||||
%asm {{
|
||||
sta _tmpseed
|
||||
stx _tmpseed+1
|
||||
sty _tmpseed+2
|
||||
stx _tmpseed+3
|
||||
sty _tmpseed+4
|
||||
lda #<_tmpseed
|
||||
ldy #>_tmpseed
|
||||
jsr MOVFM
|
||||
lda #-1
|
||||
jmp RND_0
|
||||
_tmpseed .byte 0,0,0,0,0
|
||||
}}
|
||||
}
|
||||
|
||||
%asminclude "library:c128/floats.asm"
|
||||
%asminclude "library:c64/floats_funcs.asm"
|
||||
|
||||
|
@ -171,6 +171,29 @@ asmsub GETADRAY () clobbers(X) -> uword @ AY {
|
||||
|
||||
&uword AYINT_facmo = $64 ; $64/$65 contain result of AYINT
|
||||
|
||||
sub rndf() -> float {
|
||||
%asm {{
|
||||
stx P8ZP_SCRATCH_REG
|
||||
lda #1
|
||||
jsr FREADSA
|
||||
jsr RND ; rng into fac1
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub rndseedf(ubyte s1 @A, ubyte s2 @X, ubyte s3 @Y) clobbers(X) {
|
||||
%asm {{
|
||||
pha
|
||||
tya
|
||||
ora #128 ; make sure the seed is negative
|
||||
tay
|
||||
pla
|
||||
jsr FREADS24AXY
|
||||
jmp RND
|
||||
}}
|
||||
}
|
||||
|
||||
%asminclude "library:c64/floats.asm"
|
||||
%asminclude "library:c64/floats_funcs.asm"
|
||||
|
||||
|
@ -57,7 +57,7 @@ romsub $fe4b = ROUND() clobbers(A,X,Y) ; round fac1
|
||||
romsub $fe4e = ABS() clobbers(A,X,Y) ; fac1 = ABS(fac1)
|
||||
romsub $fe51 = SIGN() clobbers(X,Y) -> ubyte @ A ; SIGN(fac1) to A, $ff, $0, $1 for negative, zero, positive
|
||||
romsub $fe54 = FCOMP(uword mflpt @ AY) clobbers(X,Y) -> ubyte @ A ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than
|
||||
romsub $fe57 = RND_0() clobbers(A,X,Y) ; fac1 = RND(fac1) float random number generator NOTE: special cx16 setup required, use RND() stub instead!!
|
||||
romsub $fe57 = RND_0() clobbers(A,X,Y) ; fac1 = RND(fac1) float random number generator NOTE: incompatible with C64's RND routine
|
||||
romsub $fe5a = CONUPK(uword mflpt @ AY) clobbers(A,X,Y) ; load mflpt value from memory in A/Y into fac2
|
||||
romsub $fe5d = ROMUPK(uword mflpt @ AY) clobbers(A,X,Y) ; load mflpt value from memory in current bank in A/Y into fac2
|
||||
romsub $fe60 = MOVFRM(uword mflpt @ AY) clobbers(A,X,Y) ; load mflpt value from memory in A/Y into fac1 (use MOVFM instead)
|
||||
@ -147,17 +147,31 @@ asmsub FREADUY (ubyte value @Y) {
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub RND() clobbers(A,X,Y) {
|
||||
|
||||
&uword AYINT_facmo = $c6 ; $c6/$c7 contain result of AYINT
|
||||
|
||||
sub rndf() -> float {
|
||||
%asm {{
|
||||
lda #0
|
||||
php
|
||||
jsr cx16.entropy_get
|
||||
plp
|
||||
jmp RND_0
|
||||
phx
|
||||
lda #1
|
||||
jsr RND_0
|
||||
plx
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub rndseedf(ubyte s1 @A, ubyte s2 @X, ubyte s3 @Y) clobbers(X) {
|
||||
%asm {{
|
||||
sta P8ZP_SCRATCH_REG
|
||||
lda #0
|
||||
php
|
||||
lda P8ZP_SCRATCH_REG
|
||||
ora #32 ; not sure why this is needed but without it the seed is not consistent
|
||||
plp ; Z=N=0
|
||||
jmp floats.RND_0
|
||||
}}
|
||||
}
|
||||
|
||||
&uword AYINT_facmo = $c6 ; $c6/$c7 contain result of AYINT
|
||||
|
||||
%asminclude "library:c64/floats.asm"
|
||||
%asminclude "library:c64/floats_funcs.asm"
|
||||
|
@ -221,15 +221,4 @@ sub ceil(float value) -> float {
|
||||
}}
|
||||
}
|
||||
|
||||
sub rndf() -> float {
|
||||
%asm {{
|
||||
stx P8ZP_SCRATCH_REG
|
||||
lda #1
|
||||
jsr FREADSA
|
||||
jsr RND ; rng into fac1
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -229,23 +229,7 @@ _divisor .word 0
|
||||
.pend
|
||||
|
||||
|
||||
randseed .proc
|
||||
; -- reset the random seeds for the byte and word random generators
|
||||
; arguments: uword seed in A/Y clobbers A
|
||||
; (default starting values are: A=$2c Y=$9e)
|
||||
sta randword._seed
|
||||
sty randword._seed+1
|
||||
clc
|
||||
adc #14
|
||||
sta randbyte._seed
|
||||
rts
|
||||
.pend
|
||||
|
||||
|
||||
randbyte .proc
|
||||
; -- 8 bit pseudo random number generator into A (by just reusing randword)
|
||||
jmp randword
|
||||
.pend
|
||||
randbyte = randword ; -- 8 bit pseudo random number generator into A (by just reusing randword)
|
||||
|
||||
randword .proc
|
||||
; -- 16 bit pseudo random number generator into AY
|
||||
|
@ -71,4 +71,16 @@ _sinecosR8 .char trunc(127.0 * sin(range(180+45) * rad(360.0/180.0)))
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub rndseed(uword seed1 @AY, uword seed2 @R0) clobbers(A,Y) {
|
||||
; -- reset the pseudo RNG's seed values. Defaults are: $a55a, $7653.
|
||||
%asm {{
|
||||
sta math.randword.sr1
|
||||
sty math.randword.sr1+1
|
||||
lda cx16.r0L
|
||||
ldy cx16.r0H
|
||||
sta math.randword.sr2
|
||||
sty math.randword.sr2+1
|
||||
rts
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
@ -130,4 +130,14 @@ sub rndf() -> float {
|
||||
return
|
||||
}}
|
||||
}
|
||||
|
||||
sub rndseedf(ubyte s1, ubyte s2, ubyte s3) {
|
||||
%ir {{
|
||||
loadm.b r0,floats.rndseedf.s1
|
||||
loadm.b r1,floats.rndseedf.s2
|
||||
loadm.b r2,floats.rndseedf.s3
|
||||
syscall 32
|
||||
}}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -159,4 +159,13 @@ math {
|
||||
return costab[radians] as byte
|
||||
}
|
||||
|
||||
|
||||
sub rndseed(uword seed1, uword seed2) {
|
||||
; -- reset the pseudo RNG's seed values. Defaults are: $a55a, $7653.
|
||||
%ir {{
|
||||
loadm.w r0,math.rndseed.seed1
|
||||
loadm.w r1,math.rndseed.seed2
|
||||
syscall 31
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,10 @@ TODO
|
||||
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- ir: get rid of IRCodeLabel, make every label start a new code chunk, give those a 'label' property.
|
||||
- ir: fix joinChunks() in the IR optimizer ?
|
||||
- replace rnd() builtin functions by regular functions in math and in floats
|
||||
- update docs for rnd() and rndseed() functions
|
||||
- ir: replace RND opcodes by syscalls
|
||||
- ir: asmsub contents remains blank in IR file
|
||||
|
||||
...
|
||||
|
||||
|
@ -1,23 +1,45 @@
|
||||
%import textio
|
||||
%import math
|
||||
%import floats
|
||||
%zeropage basicsafe
|
||||
|
||||
main {
|
||||
asmsub multi() -> ubyte @A, ubyte @Pc {
|
||||
%asm {{
|
||||
lda #42
|
||||
sec
|
||||
rts
|
||||
}}
|
||||
|
||||
sub printnumbers() {
|
||||
txt.print_ub(rnd())
|
||||
txt.spc()
|
||||
txt.print_ub(rnd())
|
||||
txt.spc()
|
||||
txt.print_ub(rnd())
|
||||
txt.nl()
|
||||
txt.print_uw(rndw())
|
||||
txt.spc()
|
||||
txt.print_uw(rndw())
|
||||
txt.spc()
|
||||
txt.print_uw(rndw())
|
||||
txt.nl()
|
||||
floats.print_f(floats.rndf())
|
||||
txt.spc()
|
||||
floats.print_f(floats.rndf())
|
||||
txt.spc()
|
||||
floats.print_f(floats.rndf())
|
||||
txt.nl()
|
||||
}
|
||||
|
||||
|
||||
sub start() {
|
||||
ubyte value
|
||||
|
||||
value = multi()
|
||||
|
||||
while 0==multi() {
|
||||
value++
|
||||
}
|
||||
|
||||
if multi() {
|
||||
value++
|
||||
}
|
||||
txt.print("initial:\n")
|
||||
math.rndseed($a55a, $7653)
|
||||
floats.rndseedf(11,22,33)
|
||||
printnumbers()
|
||||
txt.print("\nsame seeds:\n")
|
||||
math.rndseed($a55a, $7653)
|
||||
floats.rndseedf(11,22,33)
|
||||
printnumbers()
|
||||
txt.print("\ndifferent seeds:\n")
|
||||
math.rndseed($1234, $5678)
|
||||
floats.rndseedf(44,55,66)
|
||||
printnumbers()
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,8 @@ SYSCALLS:
|
||||
28 = reverse_floats array
|
||||
29 = compare strings
|
||||
30 = gfx_getpixel ; get byte pixel value at coordinates r0.w/r1.w
|
||||
31 = rndseed
|
||||
32 = rndfseed
|
||||
*/
|
||||
|
||||
enum class Syscall {
|
||||
@ -70,7 +72,9 @@ enum class Syscall {
|
||||
REVERSE_WORDS,
|
||||
REVERSE_FLOATS,
|
||||
COMPARE_STRINGS,
|
||||
GFX_GETPIXEL
|
||||
GFX_GETPIXEL,
|
||||
RNDSEED,
|
||||
RNDFSEED
|
||||
}
|
||||
|
||||
object SysCalls {
|
||||
@ -279,6 +283,17 @@ object SysCalls {
|
||||
val comparison = first.compareTo(second)
|
||||
vm.registers.setSB(0, comparison.toByte())
|
||||
}
|
||||
Syscall.RNDFSEED -> {
|
||||
val seed1 = vm.registers.getUB(0)
|
||||
val seed2 = vm.registers.getUB(1)
|
||||
val seed3 = vm.registers.getUB(2)
|
||||
vm.randomSeedFloat(seed1, seed2, seed3)
|
||||
}
|
||||
Syscall.RNDSEED -> {
|
||||
val seed1 = vm.registers.getUW(0)
|
||||
val seed2 = vm.registers.getUW(1)
|
||||
vm.randomSeed(seed1, seed2)
|
||||
}
|
||||
else -> throw AssemblyError("missing syscall ${call.name}")
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,8 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
var statusCarry = false
|
||||
var statusZero = false
|
||||
var statusNegative = false
|
||||
private var randomGenerator = Random(0xa55a7653)
|
||||
private var randomGeneratorFloats = Random(0xc0d3dbad)
|
||||
private val cx16virtualregsBaseAddress: Int
|
||||
|
||||
init {
|
||||
@ -1061,9 +1063,9 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
|
||||
private fun InsRND(i: IRInstruction) {
|
||||
when(i.type!!) {
|
||||
IRDataType.BYTE -> registers.setUB(i.reg1!!, Random.nextInt().toUByte())
|
||||
IRDataType.WORD -> registers.setUW(i.reg1!!, Random.nextInt().toUShort())
|
||||
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, Random.nextFloat())
|
||||
IRDataType.BYTE -> registers.setUB(i.reg1!!, randomGenerator.nextInt().toUByte())
|
||||
IRDataType.WORD -> registers.setUW(i.reg1!!, randomGenerator.nextInt().toUShort())
|
||||
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, randomGeneratorFloats.nextFloat())
|
||||
}
|
||||
pc++
|
||||
}
|
||||
@ -2105,6 +2107,15 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
fun waitvsync() {
|
||||
Toolkit.getDefaultToolkit().sync() // not really the same as wait on vsync, but there's noting else
|
||||
}
|
||||
|
||||
fun randomSeed(seed1: UShort, seed2: UShort) {
|
||||
randomGenerator = Random(((seed1.toUInt() shl 16) or seed2.toUInt()).toInt())
|
||||
}
|
||||
|
||||
fun randomSeedFloat(seed1: UByte, seed2: UByte, seed3: UByte) {
|
||||
val seed = (seed1.toUInt() shl 24) or (seed2.toUInt() shl 16) or (seed3.toUInt())
|
||||
randomGeneratorFloats = Random(seed.toInt())
|
||||
}
|
||||
}
|
||||
|
||||
// probably called via reflection
|
||||
|
Loading…
Reference in New Issue
Block a user