mirror of
https://github.com/irmen/prog8.git
synced 2024-09-07 19:54:26 +00:00
Merge branch 'master' into labeledchunks
# Conflicts: # codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt # docs/source/todo.rst # examples/test.p8 # virtualmachine/src/prog8/vm/VirtualMachine.kt
This commit is contained in:
commit
76428b16f0
@ -43,7 +43,6 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
|
|||||||
"abs" -> funcAbs(fcall, func, resultToStack, resultRegister, sscope)
|
"abs" -> funcAbs(fcall, func, resultToStack, resultRegister, sscope)
|
||||||
"any", "all" -> funcAnyAll(fcall, func, resultToStack, resultRegister, sscope)
|
"any", "all" -> funcAnyAll(fcall, func, resultToStack, resultRegister, sscope)
|
||||||
"sgn" -> funcSgn(fcall, func, resultToStack, resultRegister, sscope)
|
"sgn" -> funcSgn(fcall, func, resultToStack, resultRegister, sscope)
|
||||||
"rnd", "rndw" -> funcRnd(func, resultToStack, resultRegister, sscope)
|
|
||||||
"sqrt16" -> funcSqrt16(fcall, func, resultToStack, resultRegister, sscope)
|
"sqrt16" -> funcSqrt16(fcall, func, resultToStack, resultRegister, sscope)
|
||||||
"rol" -> funcRol(fcall)
|
"rol" -> funcRol(fcall)
|
||||||
"rol2" -> funcRol2(fcall)
|
"rol2" -> funcRol2(fcall)
|
||||||
@ -687,28 +686,6 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun funcRnd(func: FSignature, resultToStack: Boolean, resultRegister: RegisterOrPair?, scope: Subroutine?) {
|
|
||||||
when(func.name) {
|
|
||||||
"rnd" -> {
|
|
||||||
if(resultToStack)
|
|
||||||
asmgen.out(" jsr prog8_lib.func_rnd_stack")
|
|
||||||
else {
|
|
||||||
asmgen.out(" jsr math.randbyte")
|
|
||||||
assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, scope, asmgen), CpuRegister.A)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"rndw" -> {
|
|
||||||
if(resultToStack)
|
|
||||||
asmgen.out(" jsr prog8_lib.func_rndw_stack")
|
|
||||||
else {
|
|
||||||
asmgen.out(" jsr math.randword")
|
|
||||||
assignAsmGen.assignRegisterpairWord(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, false, scope, asmgen), RegisterOrPair.AY)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> throw AssemblyError("wrong func")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun funcPokeW(fcall: IFunctionCall) {
|
private fun funcPokeW(fcall: IFunctionCall) {
|
||||||
when(val addrExpr = fcall.args[0]) {
|
when(val addrExpr = fcall.args[0]) {
|
||||||
is NumericLiteral -> {
|
is NumericLiteral -> {
|
||||||
|
@ -852,7 +852,8 @@ internal class AssignmentAsmGen(private val program: Program,
|
|||||||
fun assignViaExprEval(addressExpression: Expression) {
|
fun assignViaExprEval(addressExpression: Expression) {
|
||||||
asmgen.assignExpressionToVariable(addressExpression, "P8ZP_SCRATCH_W2", DataType.UWORD, null)
|
asmgen.assignExpressionToVariable(addressExpression, "P8ZP_SCRATCH_W2", DataType.UWORD, null)
|
||||||
asmgen.loadAFromZpPointerVar("P8ZP_SCRATCH_W2")
|
asmgen.loadAFromZpPointerVar("P8ZP_SCRATCH_W2")
|
||||||
assignRegisterByte(target, CpuRegister.A)
|
asmgen.out(" ldy #0")
|
||||||
|
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||||
}
|
}
|
||||||
|
|
||||||
when (value.addressExpression) {
|
when (value.addressExpression) {
|
||||||
@ -1972,18 +1973,10 @@ internal class AssignmentAsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun assignRegisterByte(target: AsmAssignTarget, register: CpuRegister) {
|
internal fun assignRegisterByte(target: AsmAssignTarget, register: CpuRegister) {
|
||||||
// we make an exception in the type check for assigning something to a cx16 virtual register, or a register pair
|
// we make an exception in the type check for assigning something to a register pair AX, AY or XY
|
||||||
// these will be correctly typecasted from a byte to a word value
|
// these will be correctly typecasted from a byte to a word value here
|
||||||
if(target.register !in Cx16VirtualRegisters &&
|
if(target.register !in setOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY))
|
||||||
target.register!=RegisterOrPair.AX && target.register!=RegisterOrPair.AY && target.register!=RegisterOrPair.XY) {
|
require(target.datatype in ByteDatatypes)
|
||||||
if(target.kind== TargetStorageKind.VARIABLE) {
|
|
||||||
val parts = target.asmVarname.split('.')
|
|
||||||
if (parts.size != 2 || parts[0] != "cx16")
|
|
||||||
require(target.datatype in ByteDatatypes)
|
|
||||||
} else {
|
|
||||||
require(target.datatype in ByteDatatypes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
when(target.kind) {
|
when(target.kind) {
|
||||||
TargetStorageKind.VARIABLE -> {
|
TargetStorageKind.VARIABLE -> {
|
||||||
|
@ -4,7 +4,6 @@ import prog8.code.StStaticVariable
|
|||||||
import prog8.code.ast.*
|
import prog8.code.ast.*
|
||||||
import prog8.code.core.AssemblyError
|
import prog8.code.core.AssemblyError
|
||||||
import prog8.code.core.DataType
|
import prog8.code.core.DataType
|
||||||
import prog8.code.core.Position
|
|
||||||
import prog8.intermediate.*
|
import prog8.intermediate.*
|
||||||
|
|
||||||
|
|
||||||
@ -26,8 +25,6 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
|||||||
"rsavex",
|
"rsavex",
|
||||||
"rrestore",
|
"rrestore",
|
||||||
"rrestorex" -> emptyList() // vm doesn't have registers to save/restore
|
"rrestorex" -> emptyList() // vm doesn't have registers to save/restore
|
||||||
"rnd" -> funcRnd(resultRegister, call.position)
|
|
||||||
"rndw" -> funcRndw(resultRegister, call.position)
|
|
||||||
"callfar" -> throw AssemblyError("callfar() is for cx16 target only")
|
"callfar" -> throw AssemblyError("callfar() is for cx16 target only")
|
||||||
"callrom" -> throw AssemblyError("callrom() is for cx16 target only")
|
"callrom" -> throw AssemblyError("callrom() is for cx16 target only")
|
||||||
"msb" -> funcMsb(call, resultRegister)
|
"msb" -> funcMsb(call, resultRegister)
|
||||||
@ -361,18 +358,6 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun funcRnd(resultRegister: Int, position: Position): IRCodeChunks {
|
|
||||||
val code = IRCodeChunk(null, position, null)
|
|
||||||
code += IRInstruction(Opcode.RND, IRDataType.BYTE, reg1=resultRegister)
|
|
||||||
return listOf(code)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun funcRndw(resultRegister: Int, position: Position): IRCodeChunks {
|
|
||||||
val code = IRCodeChunk(null, position, null)
|
|
||||||
code += IRInstruction(Opcode.RND, IRDataType.WORD, reg1=resultRegister)
|
|
||||||
return listOf(code)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun funcMemory(call: PtBuiltinFunctionCall, resultRegister: Int): IRCodeChunks {
|
private fun funcMemory(call: PtBuiltinFunctionCall, resultRegister: Int): IRCodeChunks {
|
||||||
val name = (call.args[0] as PtString).value
|
val name = (call.args[0] as PtString).value
|
||||||
val code = IRCodeChunk(null, call.position, null)
|
val code = IRCodeChunk(null, call.position, null)
|
||||||
|
@ -56,7 +56,7 @@ romsub $af4b = ROUND() clobbers(A,X,Y) ; round fac1
|
|||||||
romsub $af4e = ABS() clobbers(A,X,Y) ; fac1 = ABS(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 $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 $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 $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 $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)
|
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
|
&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:c128/floats.asm"
|
||||||
%asminclude "library:c64/floats_funcs.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
|
&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.asm"
|
||||||
%asminclude "library:c64/floats_funcs.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 $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 $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 $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 $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 $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)
|
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 {{
|
%asm {{
|
||||||
lda #0
|
phx
|
||||||
php
|
lda #1
|
||||||
jsr cx16.entropy_get
|
jsr RND_0
|
||||||
plp
|
plx
|
||||||
jmp RND_0
|
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.asm"
|
||||||
%asminclude "library:c64/floats_funcs.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,60 +229,32 @@ _divisor .word 0
|
|||||||
.pend
|
.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
|
|
||||||
|
|
||||||
randword .proc
|
randword .proc
|
||||||
; -- 16 bit pseudo random number generator into AY
|
; -- 16 bit pseudo random number generator into AY
|
||||||
|
; default seed = $00c2 $1137
|
||||||
; rand64k ;Factors of 65535: 3 5 17 257
|
; routine from https://codebase64.org/doku.php?id=base:x_abc_random_number_generator_8_16_bit
|
||||||
lda sr1+1
|
inc x1
|
||||||
asl a
|
clc
|
||||||
asl a
|
x1=*+1
|
||||||
eor sr1+1
|
lda #$00 ;x1
|
||||||
asl a
|
c1=*+1
|
||||||
eor sr1+1
|
eor #$c2 ;c1
|
||||||
asl a
|
a1=*+1
|
||||||
asl a
|
eor #$11 ;a1
|
||||||
eor sr1+1
|
sta a1
|
||||||
asl a
|
b1=*+1
|
||||||
rol sr1 ;shift this left, "random" bit comes from low
|
adc #$37 ;b1
|
||||||
rol sr1+1
|
sta b1
|
||||||
; rand32k ;Factors of 32767: 7 31 151 are independent and can be combined
|
lsr a
|
||||||
lda sr2+1
|
eor a1
|
||||||
asl a
|
adc c1
|
||||||
eor sr2+1
|
sta c1
|
||||||
asl a
|
ldy b1
|
||||||
asl a
|
|
||||||
ror sr2 ;shift this right, random bit comes from high - nicer when eor with sr1
|
|
||||||
rol sr2+1
|
|
||||||
lda sr1+1 ;can be left out
|
|
||||||
eor sr2+1 ;if you dont use
|
|
||||||
tay ;y as suggested
|
|
||||||
lda sr1 ;mix up lowbytes of SR1
|
|
||||||
eor sr2 ;and SR2 to combine both
|
|
||||||
rts
|
rts
|
||||||
|
|
||||||
sr1 .word $a55a
|
|
||||||
sr2 .word $7653
|
|
||||||
|
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
|
randbyte = randword ; -- 8 bit pseudo random number generator into A (by just reusing randword)
|
||||||
|
|
||||||
|
|
||||||
; ----------- optimized multiplications (stack) : ---------
|
; ----------- optimized multiplications (stack) : ---------
|
||||||
stack_mul_byte_3 .proc
|
stack_mul_byte_3 .proc
|
||||||
|
@ -71,4 +71,28 @@ _sinecosR8 .char trunc(127.0 * sin(range(180+45) * rad(360.0/180.0)))
|
|||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
asmsub rnd() -> ubyte @A {
|
||||||
|
%asm {{
|
||||||
|
jmp math.randbyte
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
asmsub rndw() -> uword @AY {
|
||||||
|
%asm {{
|
||||||
|
jmp math.randword
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
asmsub rndseed(uword seed1 @AY, uword seed2 @R0) clobbers(A,Y) {
|
||||||
|
; -- set new pseudo RNG's seed values. Defaults are: $00c2, $1137
|
||||||
|
%asm {{
|
||||||
|
sta math.randword.x1
|
||||||
|
sty math.randword.c1
|
||||||
|
lda cx16.r0L
|
||||||
|
sta math.randword.a1
|
||||||
|
lda cx16.r0H
|
||||||
|
sta math.randword.b1
|
||||||
|
rts
|
||||||
|
}}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -244,24 +244,6 @@ func_sqrt16_into_A .proc
|
|||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
func_rnd_stack .proc
|
|
||||||
; -- put a random ubyte on the estack
|
|
||||||
jsr math.randbyte
|
|
||||||
sta P8ESTACK_LO,x
|
|
||||||
dex
|
|
||||||
rts
|
|
||||||
.pend
|
|
||||||
|
|
||||||
func_rndw_stack .proc
|
|
||||||
; -- put a random uword on the estack
|
|
||||||
jsr math.randword
|
|
||||||
sta P8ESTACK_LO,x
|
|
||||||
tya
|
|
||||||
sta P8ESTACK_HI,x
|
|
||||||
dex
|
|
||||||
rts
|
|
||||||
.pend
|
|
||||||
|
|
||||||
|
|
||||||
func_sort_ub .proc
|
func_sort_ub .proc
|
||||||
; 8bit unsigned sort
|
; 8bit unsigned sort
|
||||||
|
@ -126,8 +126,18 @@ sub ceil(float value) -> float {
|
|||||||
|
|
||||||
sub rndf() -> float {
|
sub rndf() -> float {
|
||||||
%ir {{
|
%ir {{
|
||||||
rnd.f fr0
|
syscall 35
|
||||||
return
|
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,27 @@ math {
|
|||||||
return costab[radians] as byte
|
return costab[radians] as byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub rnd() -> ubyte {
|
||||||
|
%ir {{
|
||||||
|
syscall 33
|
||||||
|
return
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub rndw() -> uword {
|
||||||
|
%ir {{
|
||||||
|
syscall 34
|
||||||
|
return
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
return
|
||||||
|
}}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1005,7 +1005,7 @@ internal class AstChecker(private val program: Program,
|
|||||||
// It's not (yet) possible to handle these multiple return values because assignments
|
// It's not (yet) possible to handle these multiple return values because assignments
|
||||||
// are only to a single unique target at the same time.
|
// are only to a single unique target at the same time.
|
||||||
// EXCEPTION:
|
// EXCEPTION:
|
||||||
// if the asmsub returns multiple values and one of them is via a status register bit,
|
// if the asmsub returns multiple values and one of them is via a status register bit (such as carry),
|
||||||
// it *is* possible to handle them by just actually assigning the register value and
|
// it *is* possible to handle them by just actually assigning the register value and
|
||||||
// dealing with the status bit as just being that, the status bit after the call.
|
// dealing with the status bit as just being that, the status bit after the call.
|
||||||
val (returnRegisters, _) = stmt.asmReturnvaluesRegisters.partition { rr -> rr.registerOrPair != null }
|
val (returnRegisters, _) = stmt.asmReturnvaluesRegisters.partition { rr -> rr.registerOrPair != null }
|
||||||
|
@ -150,6 +150,13 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter,
|
|||||||
override fun visit(functionCallStatement: FunctionCallStatement) = visitFunctionCall(functionCallStatement)
|
override fun visit(functionCallStatement: FunctionCallStatement) = visitFunctionCall(functionCallStatement)
|
||||||
|
|
||||||
private fun visitFunctionCall(call: IFunctionCall) {
|
private fun visitFunctionCall(call: IFunctionCall) {
|
||||||
|
if(call.target.nameInSource==listOf("rnd") || call.target.nameInSource==listOf("rndw")) {
|
||||||
|
val target = call.target.targetStatement(program)
|
||||||
|
if(target==null) {
|
||||||
|
errors.err("rnd() and rndw() builtin functions have been moved into the math module", call.position)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
when (val target = call.target.targetStatement(program)) {
|
when (val target = call.target.targetStatement(program)) {
|
||||||
is Subroutine -> {
|
is Subroutine -> {
|
||||||
val expectedNumberOfArgs: Int = target.parameters.size
|
val expectedNumberOfArgs: Int = target.parameters.size
|
||||||
|
@ -91,6 +91,10 @@ internal class VerifyFunctionArgTypes(val program: Program, val errors: IErrorRe
|
|||||||
if(target.asmReturnvaluesRegisters.size>1) {
|
if(target.asmReturnvaluesRegisters.size>1) {
|
||||||
// multiple return values will NOT work inside an expression.
|
// multiple return values will NOT work inside an expression.
|
||||||
// they MIGHT work in a regular assignment or just a function call statement.
|
// they MIGHT work in a regular assignment or just a function call statement.
|
||||||
|
// EXCEPTION:
|
||||||
|
// if the asmsub returns multiple values and one of them is via a status register bit (such as carry),
|
||||||
|
// it *is* possible to handle them by just actually assigning the register value and
|
||||||
|
// dealing with the status bit as just being that, the status bit after the call.
|
||||||
val parent = if(call is Statement) call.parent else if(call is Expression) call.parent else null
|
val parent = if(call is Statement) call.parent else if(call is Expression) call.parent else null
|
||||||
if (call !is FunctionCallStatement) {
|
if (call !is FunctionCallStatement) {
|
||||||
val checkParent =
|
val checkParent =
|
||||||
@ -99,7 +103,10 @@ internal class VerifyFunctionArgTypes(val program: Program, val errors: IErrorRe
|
|||||||
else
|
else
|
||||||
parent
|
parent
|
||||||
if (checkParent !is Assignment && checkParent !is VarDecl) {
|
if (checkParent !is Assignment && checkParent !is VarDecl) {
|
||||||
return Pair("can't use subroutine call that returns multiple return values here", call.position)
|
val (returnRegisters, _) = target.asmReturnvaluesRegisters.partition { rr -> rr.registerOrPair != null }
|
||||||
|
if (returnRegisters.size>1) {
|
||||||
|
return Pair("can't use subroutine call that returns multiple return values here", call.position)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,18 +44,18 @@ class TestBuiltinFunctions: FunSpec({
|
|||||||
conv.returns.reg shouldBe RegisterOrPair.A
|
conv.returns.reg shouldBe RegisterOrPair.A
|
||||||
}
|
}
|
||||||
|
|
||||||
test("not-pure func with fixed type") {
|
test("not-pure func with varying result value type") {
|
||||||
val func = BuiltinFunctions.getValue("rnd")
|
val func = BuiltinFunctions.getValue("cmp")
|
||||||
func.name shouldBe "rnd"
|
func.name shouldBe "cmp"
|
||||||
func.parameters.size shouldBe 0
|
func.parameters.size shouldBe 2
|
||||||
func.pure shouldBe false
|
func.pure shouldBe false
|
||||||
func.returnType shouldBe DataType.UBYTE
|
func.returnType shouldBe null
|
||||||
|
|
||||||
val conv = func.callConvention(emptyList())
|
val conv = func.callConvention(listOf(DataType.UWORD, DataType.UWORD))
|
||||||
conv.params.size shouldBe 0
|
conv.params.size shouldBe 2
|
||||||
conv.returns.dt shouldBe DataType.UBYTE
|
conv.returns.dt shouldBe null
|
||||||
conv.returns.floatFac1 shouldBe false
|
conv.returns.floatFac1 shouldBe false
|
||||||
conv.returns.reg shouldBe RegisterOrPair.A
|
conv.returns.reg shouldBe null
|
||||||
}
|
}
|
||||||
|
|
||||||
test("func without return type") {
|
test("func without return type") {
|
||||||
|
@ -258,8 +258,8 @@ class TestSubroutines: FunSpec({
|
|||||||
sub start() {
|
sub start() {
|
||||||
label()
|
label()
|
||||||
label(1)
|
label(1)
|
||||||
void rnd()
|
void cmp(22,44)
|
||||||
void rnd(1)
|
void cmp(11)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
@ -919,4 +919,19 @@ main {
|
|||||||
}"""
|
}"""
|
||||||
compileText(C64Target(), true, text, writeAssembly = true) shouldNotBe null
|
compileText(C64Target(), true, text, writeAssembly = true) shouldNotBe null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test("memory reads byte into word variable") {
|
||||||
|
val text = """
|
||||||
|
main {
|
||||||
|
sub start() {
|
||||||
|
uword @shared ww
|
||||||
|
uword address = $1000
|
||||||
|
ww = @(address+100)
|
||||||
|
ww = @(address+1000)
|
||||||
|
cx16.r0 = @(address+100)
|
||||||
|
cx16.r0 = @(address+1000)
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
compileText(C64Target(), false, text, writeAssembly = true) shouldNotBe null
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
%import floats
|
%import floats
|
||||||
%import string
|
%import string
|
||||||
%import syslib
|
%import syslib
|
||||||
|
%import math
|
||||||
%import test_stack
|
%import test_stack
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
@ -281,17 +282,17 @@ main {
|
|||||||
txt.nl()
|
txt.nl()
|
||||||
|
|
||||||
|
|
||||||
ub = rnd()
|
ub = math.rnd()
|
||||||
txt.print_ub(ub)
|
txt.print_ub(ub)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
ub = zero+rnd()*1+zero
|
ub = zero+math.rnd()*1+zero
|
||||||
txt.print_ub(ub)
|
txt.print_ub(ub)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
|
|
||||||
uw = rndw()
|
uw = math.rndw()
|
||||||
txt.print_uw(uw)
|
txt.print_uw(uw)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
uw = zero+rndw()*1+zero
|
uw = zero+math.rndw()*1+zero
|
||||||
txt.print_uw(uw)
|
txt.print_uw(uw)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
|
|
||||||
|
@ -119,8 +119,6 @@ private val functionSignatures: List<FSignature> = listOf(
|
|||||||
FSignature("rsavex" , false, emptyList(), null),
|
FSignature("rsavex" , false, emptyList(), null),
|
||||||
FSignature("rrestore" , false, emptyList(), null),
|
FSignature("rrestore" , false, emptyList(), null),
|
||||||
FSignature("rrestorex" , false, emptyList(), null),
|
FSignature("rrestorex" , false, emptyList(), null),
|
||||||
FSignature("rnd" , false, emptyList(), DataType.UBYTE),
|
|
||||||
FSignature("rndw" , false, emptyList(), DataType.UWORD),
|
|
||||||
FSignature("memory" , true, listOf(FParam("name", arrayOf(DataType.STR)), FParam("size", arrayOf(DataType.UWORD)), FParam("alignment", arrayOf(DataType.UWORD))), DataType.UWORD),
|
FSignature("memory" , true, listOf(FParam("name", arrayOf(DataType.STR)), FParam("size", arrayOf(DataType.UWORD)), FParam("alignment", arrayOf(DataType.UWORD))), DataType.UWORD),
|
||||||
FSignature("callfar" , false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("arg", arrayOf(DataType.UWORD))), null),
|
FSignature("callfar" , false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("arg", arrayOf(DataType.UWORD))), null),
|
||||||
FSignature("callrom" , false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("arg", arrayOf(DataType.UWORD))), null),
|
FSignature("callrom" , false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("arg", arrayOf(DataType.UWORD))), null),
|
||||||
|
@ -71,7 +71,7 @@ Language features
|
|||||||
- Floating point math also supported if the target system provides floating point library routines (C64 and Cx16 both do).
|
- Floating point math also supported if the target system provides floating point library routines (C64 and Cx16 both do).
|
||||||
- Strings can contain escaped characters but also many symbols directly if they have a petscii equivalent, such as "♠♥♣♦π▚●○╳". Characters like ^, _, \\, {, } and | are also accepted and converted to the closest petscii equivalents.
|
- Strings can contain escaped characters but also many symbols directly if they have a petscii equivalent, such as "♠♥♣♦π▚●○╳". Characters like ^, _, \\, {, } and | are also accepted and converted to the closest petscii equivalents.
|
||||||
- High-level code optimizations, such as const-folding, expression and statement simplifications/rewriting.
|
- High-level code optimizations, such as const-folding, expression and statement simplifications/rewriting.
|
||||||
- Many built-in functions, such as ``sin``, ``cos``, ``rnd``, ``abs``, ``sqrt``, ``msb``, ``rol``, ``ror``, ``sort`` and ``reverse``
|
- Many built-in functions, such as ``sin``, ``cos``, ``abs``, ``sqrt``, ``msb``, ``rol``, ``ror``, ``sort`` and ``reverse``
|
||||||
- Programs can be run multiple times without reloading because of automatic variable (re)initializations.
|
- Programs can be run multiple times without reloading because of automatic variable (re)initializations.
|
||||||
- Supports the sixteen 'virtual' 16-bit registers R0 .. R15 from the Commander X16, also on the other machines.
|
- Supports the sixteen 'virtual' 16-bit registers R0 .. R15 from the Commander X16, also on the other machines.
|
||||||
- If you only use standard kernal and core prog8 library routines, it is possible to compile the *exact same program* for different machines (just change the compilation target flag)!
|
- If you only use standard kernal and core prog8 library routines, it is possible to compile the *exact same program* for different machines (just change the compilation target flag)!
|
||||||
|
@ -257,7 +257,14 @@ tan(x)
|
|||||||
Tangent.
|
Tangent.
|
||||||
|
|
||||||
rndf()
|
rndf()
|
||||||
returns a pseudo-random float between 0.0 and 1.0
|
returns the next random float between 0.0 and 1.0 from the Pseudo RNG sequence.
|
||||||
|
|
||||||
|
rndseedf(ubyte s1, ubyte s2, ubyte s3)
|
||||||
|
Sets a new seed for the float pseudo-RNG sequence. The seed consists of a three byte value.
|
||||||
|
Do not use zeros for the seed!
|
||||||
|
|
||||||
|
.. attention::
|
||||||
|
The rndseedf and maybe the rndf routines may change a bit in the future.
|
||||||
|
|
||||||
|
|
||||||
graphics
|
graphics
|
||||||
@ -276,12 +283,22 @@ Use the ``gfx2`` library if you want full-screen graphics or non-monochrome draw
|
|||||||
|
|
||||||
math
|
math
|
||||||
----
|
----
|
||||||
Low level math routines. You should not normally have to bother with this directly.
|
Low level integer math routines (which you usually don't have to bother with directly, but they are used by the compiler internally).
|
||||||
The compiler needs it to implement most of the math operations in your programs.
|
Pseudo-Random number generators (byte and word).
|
||||||
|
Various 8-bit integer trig functions that use lookup tables to quickly calculate sine and cosines.
|
||||||
|
Usually a custom lookup table is the way to go if your application needs these,
|
||||||
|
but perhaps the provided ones can be of service too.
|
||||||
|
|
||||||
However there's a bunch of 8-bit integer trig functions in here too that use lookup tables
|
|
||||||
to quickly calculate sine and cosines. Usually a custom lookup table is the way to go if your
|
rnd()
|
||||||
application needs this, but perhaps the provided ones can be of service too:
|
Returns next random byte 0-255 from the pseudo-RNG sequence.
|
||||||
|
|
||||||
|
rndw()
|
||||||
|
Returns next random word 0-65535 from the pseudo-RNG sequence.
|
||||||
|
|
||||||
|
rndseed(uword seed1, uword seed2)
|
||||||
|
Sets a new seed for the pseudo-RNG sequence (both rnd and rndw). The seed consists of two words.
|
||||||
|
Do not use zeros for the seed!
|
||||||
|
|
||||||
sin8u(x)
|
sin8u(x)
|
||||||
Fast 8-bit ubyte sine of angle 0..255, result is in range 0..255
|
Fast 8-bit ubyte sine of angle 0..255, result is in range 0..255
|
||||||
|
@ -514,16 +514,26 @@ if statements
|
|||||||
Conditional execution means that the flow of execution changes based on certiain conditions,
|
Conditional execution means that the flow of execution changes based on certiain conditions,
|
||||||
rather than having fixed gotos or subroutine calls::
|
rather than having fixed gotos or subroutine calls::
|
||||||
|
|
||||||
if aa>4 goto overflow
|
if xx==5 {
|
||||||
|
yy = 99
|
||||||
|
zz = 42
|
||||||
|
} else {
|
||||||
|
aa = 3
|
||||||
|
bb = 9
|
||||||
|
}
|
||||||
|
|
||||||
if xx==3 yy = 4
|
if xx==5
|
||||||
if xx==3 yy = 4 else aa = 2
|
yy = 42
|
||||||
|
else if xx==6
|
||||||
|
yy = 43
|
||||||
|
else
|
||||||
|
yy = 44
|
||||||
|
|
||||||
if xx==5 {
|
if aa>4 goto some_label
|
||||||
yy = 99
|
|
||||||
} else {
|
if xx==3 yy = 4
|
||||||
aa = 3
|
|
||||||
}
|
if xx==3 yy = 4 else aa = 2
|
||||||
|
|
||||||
|
|
||||||
Conditional jumps (``if condition goto label``) are compiled using 6502's branching instructions (such as ``bne`` and ``bcc``) so
|
Conditional jumps (``if condition goto label``) are compiled using 6502's branching instructions (such as ``bne`` and ``bcc``) so
|
||||||
@ -848,12 +858,6 @@ popw(value)
|
|||||||
pops a 16-bit word value off the CPU hardware stack into the given variable. Only variables can be used.
|
pops a 16-bit word value off the CPU hardware stack into the given variable. Only variables can be used.
|
||||||
Lowlevel function that should normally not be used.
|
Lowlevel function that should normally not be used.
|
||||||
|
|
||||||
rnd()
|
|
||||||
returns a pseudo-random byte from 0..255
|
|
||||||
|
|
||||||
rndw()
|
|
||||||
returns a pseudo-random word from 0..65535
|
|
||||||
|
|
||||||
rol(x)
|
rol(x)
|
||||||
Rotate the bits in x (byte or word) one position to the left.
|
Rotate the bits in x (byte or word) one position to the left.
|
||||||
This uses the CPU's rotate semantics: bit 0 will be set to the current value of the Carry flag,
|
This uses the CPU's rotate semantics: bit 0 will be set to the current value of the Carry flag,
|
||||||
|
@ -783,19 +783,23 @@ Note: to do an indirect *JSR* to a routine with a varying address, you can use t
|
|||||||
(which is not very efficient) or you have to write a small piece of inline assembly.
|
(which is not very efficient) or you have to write a small piece of inline assembly.
|
||||||
|
|
||||||
|
|
||||||
Conditional execution
|
if statements
|
||||||
^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
With the 'if' / 'else' statement you can execute code depending on the value of a condition::
|
With the 'if' / 'else' statement you can execute code depending on the value of a condition::
|
||||||
|
|
||||||
if <expression> <statements> [else <statements> ]
|
if <expression> <statements> [else <statements> ]
|
||||||
|
|
||||||
where <statements> can be just a single statement for instance just a ``goto``, or it can be a block such as this::
|
If <statements> is just a single statement, for instance just a ``goto`` or a single assignment,
|
||||||
|
it's possible to just write the statement without any curly braces.
|
||||||
|
However if <statements> is a block of multiple statements, you'll have to enclose it in curly braces::
|
||||||
|
|
||||||
if <expression> {
|
if <expression> {
|
||||||
<statements>
|
<statements>
|
||||||
|
} else if <expression> {
|
||||||
|
<statements>
|
||||||
} else {
|
} else {
|
||||||
<alternative statements>
|
<statements>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -807,7 +811,7 @@ itself defines on what status register bit it should branch on::
|
|||||||
|
|
||||||
if_XX <statements> [else <statements> ]
|
if_XX <statements> [else <statements> ]
|
||||||
|
|
||||||
where <statements> can be just a single statement for instance just a ``goto``, or it can be a block such as this::
|
where <statements> can be just a single statement or a block again::
|
||||||
|
|
||||||
if_XX {
|
if_XX {
|
||||||
<statements>
|
<statements>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
%import syslib
|
%import syslib
|
||||||
%import textio
|
%import textio
|
||||||
|
%import math
|
||||||
%import test_stack
|
%import test_stack
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
@ -41,7 +42,7 @@ main {
|
|||||||
active_height--
|
active_height--
|
||||||
upwards = false
|
upwards = false
|
||||||
} else {
|
} else {
|
||||||
target_height = 8 + rnd() % 16
|
target_height = 8 + math.rnd() % 16
|
||||||
if upwards
|
if upwards
|
||||||
mountain = 233
|
mountain = 233
|
||||||
else
|
else
|
||||||
@ -56,7 +57,7 @@ main {
|
|||||||
txt.scroll_left(true)
|
txt.scroll_left(true)
|
||||||
|
|
||||||
; float the balloon
|
; float the balloon
|
||||||
if rnd() & %10000
|
if math.rnd() & %10000
|
||||||
c64.SPXY[1] ++
|
c64.SPXY[1] ++
|
||||||
else
|
else
|
||||||
c64.SPXY[1] --
|
c64.SPXY[1] --
|
||||||
@ -70,10 +71,10 @@ main {
|
|||||||
txt.setcc(39, yy, 160, 8) ; draw mountain
|
txt.setcc(39, yy, 160, 8) ; draw mountain
|
||||||
}
|
}
|
||||||
|
|
||||||
yy = rnd()
|
yy = math.rnd()
|
||||||
if yy > 100 {
|
if yy > 100 {
|
||||||
; draw a star
|
; draw a star
|
||||||
txt.setcc(39, yy % (active_height-1), '.', rnd())
|
txt.setcc(39, yy % (active_height-1), '.', math.rnd())
|
||||||
}
|
}
|
||||||
|
|
||||||
if yy > 200 {
|
if yy > 200 {
|
||||||
@ -84,7 +85,7 @@ main {
|
|||||||
tree = 88
|
tree = 88
|
||||||
else if yy & %00100000 != 0
|
else if yy & %00100000 != 0
|
||||||
tree = 65
|
tree = 65
|
||||||
if rnd() > 130
|
if math.rnd() > 130
|
||||||
treecolor = 13
|
treecolor = 13
|
||||||
txt.setcc(39, active_height, tree, treecolor)
|
txt.setcc(39, active_height, tree, treecolor)
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
%import textio
|
%import textio
|
||||||
|
%import math
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
; Note: this program is compatible with C64 and CX16.
|
; Note: this program is compatible with C64 and CX16.
|
||||||
@ -22,11 +23,11 @@ main {
|
|||||||
; Setup Starting Ball Positions
|
; Setup Starting Ball Positions
|
||||||
ubyte lp
|
ubyte lp
|
||||||
for lp in 0 to ballCount-1 {
|
for lp in 0 to ballCount-1 {
|
||||||
BX[lp] = rnd() % txt.DEFAULT_WIDTH
|
BX[lp] = math.rnd() % txt.DEFAULT_WIDTH
|
||||||
BY[lp] = rnd() % txt.DEFAULT_HEIGHT
|
BY[lp] = math.rnd() % txt.DEFAULT_HEIGHT
|
||||||
BC[lp] = rnd() & 15
|
BC[lp] = math.rnd() & 15
|
||||||
DX[lp] = rnd() & 1
|
DX[lp] = math.rnd() & 1
|
||||||
DY[lp] = rnd() & 1
|
DY[lp] = math.rnd() & 1
|
||||||
}
|
}
|
||||||
|
|
||||||
; display balls
|
; display balls
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
%import graphics
|
%import graphics
|
||||||
|
%import math
|
||||||
|
|
||||||
; note: this program is tuned for the CX16, but with some minor modifications can run on other systems too.
|
; note: this program is tuned for the CX16, but with some minor modifications can run on other systems too.
|
||||||
|
|
||||||
@ -15,7 +16,7 @@ main {
|
|||||||
graphics.enable_bitmap_mode()
|
graphics.enable_bitmap_mode()
|
||||||
|
|
||||||
repeat {
|
repeat {
|
||||||
background_color = rnd()
|
background_color = math.rnd()
|
||||||
graphics.clear_screen(0, background_color)
|
graphics.clear_screen(0, background_color)
|
||||||
num_circles = 0
|
num_circles = 0
|
||||||
draw_circles()
|
draw_circles()
|
||||||
@ -28,14 +29,14 @@ main {
|
|||||||
ubyte @zp radius
|
ubyte @zp radius
|
||||||
|
|
||||||
while num_circles<MAX_NUM_CIRCLES {
|
while num_circles<MAX_NUM_CIRCLES {
|
||||||
x = rndw() % graphics.WIDTH
|
x = math.rndw() % graphics.WIDTH
|
||||||
y = rndw() % graphics.HEIGHT
|
y = math.rndw() % graphics.HEIGHT
|
||||||
radius = GROWTH_RATE * 2 ; use a bit of a buffer between circles.
|
radius = GROWTH_RATE * 2 ; use a bit of a buffer between circles.
|
||||||
if not_colliding() {
|
if not_colliding() {
|
||||||
radius -= GROWTH_RATE
|
radius -= GROWTH_RATE
|
||||||
ubyte color = rnd()
|
ubyte color = math.rnd()
|
||||||
while color==background_color
|
while color==background_color
|
||||||
color = rnd()
|
color = math.rnd()
|
||||||
graphics.colors(color, 0)
|
graphics.colors(color, 0)
|
||||||
while not_edge() and not_colliding() {
|
while not_edge() and not_colliding() {
|
||||||
graphics.disc(x, y as ubyte, radius)
|
graphics.disc(x, y as ubyte, radius)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
%import textio
|
%import textio
|
||||||
|
%import math
|
||||||
|
|
||||||
; Amiga 'copper' bars color cycling effect
|
; Amiga 'copper' bars color cycling effect
|
||||||
|
|
||||||
@ -126,7 +127,7 @@ colors {
|
|||||||
|
|
||||||
sub random_rgb12() {
|
sub random_rgb12() {
|
||||||
do {
|
do {
|
||||||
uword rr = rndw()
|
uword rr = math.rndw()
|
||||||
target_red = msb(rr) & 15
|
target_red = msb(rr) & 15
|
||||||
target_green = lsb(rr)
|
target_green = lsb(rr)
|
||||||
target_blue = target_green & 15
|
target_blue = target_green & 15
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
%import gfx2
|
%import gfx2
|
||||||
%import floats
|
%import floats
|
||||||
%import textio
|
%import textio
|
||||||
|
%import math
|
||||||
%zeropage dontuse
|
%zeropage dontuse
|
||||||
|
|
||||||
main {
|
main {
|
||||||
@ -76,7 +77,7 @@ main {
|
|||||||
sys.wait(2*60)
|
sys.wait(2*60)
|
||||||
|
|
||||||
repeat 255
|
repeat 255
|
||||||
gfx2.line(rndw() % 640, rndw() % 480, rndw() % 640, rndw() % 480, 1)
|
gfx2.line(math.rndw() % 640, math.rndw() % 480, math.rndw() % 640, math.rndw() % 480, 1)
|
||||||
|
|
||||||
sys.wait(1*60)
|
sys.wait(1*60)
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
%import syslib
|
%import syslib
|
||||||
%import textio
|
%import textio
|
||||||
|
%import math
|
||||||
%import test_stack
|
%import test_stack
|
||||||
%import psg
|
%import psg
|
||||||
|
|
||||||
@ -346,7 +347,7 @@ waitkey:
|
|||||||
xpos = startXpos
|
xpos = startXpos
|
||||||
ypos = startYpos
|
ypos = startYpos
|
||||||
speedlevel = 1
|
speedlevel = 1
|
||||||
nextBlock = rnd() % 7
|
nextBlock = math.rnd() % 7
|
||||||
holding = 255
|
holding = 255
|
||||||
holdingAllowed = true
|
holdingAllowed = true
|
||||||
ticks_since_previous_action = 0
|
ticks_since_previous_action = 0
|
||||||
@ -362,7 +363,7 @@ waitkey:
|
|||||||
|
|
||||||
sub spawnNextBlock() {
|
sub spawnNextBlock() {
|
||||||
swapBlock(nextBlock)
|
swapBlock(nextBlock)
|
||||||
nextBlock = (rnd() + lsb(c64.RDTIM16())) % 7
|
nextBlock = (math.rnd() + lsb(c64.RDTIM16())) % 7
|
||||||
drawNextBlock()
|
drawNextBlock()
|
||||||
holdingAllowed = true
|
holdingAllowed = true
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
%import textio
|
%import textio
|
||||||
|
%import math
|
||||||
%import cx16logo
|
%import cx16logo
|
||||||
|
|
||||||
; Note: this program is compatible with C64 and CX16.
|
; Note: this program is compatible with C64 and CX16.
|
||||||
@ -6,8 +7,8 @@
|
|||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
repeat {
|
repeat {
|
||||||
ubyte col = rnd() % (txt.DEFAULT_WIDTH-13) + 3
|
ubyte col = math.rnd() % (txt.DEFAULT_WIDTH-13) + 3
|
||||||
ubyte row = rnd() % (txt.DEFAULT_HEIGHT-7)
|
ubyte row = math.rnd() % (txt.DEFAULT_HEIGHT-7)
|
||||||
cx16logo.logo_at(col, row)
|
cx16logo.logo_at(col, row)
|
||||||
txt.plot(col-3, row+7 )
|
txt.plot(col-3, row+7 )
|
||||||
txt.print("commander x16")
|
txt.print("commander x16")
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
%import textio
|
%import textio
|
||||||
|
%import math
|
||||||
|
|
||||||
; Even though prog8 only has support for extremely limited recursion,
|
; Even though prog8 only has support for extremely limited recursion,
|
||||||
; you can write recursive algorithms with a bit of extra work by building your own explicit stack structure.
|
; you can write recursive algorithms with a bit of extra work by building your own explicit stack structure.
|
||||||
@ -135,8 +136,8 @@ carve_restart_after_repath:
|
|||||||
; for too long on bad rng... just accept a few unused cells in that case.
|
; for too long on bad rng... just accept a few unused cells in that case.
|
||||||
repeat 255 {
|
repeat 255 {
|
||||||
do {
|
do {
|
||||||
cx = rnd() % numCellsHoriz
|
cx = math.rnd() % numCellsHoriz
|
||||||
cy = rnd() % numCellsVert
|
cy = math.rnd() % numCellsVert
|
||||||
} until not @(celladdr(cx, cy)) & STONE
|
} until not @(celladdr(cx, cy)) & STONE
|
||||||
if available_uncarved()
|
if available_uncarved()
|
||||||
return true
|
return true
|
||||||
@ -164,7 +165,7 @@ carve_restart_after_repath:
|
|||||||
|
|
||||||
ubyte[4] bitflags = [LEFT,RIGHT,UP,DOWN]
|
ubyte[4] bitflags = [LEFT,RIGHT,UP,DOWN]
|
||||||
repeat {
|
repeat {
|
||||||
ubyte choice = candidates & bitflags[rnd() & 3]
|
ubyte choice = candidates & bitflags[math.rnd() & 3]
|
||||||
if choice
|
if choice
|
||||||
return choice
|
return choice
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
%import textio
|
%import textio
|
||||||
%import conv
|
%import conv
|
||||||
|
%import math
|
||||||
%import test_stack
|
%import test_stack
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
@ -12,7 +13,7 @@ main {
|
|||||||
sub start() {
|
sub start() {
|
||||||
str name = "????????????????????????????????????????"
|
str name = "????????????????????????????????????????"
|
||||||
str input = "??????????"
|
str input = "??????????"
|
||||||
ubyte secretnumber = rnd() % 99 + 1 ; random number 1..100
|
ubyte secretnumber = math.rnd() % 99 + 1 ; random number 1..100
|
||||||
ubyte attempts_left
|
ubyte attempts_left
|
||||||
|
|
||||||
txt.lowercase()
|
txt.lowercase()
|
||||||
|
@ -106,7 +106,7 @@ main {
|
|||||||
ubyte @zp ii
|
ubyte @zp ii
|
||||||
for ii in 0 to 7 {
|
for ii in 0 to 7 {
|
||||||
; use 16 bit rng for a bit more randomness instead of the 8-bit rng
|
; use 16 bit rng for a bit more randomness instead of the 8-bit rng
|
||||||
if rnd() > s {
|
if math.rnd() > s {
|
||||||
b |= bittab[ii]
|
b |= bittab[ii]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
%import textio
|
%import textio
|
||||||
%import syslib
|
%import syslib
|
||||||
|
%import math
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
|
|
||||||
@ -41,7 +42,7 @@ main {
|
|||||||
for i in 0 to 7 {
|
for i in 0 to 7 {
|
||||||
c64.SPRPTR[i] = $0a00 / 64
|
c64.SPRPTR[i] = $0a00 / 64
|
||||||
c64.SPXY[i*2] = 50+25*i
|
c64.SPXY[i*2] = 50+25*i
|
||||||
c64.SPXY[i*2+1] = rnd()
|
c64.SPXY[i*2+1] = math.rnd()
|
||||||
}
|
}
|
||||||
|
|
||||||
c64.SPENA = 255 ; enable all sprites
|
c64.SPENA = 255 ; enable all sprites
|
||||||
@ -59,7 +60,7 @@ irq {
|
|||||||
ubyte @zp i
|
ubyte @zp i
|
||||||
for i in 0 to 14 step 2 {
|
for i in 0 to 14 step 2 {
|
||||||
c64.SPXY[i+1]--
|
c64.SPXY[i+1]--
|
||||||
ubyte @zp r = rnd()
|
ubyte @zp r = math.rnd()
|
||||||
if r>200
|
if r>200
|
||||||
c64.SPXY[i]++
|
c64.SPXY[i]++
|
||||||
else if r<40
|
else if r<40
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
%import syslib
|
%import syslib
|
||||||
%import textio
|
%import textio
|
||||||
|
%import math
|
||||||
%import test_stack
|
%import test_stack
|
||||||
|
|
||||||
|
|
||||||
@ -261,7 +262,7 @@ waitkey:
|
|||||||
xpos = startXpos
|
xpos = startXpos
|
||||||
ypos = startYpos
|
ypos = startYpos
|
||||||
speedlevel = 1
|
speedlevel = 1
|
||||||
nextBlock = rnd() % 7
|
nextBlock = math.rnd() % 7
|
||||||
holding = 255
|
holding = 255
|
||||||
holdingAllowed = true
|
holdingAllowed = true
|
||||||
}
|
}
|
||||||
@ -276,7 +277,7 @@ waitkey:
|
|||||||
|
|
||||||
sub spawnNextBlock() {
|
sub spawnNextBlock() {
|
||||||
swapBlock(nextBlock)
|
swapBlock(nextBlock)
|
||||||
nextBlock = (rnd() + c64.RASTER) % 7
|
nextBlock = (math.rnd() + c64.RASTER) % 7
|
||||||
drawNextBlock()
|
drawNextBlock()
|
||||||
holdingAllowed = true
|
holdingAllowed = true
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
; NOTE: meant to test to virtual machine output target (use -target virtual)
|
; NOTE: meant to test to virtual machine output target (use -target virtual)
|
||||||
|
|
||||||
|
%import math
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
@ -10,10 +12,10 @@ main {
|
|||||||
|
|
||||||
ubyte pi
|
ubyte pi
|
||||||
for pi in 0 to 127 {
|
for pi in 0 to 127 {
|
||||||
particleX[pi] = rndw() % 319 as word
|
particleX[pi] = math.rndw() % 319 as word
|
||||||
particleY[pi] = rndw() % 240 as word
|
particleY[pi] = math.rndw() % 240 as word
|
||||||
particleDX[pi] = (rnd() & 1)*2 as byte - 1
|
particleDX[pi] = (math.rnd() & 1)*2 as byte - 1
|
||||||
particleDY[pi] = (rnd() & 1)*2 as byte - 1
|
particleDY[pi] = (math.rnd() & 1)*2 as byte - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
sys.gfx_enable(0) ; enable lo res screen
|
sys.gfx_enable(0) ; enable lo res screen
|
||||||
|
@ -126,7 +126,6 @@ mod reg1, value - remainder (modulo) of unsigned div
|
|||||||
sqrt reg1, reg2 - reg1 is the square root of reg2
|
sqrt reg1, reg2 - reg1 is the square root of reg2
|
||||||
sgn reg1, reg2 - reg1 is the sign of reg2 (0, 1 or -1)
|
sgn reg1, reg2 - reg1 is the sign of reg2 (0, 1 or -1)
|
||||||
cmp reg1, reg2 - set processor status bits C, N, Z according to comparison of reg1 with reg2. (semantics taken from 6502/68000 CMP instruction)
|
cmp reg1, reg2 - set processor status bits C, N, Z according to comparison of reg1 with reg2. (semantics taken from 6502/68000 CMP instruction)
|
||||||
rnd reg1 - get a random number (byte, word or float)
|
|
||||||
|
|
||||||
NOTE: because mul/div are constrained (truncated) to remain in 8 or 16 bits, there is NO NEED for separate signed/unsigned mul and div instructions. The result is identical.
|
NOTE: because mul/div are constrained (truncated) to remain in 8 or 16 bits, there is NO NEED for separate signed/unsigned mul and div instructions. The result is identical.
|
||||||
|
|
||||||
@ -288,7 +287,6 @@ enum class Opcode {
|
|||||||
SQRT,
|
SQRT,
|
||||||
SGN,
|
SGN,
|
||||||
CMP,
|
CMP,
|
||||||
RND,
|
|
||||||
EXT,
|
EXT,
|
||||||
EXTS,
|
EXTS,
|
||||||
|
|
||||||
@ -588,7 +586,6 @@ val instructionFormats = mutableMapOf(
|
|||||||
Opcode.DIVSM to InstructionFormat.from("BW,<r1,<v | F,<fr1,<v"),
|
Opcode.DIVSM to InstructionFormat.from("BW,<r1,<v | F,<fr1,<v"),
|
||||||
Opcode.SQRT to InstructionFormat.from("BW,>r1,<r2 | F,>fr1,<fr2"),
|
Opcode.SQRT to InstructionFormat.from("BW,>r1,<r2 | F,>fr1,<fr2"),
|
||||||
Opcode.SGN to InstructionFormat.from("BW,>r1,<r2 | F,>fr1,<fr2"),
|
Opcode.SGN to InstructionFormat.from("BW,>r1,<r2 | F,>fr1,<fr2"),
|
||||||
Opcode.RND to InstructionFormat.from("BW,>r1 | F,>fr1"),
|
|
||||||
Opcode.MODR to InstructionFormat.from("BW,<>r1,<r2"),
|
Opcode.MODR to InstructionFormat.from("BW,<>r1,<r2"),
|
||||||
Opcode.MOD to InstructionFormat.from("BW,<>r1,<v"),
|
Opcode.MOD to InstructionFormat.from("BW,<>r1,<v"),
|
||||||
Opcode.CMP to InstructionFormat.from("BW,<r1,<r2"),
|
Opcode.CMP to InstructionFormat.from("BW,<r1,<r2"),
|
||||||
|
@ -12,9 +12,9 @@
|
|||||||
<option name="HAS_STRING_ESCAPES" value="true" />
|
<option name="HAS_STRING_ESCAPES" value="true" />
|
||||||
</options>
|
</options>
|
||||||
<keywords keywords="&;->;@;\$;and;as;asmsub;break;clobbers;do;downto;else;false;for;goto;if;if_cc;if_cs;if_eq;if_mi;if_ne;if_neg;if_nz;if_pl;if_pos;if_vc;if_vs;if_z;in;inline;not;or;repeat;return;romsub;step;sub;to;true;until;when;while;xor;~" ignore_case="false" />
|
<keywords keywords="&;->;@;\$;and;as;asmsub;break;clobbers;do;downto;else;false;for;goto;if;if_cc;if_cs;if_eq;if_mi;if_ne;if_neg;if_nz;if_pl;if_pos;if_vc;if_vs;if_z;in;inline;not;or;repeat;return;romsub;step;sub;to;true;until;when;while;xor;~" ignore_case="false" />
|
||||||
<keywords2 keywords="%address;%asm;%ir;%asmbinary;%asminclude;%breakpoint;%import;%launcher;%option;%output;%zeropage;%zpreserved;iso:;petscii:;sc:" />
|
<keywords2 keywords="%address;%asm;%asmbinary;%asminclude;%breakpoint;%import;%ir;%launcher;%option;%output;%zeropage;%zpreserved;iso:;petscii:;sc:" />
|
||||||
<keywords3 keywords="@requirezp;@shared;@zp;byte;const;float;str;ubyte;uword;bool;void;word" />
|
<keywords3 keywords="@requirezp;@shared;@zp;bool;byte;const;float;str;ubyte;uword;void;word" />
|
||||||
<keywords4 keywords="abs;all;any;avg;callfar;callrom;cmp;len;lsb;memory;mkword;msb;peek;peekw;poke;pokew;pop;popw;push;pushw;reverse;rnd;rndw;rol;rol2;ror;ror2;rrestore;rrestorex;rsave;rsavex;sgn;sizeof;sort;sqrt16;swap;|>" />
|
<keywords4 keywords="abs;all;any;avg;callfar;callrom;cmp;len;lsb;memory;mkword;msb;peek;peekw;poke;pokew;pop;popw;push;pushw;reverse;rol;rol2;ror;ror2;rrestore;rrestorex;rsave;rsavex;sgn;sizeof;sort;sqrt16;swap;|>" />
|
||||||
</highlighting>
|
</highlighting>
|
||||||
<extensionMap>
|
<extensionMap>
|
||||||
<mapping ext="p8" />
|
<mapping ext="p8" />
|
||||||
|
@ -13,8 +13,8 @@ syn keyword prog8BuiltInFunc sgn sqrt16
|
|||||||
syn keyword prog8BuiltInFunc any all len reverse sort
|
syn keyword prog8BuiltInFunc any all len reverse sort
|
||||||
|
|
||||||
" Miscellaneous functions
|
" Miscellaneous functions
|
||||||
syn keyword prog8BuiltInFunc cmp lsb msb mkword peek peekw poke pokew rnd rndw push pushw pop popw rsave rsavex rrestore rrestorex
|
syn keyword prog8BuiltInFunc cmp lsb msb mkword peek peekw poke pokew push pushw pop popw rsave rsavex rrestore rrestorex
|
||||||
syn keyword prog8BuiltInFunc rndf rol rol2 ror ror2 sizeof
|
syn keyword prog8BuiltInFunc rol rol2 ror ror2 sizeof
|
||||||
syn keyword prog8BuiltInFunc swap memory callfar callrom
|
syn keyword prog8BuiltInFunc swap memory callfar callrom
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,6 +37,8 @@ SYSCALLS:
|
|||||||
28 = reverse_floats array
|
28 = reverse_floats array
|
||||||
29 = compare strings
|
29 = compare strings
|
||||||
30 = gfx_getpixel ; get byte pixel value at coordinates r0.w/r1.w
|
30 = gfx_getpixel ; get byte pixel value at coordinates r0.w/r1.w
|
||||||
|
31 = rndseed
|
||||||
|
32 = rndfseed
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum class Syscall {
|
enum class Syscall {
|
||||||
@ -70,7 +72,12 @@ enum class Syscall {
|
|||||||
REVERSE_WORDS,
|
REVERSE_WORDS,
|
||||||
REVERSE_FLOATS,
|
REVERSE_FLOATS,
|
||||||
COMPARE_STRINGS,
|
COMPARE_STRINGS,
|
||||||
GFX_GETPIXEL
|
GFX_GETPIXEL,
|
||||||
|
RNDSEED,
|
||||||
|
RNDFSEED,
|
||||||
|
RND,
|
||||||
|
RNDW,
|
||||||
|
RNDF
|
||||||
}
|
}
|
||||||
|
|
||||||
object SysCalls {
|
object SysCalls {
|
||||||
@ -279,6 +286,26 @@ object SysCalls {
|
|||||||
val comparison = first.compareTo(second)
|
val comparison = first.compareTo(second)
|
||||||
vm.registers.setSB(0, comparison.toByte())
|
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)
|
||||||
|
}
|
||||||
|
Syscall.RND -> {
|
||||||
|
vm.registers.setUB(0, vm.randomGenerator.nextInt().toUByte())
|
||||||
|
}
|
||||||
|
Syscall.RNDW -> {
|
||||||
|
vm.registers.setUW(0, vm.randomGenerator.nextInt().toUShort())
|
||||||
|
}
|
||||||
|
Syscall.RNDF -> {
|
||||||
|
vm.registers.setFloat(0, vm.randomGeneratorFloats.nextFloat())
|
||||||
|
}
|
||||||
else -> throw AssemblyError("missing syscall ${call.name}")
|
else -> throw AssemblyError("missing syscall ${call.name}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,8 @@ class VirtualMachine(irProgram: IRProgram) {
|
|||||||
var statusCarry = false
|
var statusCarry = false
|
||||||
var statusZero = false
|
var statusZero = false
|
||||||
var statusNegative = false
|
var statusNegative = false
|
||||||
|
internal var randomGenerator = Random(0xa55a7653)
|
||||||
|
internal var randomGeneratorFloats = Random(0xc0d3dbad)
|
||||||
private val cx16virtualregsBaseAddress: Int
|
private val cx16virtualregsBaseAddress: Int
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -203,7 +205,6 @@ class VirtualMachine(irProgram: IRProgram) {
|
|||||||
Opcode.MOD -> InsMOD(ins)
|
Opcode.MOD -> InsMOD(ins)
|
||||||
Opcode.SGN -> InsSGN(ins)
|
Opcode.SGN -> InsSGN(ins)
|
||||||
Opcode.CMP -> InsCMP(ins)
|
Opcode.CMP -> InsCMP(ins)
|
||||||
Opcode.RND -> InsRND(ins)
|
|
||||||
Opcode.SQRT -> InsSQRT(ins)
|
Opcode.SQRT -> InsSQRT(ins)
|
||||||
Opcode.EXT -> InsEXT(ins)
|
Opcode.EXT -> InsEXT(ins)
|
||||||
Opcode.EXTS -> InsEXTS(ins)
|
Opcode.EXTS -> InsEXTS(ins)
|
||||||
@ -1086,15 +1087,6 @@ class VirtualMachine(irProgram: IRProgram) {
|
|||||||
nextPc()
|
nextPc()
|
||||||
}
|
}
|
||||||
|
|
||||||
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())
|
|
||||||
}
|
|
||||||
nextPc()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun InsCMP(i: IRInstruction) {
|
private fun InsCMP(i: IRInstruction) {
|
||||||
val comparison: Int
|
val comparison: Int
|
||||||
when(i.type!!) {
|
when(i.type!!) {
|
||||||
@ -2132,6 +2124,15 @@ class VirtualMachine(irProgram: IRProgram) {
|
|||||||
fun waitvsync() {
|
fun waitvsync() {
|
||||||
Toolkit.getDefaultToolkit().sync() // not really the same as wait on vsync, but there's noting else
|
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
|
// probably called via reflection
|
||||||
|
Loading…
Reference in New Issue
Block a user