From 432960da8b82b8ae4ef06566f5241f37f3080930 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 7 Dec 2018 00:08:22 +0100 Subject: [PATCH] floats and random number stuff --- compiler/examples/numbergame-c64.p8 | 36 +- compiler/examples/numbergame-novm.p8 | 20 +- compiler/examples/test.p8 | 9 +- .../src/prog8/compiler/target/c64/AsmGen.kt | 21 +- .../prog8/compiler/target/c64/Commodore64.kt | 4 +- prog8lib/c64lib.p8 | 7 +- prog8lib/c64utils.p8 | 115 ++-- prog8lib/mathlib.p8 | 64 +- prog8lib/prog8lib.p8 | 551 ++++++++++++------ prog8lib/prog8lib_OLD.p8 | 44 +- 10 files changed, 541 insertions(+), 330 deletions(-) diff --git a/compiler/examples/numbergame-c64.p8 b/compiler/examples/numbergame-c64.p8 index 2c322d56c..2853b952d 100644 --- a/compiler/examples/numbergame-c64.p8 +++ b/compiler/examples/numbergame-c64.p8 @@ -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 } } diff --git a/compiler/examples/numbergame-novm.p8 b/compiler/examples/numbergame-novm.p8 index fd6f3fe6a..9fc26e9df 100644 --- a/compiler/examples/numbergame-novm.p8 +++ b/compiler/examples/numbergame-novm.p8 @@ -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 " 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" diff --git a/compiler/src/prog8/compiler/target/c64/Commodore64.kt b/compiler/src/prog8/compiler/target/c64/Commodore64.kt index 19bfb851f..12ed53013 100644 --- a/compiler/src/prog8/compiler/target/c64/Commodore64.kt +++ b/compiler/src/prog8/compiler/target/c64/Commodore64.kt @@ -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) diff --git a/prog8lib/c64lib.p8 b/prog8lib/c64lib.p8 index 403fb9ab5..61177a8e8 100644 --- a/prog8lib/c64lib.p8 +++ b/prog8lib/c64lib.p8 @@ -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) diff --git a/prog8lib/c64utils.p8 b/prog8lib/c64utils.p8 index e8a712cd1..c5917b148 100644 --- a/prog8lib/c64utils.p8 +++ b/prog8lib/c64utils.p8 @@ -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 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 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 }} diff --git a/prog8lib/mathlib.p8 b/prog8lib/mathlib.p8 index 4e6a5458c..d73206f52 100644 --- a/prog8lib/mathlib.p8 +++ b/prog8lib/mathlib.p8 @@ -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 }} } diff --git a/prog8lib/prog8lib.p8 b/prog8lib/prog8lib.p8 index 303a41269..03622f793 100644 --- a/prog8lib/prog8lib.p8 +++ b/prog8lib/prog8lib.p8 @@ -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 + }} } diff --git a/prog8lib/prog8lib_OLD.p8 b/prog8lib/prog8lib_OLD.p8 index 8447a1c36..85132e2ca 100644 --- a/prog8lib/prog8lib_OLD.p8 +++ b/prog8lib/prog8lib_OLD.p8 @@ -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