diff --git a/compiler/examples/test.p8 b/compiler/examples/test.p8 index 5adcb41cf..3c85eaeac 100644 --- a/compiler/examples/test.p8 +++ b/compiler/examples/test.p8 @@ -2,78 +2,68 @@ %option enable_floats -~ spritedata $0a00 { - ; this memory block contains the sprite data - ; it must start on an address aligned to 64 bytes. - %option force_output ; make sure the data in this block appears in the resulting program - - ubyte[63] balloonsprite = [ %00000000,%01111111,%00000000, - %00000001,%11111111,%11000000, - %00000011,%11111111,%11100000, - %00000011,%11100011,%11100000, - %00000111,%11011100,%11110000, - %00000111,%11011101,%11110000, - %00000111,%11011100,%11110000, - %00000011,%11100011,%11100000, - %00000011,%11111111,%11100000, - %00000011,%11111111,%11100000, - %00000010,%11111111,%10100000, - %00000001,%01111111,%01000000, - %00000001,%00111110,%01000000, - %00000000,%10011100,%10000000, - %00000000,%10011100,%10000000, - %00000000,%01001001,%00000000, - %00000000,%01001001,%00000000, - %00000000,%00111110,%00000000, - %00000000,%00111110,%00000000, - %00000000,%00111110,%00000000, - %00000000,%00011100,%00000000 ] -} - ~ main { - const uword SP0X = $d000 - const uword SP0Y = $d001 - sub start() { + ubyte i=0 - c64.STROUT("balloon sprites!\n") - c64.STROUT("...we are all floating...\n") - const uword sprite_address_ptr = $0a00 // 64 - c64.SPRPTR0 = sprite_address_ptr - c64.SPRPTR1 = sprite_address_ptr - c64.SPRPTR2 = sprite_address_ptr - c64.SPRPTR3 = sprite_address_ptr - c64.SPRPTR4 = sprite_address_ptr - c64.SPRPTR5 = sprite_address_ptr - c64.SPRPTR6 = sprite_address_ptr - c64.SPRPTR7 = sprite_address_ptr - - for ubyte i in 0 to 7 { - @(SP0X+i*2) = 50+25*i - @(SP0Y+i*2) = rnd() - } - - c64.SPENA = 255 ; enable all sprites - c64utils.set_rasterirq(51) ; enable animation + repeat { + c64scr.print_ub(X) + c64.CHROUT('\n') + ubyte ubx = fastsin8(i) as ubyte + c64scr.print_ub(X) + c64.CHROUT('\n') + ;c64scr.print_ub(X) + ;byte y = fastcos8(i) + c64scr.print_ub(ubx) + ;c64.CHROUT(',') + ;c64scr.print_b(y) + c64.CHROUT('\n') + i++ + } until i==0 } -} -~ irq { -sub irq() { - c64.EXTCOL-- - ; float up & wobble horizontally - for ubyte i in 0 to 14 step 2 { - @(main.SP0Y+i)-- - ubyte r = rnd() - if r>200 - @(main.SP0X+i)++ - else if r<40 - @(main.SP0X+i)-- - } - c64.EXTCOL++ +asmsub fastsin8(ubyte angle8 @ Y) -> clobbers() -> (byte @ A) { + %asm {{ + lda sinecos8hi,y + ;sta prog8_lib.ESTACK_LO,x + ;dex + rts + }} } +asmsub fastcos8(ubyte angle8 @ Y) -> clobbers() -> (byte @ A) { + %asm {{ + lda sinecos8hi+64,y + rts + }} +} +asmsub fastsin16(ubyte angle8 @ Y) -> clobbers() -> (word @ AY) { + %asm {{ + lda sinecos8lo,y + pha + lda sinecos8hi,y + tay + pla + rts + }} +} +asmsub fastcos16(ubyte angle8 @ Y) -> clobbers() -> (word @ AY) { + %asm {{ + lda sinecos8lo+64,y + pha + lda sinecos8hi+64,y + tay + pla + rts + }} +} + %asm {{ +_ := 32767.5 * sin(range(256+64) * rad(360.0/256.0)) +sinecos8lo .byte <_ +sinecos8hi .byte >_ + + }} } diff --git a/compiler/src/prog8/ast/AstChecker.kt b/compiler/src/prog8/ast/AstChecker.kt index 3da39979b..2683ead21 100644 --- a/compiler/src/prog8/ast/AstChecker.kt +++ b/compiler/src/prog8/ast/AstChecker.kt @@ -712,6 +712,14 @@ class AstChecker(private val namespace: INameScope, return super.process(expr) } + override fun process(typecast: TypecastExpression): IExpression { + val funcTarget = (typecast.expression as? IFunctionCall)?.target?.targetStatement(namespace) + if(funcTarget is Subroutine && funcTarget.asmReturnvaluesRegisters.isNotEmpty()) { + checkResult.add(ExpressionError("cannot type cast a call to an asmsub that returns value in register - use a variable to store it first", typecast.position)) + } + return super.process(typecast) + } + override fun process(range: RangeExpr): IExpression { fun err(msg: String) { checkResult.add(SyntaxError(msg, range.position)) diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index eb437b5c6..3ec18ae5c 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -2044,6 +2044,11 @@ private class StatementTranslator(private val prog: IntermediateProgram, } private fun translate(expr: TypecastExpression) { + val funcTarget = (expr.expression as? IFunctionCall)?.target?.targetStatement(namespace) + if(funcTarget is Subroutine && funcTarget.asmReturnvaluesRegisters.isNotEmpty()) { + throw CompilerException("cannot type cast a call to an asmsub that returns value in register - use a variable to store it first") + } + translate(expr.expression) val sourceDt = expr.expression.resultingDatatype(namespace, heap) ?: throw CompilerException("don't know what type to cast") if(sourceDt==expr.type) diff --git a/compiler/src/prog8/compiler/intermediate/IntermediateProgram.kt b/compiler/src/prog8/compiler/intermediate/IntermediateProgram.kt index 17c44add8..24a58f30e 100644 --- a/compiler/src/prog8/compiler/intermediate/IntermediateProgram.kt +++ b/compiler/src/prog8/compiler/intermediate/IntermediateProgram.kt @@ -337,13 +337,20 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap } currentBlock.variables[scopedname] = value } - VarDeclType.MEMORY, VarDeclType.CONST -> { + VarDeclType.MEMORY -> { // note that constants are all folded away, but assembly code may still refer to them val lv = decl.value as LiteralValue if(lv.type!=DataType.UWORD && lv.type!=DataType.UBYTE) throw CompilerException("expected integer memory address $lv") currentBlock.memoryPointers[scopedname] = Pair(lv.asIntegerValue!!, decl.datatype) } + VarDeclType.CONST -> { + // note that constants are all folded away, but assembly code may still refer to them (if their integers) + // floating point constants are not generated at all!! + val lv = decl.value as LiteralValue + if(lv.type in IntegerDatatypes) + currentBlock.memoryPointers[scopedname] = Pair(lv.asIntegerValue!!, decl.datatype) + } } } diff --git a/prog8lib/c64utils.p8 b/prog8lib/c64utils.p8 index b655e6754..3670c643e 100644 --- a/prog8lib/c64utils.p8 +++ b/prog8lib/c64utils.p8 @@ -529,6 +529,8 @@ _raster_irq_handler ~ c64flt { ; ---- this block contains C-64 floating point related functions ---- ; @todo move to c64fp.p8 and enable float-checkin astchecker.process(decl: VarDecl) again + + const float PI = 3.141592653589793 asmsub FREADS32 () -> clobbers(A,X,Y) -> () {