floats and random number stuff

This commit is contained in:
Irmen de Jong 2018-12-07 00:08:22 +01:00
parent 662ba6460a
commit 432960da8b
10 changed files with 541 additions and 330 deletions

View File

@ -12,17 +12,17 @@
uword testword
; greeting
c64scr.print_string("Enter your name: ")
c64.VMCSB = %10111 ; switch lowercase chars
c64.STROUT("Please introduce yourself: ")
Y = c64scr.input_chars(name)
c64.CHROUT('\n')
c64.CHROUT('\n')
c64scr.print_string("Hello, ")
c64scr.print_string(name)
c64.CHROUT('.')
c64.CHROUT('\n')
c64.STROUT("Hello, ")
c64.STROUT(name)
c64.STROUT(".\nLet's play a number guessing game.\nI am thinking of a number from 1 to 100!You'll have to guess it!\n")
; create a secret random number from 1-100
c64.RNDA(0) ; fac = rnd(0)
c64.RND() ; fac = random number
c64.MUL10() ; fac *= 10
c64.MUL10() ; .. and now *100
c64.FADDH() ; add 0.5..
@ -30,41 +30,41 @@
A, Y = c64flt.GETADRAY()
secretnumber = A
c64scr.print_string("I am thinking of a number from 1 to 100!You'll have to guess it!\n")
ask_guess:
c64scr.print_string("\nYou have ")
c64.STROUT("\nYou have ")
c64scr.print_byte_decimal(attempts_left)
c64scr.print_string(" guess")
if(attempts_left>0) c64scr.print_string("es")
c64.STROUT(" guess")
if(attempts_left>0) c64.STROUT("es")
c64scr.print_string(" left.\nWhat is your next guess? ")
c64.STROUT(" left.\nWhat is your next guess? ")
Y = c64scr.input_chars(guess)
c64.CHROUT('\n')
freadstr_arg = guess
c64.FREADSTR(A)
A, Y = c64flt.GETADRAY()
if(A==secretnumber) {
c64scr.print_string("\nThat's my number, impressive!\n")
c64.STROUT("\nThat's my number, impressive!\n")
goto goodbye
}
c64scr.print_string("That is too ")
c64.STROUT("\nThat is too ")
if(A > secretnumber)
c64scr.print_string("low!\n")
c64.STROUT("low!\n")
else
c64scr.print_string("high!\n")
c64.STROUT("high!\n")
attempts_left--
if(attempts_left>0) goto ask_guess
; more efficient: if_nz goto ask_guess
; game over.
c64scr.print_string("\nToo bad! It was: ")
c64.STROUT("\nToo bad! It was: ")
c64scr.print_byte_decimal(secretnumber)
c64.CHROUT('\n')
goodbye:
c64scr.print_string("\nThanks for playing. Bye!\n")
c64.STROUT("\nThanks for playing, ")
c64.STROUT(name)
c64.STROUT(".\n")
return
}
}

View File

@ -1,4 +1,6 @@
%import c64utils
%import mathlib
~ main {
sub start() {
@ -6,27 +8,29 @@
str guess = "000000"
ubyte secretnumber = rnd() % 100
c64scr.print_string("Let's play a number guessing game!\n")
c64scr.print_string("Enter your name: ")
c64.VMCSB = %10111 ; switch lowercase chars
c64scr.print_string("Please introduce yourself: ")
Y=c64scr.input_chars(name)
c64scr.print_string("\nHello, ")
c64scr.print_string("\n\nHello, ")
c64scr.print_string(name)
c64scr.print_string(".\nI am thinking of a number from 1 to 100! You'll have to guess it!\n")
c64scr.print_string(".\nLet's play a number guessing game.\nI am thinking of a number from 1 to 100!You'll have to guess it!\n")
for ubyte attempts_left in 10 to 1 step -1 {
c64scr.print_string("\nYou have ")
c64scr.print_byte_decimal(attempts_left)
c64scr.print_string(" guess")
if attempts_left>1 c64scr.print_string("es")
c64scr.print_string(" left. What is your next guess? ")
c64scr.print_string(" left.\nWhat is your next guess? ")
Y=c64scr.input_chars(guess)
ubyte guessednumber = str2ubyte(guess)
if guessednumber==secretnumber {
c64scr.print_string("\nYou guessed it, impressive!\n")
c64scr.print_string("Thanks for playing.\n")
c64scr.print_string("\n\nYou guessed it, impressive!\n")
c64scr.print_string("Thanks for playing, ")
c64scr.print_string(name)
c64scr.print_string(".\n")
return
} else {
c64scr.print_string("That is too ")
c64scr.print_string("\n\nThat is too ")
if guessednumber<secretnumber
c64scr.print_string("low!\n")
else

View File

@ -6,14 +6,7 @@
sub start() {
;math.randseed($5566) ; if you want the exact same number sequence every restart of the program
;math.randseedr()
c64flt.print_float_ln(rndf())
c64flt.print_float_ln(rndf())
c64flt.print_float_ln(rndf())
return
math.randseed($2ae4)
ubyte loop
c64scr.print_string("random bytes:\n")

View File

@ -3,7 +3,6 @@ package prog8.compiler.target.c64
// note: to put stuff on the stack, we use Absolute,X addressing mode which is 3 bytes / 4 cycles
// possible space optimization is to use zeropage (indirect),Y which is 2 bytes, but 5 cycles
import prog8.ast.DataType
import prog8.ast.escape
import prog8.compiler.*
@ -407,8 +406,24 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
Opcode.JUMP -> " jmp ${ins.callLabel}"
Opcode.CALL -> " jsr ${ins.callLabel}"
Opcode.RETURN -> " rts"
Opcode.RSAVE -> " php | pha | txa | pha | tya | pha"
Opcode.RRESTORE -> " pla | tay | pla | tax | pla | plp"
Opcode.RSAVE -> {
// save cpu status flag and all registers A, X, Y.
// see http://6502.org/tutorials/register_preservation.html
"""
php
sta ${C64Zeropage.SCRATCH_REG}
pha
txa
pha
tya
pha
lda ${C64Zeropage.SCRATCH_REG}
"""
}
Opcode.RRESTORE -> {
// restore all registers and cpu status flag
" pla | tay | pla | tax | pla | plp"
}
Opcode.DISCARD_BYTE -> " inx"
Opcode.DISCARD_WORD -> " inx"
Opcode.DISCARD_FLOAT -> " inx | inx | inx"

View File

@ -27,7 +27,7 @@ class C64Zeropage(options: CompilationOptions) : Zeropage(options) {
companion object {
const val SCRATCH_B1 = 0x02
const val SCRATCH_B2 = 0x03
const val SCRATCH_REG = 0x03 // temp storage for a register
const val SCRATCH_W1 = 0xfb // $fb/$fc
const val SCRATCH_W2 = 0xfd // $fd/$fe
}
@ -54,7 +54,7 @@ class C64Zeropage(options: CompilationOptions) : Zeropage(options) {
0xb5, 0xb6, 0xf7, 0xf8, 0xf9, 0xfa))
}
assert(SCRATCH_B1 !in free)
assert(SCRATCH_B2 !in free)
assert(SCRATCH_REG !in free)
assert(SCRATCH_W1 !in free)
assert(SCRATCH_W2 !in free)

View File

@ -7,8 +7,8 @@
~ c64 {
memory ubyte SCRATCH_ZP1 = $02 ; scratch register #1 in ZP
memory ubyte SCRATCH_ZP2 = $03 ; scratch register #2 in ZP
memory ubyte SCRATCH_ZPB1 = $02 ; scratch byte 1 in ZP
memory ubyte SCRATCH_ZPREG = $03 ; scratch register in ZP
memory uword SCRATCH_ZPWORD1 = $fb ; scratch word in ZP ($fb/$fc)
memory uword SCRATCH_ZPWORD2 = $fd ; scratch word in ZP ($fd/$fe)
@ -169,8 +169,7 @@ 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) pseudo random number generator
asmsub RNDA (acc: ubyte @ A) -> clobbers(A,X,Y) -> () = $e09a ; fac1 = RND(A) pseudo random number generator
asmsub RND () -> clobbers(A,X,Y) -> () = $e097 ; fac1 = RND(fac1) float 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)

View File

@ -21,7 +21,6 @@ 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
@ -42,18 +41,6 @@ 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
}}
}
@ -100,12 +87,12 @@ hex_digits .text "0123456789abcdef" ; can probably be reused for other stuff as
asmsub word2hex (dataword: uword @ XY) -> clobbers(A,X,Y) -> () {
; ---- convert 16 bit word in X/Y into 4-character hexadecimal string into memory 'word2hex_output'
%asm {{
stx c64.SCRATCH_ZP2
stx c64.SCRATCH_ZPREG
tya
jsr byte2hex
stx word2hex_output
sty word2hex_output+1
lda c64.SCRATCH_ZP2
lda c64.SCRATCH_ZPREG
jsr byte2hex
stx word2hex_output+2
sty word2hex_output+3
@ -123,8 +110,8 @@ asmsub word2bcd (dataword: uword @ XY) -> clobbers(A,X) -> () {
; arithmetic is being done in BCD the result is a binary to decimal
; conversion.
%asm {{
stx c64.SCRATCH_ZP1
sty c64.SCRATCH_ZP2
stx c64.SCRATCH_ZPB1
sty c64.SCRATCH_ZPREG
sed ; switch to decimal mode
lda #0 ; ensure the result is clear
sta word2bcd_bcdbuff+0
@ -132,8 +119,8 @@ asmsub word2bcd (dataword: uword @ XY) -> clobbers(A,X) -> () {
sta word2bcd_bcdbuff+2
ldx #16 ; the number of source bits
- asl c64.SCRATCH_ZP1 ; shift out one bit
rol c64.SCRATCH_ZP2
- asl c64.SCRATCH_ZPB1 ; shift out one bit
rol c64.SCRATCH_ZPREG
lda word2bcd_bcdbuff+0 ; and add into result
adc word2bcd_bcdbuff+0
sta word2bcd_bcdbuff+0
@ -247,9 +234,9 @@ asmsub GIVUAYF (value: uword @ AY) -> clobbers(A,X,Y) -> () {
asmsub GIVAYFAY (value: uword @ AY) -> clobbers(A,X,Y) -> () {
; ---- signed 16 bit word in A/Y (lo/hi) to float in fac1
%asm {{
sta c64.SCRATCH_ZP1
sta c64.SCRATCH_ZPB1
tya
ldy c64.SCRATCH_ZP1
ldy c64.SCRATCH_ZPB1
jmp c64.GIVAYF ; this uses the inverse order, Y/A
}}
}
@ -258,9 +245,9 @@ asmsub FTOSWRDAY () -> clobbers(X) -> (uword @ AY) {
; ---- fac1 to signed word in A/Y
%asm {{
jsr c64.FTOSWORDYA ; note the inverse Y/A order
sta c64.SCRATCH_ZP1
sta c64.SCRATCH_ZPB1
tya
ldy c64.SCRATCH_ZP1
ldy c64.SCRATCH_ZPB1
rts
}}
}
@ -269,9 +256,9 @@ asmsub GETADRAY () -> clobbers(X) -> (uword @ AY) {
; ---- fac1 to unsigned word in A/Y
%asm {{
jsr c64.GETADR ; this uses the inverse order, Y/A
sta c64.SCRATCH_ZP1
sta c64.SCRATCH_ZPB1
tya
ldy c64.SCRATCH_ZP1
ldy c64.SCRATCH_ZPB1
rts
}}
}
@ -281,22 +268,22 @@ asmsub copy_mflt (source: uword @ XY) -> clobbers(A) -> () {
; ---- copy a 5 byte MFLT floating point variable to another place
; input: X/Y = source address, c64.SCRATCH_ZPWORD1 = destination address
%asm {{
stx c64.SCRATCH_ZP1
stx c64.SCRATCH_ZPB1
sty c64.SCRATCH_ZPWORD1+1
ldy #0
lda (c64.SCRATCH_ZP1),y
lda (c64.SCRATCH_ZPB1),y
sta (c64.SCRATCH_ZPWORD1),y
iny
lda (c64.SCRATCH_ZP1),y
lda (c64.SCRATCH_ZPB1),y
sta (c64.SCRATCH_ZPWORD1),y
iny
lda (c64.SCRATCH_ZP1),y
lda (c64.SCRATCH_ZPB1),y
sta (c64.SCRATCH_ZPWORD1),y
iny
lda (c64.SCRATCH_ZP1),y
lda (c64.SCRATCH_ZPB1),y
sta (c64.SCRATCH_ZPWORD1),y
iny
lda (c64.SCRATCH_ZP1),y
lda (c64.SCRATCH_ZPB1),y
sta (c64.SCRATCH_ZPWORD1),y
ldy c64.SCRATCH_ZPWORD1+1
rts
@ -306,15 +293,15 @@ asmsub copy_mflt (source: uword @ XY) -> clobbers(A) -> () {
asmsub float_add_one (mflt: uword @ XY) -> clobbers(A,X,Y) -> () {
; ---- add 1 to the MFLT pointed to by X/Y. Clobbers A, X, Y
%asm {{
stx c64.SCRATCH_ZP1
sty c64.SCRATCH_ZP2
stx c64.SCRATCH_ZPB1
sty c64.SCRATCH_ZPREG
txa
jsr c64.MOVFM ; fac1 = float XY
lda #<c64.FL_FONE
ldy #>c64.FL_FONE
jsr c64.FADD ; fac1 += 1
ldx c64.SCRATCH_ZP1
ldy c64.SCRATCH_ZP2
ldx c64.SCRATCH_ZPB1
ldy c64.SCRATCH_ZPREG
jmp c64.FTOMEMXY ; float XY = fac1
}}
}
@ -322,16 +309,16 @@ asmsub float_add_one (mflt: uword @ XY) -> clobbers(A,X,Y) -> () {
asmsub float_sub_one (mflt: uword @ XY) -> clobbers(A,X,Y) -> () {
; ---- subtract 1 from the MFLT pointed to by X/Y. Clobbers A, X, Y
%asm {{
stx c64.SCRATCH_ZP1
sty c64.SCRATCH_ZP2
stx c64.SCRATCH_ZPB1
sty c64.SCRATCH_ZPREG
lda #<c64.FL_FONE
ldy #>c64.FL_FONE
jsr c64.MOVFM ; fac1 = 1
txa
ldy c64.SCRATCH_ZP2
ldy c64.SCRATCH_ZPREG
jsr c64.FSUB ; fac1 = float XY - 1
ldx c64.SCRATCH_ZP1
ldy c64.SCRATCH_ZP2
ldx c64.SCRATCH_ZPB1
ldy c64.SCRATCH_ZPREG
jmp c64.FTOMEMXY ; float XY = fac1
}}
}
@ -339,15 +326,15 @@ asmsub float_sub_one (mflt: uword @ XY) -> clobbers(A,X,Y) -> () {
asmsub float_add_SW1_to_XY (mflt: uword @ XY) -> clobbers(A,X,Y) -> () {
; ---- add MFLT pointed to by SCRATCH_ZPWORD1 to the MFLT pointed to by X/Y. Clobbers A, X, Y
%asm {{
stx c64.SCRATCH_ZP1
sty c64.SCRATCH_ZP2
stx c64.SCRATCH_ZPB1
sty c64.SCRATCH_ZPREG
txa
jsr c64.MOVFM ; fac1 = float XY
lda c64.SCRATCH_ZPWORD1
ldy c64.SCRATCH_ZPWORD1+1
jsr c64.FADD ; fac1 += SCRATCH_ZPWORD1
ldx c64.SCRATCH_ZP1
ldy c64.SCRATCH_ZP2
ldx c64.SCRATCH_ZPB1
ldy c64.SCRATCH_ZPREG
jmp c64.FTOMEMXY ; float XY = fac1
}}
}
@ -355,16 +342,16 @@ asmsub float_add_SW1_to_XY (mflt: uword @ XY) -> clobbers(A,X,Y) -> () {
asmsub float_sub_SW1_from_XY (mflt: uword @ XY) -> clobbers(A,X,Y) -> () {
; ---- subtract MFLT pointed to by SCRATCH_ZPWORD1 from the MFLT pointed to by X/Y. Clobbers A, X, Y
%asm {{
stx c64.SCRATCH_ZP1
sty c64.SCRATCH_ZP2
stx c64.SCRATCH_ZPB1
sty c64.SCRATCH_ZPREG
lda c64.SCRATCH_ZPWORD1
ldy c64.SCRATCH_ZPWORD1+1
jsr c64.MOVFM ; fac1 = SCRATCH_ZPWORD1
txa
ldy c64.SCRATCH_ZP2
ldy c64.SCRATCH_ZPREG
jsr c64.FSUB ; fac1 = float XY - SCRATCH_ZPWORD1
ldx c64.SCRATCH_ZP1
ldy c64.SCRATCH_ZP2
ldx c64.SCRATCH_ZPB1
ldy c64.SCRATCH_ZPREG
jmp c64.FTOMEMXY ; float XY = fac1
}}
}
@ -430,7 +417,7 @@ asmsub clear_screen (char: ubyte @ A, color: ubyte @ Y) -> clobbers(A,X) -> ()
%asm {{
sta _loop + 1 ; self-modifying
stx c64.SCRATCH_ZP1
stx c64.SCRATCH_ZPB1
ldx #0
_loop lda #0
sta c64.Screen,x
@ -446,7 +433,7 @@ _loop lda #0
bne _loop
lda _loop+1 ; restore A and X
ldx c64.SCRATCH_ZP1
ldx c64.SCRATCH_ZPB1
rts
}}
@ -672,10 +659,10 @@ asmsub print_string (text: str @ XY) -> clobbers(A,Y) -> () {
; a call to this subroutine with a string argument of just one char,
; by just one call to c64.CHROUT of that single char. @todo do this
%asm {{
stx c64.SCRATCH_ZP1
sty c64.SCRATCH_ZP2
stx c64.SCRATCH_ZPB1
sty c64.SCRATCH_ZPREG
ldy #0
- lda (c64.SCRATCH_ZP1),y
- lda (c64.SCRATCH_ZPB1),y
beq +
jsr c64.CHROUT
iny
@ -688,14 +675,14 @@ asmsub print_string (text: str @ XY) -> clobbers(A,Y) -> () {
asmsub print_pstring (text: str_p @ XY) -> clobbers(A,X) -> (ubyte @ Y) {
; ---- print pstring (length as first byte) from X/Y, returns str len in Y
%asm {{
stx c64.SCRATCH_ZP1
sty c64.SCRATCH_ZP2
stx c64.SCRATCH_ZPB1
sty c64.SCRATCH_ZPREG
ldy #0
lda (c64.SCRATCH_ZP1),y
lda (c64.SCRATCH_ZPB1),y
beq +
tax
- iny
lda (c64.SCRATCH_ZP1),y
lda (c64.SCRATCH_ZPB1),y
jsr c64.CHROUT
dex
bne -
@ -761,10 +748,10 @@ asmsub print_word_hex (prefix: ubyte @ Pc, dataword: uword @ XY) -> clobbers(A,
; ---- print the (unsigned) word in X/Y in hexadecimal form (4 digits)
; (if Carry is set, a radix prefix '$' is printed as well)
%asm {{
stx c64.SCRATCH_ZP1
stx c64.SCRATCH_ZPB1
tya
jsr print_byte_hex
lda c64.SCRATCH_ZP1
lda c64.SCRATCH_ZPB1
clc
jmp print_byte_hex
}}
@ -828,17 +815,17 @@ asmsub input_chars (buffer: uword @ AX) -> clobbers(A) -> (ubyte @ Y) {
; It assumes the keyboard is selected as I/O channel!!
%asm {{
sta c64.SCRATCH_ZP1
stx c64.SCRATCH_ZP2
sta c64.SCRATCH_ZPB1
stx c64.SCRATCH_ZPREG
ldy #0 ; char counter = 0
- jsr c64.CHRIN
cmp #$0d ; return (ascii 13) pressed?
beq + ; yes, end.
sta (c64.SCRATCH_ZP1),y ; else store char in buffer
sta (c64.SCRATCH_ZPB1),y ; else store char in buffer
iny
bne -
+ lda #0
sta (c64.SCRATCH_ZP1),y ; finish string with 0 byte
sta (c64.SCRATCH_ZPB1),y ; finish string with 0 byte
rts
}}

View File

@ -12,8 +12,8 @@
~ math {
; note: the following ZP scratch registers must be the same as in c64lib
memory ubyte SCRATCH_ZP1 = $02 ; scratch register #1 in ZP
memory ubyte SCRATCH_ZP2 = $03 ; scratch register #2 in ZP
memory ubyte SCRATCH_ZPB1 = $02 ; scratch byte 1 in ZP
memory ubyte SCRATCH_ZPREG = $03 ; scratch register in ZP
memory uword SCRATCH_ZPWORD1 = $fb ; scratch word in ZP ($fb/$fc)
memory uword SCRATCH_ZPWORD2 = $fd ; scratch word in ZP ($fd/$fe)
@ -22,14 +22,14 @@
asmsub multiply_bytes (byte1: ubyte @ X, byte2: ubyte @ Y) -> clobbers(X) -> (ubyte @ A) {
; ---- multiply 2 bytes, result as byte in A (signed or unsigned)
%asm {{
stx SCRATCH_ZP1
sty SCRATCH_ZP2
stx SCRATCH_ZPB1
sty SCRATCH_ZPREG
ldx #8
- asl a
asl SCRATCH_ZP1
asl SCRATCH_ZPB1
bcc +
clc
adc SCRATCH_ZP2
adc SCRATCH_ZPREG
+ dex
bne -
rts
@ -41,19 +41,19 @@ asmsub multiply_bytes_16 (byte1: ubyte @ X, byte2: ubyte @ Y) -> clobbers(A) -
; ---- multiply 2 bytes, result as word in X/Y (unsigned)
%asm {{
lda #0
_m_with_add stx SCRATCH_ZP1
sty SCRATCH_ZP2
_m_with_add stx SCRATCH_ZPB1
sty SCRATCH_ZPREG
ldx #8
lsr SCRATCH_ZP1
lsr SCRATCH_ZPB1
- bcc +
clc
adc SCRATCH_ZP2
adc SCRATCH_ZPREG
+ ror a
ror SCRATCH_ZP1
ror SCRATCH_ZPB1
dex
bne -
tay
ldx SCRATCH_ZP1
ldx SCRATCH_ZPB1
rts
}}
}
@ -104,21 +104,21 @@ asmsub divmod_bytes (number: ubyte @ X, divisor: ubyte @ Y) -> clobbers() -> (
; ---- divide X by Y, result quotient in X, remainder in A (unsigned)
; division by zero will result in quotient = 255 and remainder = original number
%asm {{
stx SCRATCH_ZP1
sty SCRATCH_ZP2
stx SCRATCH_ZPB1
sty SCRATCH_ZPREG
lda #0
ldx #8
asl SCRATCH_ZP1
asl SCRATCH_ZPB1
- rol a
cmp SCRATCH_ZP2
cmp SCRATCH_ZPREG
bcc +
sbc SCRATCH_ZP2
+ rol SCRATCH_ZP1
sbc SCRATCH_ZPREG
+ rol SCRATCH_ZPB1
dex
bne -
ldx SCRATCH_ZP1
ldx SCRATCH_ZPB1
rts
}}
}
@ -130,7 +130,7 @@ asmsub divmod_words (divisor: uword @ XY) -> clobbers(A) -> (uword @ XY) {
; division by zero will result in quotient = 65535 and remainder = divident
%asm {{
remainder = SCRATCH_ZP1
remainder = SCRATCH_ZPB1
stx SCRATCH_ZPWORD2
sty SCRATCH_ZPWORD2+1
@ -171,30 +171,20 @@ remainder = SCRATCH_ZP1
}}
}
asmsub randseed (seed: uword @ AY) -> clobbers() -> () {
asmsub randseed (seed: uword @ AY) -> clobbers(A, Y) -> () {
; ---- 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
stx SCRATCH_ZPREG
clc
sbc #100
adc #14
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
jsr c64.FREADSA
jsr c64.RND ; reseed the float rng using the (negative) number in A
ldx SCRATCH_ZPREG
rts
}}
}
@ -218,7 +208,6 @@ _magic .byte $1d
_magiceors .byte $1d, $2b, $2d, $4d, $5f, $63, $65, $69
.byte $71, $87, $8d, $a9, $c3, $cf, $e7, $f5
;returns - this comment avoids compiler warning
}}
}
@ -266,7 +255,6 @@ _magic .word $3f1d
_magiceors .word $3f1d, $3f81, $3fa5, $3fc5, $4075, $409d, $40cd, $4109
.word $413f, $414b, $4153, $4159, $4193, $4199, $41af, $41bb
;returns - this comment avoids compiler warning
}}
}

View File

@ -6,9 +6,12 @@
~ prog8_lib {
; @TODO move all this assembly to a real .asm file instead and include that...
; note: the following ZP scratch registers must be the same as in c64lib
memory ubyte SCRATCH_ZP1 = $02 ; scratch register #1 in ZP
memory ubyte SCRATCH_ZP2 = $03 ; scratch register #2 in ZP
memory ubyte SCRATCH_ZPB1 = $02 ; scratch byte 1 in ZP
memory ubyte SCRATCH_ZPREG = $03 ; scratch register 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
@ -19,7 +22,7 @@
; 16-bit rotate right (as opposed to the 6502's usual 17-bit rotate with carry)
; the word is placed in SCRATCH_ZPWORD1
ror2_word
ror2_word .proc
lsr SCRATCH_ZPWORD1+1
ror SCRATCH_ZPWORD1
bcc +
@ -27,297 +30,495 @@ ror2_word
ora #$80
sta SCRATCH_ZPWORD1+1
+ rts
.pend
; @todo: implement stubs!
; @todo: move float operations to their own library (only included when floats are enabled)
ub2float
ub2float .proc
rts
.warn "not implemented"
.pend
b2float
b2float .proc
rts
.warn "not implemented"
.pend
uw2float
uw2float .proc
rts
.warn "not implemented"
.pend
w2float
w2float .proc
rts
.warn "not implemented"
.pend
push_float
push_float .proc
; ---- 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
lda (SCRATCH_ZPWORD1),y
sta ESTACK_LO,x
iny
lda SCRATCH_ZPWORD1,y
lda (SCRATCH_ZPWORD1),y
sta ESTACK_HI,x
dex
iny
lda SCRATCH_ZPWORD1,y
lda (SCRATCH_ZPWORD1),y
sta ESTACK_LO,x
iny
lda SCRATCH_ZPWORD1,y
lda (SCRATCH_ZPWORD1),y
sta ESTACK_HI,x
dex
iny
lda SCRATCH_ZPWORD1,y
lda (SCRATCH_ZPWORD1),y
sta ESTACK_LO,x
dex
rts
.pend
push_float_from_indexed_var
push_float_from_indexed_var .proc
rts
.warn "not implemented"
.pend
pop_float
; ---- pops mflpt5 from stack to memory A/Y @TODO CHECK ORDER OF POPS
pop_float .proc
; ---- pops mflpt5 from stack to memory A/Y
; (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
sta (SCRATCH_ZPWORD1),y
dey
inx
lda ESTACK_LO,x
sta SCRATCH_ZPWORD1,y
dey
lda ESTACK_HI,x
sta SCRATCH_ZPWORD1,y
sta (SCRATCH_ZPWORD1),y
dey
lda ESTACK_LO,x
sta (SCRATCH_ZPWORD1),y
dey
inx
lda ESTACK_LO,x
sta SCRATCH_ZPWORD1,y
lda ESTACK_HI,x
sta (SCRATCH_ZPWORD1),y
dey
sta SCRATCH_ZPWORD1,y
lda ESTACK_LO,x
sta (SCRATCH_ZPWORD1),y
rts
.pend
pop_float_to_indexed_var
pop_float_to_indexed_var .proc
rts
.warn "not implemented"
.pend
pop_mem_float
pop_mem_float .proc
rts
.warn "not implemented"
.pend
copy_float
copy_float .proc
; -- 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
lda (SCRATCH_ZPWORD1),y
sta (SCRATCH_ZPWORD2),y
iny
lda SCRATCH_ZPWORD1,y
sta SCRATCH_ZPWORD2,y
lda (SCRATCH_ZPWORD1),y
sta (SCRATCH_ZPWORD2),y
iny
lda SCRATCH_ZPWORD1,y
sta SCRATCH_ZPWORD2,y
lda (SCRATCH_ZPWORD1),y
sta (SCRATCH_ZPWORD2),y
iny
lda SCRATCH_ZPWORD1,y
sta SCRATCH_ZPWORD2,y
lda (SCRATCH_ZPWORD1),y
sta (SCRATCH_ZPWORD2),y
iny
lda SCRATCH_ZPWORD1,y
sta SCRATCH_ZPWORD2,y
lda (SCRATCH_ZPWORD1),y
sta (SCRATCH_ZPWORD2),y
rts
.pend
inc_var_f
inc_var_f .proc
rts
.warn "not implemented"
.pend
dec_var_f
dec_var_f .proc
rts
.warn "not implemented"
.pend
div_f
div_f .proc
rts
.warn "not implemented"
.pend
add_f
add_f .proc
rts
.warn "not implemented"
.pend
sub_f
sub_f .proc
rts
.warn "not implemented"
.pend
mul_f
mul_f .proc
rts
.warn "not implemented"
.pend
neg_f
neg_f .proc
rts
.warn "not implemented"
.pend
add_w
rts ; @todo inline?
add_uw
add_w .proc
rts ; @todo inline?
.warn "not implemented"
.pend
sub_w
add_uw .proc
rts ; @todo inline?
sub_uw
rts ; @todo inline?
mul_b
rts
mul_ub
rts
mul_w
rts
mul_uw
rts
div_b
rts
div_ub
rts
div_w
rts
div_uw
rts
remainder_b
rts
remainder_ub
rts
remainder_w
rts
remainder_uw
rts
remainder_f
rts
.warn "not implemented"
.pend
equal_ub
sub_w .proc
rts ; @todo inline?
.warn "not implemented"
.pend
sub_uw .proc
rts ; @todo inline?
.warn "not implemented"
.pend
mul_b .proc
rts
.warn "not implemented"
.pend
mul_ub .proc
rts
.warn "not implemented"
.pend
mul_w .proc
rts
.warn "not implemented"
.pend
mul_uw .proc
rts
.warn "not implemented"
.pend
div_b .proc
rts
.warn "not implemented"
.pend
div_ub .proc
rts
.warn "not implemented"
.pend
div_w .proc
rts
.warn "not implemented"
.pend
div_uw .proc
rts
.warn "not implemented"
.pend
remainder_b .proc
rts
.warn "not implemented"
.pend
remainder_ub .proc
rts
.warn "not implemented"
.pend
remainder_w .proc
rts
.warn "not implemented"
.pend
remainder_uw .proc
rts
.warn "not implemented"
.pend
remainder_f .proc
rts
.warn "not implemented"
.pend
equal_ub .proc
rts
.warn "not implemented"
.pend
equal_b
equal_b .proc
rts
.warn "not implemented"
.pend
equal_w
equal_w .proc
rts
.warn "not implemented"
.pend
equal_uw
equal_uw .proc
rts
.warn "not implemented"
.pend
equal_f
equal_f .proc
rts
.warn "not implemented"
.pend
less_ub
less_ub .proc
rts
.warn "not implemented"
.pend
less_b
less_b .proc
rts
.warn "not implemented"
.pend
less_w
less_w .proc
rts
.warn "not implemented"
.pend
less_uw
less_uw .proc
rts
.warn "not implemented"
.pend
less_f
less_f .proc
rts
.warn "not implemented"
.pend
lesseq_ub
lesseq_ub .proc
rts
.warn "not implemented"
.pend
lesseq_b
lesseq_b .proc
rts
.warn "not implemented"
.pend
lesseq_w
lesseq_w .proc
rts
.warn "not implemented"
.pend
lesseq_uw
lesseq_uw .proc
rts
.warn "not implemented"
.pend
lesseq_f
lesseq_f .proc
rts
.warn "not implemented"
.pend
greater_ub
greater_ub .proc
rts
.warn "not implemented"
.pend
greater_b
greater_b .proc
rts
.warn "not implemented"
.pend
greater_w
greater_w .proc
rts
.warn "not implemented"
.pend
greater_uw
greater_uw .proc
rts
.warn "not implemented"
.pend
greater_f
greater_f .proc
rts
.warn "not implemented"
.pend
greatereq_ub
greatereq_ub .proc
rts
.warn "not implemented"
.pend
greatereq_b
greatereq_b .proc
rts
.warn "not implemented"
.pend
greatereq_w
greatereq_w .proc
rts
.warn "not implemented"
.pend
greatereq_uw
greatereq_uw .proc
rts
.warn "not implemented"
.pend
greatereq_f
greatereq_f .proc
rts
.warn "not implemented"
.pend
func_sin
rts
func_cos
rts
func_abs
rts
func_acos
rts
func_asin
rts
func_tan
rts
func_atan
rts
func_ln
rts
func_log2
rts
func_log10
rts
func_sqrt
rts
func_rad
rts
func_deg
rts
func_round
rts
func_floor
rts
func_ceil
rts
func_max
rts
func_min
rts
func_avg
rts
func_sum
rts
func_len
rts
func_any
rts
func_all
func_sin .proc
rts
.warn "not implemented"
.pend
func_rnd
func_cos .proc
rts
.warn "not implemented"
.pend
func_abs .proc
rts
.warn "not implemented"
.pend
func_acos .proc
rts
.warn "not implemented"
.pend
func_asin .proc
rts
.warn "not implemented"
.pend
func_tan .proc
rts
.warn "not implemented"
.pend
func_atan .proc
rts
.warn "not implemented"
.pend
func_ln .proc
rts
.warn "not implemented"
.pend
func_log2 .proc
rts
.warn "not implemented"
.pend
func_log10 .proc
rts
.warn "not implemented"
.pend
func_sqrt .proc
rts
.warn "not implemented"
.pend
func_rad .proc
rts
.warn "not implemented"
.pend
func_deg .proc
rts
.warn "not implemented"
.pend
func_round .proc
rts
.warn "not implemented"
.pend
func_floor .proc
rts
.warn "not implemented"
.pend
func_ceil .proc
rts
.warn "not implemented"
.pend
func_max .proc
rts
.warn "not implemented--what does it max over???"
.pend
func_min .proc
rts
.warn "not implemented--what does it min over???"
.pend
func_avg .proc
rts
.warn "not implemented--what does it avg over???"
.pend
func_sum .proc
rts
.warn "not implemented--what does it sum over???"
.pend
func_len .proc
rts
.warn "not implemented--of what does it take len?"
.pend
func_any .proc
rts
.warn "not implemented--of what does it do any?"
.pend
func_all .proc
rts
.warn "not implemented--of what does it do all?"
.pend
func_rnd .proc
; -- put a random ubyte on the estack
jsr math.randbyte
sta ESTACK_LO,x
dex
rts
.pend
func_rndw
func_rndw .proc
; -- put a random uword on the estack
jsr math.randword
sta ESTACK_LO,x
@ -325,36 +526,60 @@ func_rndw
sta ESTACK_HI,x
dex
rts
.pend
func_rndf
func_rndf .proc
; -- put a random floating point value on the stack
stx SCRATCH_ZP1
lda #39
jsr c64.RNDA ; rng into fac1
stx SCRATCH_ZPREG
lda #1
jsr c64.FREADSA
jsr c64.RND ; rng into fac1
ldx #<_rndf_rnum5
ldy #>_rndf_rnum5
jsr c64.FTOMEMXY ; fac1 to mem X/Y
ldx SCRATCH_ZP1
ldx SCRATCH_ZPREG
lda #<_rndf_rnum5
ldy #>_rndf_rnum5
jmp push_float
_rndf_rnum5 .fill 5
.pend
func_wrd
func_wrd .proc
rts
func_uwrd
.warn "not implemented"
.pend
func_uwrd .proc
rts
func_str2byte
.warn "not implemented"
.pend
func_str2byte .proc
rts
func_str2ubyte
.warn "not implemented"
.pend
func_str2ubyte .proc
rts
func_str2word
.warn "not implemented"
.pend
func_str2word .proc
rts
func_str2uword
.warn "not implemented"
.pend
func_str2uword .proc
rts
func_str2float
.warn "not implemented"
.pend
func_str2float .proc
rts
.warn "not implemented"
.pend
}}
}

View File

@ -7,8 +7,8 @@
~ prog8_lib {
; note: the following ZP scratch registers must be the same as in c64lib
memory byte SCRATCH_ZP1 = $02 ; scratch register #1 in ZP
memory byte SCRATCH_ZP2 = $03 ; scratch register #2 in ZP
memory byte SCRATCH_ZPB1 = $02 ; scratch byte 1 in ZP
memory byte SCRATCH_ZPREG = $03 ; scratch register in ZP
memory word SCRATCH_ZPWORD1 = $fb ; scratch word in ZP ($fb/$fc)
memory word SCRATCH_ZPWORD2 = $fd ; scratch word in ZP ($fd/$fe)
@ -33,17 +33,17 @@ jsr_indirect_tmp
jsr_indirect_AX
sta SCRATCH_ZP1
stx SCRATCH_ZP2
jmp (SCRATCH_ZP1)
sta SCRATCH_ZPB1
stx SCRATCH_ZPREG
jmp (SCRATCH_ZPB1)
jsr_indirect_AY
sta SCRATCH_ZP1
sty SCRATCH_ZP2
jmp (SCRATCH_ZP1)
sta SCRATCH_ZPB1
sty SCRATCH_ZPREG
jmp (SCRATCH_ZPB1)
jsr_indirect_XY
stx SCRATCH_ZP1
sty SCRATCH_ZP2
jmp (SCRATCH_ZP1)
stx SCRATCH_ZPB1
sty SCRATCH_ZPREG
jmp (SCRATCH_ZPB1)
; copy memory UP from (SCRATCH_ZPWORD1) to (SCRATCH_ZPWORD2) of length X/Y (16-bit, X=lo, Y=hi)
@ -51,7 +51,7 @@ jsr_indirect_XY
memcopy16_up
source = SCRATCH_ZPWORD1
dest = SCRATCH_ZPWORD2
length = SCRATCH_ZP1 ; (and SCRATCH_ZP2)
length = SCRATCH_ZPB1 ; (and SCRATCH_ZPREG)
stx length
sty length+1
@ -91,10 +91,10 @@ memcopy
; fill memory from (SCRATCH_ZPWORD1), length XY, with value in A.
; clobbers X, Y
memset stx SCRATCH_ZP1
sty SCRATCH_ZP2
memset stx SCRATCH_ZPB1
sty SCRATCH_ZPREG
ldy #0
ldx SCRATCH_ZP2
ldx SCRATCH_ZPREG
beq _lastpage
_fullpage sta (SCRATCH_ZPWORD1),y
@ -104,7 +104,7 @@ _fullpage sta (SCRATCH_ZPWORD1),y
dex
bne _fullpage
_lastpage ldy SCRATCH_ZP1
_lastpage ldy SCRATCH_ZPB1
beq +
- dey
sta (SCRATCH_ZPWORD1),y
@ -122,10 +122,10 @@ memsetw
sta _mod2+1 ; self-modify
sty _mod2b+1 ; self-modify
ldx SCRATCH_ZPWORD1
stx SCRATCH_ZP1
stx SCRATCH_ZPB1
ldx SCRATCH_ZPWORD1+1
inx
stx SCRATCH_ZP2 ; second page
stx SCRATCH_ZPREG ; second page
ldy #0
ldx SCRATCH_ZPWORD2+1
@ -134,17 +134,17 @@ memsetw
_fullpage
_mod1 lda #0 ; self-modified
sta (SCRATCH_ZPWORD1),y ; first page
sta (SCRATCH_ZP1),y ; second page
sta (SCRATCH_ZPB1),y ; second page
iny
_mod1b lda #0 ; self-modified
sta (SCRATCH_ZPWORD1),y ; first page
sta (SCRATCH_ZP1),y ; second page
sta (SCRATCH_ZPB1),y ; second page
iny
bne _fullpage
inc SCRATCH_ZPWORD1+1 ; next page pair
inc SCRATCH_ZPWORD1+1 ; next page pair
inc SCRATCH_ZP1+1 ; next page pair
inc SCRATCH_ZP1+1 ; next page pair
inc SCRATCH_ZPB1+1 ; next page pair
inc SCRATCH_ZPB1+1 ; next page pair
dex
bne _fullpage