From 5471c5211c98888918fbeb9d718abfd08643e45c Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Mon, 21 Jan 2019 00:00:26 +0100 Subject: [PATCH] make %asminclude work, restructure prog8lib into separate asm file --- compiler/res/prog8lib/math.asm | 704 +++++++ compiler/res/prog8lib/math.p8 | 11 + compiler/res/prog8lib/prog8lib.asm | 1025 ++++++++++ compiler/res/prog8lib/prog8lib.p8 | 1747 +---------------- compiler/src/prog8/CompilerMain.kt | 15 +- compiler/src/prog8/ast/AstChecker.kt | 4 +- compiler/src/prog8/compiler/Compiler.kt | 30 +- .../src/prog8/compiler/target/c64/AsmGen.kt | 22 +- compiler/src/prog8/parser/ModuleParsing.kt | 15 +- docs/source/syntaxreference.rst | 3 +- examples/bdmusic.p8 | 4 +- examples/cube3d-float.p8 | 2 +- examples/cube3d-sprites.p8 | 2 +- examples/cube3d.p8 | 2 +- examples/mandelbrot.p8 | 2 +- examples/test.p8 | 51 +- 16 files changed, 1814 insertions(+), 1825 deletions(-) create mode 100644 compiler/res/prog8lib/math.asm create mode 100644 compiler/res/prog8lib/math.p8 create mode 100644 compiler/res/prog8lib/prog8lib.asm diff --git a/compiler/res/prog8lib/math.asm b/compiler/res/prog8lib/math.asm new file mode 100644 index 000000000..9ee0137ed --- /dev/null +++ b/compiler/res/prog8lib/math.asm @@ -0,0 +1,704 @@ +; Prog8 internal Math library routines - always included by the compiler +; +; Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0 +; +; indent format: TABS, size=8 + + +; some more interesting routines can be found here: +; http://6502org.wikidot.com/software-math +; http://codebase64.org/doku.php?id=base:6502_6510_maths +; + +multiply_bytes .proc + ; -- multiply 2 bytes A and Y, result as byte in A (signed or unsigned) + sta c64.SCRATCH_ZPB1 ; num1 + sty c64.SCRATCH_ZPREG ; num2 + lda #0 + beq _enterloop +_doAdd clc + adc c64.SCRATCH_ZPB1 +_loop asl c64.SCRATCH_ZPB1 +_enterloop lsr c64.SCRATCH_ZPREG + bcs _doAdd + bne _loop + rts + .pend + + +multiply_bytes_16 .proc + ; -- multiply 2 bytes A and Y, result as word in A/Y (unsigned) + sta c64.SCRATCH_ZPB1 + sty c64.SCRATCH_ZPREG + stx c64.SCRATCH_ZPREGX + lda #0 + ldx #8 + lsr c64.SCRATCH_ZPB1 +- bcc + + clc + adc c64.SCRATCH_ZPREG ++ ror a + ror c64.SCRATCH_ZPB1 + dex + bne - + tay + lda c64.SCRATCH_ZPB1 + ldx c64.SCRATCH_ZPREGX + rts + .pend + + +multiply_words .proc + ; -- multiply two 16-bit words into a 32-bit result (signed and unsigned) + ; input: A/Y = first 16-bit number, c64.SCRATCH_ZPWORD1 in ZP = second 16-bit number + ; output: multiply_words.result 4-bytes/32-bits product, LSB order (low-to-high) + + sta c64.SCRATCH_ZPWORD2 + sty c64.SCRATCH_ZPWORD2+1 + stx c64.SCRATCH_ZPREGX + +mult16 lda #$00 + sta multiply_words_result+2 ; clear upper bits of product + sta multiply_words_result+3 + ldx #16 ; for all 16 bits... +- lsr c64.SCRATCH_ZPWORD1+1 ; divide multiplier by 2 + ror c64.SCRATCH_ZPWORD1 + bcc + + lda multiply_words_result+2 ; get upper half of product and add multiplicand + clc + adc c64.SCRATCH_ZPWORD2 + sta multiply_words_result+2 + lda multiply_words_result+3 + adc c64.SCRATCH_ZPWORD2+1 ++ ror a ; rotate partial product + sta multiply_words_result+3 + ror multiply_words_result+2 + ror multiply_words_result+1 + ror multiply_words_result + dex + bne - + ldx c64.SCRATCH_ZPREGX + rts + +multiply_words_result .byte 0,0,0,0 + .pend + + +divmod_ub .proc + ; -- divide A by Y, result quotient in Y, remainder in A (unsigned) + ; division by zero will result in quotient = 255 and remainder = original number + sty c64.SCRATCH_ZPREG + sta c64.SCRATCH_ZPB1 + stx c64.SCRATCH_ZPREGX + + lda #0 + ldx #8 + asl c64.SCRATCH_ZPB1 +- rol a + cmp c64.SCRATCH_ZPREG + bcc + + sbc c64.SCRATCH_ZPREG ++ rol c64.SCRATCH_ZPB1 + dex + bne - + ldy c64.SCRATCH_ZPB1 + ldx c64.SCRATCH_ZPREGX + rts + .pend + +divmod_uw_asm .proc + ; -- divide two unsigned words (16 bit each) into 16 bit results + ; input: c64.SCRATCH_ZPWORD1 in ZP: 16 bit number, A/Y: 16 bit divisor + ; output: c64.SCRATCH_ZPWORD2 in ZP: 16 bit remainder, A/Y: 16 bit division result + ; division by zero will result in quotient = 65535 and remainder = divident + + +dividend = c64.SCRATCH_ZPWORD1 +remainder = c64.SCRATCH_ZPWORD2 +result = dividend ;save memory by reusing divident to store the result + + sta _divisor + sty _divisor+1 + stx c64.SCRATCH_ZPREGX + lda #0 ;preset remainder to 0 + sta remainder + sta remainder+1 + ldx #16 ;repeat for each bit: ... + +- asl dividend ;dividend lb & hb*2, msb -> Carry + rol dividend+1 + rol remainder ;remainder lb & hb * 2 + msb from carry + rol remainder+1 + lda remainder + sec + sbc _divisor ;substract divisor to see if it fits in + tay ;lb result -> Y, for we may need it later + lda remainder+1 + sbc _divisor+1 + bcc + ;if carry=0 then divisor didn't fit in yet + + sta remainder+1 ;else save substraction result as new remainder, + sty remainder + inc result ;and INCrement result cause divisor fit in 1 times + ++ dex + bne - + + lda result + ldy result+1 + ldx c64.SCRATCH_ZPREGX + rts +_divisor .word 0 + .pend + + +randseed .proc + ; -- reset the random seeds for the byte and word random generators + ; arguments: uword seed in A/Y clobbers A + ; (default starting values are: A=$2c Y=$9e) + sta randword._seed + sty randword._seed+1 + clc + adc #14 + sta randbyte._seed + rts + .pend + + +randbyte .proc + ; -- 8-bit pseudo random number generator into A + lda _seed + beq _eor + asl a + beq _done ; if the input was $80, skip the EOR + bcc _done +_eor eor #$1d ; xor with magic value see below for possible values +_done sta _seed + rts + +_seed .byte $3a + + ; possible 'magic' eor bytes are: + ; $1d, $2b, $2d, $4d, $5f, $63, $65, $69 + ; $71, $87, $8d, $a9, $c3, $cf, $e7, $f5 + + .pend + + +randword .proc + ; -- 16 bit pseudo random number generator into AY + +magic_eor = $3f1d + ; possible magic eor words are: + ; $3f1d, $3f81, $3fa5, $3fc5, $4075, $409d, $40cd, $4109 + ; $413f, $414b, $4153, $4159, $4193, $4199, $41af, $41bb + + lda _seed + beq _lowZero ; $0000 and $8000 are special values to test for + + ; Do a normal shift + asl _seed + lda _seed+1 + rol a + bcc _noEor + +_doEor ; high byte is in A + eor #>magic_eor + sta _seed+1 + lda _seed + eor #b (signed and unsigned) + inx + lda c64.ESTACK_LO,x + ldy c64.ESTACK_LO+1,x + jsr math.multiply_bytes + sta c64.ESTACK_LO+1,x + rts + .pend + +mul_word .proc + inx + lda c64.ESTACK_LO,x + sta c64.SCRATCH_ZPWORD1 + lda c64.ESTACK_HI,x + sta c64.SCRATCH_ZPWORD1+1 + lda c64.ESTACK_LO+1,x + ldy c64.ESTACK_HI+1,x + stx c64.SCRATCH_ZPREGX + jsr math.multiply_words + ldx c64.SCRATCH_ZPREGX + lda math.multiply_words.multiply_words_result + sta c64.ESTACK_LO+1,x + lda math.multiply_words.multiply_words_result+1 + sta c64.ESTACK_HI+1,x + rts + .pend + +idiv_b .proc + ; signed division: use unsigned division and fix sign of result afterwards + inx + lda c64.ESTACK_LO,x + eor c64.ESTACK_LO+1,x + php ; save sign of result + lda c64.ESTACK_LO,x + bpl + + eor #$ff + sec + adc #0 ; make num1 positive ++ tay + inx + lda c64.ESTACK_LO,x + bpl + + eor #$ff + sec + adc #0 ; make num2 positive ++ jsr math.divmod_ub + sta _remainder + tya + plp ; get sign of result + bpl + + eor #$ff + sec + adc #0 ; negate result ++ sta c64.ESTACK_LO,x + dex + rts +_remainder .byte 0 + .pend + +idiv_ub .proc + inx + ldy c64.ESTACK_LO,x + lda c64.ESTACK_LO+1,x + jsr math.divmod_ub + tya + sta c64.ESTACK_LO+1,x + rts + .pend + +idiv_w .proc + ; signed division: use unsigned division and fix sign of result afterwards + lda c64.ESTACK_HI+2,x + eor c64.ESTACK_HI+1,x + php ; save sign of result + lda c64.ESTACK_HI+1,x + bpl + + jsr neg_w ; make value positive ++ inx + lda c64.ESTACK_HI+1,x + bpl + + jsr neg_w ; make value positive ++ lda c64.ESTACK_LO+1,x + sta c64.SCRATCH_ZPWORD1 + lda c64.ESTACK_HI+1,x + sta c64.SCRATCH_ZPWORD1+1 + lda c64.ESTACK_LO,x + ldy c64.ESTACK_HI,x + jsr math.divmod_uw_asm + sta c64.ESTACK_LO+1,x + tya + sta c64.ESTACK_HI+1,x + plp + bpl + + jmp neg_w ; negate result ++ rts + .pend + +idiv_uw .proc + inx + lda c64.ESTACK_LO+1,x + sta c64.SCRATCH_ZPWORD1 + lda c64.ESTACK_HI+1,x + sta c64.SCRATCH_ZPWORD1+1 + lda c64.ESTACK_LO,x + ldy c64.ESTACK_HI,x + jsr math.divmod_uw_asm + sta c64.ESTACK_LO+1,x + tya + sta c64.ESTACK_HI+1,x + rts + .pend + +remainder_ub .proc + inx + ldy c64.ESTACK_LO,x ; right operand + lda c64.ESTACK_LO+1,x ; left operand + jsr math.divmod_ub + sta c64.ESTACK_LO+1,x + rts + .pend + +remainder_uw .proc + inx + lda c64.ESTACK_LO+1,x + sta c64.SCRATCH_ZPWORD1 + lda c64.ESTACK_HI+1,x + sta c64.SCRATCH_ZPWORD1+1 + lda c64.ESTACK_LO,x + ldy c64.ESTACK_HI,x + jsr math.divmod_uw_asm + lda c64.SCRATCH_ZPWORD2 + sta c64.ESTACK_LO+1,x + lda c64.SCRATCH_ZPWORD2+1 + sta c64.ESTACK_HI+1,x + rts + .pend + +equal_w .proc + ; -- are the two words on the stack identical? + lda c64.ESTACK_LO+1,x + cmp c64.ESTACK_LO+2,x + bne equal_b._equal_b_false + lda c64.ESTACK_HI+1,x + cmp c64.ESTACK_HI+2,x + bne equal_b._equal_b_false + beq equal_b._equal_b_true + .pend + +notequal_b .proc + ; -- are the two bytes on the stack different? + inx + lda c64.ESTACK_LO,x + eor c64.ESTACK_LO+1,x + sta c64.ESTACK_LO+1,x + rts + .pend + +notequal_w .proc + ; -- are the two words on the stack different? + inx + lda c64.ESTACK_LO,x + eor c64.ESTACK_LO+1,x + beq + + sta c64.ESTACK_LO+1,x + rts ++ lda c64.ESTACK_HI,x + eor c64.ESTACK_HI+1,x + sta c64.ESTACK_LO+1,x + rts + .pend + +less_ub .proc + lda c64.ESTACK_LO+2,x + cmp c64.ESTACK_LO+1,x + bcc equal_b._equal_b_true + bcs equal_b._equal_b_false + .pend + +less_b .proc + ; see http://www.6502.org/tutorials/compare_beyond.html + lda c64.ESTACK_LO+2,x + sec + sbc c64.ESTACK_LO+1,x + bvc + + eor #$80 ++ bmi equal_b._equal_b_true + bpl equal_b._equal_b_false + .pend + +less_uw .proc + lda c64.ESTACK_HI+2,x + cmp c64.ESTACK_HI+1,x + bcc equal_b._equal_b_true + bne equal_b._equal_b_false + lda c64.ESTACK_LO+2,x + cmp c64.ESTACK_LO+1,x + bcc equal_b._equal_b_true + bcs equal_b._equal_b_false + .pend + +less_w .proc + lda c64.ESTACK_LO+2,x + cmp c64.ESTACK_LO+1,x + lda c64.ESTACK_HI+2,x + sbc c64.ESTACK_HI+1,x + bvc + + eor #$80 ++ bmi equal_b._equal_b_true + bpl equal_b._equal_b_false + .pend + +equal_b .proc + ; -- are the two bytes on the stack identical? + lda c64.ESTACK_LO+2,x + cmp c64.ESTACK_LO+1,x + bne _equal_b_false +_equal_b_true lda #1 +_equal_b_store inx + sta c64.ESTACK_LO+1,x + rts +_equal_b_false lda #0 + beq _equal_b_store + .pend + +lesseq_ub .proc + lda c64.ESTACK_LO+2,x + cmp c64.ESTACK_LO+1,x + bcc equal_b._equal_b_true + beq equal_b._equal_b_true + bcs equal_b._equal_b_false + .pend + +lesseq_b .proc + ; see http://www.6502.org/tutorials/compare_beyond.html + lda c64.ESTACK_LO+2,x + clc + sbc c64.ESTACK_LO+1,x + bvc + + eor #$80 ++ bmi equal_b._equal_b_true + bpl equal_b._equal_b_false + .pend + +lesseq_uw .proc + lda c64.ESTACK_HI+1,x + cmp c64.ESTACK_HI+2,x + bcc equal_b._equal_b_false + bne equal_b._equal_b_true + lda c64.ESTACK_LO+1,x + cmp c64.ESTACK_LO+2,x + bcs equal_b._equal_b_true + bcc equal_b._equal_b_false + .pend + +lesseq_w .proc + lda c64.ESTACK_LO+1,x + cmp c64.ESTACK_LO+2,x + lda c64.ESTACK_HI+1,x + sbc c64.ESTACK_HI+2,x + bvc + + eor #$80 ++ bpl equal_b._equal_b_true + bmi equal_b._equal_b_false + .pend + +greater_ub .proc + lda c64.ESTACK_LO+2,x + cmp c64.ESTACK_LO+1,x + beq equal_b._equal_b_false + bcs equal_b._equal_b_true + bcc equal_b._equal_b_false + .pend + +greater_b .proc + ; see http://www.6502.org/tutorials/compare_beyond.html + lda c64.ESTACK_LO+2,x + clc + sbc c64.ESTACK_LO+1,x + bvc + + eor #$80 ++ bpl equal_b._equal_b_true + bmi equal_b._equal_b_false + .pend + +greater_uw .proc + lda c64.ESTACK_HI+1,x + cmp c64.ESTACK_HI+2,x + bcc equal_b._equal_b_true + bne equal_b._equal_b_false + lda c64.ESTACK_LO+1,x + cmp c64.ESTACK_LO+2,x + bcc equal_b._equal_b_true + bcs equal_b._equal_b_false + .pend + +greater_w .proc + lda c64.ESTACK_LO+1,x + cmp c64.ESTACK_LO+2,x + lda c64.ESTACK_HI+1,x + sbc c64.ESTACK_HI+2,x + bvc + + eor #$80 ++ bmi equal_b._equal_b_true + bpl equal_b._equal_b_false + .pend + +greatereq_ub .proc + lda c64.ESTACK_LO+2,x + cmp c64.ESTACK_LO+1,x + bcs equal_b._equal_b_true + bcc equal_b._equal_b_false + .pend + +greatereq_b .proc + ; see http://www.6502.org/tutorials/compare_beyond.html + lda c64.ESTACK_LO+2,x + sec + sbc c64.ESTACK_LO+1,x + bvc + + eor #$80 ++ bpl equal_b._equal_b_true + bmi equal_b._equal_b_false + .pend + +greatereq_uw .proc + lda c64.ESTACK_HI+2,x + cmp c64.ESTACK_HI+1,x + bcc equal_b._equal_b_false + bne equal_b._equal_b_true + lda c64.ESTACK_LO+2,x + cmp c64.ESTACK_LO+1,x + bcs equal_b._equal_b_true + bcc equal_b._equal_b_false + .pend + +greatereq_w .proc + lda c64.ESTACK_LO+2,x + cmp c64.ESTACK_LO+1,x + lda c64.ESTACK_HI+2,x + sbc c64.ESTACK_HI+1,x + bvc + + eor #$80 ++ bpl equal_b._equal_b_true + bmi equal_b._equal_b_false + .pend + + +func_sin8 .proc + ldy c64.ESTACK_LO+1,x + lda _sinecos8,y + sta c64.ESTACK_LO+1,x + rts +_sinecos8 .char 127 * sin(range(256+64) * rad(360.0/256.0)) + .pend + +func_sin8u .proc + ldy c64.ESTACK_LO+1,x + lda _sinecos8u,y + sta c64.ESTACK_LO+1,x + rts +_sinecos8u .byte 128 + 127.5 * sin(range(256+64) * rad(360.0/256.0)) + .pend + +func_sin16 .proc + ldy c64.ESTACK_LO+1,x + lda _sinecos8lo,y + sta c64.ESTACK_LO+1,x + lda _sinecos8hi,y + sta c64.ESTACK_HI+1,x + rts + +_ := 32767 * sin(range(256+64) * rad(360.0/256.0)) +_sinecos8lo .byte <_ +_sinecos8hi .byte >_ + .pend + +func_sin16u .proc + ldy c64.ESTACK_LO+1,x + lda _sinecos8ulo,y + sta c64.ESTACK_LO+1,x + lda _sinecos8uhi,y + sta c64.ESTACK_HI+1,x + rts + +_ := 32768 + 32767.5 * sin(range(256+64) * rad(360.0/256.0)) +_sinecos8ulo .byte <_ +_sinecos8uhi .byte >_ + .pend + +func_cos8 .proc + ldy c64.ESTACK_LO+1,x + lda func_sin8._sinecos8+64,y + sta c64.ESTACK_LO+1,x + rts + .pend + +func_cos8u .proc + ldy c64.ESTACK_LO+1,x + lda func_sin8u._sinecos8u+64,y + sta c64.ESTACK_LO+1,x + rts + .pend + +func_cos16 .proc + ldy c64.ESTACK_LO+1,x + lda func_sin16._sinecos8lo+64,y + sta c64.ESTACK_LO+1,x + lda func_sin16._sinecos8hi+64,y + sta c64.ESTACK_HI+1,x + rts + .pend + +func_cos16u .proc + ldy c64.ESTACK_LO+1,x + lda func_sin16u._sinecos8ulo+64,y + sta c64.ESTACK_LO+1,x + lda func_sin16u._sinecos8uhi+64,y + sta c64.ESTACK_HI+1,x + rts + .pend + + +peek_address .proc + ; -- peek address on stack into c64.SCRATCH_ZPWORD1 + lda c64.ESTACK_LO+1,x + sta c64.SCRATCH_ZPWORD1 + lda c64.ESTACK_HI+1,x + sta c64.SCRATCH_ZPWORD1+1 + rts + .pend + +func_any_b .proc + inx + lda c64.ESTACK_LO,x ; array size +_entry sta _cmp_mod+1 ; self-modifying code + jsr peek_address + ldy #0 +- lda (c64.SCRATCH_ZPWORD1),y + bne _got_any + iny +_cmp_mod cpy #255 ; modified + bne - + lda #0 + sta c64.ESTACK_LO+1,x + rts +_got_any lda #1 + sta c64.ESTACK_LO+1,x + rts + .pend + +func_any_w .proc + inx + lda c64.ESTACK_LO,x ; array size + asl a ; times 2 because of word + jmp func_any_b._entry + .pend + +func_all_b .proc + inx + lda c64.ESTACK_LO,x ; array size + sta _cmp_mod+1 ; self-modifying code + jsr peek_address + ldy #0 +- lda (c64.SCRATCH_ZPWORD1),y + beq _got_not_all + iny +_cmp_mod cpy #255 ; modified + bne - + lda #1 + sta c64.ESTACK_LO+1,x + rts +_got_not_all lda #0 + sta c64.ESTACK_LO+1,x + rts + .pend + +func_all_w .proc + inx + lda c64.ESTACK_LO,x ; array size + asl a ; times 2 because of word + sta _cmp_mod+1 ; self-modifying code + jsr peek_address + ldy #0 +- lda (c64.SCRATCH_ZPWORD1),y + bne + + iny + lda (c64.SCRATCH_ZPWORD1),y + bne + + lda #0 + sta c64.ESTACK_LO+1,x + rts ++ iny +_cmp_mod cpy #255 ; modified + bne - + lda #1 + sta c64.ESTACK_LO+1,x + rts + .pend + +func_max_ub .proc + jsr pop_array_and_lengthmin1Y + lda #0 + sta c64.SCRATCH_ZPB1 +- lda (c64.SCRATCH_ZPWORD1),y + cmp c64.SCRATCH_ZPB1 + bcc + + sta c64.SCRATCH_ZPB1 ++ dey + cpy #255 + bne - + lda c64.SCRATCH_ZPB1 + sta c64.ESTACK_LO,x + dex + rts + .pend + +func_max_b .proc + jsr pop_array_and_lengthmin1Y + lda #-128 + sta c64.SCRATCH_ZPB1 +- lda (c64.SCRATCH_ZPWORD1),y + sec + sbc c64.SCRATCH_ZPB1 + bvc + + eor #$80 ++ bmi + + lda (c64.SCRATCH_ZPWORD1),y + sta c64.SCRATCH_ZPB1 ++ dey + cpy #255 + bne - + lda c64.SCRATCH_ZPB1 + sta c64.ESTACK_LO,x + dex + rts + .pend + +func_max_uw .proc + lda #0 + sta _result_maxuw + sta _result_maxuw+1 + jsr pop_array_and_lengthmin1Y + tya + asl a + tay +_loop + iny + lda (c64.SCRATCH_ZPWORD1),y + dey + cmp _result_maxuw+1 + bcc _lesseq + bne _greater + lda (c64.SCRATCH_ZPWORD1),y + cmp _result_maxuw + bcc _lesseq +_greater lda (c64.SCRATCH_ZPWORD1),y + sta _result_maxuw + iny + lda (c64.SCRATCH_ZPWORD1),y + sta _result_maxuw+1 + dey +_lesseq dey + dey + cpy #254 + bne _loop + lda _result_maxuw + sta c64.ESTACK_LO,x + lda _result_maxuw+1 + sta c64.ESTACK_HI,x + dex + rts +_result_maxuw .word 0 + .pend + +func_max_w .proc + lda #$00 + sta _result_maxw + lda #$80 + sta _result_maxw+1 + jsr pop_array_and_lengthmin1Y + tya + asl a + tay +_loop + lda (c64.SCRATCH_ZPWORD1),y + cmp _result_maxw + iny + lda (c64.SCRATCH_ZPWORD1),y + dey + sbc _result_maxw+1 + bvc + + eor #$80 ++ bmi _lesseq + lda (c64.SCRATCH_ZPWORD1),y + sta _result_maxw + iny + lda (c64.SCRATCH_ZPWORD1),y + sta _result_maxw+1 + dey +_lesseq dey + dey + cpy #254 + bne _loop + lda _result_maxw + sta c64.ESTACK_LO,x + lda _result_maxw+1 + sta c64.ESTACK_HI,x + dex + rts +_result_maxw .word 0 + .pend + + +func_sum_b .proc + jsr pop_array_and_lengthmin1Y + lda #0 + sta c64.ESTACK_LO,x + sta c64.ESTACK_HI,x +_loop lda (c64.SCRATCH_ZPWORD1),y + pha + clc + adc c64.ESTACK_LO,x + sta c64.ESTACK_LO,x + ; sign extend the high byte + pla + and #$80 + beq + + lda #$ff ++ adc c64.ESTACK_HI,x + sta c64.ESTACK_HI,x + dey + cpy #255 + bne _loop + dex + rts + .pend + +func_sum_ub .proc + jsr pop_array_and_lengthmin1Y + lda #0 + sta c64.ESTACK_LO,x + sta c64.ESTACK_HI,x +- lda (c64.SCRATCH_ZPWORD1),y + clc + adc c64.ESTACK_LO,x + sta c64.ESTACK_LO,x + bcc + + inc c64.ESTACK_HI,x ++ dey + cpy #255 + bne - + dex + rts + .pend + +func_sum_uw .proc + jsr pop_array_and_lengthmin1Y + tya + asl a + tay + lda #0 + sta c64.ESTACK_LO,x + sta c64.ESTACK_HI,x +- lda (c64.SCRATCH_ZPWORD1),y + iny + clc + adc c64.ESTACK_LO,x + sta c64.ESTACK_LO,x + lda (c64.SCRATCH_ZPWORD1),y + adc c64.ESTACK_HI,x + sta c64.ESTACK_HI,x + dey + dey + dey + cpy #254 + bne - + dex + rts + .pend + +func_sum_w .proc + jmp func_sum_uw + .pend + + +pop_array_and_lengthmin1Y .proc + inx + ldy c64.ESTACK_LO,x + dey ; length minus 1, for iteration + lda c64.ESTACK_LO+1,x + sta c64.SCRATCH_ZPWORD1 + lda c64.ESTACK_HI+1,x + sta c64.SCRATCH_ZPWORD1+1 + inx + rts + .pend + +func_min_ub .proc + jsr pop_array_and_lengthmin1Y + lda #255 + sta c64.SCRATCH_ZPB1 +- lda (c64.SCRATCH_ZPWORD1),y + cmp c64.SCRATCH_ZPB1 + bcs + + sta c64.SCRATCH_ZPB1 ++ dey + cpy #255 + bne - + lda c64.SCRATCH_ZPB1 + sta c64.ESTACK_LO,x + dex + rts + .pend + + +func_min_b .proc + jsr pop_array_and_lengthmin1Y + lda #127 + sta c64.SCRATCH_ZPB1 +- lda (c64.SCRATCH_ZPWORD1),y + clc + sbc c64.SCRATCH_ZPB1 + bvc + + eor #$80 ++ bpl + + lda (c64.SCRATCH_ZPWORD1),y + sta c64.SCRATCH_ZPB1 ++ dey + cpy #255 + bne - + lda c64.SCRATCH_ZPB1 + sta c64.ESTACK_LO,x + dex + rts + .pend + +func_min_uw .proc + lda #$ff + sta _result_minuw + sta _result_minuw+1 + jsr pop_array_and_lengthmin1Y + tya + asl a + tay +_loop + iny + lda (c64.SCRATCH_ZPWORD1),y + dey + cmp _result_minuw+1 + bcc _less + bne _gtequ + lda (c64.SCRATCH_ZPWORD1),y + cmp _result_minuw + bcs _gtequ +_less lda (c64.SCRATCH_ZPWORD1),y + sta _result_minuw + iny + lda (c64.SCRATCH_ZPWORD1),y + sta _result_minuw+1 + dey +_gtequ dey + dey + cpy #254 + bne _loop + lda _result_minuw + sta c64.ESTACK_LO,x + lda _result_minuw+1 + sta c64.ESTACK_HI,x + dex + rts +_result_minuw .word 0 + .pend + +func_min_w .proc + lda #$ff + sta _result_minw + lda #$7f + sta _result_minw+1 + jsr pop_array_and_lengthmin1Y + tya + asl a + tay +_loop + lda (c64.SCRATCH_ZPWORD1),y + cmp _result_minw + iny + lda (c64.SCRATCH_ZPWORD1),y + dey + sbc _result_minw+1 + bvc + + eor #$80 ++ bpl _gtequ + lda (c64.SCRATCH_ZPWORD1),y + sta _result_minw + iny + lda (c64.SCRATCH_ZPWORD1),y + sta _result_minw+1 + dey +_gtequ dey + dey + cpy #254 + bne _loop + lda _result_minw + sta c64.ESTACK_LO,x + lda _result_minw+1 + sta c64.ESTACK_HI,x + dex + rts +_result_minw .word 0 + .pend + + +func_len_str .proc + ; -- push length of 0-terminated string on stack + jsr peek_address + ldy #0 +- lda (c64.SCRATCH_ZPWORD1),y + beq + + iny + bne - ++ tya + sta c64.ESTACK_LO+1,x + rts + .pend + +func_len_strp .proc + ; -- push length of pascal-string on stack + jsr peek_address + ldy #0 + lda (c64.SCRATCH_ZPWORD1),y ; first byte is length + sta c64.ESTACK_LO+1,x + rts + .pend + +func_rnd .proc + ; -- put a random ubyte on the estack + jsr math.randbyte + sta c64.ESTACK_LO,x + dex + rts + .pend + +func_rndw .proc + ; -- put a random uword on the estack + jsr math.randword + sta c64.ESTACK_LO,x + tya + sta c64.ESTACK_HI,x + dex + rts + .pend + + +func_memcopy .proc + ; note: clobbers A,Y + inx + stx c64.SCRATCH_ZPREGX + lda c64.ESTACK_LO+2,x + sta c64.SCRATCH_ZPWORD1 + lda c64.ESTACK_HI+2,x + sta c64.SCRATCH_ZPWORD1+1 + lda c64.ESTACK_LO+1,x + ldy c64.ESTACK_HI+1,x + pha + lda c64.ESTACK_LO,x + tax + pla + jsr c64utils.memcopy + ldx c64.SCRATCH_ZPREGX + inx + inx + rts + .pend diff --git a/compiler/res/prog8lib/prog8lib.p8 b/compiler/res/prog8lib/prog8lib.p8 index 5bc92765c..97f8bfa55 100644 --- a/compiler/res/prog8lib/prog8lib.p8 +++ b/compiler/res/prog8lib/prog8lib.p8 @@ -4,1751 +4,8 @@ ; ; indent format: TABS, size=8 +%import c64lib ~ prog8_lib { - - %asm {{ - -init_system .proc - ; -- initializes the machine to a sane starting state - ; Called automatically by the loader program logic. - ; This means that the BASIC, KERNAL and CHARGEN ROMs are banked in, - ; the VIC, SID and CIA chips are reset, screen is cleared, and the default IRQ is set. - ; Also a different color scheme is chosen to identify ourselves a little. - ; Uppercase charset is activated, and all three registers set to 0, status flags cleared. - sei - cld - lda #%00101111 - sta $00 - lda #%00100111 - sta $01 - jsr c64.IOINIT - jsr c64.RESTOR - jsr c64.CINT - lda #6 - sta c64.EXTCOL - lda #7 - sta c64.COLOR - lda #0 - sta c64.BGCOL0 - tax - tay - clc - clv - cli - rts - .pend - - -add_a_to_zpword .proc - ; -- add ubyte in A to the uword in c64.SCRATCH_ZPWORD1 - clc - adc c64.SCRATCH_ZPWORD1 - sta c64.SCRATCH_ZPWORD1 - bcc + - inc c64.SCRATCH_ZPWORD1+1 -+ rts - .pend - -pop_index_times_5 .proc - inx - lda c64.ESTACK_LO,x - sta c64.SCRATCH_ZPB1 - asl a - asl a - clc - adc c64.SCRATCH_ZPB1 ; A*=5 - rts - .pend - -neg_b .proc - lda c64.ESTACK_LO+1,x - eor #255 - clc - adc #1 - sta c64.ESTACK_LO+1,x - rts - .pend - -neg_w .proc - sec - lda #0 - sbc c64.ESTACK_LO+1,x - sta c64.ESTACK_LO+1,x - lda #0 - sbc c64.ESTACK_HI+1,x - sta c64.ESTACK_HI+1,x - rts - .pend - -inv_word .proc - lda c64.ESTACK_LO+1,x - eor #255 - sta c64.ESTACK_LO+1,x - lda c64.ESTACK_HI+1,x - eor #255 - sta c64.ESTACK_HI+1,x - rts - .pend - -not_byte .proc - lda c64.ESTACK_LO+1,x - beq + - lda #0 - beq ++ -+ lda #1 -+ sta c64.ESTACK_LO+1,x - rts - .pend - -not_word .proc - lda c64.ESTACK_LO + 1,x - ora c64.ESTACK_HI + 1,x - beq + - lda #0 - beq ++ -+ lda #1 -+ sta c64.ESTACK_LO + 1,x - sta c64.ESTACK_HI + 1,x - rts - .pend - -abs_b .proc - ; -- push abs(byte) on stack (as byte) - lda c64.ESTACK_LO+1,x - bmi neg_b - rts - .pend - -abs_w .proc - ; -- push abs(word) on stack (as word) - lda c64.ESTACK_HI+1,x - bmi neg_w - rts - .pend - -add_w .proc - ; -- push word+word / uword+uword - inx - clc - lda c64.ESTACK_LO,x - adc c64.ESTACK_LO+1,x - sta c64.ESTACK_LO+1,x - lda c64.ESTACK_HI,x - adc c64.ESTACK_HI+1,x - sta c64.ESTACK_HI+1,x - rts - .pend - -sub_w .proc - ; -- push word-word - inx - sec - lda c64.ESTACK_LO+1,x - sbc c64.ESTACK_LO,x - sta c64.ESTACK_LO+1,x - lda c64.ESTACK_HI+1,x - sbc c64.ESTACK_HI,x - sta c64.ESTACK_HI+1,x - rts - .pend - -mul_byte .proc - ; -- b*b->b (signed and unsigned) - inx - lda c64.ESTACK_LO,x - ldy c64.ESTACK_LO+1,x - jsr math.multiply_bytes - sta c64.ESTACK_LO+1,x - rts - .pend - -mul_word .proc - inx - lda c64.ESTACK_LO,x - sta c64.SCRATCH_ZPWORD1 - lda c64.ESTACK_HI,x - sta c64.SCRATCH_ZPWORD1+1 - lda c64.ESTACK_LO+1,x - ldy c64.ESTACK_HI+1,x - stx c64.SCRATCH_ZPREGX - jsr math.multiply_words - ldx c64.SCRATCH_ZPREGX - lda math.multiply_words.multiply_words_result - sta c64.ESTACK_LO+1,x - lda math.multiply_words.multiply_words_result+1 - sta c64.ESTACK_HI+1,x - rts - .pend - -idiv_b .proc - ; signed division: use unsigned division and fix sign of result afterwards - inx - lda c64.ESTACK_LO,x - eor c64.ESTACK_LO+1,x - php ; save sign of result - lda c64.ESTACK_LO,x - bpl + - eor #$ff - sec - adc #0 ; make num1 positive -+ tay - inx - lda c64.ESTACK_LO,x - bpl + - eor #$ff - sec - adc #0 ; make num2 positive -+ jsr math.divmod_ub - sta _remainder - tya - plp ; get sign of result - bpl + - eor #$ff - sec - adc #0 ; negate result -+ sta c64.ESTACK_LO,x - dex - rts -_remainder .byte 0 - .pend - -idiv_ub .proc - inx - ldy c64.ESTACK_LO,x - lda c64.ESTACK_LO+1,x - jsr math.divmod_ub - tya - sta c64.ESTACK_LO+1,x - rts - .pend - -idiv_w .proc - ; signed division: use unsigned division and fix sign of result afterwards - lda c64.ESTACK_HI+2,x - eor c64.ESTACK_HI+1,x - php ; save sign of result - lda c64.ESTACK_HI+1,x - bpl + - jsr neg_w ; make value positive -+ inx - lda c64.ESTACK_HI+1,x - bpl + - jsr neg_w ; make value positive -+ lda c64.ESTACK_LO+1,x - sta c64.SCRATCH_ZPWORD1 - lda c64.ESTACK_HI+1,x - sta c64.SCRATCH_ZPWORD1+1 - lda c64.ESTACK_LO,x - ldy c64.ESTACK_HI,x - jsr math.divmod_uw_asm - sta c64.ESTACK_LO+1,x - tya - sta c64.ESTACK_HI+1,x - plp - bpl + - jmp neg_w ; negate result -+ rts - .pend - -idiv_uw .proc - inx - lda c64.ESTACK_LO+1,x - sta c64.SCRATCH_ZPWORD1 - lda c64.ESTACK_HI+1,x - sta c64.SCRATCH_ZPWORD1+1 - lda c64.ESTACK_LO,x - ldy c64.ESTACK_HI,x - jsr math.divmod_uw_asm - sta c64.ESTACK_LO+1,x - tya - sta c64.ESTACK_HI+1,x - rts - .pend - -remainder_ub .proc - inx - ldy c64.ESTACK_LO,x ; right operand - lda c64.ESTACK_LO+1,x ; left operand - jsr math.divmod_ub - sta c64.ESTACK_LO+1,x - rts - .pend - -remainder_uw .proc - inx - lda c64.ESTACK_LO+1,x - sta c64.SCRATCH_ZPWORD1 - lda c64.ESTACK_HI+1,x - sta c64.SCRATCH_ZPWORD1+1 - lda c64.ESTACK_LO,x - ldy c64.ESTACK_HI,x - jsr math.divmod_uw_asm - lda c64.SCRATCH_ZPWORD2 - sta c64.ESTACK_LO+1,x - lda c64.SCRATCH_ZPWORD2+1 - sta c64.ESTACK_HI+1,x - rts - .pend - -equal_w .proc - ; -- are the two words on the stack identical? - lda c64.ESTACK_LO+1,x - cmp c64.ESTACK_LO+2,x - bne equal_b._equal_b_false - lda c64.ESTACK_HI+1,x - cmp c64.ESTACK_HI+2,x - bne equal_b._equal_b_false - beq equal_b._equal_b_true - .pend - -notequal_b .proc - ; -- are the two bytes on the stack different? - inx - lda c64.ESTACK_LO,x - eor c64.ESTACK_LO+1,x - sta c64.ESTACK_LO+1,x - rts - .pend - -notequal_w .proc - ; -- are the two words on the stack different? - inx - lda c64.ESTACK_LO,x - eor c64.ESTACK_LO+1,x - beq + - sta c64.ESTACK_LO+1,x - rts -+ lda c64.ESTACK_HI,x - eor c64.ESTACK_HI+1,x - sta c64.ESTACK_LO+1,x - rts - .pend - -less_ub .proc - lda c64.ESTACK_LO+2,x - cmp c64.ESTACK_LO+1,x - bcc equal_b._equal_b_true - bcs equal_b._equal_b_false - .pend - -less_b .proc - ; see http://www.6502.org/tutorials/compare_beyond.html - lda c64.ESTACK_LO+2,x - sec - sbc c64.ESTACK_LO+1,x - bvc + - eor #$80 -+ bmi equal_b._equal_b_true - bpl equal_b._equal_b_false - .pend - -less_uw .proc - lda c64.ESTACK_HI+2,x - cmp c64.ESTACK_HI+1,x - bcc equal_b._equal_b_true - bne equal_b._equal_b_false - lda c64.ESTACK_LO+2,x - cmp c64.ESTACK_LO+1,x - bcc equal_b._equal_b_true - bcs equal_b._equal_b_false - .pend - -less_w .proc - lda c64.ESTACK_LO+2,x - cmp c64.ESTACK_LO+1,x - lda c64.ESTACK_HI+2,x - sbc c64.ESTACK_HI+1,x - bvc + - eor #$80 -+ bmi equal_b._equal_b_true - bpl equal_b._equal_b_false - .pend - -equal_b .proc - ; -- are the two bytes on the stack identical? - lda c64.ESTACK_LO+2,x - cmp c64.ESTACK_LO+1,x - bne _equal_b_false -_equal_b_true lda #1 -_equal_b_store inx - sta c64.ESTACK_LO+1,x - rts -_equal_b_false lda #0 - beq _equal_b_store - .pend - -lesseq_ub .proc - lda c64.ESTACK_LO+2,x - cmp c64.ESTACK_LO+1,x - bcc equal_b._equal_b_true - beq equal_b._equal_b_true - bcs equal_b._equal_b_false - .pend - -lesseq_b .proc - ; see http://www.6502.org/tutorials/compare_beyond.html - lda c64.ESTACK_LO+2,x - clc - sbc c64.ESTACK_LO+1,x - bvc + - eor #$80 -+ bmi equal_b._equal_b_true - bpl equal_b._equal_b_false - .pend - -lesseq_uw .proc - lda c64.ESTACK_HI+1,x - cmp c64.ESTACK_HI+2,x - bcc equal_b._equal_b_false - bne equal_b._equal_b_true - lda c64.ESTACK_LO+1,x - cmp c64.ESTACK_LO+2,x - bcs equal_b._equal_b_true - bcc equal_b._equal_b_false - .pend - -lesseq_w .proc - lda c64.ESTACK_LO+1,x - cmp c64.ESTACK_LO+2,x - lda c64.ESTACK_HI+1,x - sbc c64.ESTACK_HI+2,x - bvc + - eor #$80 -+ bpl equal_b._equal_b_true - bmi equal_b._equal_b_false - .pend - -greater_ub .proc - lda c64.ESTACK_LO+2,x - cmp c64.ESTACK_LO+1,x - beq equal_b._equal_b_false - bcs equal_b._equal_b_true - bcc equal_b._equal_b_false - .pend - -greater_b .proc - ; see http://www.6502.org/tutorials/compare_beyond.html - lda c64.ESTACK_LO+2,x - clc - sbc c64.ESTACK_LO+1,x - bvc + - eor #$80 -+ bpl equal_b._equal_b_true - bmi equal_b._equal_b_false - .pend - -greater_uw .proc - lda c64.ESTACK_HI+1,x - cmp c64.ESTACK_HI+2,x - bcc equal_b._equal_b_true - bne equal_b._equal_b_false - lda c64.ESTACK_LO+1,x - cmp c64.ESTACK_LO+2,x - bcc equal_b._equal_b_true - bcs equal_b._equal_b_false - .pend - -greater_w .proc - lda c64.ESTACK_LO+1,x - cmp c64.ESTACK_LO+2,x - lda c64.ESTACK_HI+1,x - sbc c64.ESTACK_HI+2,x - bvc + - eor #$80 -+ bmi equal_b._equal_b_true - bpl equal_b._equal_b_false - .pend - -greatereq_ub .proc - lda c64.ESTACK_LO+2,x - cmp c64.ESTACK_LO+1,x - bcs equal_b._equal_b_true - bcc equal_b._equal_b_false - .pend - -greatereq_b .proc - ; see http://www.6502.org/tutorials/compare_beyond.html - lda c64.ESTACK_LO+2,x - sec - sbc c64.ESTACK_LO+1,x - bvc + - eor #$80 -+ bpl equal_b._equal_b_true - bmi equal_b._equal_b_false - .pend - -greatereq_uw .proc - lda c64.ESTACK_HI+2,x - cmp c64.ESTACK_HI+1,x - bcc equal_b._equal_b_false - bne equal_b._equal_b_true - lda c64.ESTACK_LO+2,x - cmp c64.ESTACK_LO+1,x - bcs equal_b._equal_b_true - bcc equal_b._equal_b_false - .pend - -greatereq_w .proc - lda c64.ESTACK_LO+2,x - cmp c64.ESTACK_LO+1,x - lda c64.ESTACK_HI+2,x - sbc c64.ESTACK_HI+1,x - bvc + - eor #$80 -+ bpl equal_b._equal_b_true - bmi equal_b._equal_b_false - .pend - - -func_sin8 .proc - ldy c64.ESTACK_LO+1,x - lda _sinecos8,y - sta c64.ESTACK_LO+1,x - rts -_sinecos8 .char 127 * sin(range(256+64) * rad(360.0/256.0)) - .pend - -func_sin8u .proc - ldy c64.ESTACK_LO+1,x - lda _sinecos8u,y - sta c64.ESTACK_LO+1,x - rts -_sinecos8u .byte 128 + 127.5 * sin(range(256+64) * rad(360.0/256.0)) - .pend - -func_sin16 .proc - ldy c64.ESTACK_LO+1,x - lda _sinecos8lo,y - sta c64.ESTACK_LO+1,x - lda _sinecos8hi,y - sta c64.ESTACK_HI+1,x - rts - -_ := 32767 * sin(range(256+64) * rad(360.0/256.0)) -_sinecos8lo .byte <_ -_sinecos8hi .byte >_ - .pend - -func_sin16u .proc - ldy c64.ESTACK_LO+1,x - lda _sinecos8ulo,y - sta c64.ESTACK_LO+1,x - lda _sinecos8uhi,y - sta c64.ESTACK_HI+1,x - rts - -_ := 32768 + 32767.5 * sin(range(256+64) * rad(360.0/256.0)) -_sinecos8ulo .byte <_ -_sinecos8uhi .byte >_ - .pend - -func_cos8 .proc - ldy c64.ESTACK_LO+1,x - lda func_sin8._sinecos8+64,y - sta c64.ESTACK_LO+1,x - rts - .pend - -func_cos8u .proc - ldy c64.ESTACK_LO+1,x - lda func_sin8u._sinecos8u+64,y - sta c64.ESTACK_LO+1,x - rts - .pend - -func_cos16 .proc - ldy c64.ESTACK_LO+1,x - lda func_sin16._sinecos8lo+64,y - sta c64.ESTACK_LO+1,x - lda func_sin16._sinecos8hi+64,y - sta c64.ESTACK_HI+1,x - rts - .pend - -func_cos16u .proc - ldy c64.ESTACK_LO+1,x - lda func_sin16u._sinecos8ulo+64,y - sta c64.ESTACK_LO+1,x - lda func_sin16u._sinecos8uhi+64,y - sta c64.ESTACK_HI+1,x - rts - .pend - - -peek_address .proc - ; -- peek address on stack into c64.SCRATCH_ZPWORD1 - lda c64.ESTACK_LO+1,x - sta c64.SCRATCH_ZPWORD1 - lda c64.ESTACK_HI+1,x - sta c64.SCRATCH_ZPWORD1+1 - rts - .pend - -func_any_b .proc - inx - lda c64.ESTACK_LO,x ; array size -_entry sta _cmp_mod+1 ; self-modifying code - jsr peek_address - ldy #0 -- lda (c64.SCRATCH_ZPWORD1),y - bne _got_any - iny -_cmp_mod cpy #255 ; modified - bne - - lda #0 - sta c64.ESTACK_LO+1,x - rts -_got_any lda #1 - sta c64.ESTACK_LO+1,x - rts - .pend - -func_any_w .proc - inx - lda c64.ESTACK_LO,x ; array size - asl a ; times 2 because of word - jmp func_any_b._entry - .pend - -func_all_b .proc - inx - lda c64.ESTACK_LO,x ; array size - sta _cmp_mod+1 ; self-modifying code - jsr peek_address - ldy #0 -- lda (c64.SCRATCH_ZPWORD1),y - beq _got_not_all - iny -_cmp_mod cpy #255 ; modified - bne - - lda #1 - sta c64.ESTACK_LO+1,x - rts -_got_not_all lda #0 - sta c64.ESTACK_LO+1,x - rts - .pend - -func_all_w .proc - inx - lda c64.ESTACK_LO,x ; array size - asl a ; times 2 because of word - sta _cmp_mod+1 ; self-modifying code - jsr peek_address - ldy #0 -- lda (c64.SCRATCH_ZPWORD1),y - bne + - iny - lda (c64.SCRATCH_ZPWORD1),y - bne + - lda #0 - sta c64.ESTACK_LO+1,x - rts -+ iny -_cmp_mod cpy #255 ; modified - bne - - lda #1 - sta c64.ESTACK_LO+1,x - rts - .pend - -func_max_ub .proc - jsr pop_array_and_lengthmin1Y - lda #0 - sta c64.SCRATCH_ZPB1 -- lda (c64.SCRATCH_ZPWORD1),y - cmp c64.SCRATCH_ZPB1 - bcc + - sta c64.SCRATCH_ZPB1 -+ dey - cpy #255 - bne - - lda c64.SCRATCH_ZPB1 - sta c64.ESTACK_LO,x - dex - rts - .pend - -func_max_b .proc - jsr pop_array_and_lengthmin1Y - lda #-128 - sta c64.SCRATCH_ZPB1 -- lda (c64.SCRATCH_ZPWORD1),y - sec - sbc c64.SCRATCH_ZPB1 - bvc + - eor #$80 -+ bmi + - lda (c64.SCRATCH_ZPWORD1),y - sta c64.SCRATCH_ZPB1 -+ dey - cpy #255 - bne - - lda c64.SCRATCH_ZPB1 - sta c64.ESTACK_LO,x - dex - rts - .pend - -func_max_uw .proc - lda #0 - sta _result_maxuw - sta _result_maxuw+1 - jsr pop_array_and_lengthmin1Y - tya - asl a - tay ; times 2 because of word array -_loop - iny - lda (c64.SCRATCH_ZPWORD1),y - dey - cmp _result_maxuw+1 - bcc _lesseq - bne _greater - lda (c64.SCRATCH_ZPWORD1),y - cmp _result_maxuw - bcc _lesseq -_greater lda (c64.SCRATCH_ZPWORD1),y - sta _result_maxuw - iny - lda (c64.SCRATCH_ZPWORD1),y - sta _result_maxuw+1 - dey -_lesseq dey - dey - cpy #254 - bne _loop - lda _result_maxuw - sta c64.ESTACK_LO,x - lda _result_maxuw+1 - sta c64.ESTACK_HI,x - dex - rts -_result_maxuw .word 0 - .pend - -func_max_w .proc - lda #$00 - sta _result_maxw - lda #$80 - sta _result_maxw+1 - jsr pop_array_and_lengthmin1Y - tya - asl a - tay ; times 2 because of word array -_loop - lda (c64.SCRATCH_ZPWORD1),y - cmp _result_maxw - iny - lda (c64.SCRATCH_ZPWORD1),y - dey - sbc _result_maxw+1 - bvc + - eor #$80 -+ bmi _lesseq - lda (c64.SCRATCH_ZPWORD1),y - sta _result_maxw - iny - lda (c64.SCRATCH_ZPWORD1),y - sta _result_maxw+1 - dey -_lesseq dey - dey - cpy #254 - bne _loop - lda _result_maxw - sta c64.ESTACK_LO,x - lda _result_maxw+1 - sta c64.ESTACK_HI,x - dex - rts -_result_maxw .word 0 - .pend - - -func_sum_b .proc - jsr pop_array_and_lengthmin1Y - lda #0 - sta c64.ESTACK_LO,x - sta c64.ESTACK_HI,x -_loop lda (c64.SCRATCH_ZPWORD1),y - pha - clc - adc c64.ESTACK_LO,x - sta c64.ESTACK_LO,x - ; sign extend the high byte - pla - and #$80 - beq + - lda #$ff -+ adc c64.ESTACK_HI,x - sta c64.ESTACK_HI,x - dey - cpy #255 - bne _loop - dex - rts - .pend - -func_sum_ub .proc - jsr pop_array_and_lengthmin1Y - lda #0 - sta c64.ESTACK_LO,x - sta c64.ESTACK_HI,x -- lda (c64.SCRATCH_ZPWORD1),y - clc - adc c64.ESTACK_LO,x - sta c64.ESTACK_LO,x - bcc + - inc c64.ESTACK_HI,x -+ dey - cpy #255 - bne - - dex - rts - .pend - -func_sum_uw .proc - jsr pop_array_and_lengthmin1Y - tya - asl a - tay - lda #0 - sta c64.ESTACK_LO,x - sta c64.ESTACK_HI,x -- lda (c64.SCRATCH_ZPWORD1),y - iny - clc - adc c64.ESTACK_LO,x - sta c64.ESTACK_LO,x - lda (c64.SCRATCH_ZPWORD1),y - adc c64.ESTACK_HI,x - sta c64.ESTACK_HI,x - dey - dey - dey - cpy #254 - bne - - dex - rts - .pend - -func_sum_w .proc - jmp func_sum_uw - .pend - - -pop_array_and_lengthmin1Y .proc - inx - ldy c64.ESTACK_LO,x - dey ; length minus 1, for iteration - lda c64.ESTACK_LO+1,x - sta c64.SCRATCH_ZPWORD1 - lda c64.ESTACK_HI+1,x - sta c64.SCRATCH_ZPWORD1+1 - inx - rts - .pend - -func_min_ub .proc - jsr pop_array_and_lengthmin1Y - lda #255 - sta c64.SCRATCH_ZPB1 -- lda (c64.SCRATCH_ZPWORD1),y - cmp c64.SCRATCH_ZPB1 - bcs + - sta c64.SCRATCH_ZPB1 -+ dey - cpy #255 - bne - - lda c64.SCRATCH_ZPB1 - sta c64.ESTACK_LO,x - dex - rts - .pend - - -func_min_b .proc - jsr pop_array_and_lengthmin1Y - lda #127 - sta c64.SCRATCH_ZPB1 -- lda (c64.SCRATCH_ZPWORD1),y - clc - sbc c64.SCRATCH_ZPB1 - bvc + - eor #$80 -+ bpl + - lda (c64.SCRATCH_ZPWORD1),y - sta c64.SCRATCH_ZPB1 -+ dey - cpy #255 - bne - - lda c64.SCRATCH_ZPB1 - sta c64.ESTACK_LO,x - dex - rts - .pend - -func_min_uw .proc - lda #$ff - sta _result_minuw - sta _result_minuw+1 - jsr pop_array_and_lengthmin1Y - tya - asl a - tay ; times 2 because of word array -_loop - iny - lda (c64.SCRATCH_ZPWORD1),y - dey - cmp _result_minuw+1 - bcc _less - bne _gtequ - lda (c64.SCRATCH_ZPWORD1),y - cmp _result_minuw - bcs _gtequ -_less lda (c64.SCRATCH_ZPWORD1),y - sta _result_minuw - iny - lda (c64.SCRATCH_ZPWORD1),y - sta _result_minuw+1 - dey -_gtequ dey - dey - cpy #254 - bne _loop - lda _result_minuw - sta c64.ESTACK_LO,x - lda _result_minuw+1 - sta c64.ESTACK_HI,x - dex - rts -_result_minuw .word 0 - .pend - -func_min_w .proc - lda #$ff - sta _result_minw - lda #$7f - sta _result_minw+1 - jsr pop_array_and_lengthmin1Y - tya - asl a - tay ; times 2 because of word array -_loop - lda (c64.SCRATCH_ZPWORD1),y - cmp _result_minw - iny - lda (c64.SCRATCH_ZPWORD1),y - dey - sbc _result_minw+1 - bvc + - eor #$80 -+ bpl _gtequ - lda (c64.SCRATCH_ZPWORD1),y - sta _result_minw - iny - lda (c64.SCRATCH_ZPWORD1),y - sta _result_minw+1 - dey -_gtequ dey - dey - cpy #254 - bne _loop - lda _result_minw - sta c64.ESTACK_LO,x - lda _result_minw+1 - sta c64.ESTACK_HI,x - dex - rts -_result_minw .word 0 - .pend - - -func_len_str .proc - ; -- push length of 0-terminated string on stack - jsr peek_address - ldy #0 -- lda (c64.SCRATCH_ZPWORD1),y - beq + - iny - bne - -+ tya - sta c64.ESTACK_LO+1,x - rts - .pend - -func_len_strp .proc - ; -- push length of pascal-string on stack - jsr peek_address - ldy #0 - lda (c64.SCRATCH_ZPWORD1),y ; first byte is length - sta c64.ESTACK_LO+1,x - rts - .pend - -func_rnd .proc - ; -- put a random ubyte on the estack - jsr math.randbyte - sta c64.ESTACK_LO,x - dex - rts - .pend - -func_rndw .proc - ; -- put a random uword on the estack - jsr math.randword - sta c64.ESTACK_LO,x - tya - sta c64.ESTACK_HI,x - dex - rts - .pend - - -func_memcopy .proc ; clobbers A,Y - inx - stx c64.SCRATCH_ZPREGX - lda c64.ESTACK_LO+2,x - sta c64.SCRATCH_ZPWORD1 - lda c64.ESTACK_HI+2,x - sta c64.SCRATCH_ZPWORD1+1 - lda c64.ESTACK_LO+1,x - ldy c64.ESTACK_HI+1,x - pha - lda c64.ESTACK_LO,x - tax - pla - jsr c64utils.memcopy - ldx c64.SCRATCH_ZPREGX - inx - inx - rts - .pend - - }} -} - - -~ math { - -; some more interesting routines can be found here: -; http://6502org.wikidot.com/software-math -; http://codebase64.org/doku.php?id=base:6502_6510_maths -; - - -asmsub multiply_bytes (ubyte byte1 @ A, ubyte byte2 @ Y) -> clobbers() -> (ubyte @ A) { - ; ---- multiply 2 bytes, result as byte in A (signed or unsigned) - %asm {{ - sta c64.SCRATCH_ZPB1 ; num1 - sty c64.SCRATCH_ZPREG ; num2 - lda #0 - beq _enterloop -_doAdd clc - adc c64.SCRATCH_ZPB1 -_loop asl c64.SCRATCH_ZPB1 -_enterloop lsr c64.SCRATCH_ZPREG - bcs _doAdd - bne _loop - rts - }} -} - - -asmsub multiply_bytes_16 (ubyte byte1 @ A, ubyte byte2 @ Y) -> clobbers(X) -> (uword @ AY) { - ; ---- multiply 2 bytes, result as word in A/Y (unsigned) - %asm {{ - sta c64.SCRATCH_ZPB1 - sty c64.SCRATCH_ZPREG - lda #0 - ldx #8 - lsr c64.SCRATCH_ZPB1 -- bcc + - clc - adc c64.SCRATCH_ZPREG -+ ror a - ror c64.SCRATCH_ZPB1 - dex - bne - - tay - lda c64.SCRATCH_ZPB1 - rts - }} -} - -asmsub multiply_words (uword number @ AY) -> clobbers(A,X) -> () { - ; ---- multiply two 16-bit words into a 32-bit result (signed and unsigned) - ; input: A/Y = first 16-bit number, c64.SCRATCH_ZPWORD1 in ZP = second 16-bit number - ; output: multiply_words.result 4-bytes/32-bits product, LSB order (low-to-high) - - %asm {{ - sta c64.SCRATCH_ZPWORD2 - sty c64.SCRATCH_ZPWORD2+1 - -mult16 lda #$00 - sta multiply_words_result+2 ; clear upper bits of product - sta multiply_words_result+3 - ldx #16 ; for all 16 bits... -- lsr c64.SCRATCH_ZPWORD1+1 ; divide multiplier by 2 - ror c64.SCRATCH_ZPWORD1 - bcc + - lda multiply_words_result+2 ; get upper half of product and add multiplicand - clc - adc c64.SCRATCH_ZPWORD2 - sta multiply_words_result+2 - lda multiply_words_result+3 - adc c64.SCRATCH_ZPWORD2+1 -+ ror a ; rotate partial product - sta multiply_words_result+3 - ror multiply_words_result+2 - ror multiply_words_result+1 - ror multiply_words_result - dex - bne - - rts - -multiply_words_result .byte 0,0,0,0 - - }} -} - -asmsub divmod_ub (ubyte number @ A, ubyte divisor @ Y) -> clobbers() -> (ubyte @ Y, ubyte @ A) { - ; ---- divide A by Y, result quotient in Y, remainder in A (unsigned) - ; division by zero will result in quotient = 255 and remainder = original number - %asm {{ - sty c64.SCRATCH_ZPREG - sta c64.SCRATCH_ZPB1 - stx c64.SCRATCH_ZPREGX - - lda #0 - ldx #8 - asl c64.SCRATCH_ZPB1 -- rol a - cmp c64.SCRATCH_ZPREG - bcc + - sbc c64.SCRATCH_ZPREG -+ rol c64.SCRATCH_ZPB1 - dex - bne - - - ldy c64.SCRATCH_ZPB1 - ldx c64.SCRATCH_ZPREGX - rts - }} -} - -asmsub divmod_uw_asm (uword divisor @ AY) -> clobbers() -> (uword @ AY) { - ; ---- divide two unsigned words (16 bit each) into 16 bit results - ; input: c64.SCRATCH_ZPWORD1 in ZP: 16 bit number, A/Y: 16 bit divisor - ; output: c64.SCRATCH_ZPWORD2 in ZP: 16 bit remainder, A/Y: 16 bit division result - ; division by zero will result in quotient = 65535 and remainder = divident - - %asm {{ - -dividend = c64.SCRATCH_ZPWORD1 -remainder = c64.SCRATCH_ZPWORD2 -result = dividend ;save memory by reusing divident to store the result - - sta _divisor - sty _divisor+1 - stx c64.SCRATCH_ZPREGX - lda #0 ;preset remainder to 0 - sta remainder - sta remainder+1 - ldx #16 ;repeat for each bit: ... - -- asl dividend ;dividend lb & hb*2, msb -> Carry - rol dividend+1 - rol remainder ;remainder lb & hb * 2 + msb from carry - rol remainder+1 - lda remainder - sec - sbc _divisor ;substract divisor to see if it fits in - tay ;lb result -> Y, for we may need it later - lda remainder+1 - sbc _divisor+1 - bcc + ;if carry=0 then divisor didn't fit in yet - - sta remainder+1 ;else save substraction result as new remainder, - sty remainder - inc result ;and INCrement result cause divisor fit in 1 times - -+ dex - bne - - - lda result - ldy result+1 - ldx c64.SCRATCH_ZPREGX - rts -_divisor .word 0 - }} -} - -asmsub randseed (uword seed @ 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 - stx c64.SCRATCH_ZPREG - clc - adc #14 - sta randbyte._seed - ora #$80 ; make negative - ; jsr c64flt.FREADSA - ; jsr c64flt.RND ; reseed the float rng using the (negative) number in A - ldx c64.SCRATCH_ZPREG - rts - }} -} - - -asmsub randbyte () -> clobbers() -> (ubyte @ A) { - ; ---- 8-bit pseudo random number generator into A - - %asm {{ - lda _seed - beq + - asl a - beq ++ ;if the input was $80, skip the EOR - bcc ++ -+ eor _magic ; #$1d ; could be self-modifying code to set new magic -+ sta _seed - rts - -_seed .byte $3a -_magic .byte $1d -_magiceors .byte $1d, $2b, $2d, $4d, $5f, $63, $65, $69 - .byte $71, $87, $8d, $a9, $c3, $cf, $e7, $f5 - - }} -} - -asmsub randword () -> clobbers() -> (uword @ AY) { - ; ---- 16 bit pseudo random number generator into AY - - %asm {{ - lda _seed - beq _lowZero ; $0000 and $8000 are special values to test for - - ; Do a normal shift - asl _seed - lda _seed+1 - rol a - bcc _noEor - -_doEor ; high byte is in A - eor _magic+1 ; #>magic ; could be self-modifying code to set new magic - sta _seed+1 - lda _seed - eor _magic ; #) { } private fun compileMain(args: Array) { - var startEmu = false + var emulatorToStart = "" var moduleFile = "" for (arg in args) { if(arg=="--emu") - startEmu = true + emulatorToStart = "x64" + else if(arg=="--emu2") + emulatorToStart = "x64sc" else if(!arg.startsWith("--")) moduleFile = arg } @@ -139,9 +141,9 @@ private fun compileMain(args: Array) { throw x } - if(startEmu) { - println("\nStarting C64 emulator...") - val cmdline = listOf("x64sc", "-silent", "-moncommands", "$programname.vice-mon-list", + if(emulatorToStart.isNotEmpty()) { + println("\nStarting C-64 emulator $emulatorToStart...") + val cmdline = listOf(emulatorToStart, "-silent", "-moncommands", "$programname.vice-mon-list", "-autostartprgmode", "1", "-autostart-warp", "-autostart", programname+".prg") val process = ProcessBuilder(cmdline).inheritIO().start() process.waitFor() @@ -184,7 +186,8 @@ fun determineCompilationOptions(moduleAst: Module): CompilationOptions { private fun usage() { System.err.println("Missing argument(s):") - System.err.println(" [--emu] auto-start the C64 emulator after successful compilation") + System.err.println(" [--emu] auto-start the 'x64' C-64 emulator after successful compilation") + System.err.println(" [--emu2] auto-start the 'x64sc' C-64 emulator after successful compilation") System.err.println(" [--vm] launch the prog8 virtual machine instead of the compiler") System.err.println(" modulefile main module file to compile") exitProcess(1) diff --git a/compiler/src/prog8/ast/AstChecker.kt b/compiler/src/prog8/ast/AstChecker.kt index 75f4a21ff..8a13b0319 100644 --- a/compiler/src/prog8/ast/AstChecker.kt +++ b/compiler/src/prog8/ast/AstChecker.kt @@ -611,8 +611,8 @@ class AstChecker(private val namespace: INameScope, } "%asminclude" -> { if(directive.parent !is INameScope || directive.parent is Module) err("this directive may only occur in a block") - if(directive.args.size!=2 || directive.args[0].str==null || directive.args[1].name==null) - err("invalid asminclude directive, expected arguments: \"filename\", scopelabel") + if(directive.args.size!=2 || directive.args[0].str==null || directive.args[1].str==null) + err("invalid asminclude directive, expected arguments: \"filename\", \"scopelabel\"") } "%asmbinary" -> { if(directive.parent !is INameScope || directive.parent is Module) err("this directive may only occur in a block") diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 9aec7d2e8..edde5ee9e 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -6,7 +6,12 @@ import prog8.compiler.intermediate.IntermediateProgram import prog8.compiler.intermediate.Opcode import prog8.compiler.intermediate.Value import prog8.optimizing.same +import prog8.parser.tryGetEmbeddedResource import prog8.stackvm.Syscall +import java.io.File +import java.io.InputStream +import java.io.InputStreamReader +import java.nio.file.Paths import java.util.* import kotlin.math.abs @@ -220,8 +225,8 @@ private class StatementTranslator(private val prog: IntermediateProgram, is Return -> translate(stmt) is Directive -> { when(stmt.directive) { - "%asminclude" -> throw CompilerException("can't use %asminclude in stackvm") - "%asmbinary" -> throw CompilerException("can't use %asmbinary in stackvm") + "%asminclude" -> translateAsmInclude(stmt.args) + "%asmbinary" -> translateAsmBinary(stmt.args) "%breakpoint" -> { prog.line(stmt.position) prog.instr(Opcode.BREAKPOINT) @@ -959,6 +964,7 @@ private class StatementTranslator(private val prog: IntermediateProgram, var restoreX = Register.X in subroutine.asmClobbers if(restoreX) prog.instr(Opcode.RSAVEX) + // We don't bother about saving A and Y. They're considered expendable. if(subroutine.isAsmSubroutine) { if(subroutine.parameters.size!=subroutine.asmParameterRegisters.size) @@ -2185,4 +2191,24 @@ private class StatementTranslator(private val prog: IntermediateProgram, } } + private fun translateAsmInclude(args: List) { + val scopeprefix = if(args[1].str!!.isNotBlank()) "${args[1].str}\t.proc\n" else "" + val scopeprefixEnd = if(args[1].str!!.isNotBlank()) "\t.pend\n" else "" + val filename=args[0].str!! + val sourcecode = + if(filename.startsWith("library:")) { + val resource = tryGetEmbeddedResource(filename.substring(8)) ?: throw IllegalArgumentException("library file '$filename' not found") + resource.bufferedReader().use { it.readText() } + } else { + // TODO: look in directory of parent source file first + File(filename).readText() + } + + prog.instr(Opcode.INLINE_ASSEMBLY, callLabel=scopeprefix+sourcecode+scopeprefixEnd) + } + + private fun translateAsmBinary(args: List) { + TODO("asmbinary not implemented $args") + } + } diff --git a/compiler/src/prog8/compiler/target/c64/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/AsmGen.kt index 3b845969f..eac378fb1 100644 --- a/compiler/src/prog8/compiler/target/c64/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/AsmGen.kt @@ -423,7 +423,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, Opcode.DISCARD_BYTE -> " inx" Opcode.DISCARD_WORD -> " inx" Opcode.DISCARD_FLOAT -> " inx | inx | inx" - Opcode.INLINE_ASSEMBLY -> "@inline@" + (ins.callLabel ?: "") // All of the inline assembly is stored in the calllabel property. + Opcode.INLINE_ASSEMBLY -> "@inline@" + (ins.callLabel ?: "") // All of the inline assembly is stored in the calllabel property. the '@inline@' is a special marker to process it. Opcode.SYSCALL -> { if (ins.arg!!.numericValue() in syscallsForStackVm.map { it.callNr }) throw CompilerException("cannot translate vm syscalls to real assembly calls - use *real* subroutine calls instead. Syscall ${ins.arg.numericValue()}") @@ -965,18 +965,22 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, } } - for(pattern in patterns.filter { it.sequence.size <= segment.size || (it.altSequence != null && it.altSequence.size <= segment.size)}) { - val opcodesList = if(pattern.sequence.size<=opcodes.size) opcodes.subList(0, pattern.sequence.size) else null - val opcodesListAlt = if(pattern.altSequence!=null && pattern.altSequence.size<=opcodes.size) opcodes.subList(0, pattern.altSequence.size) else null - + // add any matching patterns from the big list + for(pattern in patterns) { + if(pattern.sequence.size > segment.size || (pattern.altSequence!=null && pattern.altSequence.size > segment.size)) + continue // don't process patterns that don't fit + val opcodesList = opcodes.subList(0, pattern.sequence.size) if(pattern.sequence == opcodesList) { val asm = pattern.asm(segment) if(asm!=null) result.add(AsmFragment(asm, pattern.sequence.size)) - } else if(opcodesListAlt!=null && pattern.altSequence == opcodesListAlt) { - val asm = pattern.asm(segment) - if(asm!=null) - result.add(AsmFragment(asm, pattern.sequence.size)) + } else if(pattern.altSequence!=null) { + val opcodesListAlt = opcodes.subList(0, pattern.altSequence.size) + if(pattern.altSequence == opcodesListAlt) { + val asm = pattern.asm(segment) + if (asm != null) + result.add(AsmFragment(asm, pattern.sequence.size)) + } } } diff --git a/compiler/src/prog8/parser/ModuleParsing.kt b/compiler/src/prog8/parser/ModuleParsing.kt index 177da4341..35b6aad8f 100644 --- a/compiler/src/prog8/parser/ModuleParsing.kt +++ b/compiler/src/prog8/parser/ModuleParsing.kt @@ -5,6 +5,8 @@ import prog8.ast.* import prog8.compiler.LauncherType import prog8.compiler.OutputType import prog8.determineCompilationOptions +import java.io.InputStream +import java.net.URL import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths @@ -52,7 +54,9 @@ fun importModule(stream: CharStream, moduleName: String, isLibrary: Boolean): Mo lines.add(0, Directive("%import", listOf(DirectiveArg(null, "c64utils", null, moduleAst.position)), moduleAst.position)) } } - // always import the prog8 compiler library + // always import the prog8lib and math compiler libraries + if(!moduleAst.position.file.startsWith("math.")) + lines.add(0, Directive("%import", listOf(DirectiveArg(null, "math", null, moduleAst.position)), moduleAst.position)) if(!moduleAst.position.file.startsWith("prog8lib.")) lines.add(0, Directive("%import", listOf(DirectiveArg(null, "prog8lib", null, moduleAst.position)), moduleAst.position)) @@ -118,7 +122,6 @@ private fun discoverImportedModuleFile(name: String, importedFrom: Path, positio throw ParsingFailedError("$position Import: no module source file '$fileName' found (I've looked in: $locations)") } - private fun executeImportDirective(import: Directive, importedFrom: Path): Module? { if(import.directive!="%import" || import.args.size!=1 || import.args[0].name==null) throw SyntaxError("invalid import directive", import.position) @@ -128,11 +131,11 @@ private fun executeImportDirective(import: Directive, importedFrom: Path): Modul if(importedModules.containsKey(moduleName)) return null - val resource = import::class.java.getResource("/prog8lib/$moduleName.p8") + val resource = tryGetEmbeddedResource(moduleName+".p8") val importedModule = if(resource!=null) { // load the module from the embedded resource - resource.openStream().use { + resource.use { println("importing '$moduleName' (embedded library)") importModule(CharStreams.fromStream(it), moduleName, true) } @@ -144,3 +147,7 @@ private fun executeImportDirective(import: Directive, importedFrom: Path): Modul importedModule.checkImportedValid() return importedModule } + +fun tryGetEmbeddedResource(name: String): InputStream? { + return object{}.javaClass.getResourceAsStream("/prog8lib/$name") +} diff --git a/docs/source/syntaxreference.rst b/docs/source/syntaxreference.rst index 2017281e9..3350673ff 100644 --- a/docs/source/syntaxreference.rst +++ b/docs/source/syntaxreference.rst @@ -120,7 +120,7 @@ Directives The assembler will include the file as binary bytes at this point, prog8 will not process this at all. The optional offset and length can be used to select a particular piece of the file. -.. data:: %asminclude "", scopelabel +.. data:: %asminclude "", "scopelabel" Level: block. This directive can only be used inside a block. @@ -128,6 +128,7 @@ Directives prog8 will not process this at all, with one exception: the labels. The scopelabel argument will be used as a prefix to access the labels from the included source code, otherwise you would risk symbol redefinitions or duplications. + If you know what you are doing you can leave it as an empty string to not have a scope prefix. .. data:: %breakpoint diff --git a/examples/bdmusic.p8 b/examples/bdmusic.p8 index 4be1e9b15..1315717fd 100644 --- a/examples/bdmusic.p8 +++ b/examples/bdmusic.p8 @@ -44,10 +44,10 @@ sub start() { sub print_notes(ubyte n1, ubyte n2) { c64.CHROUT('\n') - c64.PLOT(0, n1/2, 24) + c64scr.PLOT(n1/2, 24) c64.COLOR=7 c64.CHROUT('Q') - c64.PLOT(0, n2/2, 24) + c64scr.PLOT(n2/2, 24) c64.COLOR=4 c64.CHROUT('Q') } diff --git a/examples/cube3d-float.p8 b/examples/cube3d-float.p8 index 7bf5d3cb2..4b57971c5 100644 --- a/examples/cube3d-float.p8 +++ b/examples/cube3d-float.p8 @@ -24,7 +24,7 @@ c64scr.clear_screenchars(32) draw_edges() time+=0.2 - c64.PLOT(0,0,0) + c64scr.PLOT(0,0) c64scr.print("3d cube! (float) ") c64scr.print_ub(c64.TIME_LO) c64scr.print(" jiffies/frame") diff --git a/examples/cube3d-sprites.p8 b/examples/cube3d-sprites.p8 index 2a4924496..55ea4b7a1 100644 --- a/examples/cube3d-sprites.p8 +++ b/examples/cube3d-sprites.p8 @@ -89,7 +89,7 @@ anglex-=500 angley+=217 anglez+=452 - c64.PLOT(0,0,0) + c64scr.PLOT(0,0) c64scr.print("3d cube! (sprites) ") c64scr.print_ub(c64.TIME_LO) c64scr.print(" jiffies/frame ") diff --git a/examples/cube3d.p8 b/examples/cube3d.p8 index 9708daebe..d84ef430f 100644 --- a/examples/cube3d.p8 +++ b/examples/cube3d.p8 @@ -29,7 +29,7 @@ anglex+=1000 angley+=433 anglez+=907 - c64.PLOT(0,0,0) + c64scr.PLOT(0,0) c64scr.print("3d cube! (integer) ") c64scr.print_ub(c64.TIME_LO) c64scr.print(" jiffies/frame") diff --git a/examples/mandelbrot.p8 b/examples/mandelbrot.p8 index dc4aea70f..3a9dae9c3 100644 --- a/examples/mandelbrot.p8 +++ b/examples/mandelbrot.p8 @@ -38,7 +38,7 @@ } float duration = floor(((c64.TIME_LO as float) + 256.0*(c64.TIME_MID as float) + 65536.0*(c64.TIME_HI as float))/60.0) - c64.PLOT(0, 0, 21) + c64scr.PLOT(0, 21) c64scr.print("finished in ") c64flt.print_f(duration) c64scr.print(" seconds!\n") diff --git a/examples/test.p8 b/examples/test.p8 index 6fc746631..7accf2b05 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -29,58 +29,9 @@ uword[3] uwa2 word[3] wa2 -; ub1 = ub2 & 44 -; b1 = b2 & 44 -; uw1 = uw2 & 4444 -; w1 = w2 & 4444 -; ub1 = ub2 | 44 -; b1 = b2 | 44 -; uw1 = uw2 | 4444 -; w1 = w2 | 4444 -; ub1 = ub2 ^ 44 -; b1 = b2 ^ 44 -; uw1 = uw2 ^ 4444 -; w1 = w2 ^ 4444 -; -; ub1 = ub2 & ub1 -; b1 = b2 & b1 -; uw1 = uw2 & uw1 -; w1 = w2 & w1 -; ub1 = ub2 | ub1 -; b1 = b2 | b1 -; uw1 = uw2 | uw1 -; w1 = w2 | w1 -; ub1 = ub2 ^ ub1 -; b1 = b2 ^ b1 -; uw1 = uw2 ^ uw1 -; w1 = w2 ^ w1 - swap(ub1, ub2) - swap(b1, b2) - swap(uw1, uw2) - swap(w1, w2) - swap(@($d020), @($d021)) - swap(mub1, mub2) - swap(muw1, muw2) - swap(mub1, ub2) - swap(muw1, uw2) + ub1=ub2*ub1 - swap(uba1[1], uba2[2]) - swap(ba1[1], ba2[2]) - swap(uwa1[1], uwa2[2]) - swap(wa1[1], wa2[2]) - - ubyte i1 - ubyte i2 - swap(uba1[i1], uba2[i2]) - swap(ba1[i1], ba2[i2]) - swap(uwa1[i1], uwa2[i2]) - swap(wa1[i1], wa2[i2]) - - swap(uba1[1], ub1) - swap(uba1[i1], ub1) - swap(uwa1[1], uw1) - swap(uwa1[i1], uw1) }