mirror of
				https://github.com/irmen/prog8.git
				synced 2025-10-31 15:16:13 +00:00 
			
		
		
		
	retain type of consts better to avoid precision loss
this also fixed a difference in const calculation where the result could differ if you were using optimzations or not.
This commit is contained in:
		| @@ -66,7 +66,7 @@ class ConstExprEvaluator { | |||||||
| //            DataType.WORD -> result = result.toShort().toInt() | //            DataType.WORD -> result = result.toShort().toInt() | ||||||
| //            else -> { /* keep as it is */ } | //            else -> { /* keep as it is */ } | ||||||
| //        } | //        } | ||||||
|         return NumericLiteral.optimalNumeric(result.toDouble(), left.position) |         return NumericLiteral.optimalNumeric(left.type, null, result.toDouble(), left.position) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private fun bitwiseXor(left: NumericLiteral, right: NumericLiteral): NumericLiteral { |     private fun bitwiseXor(left: NumericLiteral, right: NumericLiteral): NumericLiteral { | ||||||
| @@ -133,7 +133,7 @@ class ConstExprEvaluator { | |||||||
|         val error = "cannot add $left and $right" |         val error = "cannot add $left and $right" | ||||||
|         return when (left.type) { |         return when (left.type) { | ||||||
|             in IntegerDatatypes -> when (right.type) { |             in IntegerDatatypes -> when (right.type) { | ||||||
|                 in IntegerDatatypes -> NumericLiteral.optimalInteger(left.number.toInt() + right.number.toInt(), left.position) |                 in IntegerDatatypes -> NumericLiteral.optimalInteger(left.type, right.type, left.number.toInt() + right.number.toInt(), left.position) | ||||||
|                 DataType.FLOAT -> NumericLiteral(DataType.FLOAT, left.number.toInt() + right.number, left.position) |                 DataType.FLOAT -> NumericLiteral(DataType.FLOAT, left.number.toInt() + right.number, left.position) | ||||||
|                 else -> throw ExpressionError(error, left.position) |                 else -> throw ExpressionError(error, left.position) | ||||||
|             } |             } | ||||||
| @@ -150,7 +150,7 @@ class ConstExprEvaluator { | |||||||
|         val error = "cannot subtract $left and $right" |         val error = "cannot subtract $left and $right" | ||||||
|         return when (left.type) { |         return when (left.type) { | ||||||
|             in IntegerDatatypes -> when (right.type) { |             in IntegerDatatypes -> when (right.type) { | ||||||
|                 in IntegerDatatypes -> NumericLiteral.optimalInteger(left.number.toInt() - right.number.toInt(), left.position) |                 in IntegerDatatypes -> NumericLiteral.optimalInteger(left.type, right.type, left.number.toInt() - right.number.toInt(), left.position) | ||||||
|                 DataType.FLOAT -> NumericLiteral(DataType.FLOAT, left.number.toInt() - right.number, left.position) |                 DataType.FLOAT -> NumericLiteral(DataType.FLOAT, left.number.toInt() - right.number, left.position) | ||||||
|                 else -> throw ExpressionError(error, left.position) |                 else -> throw ExpressionError(error, left.position) | ||||||
|             } |             } | ||||||
| @@ -167,7 +167,7 @@ class ConstExprEvaluator { | |||||||
|         val error = "cannot multiply ${left.type} and ${right.type}" |         val error = "cannot multiply ${left.type} and ${right.type}" | ||||||
|         return when (left.type) { |         return when (left.type) { | ||||||
|             in IntegerDatatypes -> when (right.type) { |             in IntegerDatatypes -> when (right.type) { | ||||||
|                 in IntegerDatatypes -> NumericLiteral.optimalInteger(left.number.toInt() * right.number.toInt(), left.position) |                 in IntegerDatatypes -> NumericLiteral.optimalInteger(left.type, right.type, left.number.toInt() * right.number.toInt(), left.position) | ||||||
|                 DataType.FLOAT -> NumericLiteral(DataType.FLOAT, left.number.toInt() * right.number, left.position) |                 DataType.FLOAT -> NumericLiteral(DataType.FLOAT, left.number.toInt() * right.number, left.position) | ||||||
|                 else -> throw ExpressionError(error, left.position) |                 else -> throw ExpressionError(error, left.position) | ||||||
|             } |             } | ||||||
| @@ -190,7 +190,7 @@ class ConstExprEvaluator { | |||||||
|                 in IntegerDatatypes -> { |                 in IntegerDatatypes -> { | ||||||
|                     if(right.number.toInt()==0) divideByZeroError(right.position) |                     if(right.number.toInt()==0) divideByZeroError(right.position) | ||||||
|                     val result: Int = left.number.toInt() / right.number.toInt() |                     val result: Int = left.number.toInt() / right.number.toInt() | ||||||
|                     NumericLiteral.optimalInteger(result, left.position) |                     NumericLiteral.optimalInteger(left.type, right.type, result, left.position) | ||||||
|                 } |                 } | ||||||
|                 DataType.FLOAT -> { |                 DataType.FLOAT -> { | ||||||
|                     if(right.number==0.0) divideByZeroError(right.position) |                     if(right.number==0.0) divideByZeroError(right.position) | ||||||
| @@ -219,7 +219,7 @@ class ConstExprEvaluator { | |||||||
|             in IntegerDatatypes -> when (right.type) { |             in IntegerDatatypes -> when (right.type) { | ||||||
|                 in IntegerDatatypes -> { |                 in IntegerDatatypes -> { | ||||||
|                     if(right.number.toInt()==0) divideByZeroError(right.position) |                     if(right.number.toInt()==0) divideByZeroError(right.position) | ||||||
|                     NumericLiteral.optimalNumeric(left.number.toInt().toDouble() % right.number.toInt().toDouble(), left.position) |                     NumericLiteral.optimalNumeric(left.type, right.type, left.number.toInt().toDouble() % right.number.toInt().toDouble(), left.position) | ||||||
|                 } |                 } | ||||||
|                 DataType.FLOAT -> { |                 DataType.FLOAT -> { | ||||||
|                     if(right.number ==0.0) divideByZeroError(right.position) |                     if(right.number ==0.0) divideByZeroError(right.position) | ||||||
|   | |||||||
| @@ -33,6 +33,14 @@ class ConstantFoldingOptimizer(private val program: Program, private val errors: | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     override fun after(numLiteral: NumericLiteral, parent: Node): Iterable<IAstModification> { |     override fun after(numLiteral: NumericLiteral, parent: Node): Iterable<IAstModification> { | ||||||
|  |  | ||||||
|  |         if(numLiteral.type==DataType.LONG) { | ||||||
|  |             // see if LONG values may be reduced to something smaller | ||||||
|  |             val smaller = NumericLiteral.optimalInteger(numLiteral.number.toInt(), numLiteral.position) | ||||||
|  |             if(smaller.type!=DataType.LONG) | ||||||
|  |                 return listOf(IAstModification.ReplaceNode(numLiteral, smaller, parent)) | ||||||
|  |         } | ||||||
|  |  | ||||||
|         if(parent is Assignment) { |         if(parent is Assignment) { | ||||||
|             val iDt = parent.target.inferType(program) |             val iDt = parent.target.inferType(program) | ||||||
|             if(iDt.isKnown && !iDt.isBool && !iDt.istype(numLiteral.type)) { |             if(iDt.isKnown && !iDt.isBool && !iDt.istype(numLiteral.type)) { | ||||||
| @@ -164,13 +172,13 @@ class ConstantFoldingOptimizer(private val program: Program, private val errors: | |||||||
|         if(leftconst==null && rightconst!=null && rightconst.number<0.0) { |         if(leftconst==null && rightconst!=null && rightconst.number<0.0) { | ||||||
|             if (expr.operator == "-") { |             if (expr.operator == "-") { | ||||||
|                 // X - -1 ---> X + 1 |                 // X - -1 ---> X + 1 | ||||||
|                 val posNumber = NumericLiteral.optimalNumeric(-rightconst.number, rightconst.position) |                 val posNumber = NumericLiteral.optimalNumeric(rightconst.type, null, -rightconst.number, rightconst.position) | ||||||
|                 val plusExpr = BinaryExpression(expr.left, "+", posNumber, expr.position) |                 val plusExpr = BinaryExpression(expr.left, "+", posNumber, expr.position) | ||||||
|                 return listOf(IAstModification.ReplaceNode(expr, plusExpr, parent)) |                 return listOf(IAstModification.ReplaceNode(expr, plusExpr, parent)) | ||||||
|             } |             } | ||||||
|             else if (expr.operator == "+") { |             else if (expr.operator == "+") { | ||||||
|                 // X + -1 ---> X - 1 |                 // X + -1 ---> X - 1 | ||||||
|                 val posNumber = NumericLiteral.optimalNumeric(-rightconst.number, rightconst.position) |                 val posNumber = NumericLiteral.optimalNumeric(rightconst.type, null, -rightconst.number, rightconst.position) | ||||||
|                 val plusExpr = BinaryExpression(expr.left, "-", posNumber, expr.position) |                 val plusExpr = BinaryExpression(expr.left, "-", posNumber, expr.position) | ||||||
|                 return listOf(IAstModification.ReplaceNode(expr, plusExpr, parent)) |                 return listOf(IAstModification.ReplaceNode(expr, plusExpr, parent)) | ||||||
|             } |             } | ||||||
| @@ -384,14 +392,15 @@ class ConstantFoldingOptimizer(private val program: Program, private val errors: | |||||||
|         val numval = decl.value as? NumericLiteral |         val numval = decl.value as? NumericLiteral | ||||||
|         if(decl.type== VarDeclType.CONST && numval!=null) { |         if(decl.type== VarDeclType.CONST && numval!=null) { | ||||||
|             val valueDt = numval.inferType(program) |             val valueDt = numval.inferType(program) | ||||||
|  |             if(valueDt istype DataType.LONG) { | ||||||
|  |                 return noModifications  // this is handled in the numericalvalue case | ||||||
|  |             } | ||||||
|             if(valueDt isnot decl.datatype) { |             if(valueDt isnot decl.datatype) { | ||||||
|                 if(decl.datatype!=DataType.BOOL || valueDt.isnot(DataType.UBYTE)) { |  | ||||||
|                 val cast = numval.cast(decl.datatype, true) |                 val cast = numval.cast(decl.datatype, true) | ||||||
|                 if (cast.isValid) |                 if (cast.isValid) | ||||||
|                     return listOf(IAstModification.ReplaceNode(numval, cast.valueOrZero(), decl)) |                     return listOf(IAstModification.ReplaceNode(numval, cast.valueOrZero(), decl)) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         } |  | ||||||
|         return noModifications |         return noModifications | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -15,6 +15,9 @@ | |||||||
| ; | ; | ||||||
| ; NOTE: the bitmap screen data is positioned in vram at $0:0000 | ; NOTE: the bitmap screen data is positioned in vram at $0:0000 | ||||||
| ; | ; | ||||||
|  | ; NOTE: In the future, these routines might be split out to separate modules, 1 for each screen mode, | ||||||
|  | ;       so they can be optimized a lot better.  There's already a "gfx_lores" module with a few routines for lores 256C mode. | ||||||
|  | ; | ||||||
| ; SCREEN MODE LIST: | ; SCREEN MODE LIST: | ||||||
| ;   mode 0 = reset back to default text mode | ;   mode 0 = reset back to default text mode | ||||||
| ;   mode 1 = bitmap 320 x 240 x 256c (8 bpp) | ;   mode 1 = bitmap 320 x 240 x 256c (8 bpp) | ||||||
|   | |||||||
| @@ -233,7 +233,7 @@ math { | |||||||
|     sub direction(ubyte x1, ubyte y1, ubyte x2, ubyte y2) -> ubyte { |     sub direction(ubyte x1, ubyte y1, ubyte x2, ubyte y2) -> ubyte { | ||||||
|         ; From a pair of positive coordinates, calculate discrete direction between 0 and 23 into A. |         ; From a pair of positive coordinates, calculate discrete direction between 0 and 23 into A. | ||||||
|         ; This adjusts the atan() result  so that the direction N is centered on the angle=N instead of having it as a boundary |         ; This adjusts the atan() result  so that the direction N is centered on the angle=N instead of having it as a boundary | ||||||
|         ubyte angle = atan2(x1, y1, x2, y2) - 256/48 |         ubyte angle = atan2(x1, y1, x2, y2) - (256/48 as ubyte) | ||||||
|         return 23-lsb(mkword(angle,0) / 2730) |         return 23-lsb(mkword(angle,0) / 2730) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -190,21 +190,7 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val | |||||||
|                     } |                     } | ||||||
|                     val cvalue = assignment.value.constValue(program) |                     val cvalue = assignment.value.constValue(program) | ||||||
|                     if(cvalue!=null) { |                     if(cvalue!=null) { | ||||||
|                         val number = cvalue.number |  | ||||||
|                         // more complex comparisons if the type is different, but the constant value is compatible |  | ||||||
|                         if (valuetype == DataType.BYTE && targettype == DataType.UBYTE) { |  | ||||||
|                             if(number>0) |  | ||||||
|                         return castLiteral(cvalue) |                         return castLiteral(cvalue) | ||||||
|                         } else if (valuetype == DataType.WORD && targettype == DataType.UWORD) { |  | ||||||
|                             if(number>0) |  | ||||||
|                                 return castLiteral(cvalue) |  | ||||||
|                         } else if (valuetype == DataType.UBYTE && targettype == DataType.BYTE) { |  | ||||||
|                             if(number<0x80) |  | ||||||
|                                 return castLiteral(cvalue) |  | ||||||
|                         } else if (valuetype == DataType.UWORD && targettype == DataType.WORD) { |  | ||||||
|                             if(number<0x8000) |  | ||||||
|                                 return castLiteral(cvalue) |  | ||||||
|                         } |  | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @@ -357,15 +343,72 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     override fun after(range: RangeExpression, parent: Node): Iterable<IAstModification> { |     override fun after(range: RangeExpression, parent: Node): Iterable<IAstModification> { | ||||||
|  |         val fromConst = range.from.constValue(program) | ||||||
|  |         val toConst = range.to.constValue(program) | ||||||
|  |  | ||||||
|  |         if(fromConst!=null) { | ||||||
|  |             val smaller = NumericLiteral.optimalInteger(fromConst.number.toInt(), fromConst.position) | ||||||
|  |             if(fromConst.type.largerThan(smaller.type)) { | ||||||
|  |                 val toType = range.to.inferType(program) | ||||||
|  |                 if(toType isnot smaller.type) { | ||||||
|  |                     if(toConst!=null) { | ||||||
|  |                         // can we make the to value into the same smaller type? | ||||||
|  |                         val smallerTo = NumericLiteral.optimalInteger(toConst.number.toInt(), toConst.position) | ||||||
|  |                         if(smaller.type==smallerTo.type) { | ||||||
|  |                             val newRange = RangeExpression(smaller, smallerTo, range.step, range.position) | ||||||
|  |                             return listOf(IAstModification.ReplaceNode(range, newRange, parent)) | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     val newRange = RangeExpression(smaller, range.to, range.step, range.position) | ||||||
|  |                     return listOf(IAstModification.ReplaceNode(range, newRange, parent)) | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if(toConst!=null) { | ||||||
|  |             val smaller = NumericLiteral.optimalInteger(toConst.number.toInt(), toConst.position) | ||||||
|  |             if(toConst.type.largerThan(smaller.type)) { | ||||||
|  |                 val fromType = range.from.inferType(program) | ||||||
|  |                 if(fromType isnot smaller.type) { | ||||||
|  |                     if(fromConst!=null) { | ||||||
|  |                         // can we make the from value into the same smaller type? | ||||||
|  |                         val smallerFrom = NumericLiteral.optimalInteger(fromConst.number.toInt(), fromConst.position) | ||||||
|  |                         if(smaller.type==smallerFrom.type) { | ||||||
|  |                             val newRange = RangeExpression(smallerFrom, smaller, range.step, range.position) | ||||||
|  |                             return listOf(IAstModification.ReplaceNode(range, newRange, parent)) | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     val newRange = RangeExpression(range.from, smaller, range.step, range.position) | ||||||
|  |                     return listOf(IAstModification.ReplaceNode(range, newRange, parent)) | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         val modifications = mutableListOf<IAstModification>() | ||||||
|         val fromDt = range.from.inferType(program).getOr(DataType.UNDEFINED) |         val fromDt = range.from.inferType(program).getOr(DataType.UNDEFINED) | ||||||
|         val toDt = range.to.inferType(program).getOr(DataType.UNDEFINED) |         val toDt = range.to.inferType(program).getOr(DataType.UNDEFINED) | ||||||
|         val modifications = mutableListOf<IAstModification>() |  | ||||||
|         val (commonDt, toChange) = BinaryExpression.commonDatatype(fromDt, toDt, range.from, range.to) |         val (commonDt, toChange) = BinaryExpression.commonDatatype(fromDt, toDt, range.from, range.to) | ||||||
|         if(toChange!=null) |         if(toChange!=null) | ||||||
|             addTypecastOrCastedValueModification(modifications, toChange, commonDt, range) |             addTypecastOrCastedValueModification(modifications, toChange, commonDt, range) | ||||||
|  |  | ||||||
|         return modifications |         return modifications | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     override fun after(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> { | ||||||
|  |         val constIdx = arrayIndexedExpression.indexer.constIndex() | ||||||
|  |         if(constIdx!=null) { | ||||||
|  |             val smaller = NumericLiteral.optimalInteger(constIdx, arrayIndexedExpression.indexer.position) | ||||||
|  |             val idxDt = arrayIndexedExpression.indexer.indexExpr.inferType(program).getOr(DataType.UNDEFINED) | ||||||
|  |             if(idxDt.largerThan(smaller.type)) { | ||||||
|  |                 val newIdx = ArrayIndex(smaller, smaller.position) | ||||||
|  |                 val newIndexer = ArrayIndexedExpression(arrayIndexedExpression.arrayvar, newIdx, arrayIndexedExpression.position) | ||||||
|  |                 return listOf(IAstModification.ReplaceNode(arrayIndexedExpression, newIndexer, parent)) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return noModifications | ||||||
|  |     } | ||||||
|  |  | ||||||
|     private fun addTypecastOrCastedValueModification( |     private fun addTypecastOrCastedValueModification( | ||||||
|         modifications: MutableList<IAstModification>, |         modifications: MutableList<IAstModification>, | ||||||
|         expressionToCast: Expression, |         expressionToCast: Expression, | ||||||
|   | |||||||
| @@ -498,6 +498,24 @@ class NumericLiteral(val type: DataType,    // only numerical types allowed | |||||||
|         fun fromBoolean(bool: Boolean, position: Position) = |         fun fromBoolean(bool: Boolean, position: Position) = | ||||||
|                 NumericLiteral(DataType.BOOL, if(bool) 1.0 else 0.0, position) |                 NumericLiteral(DataType.BOOL, if(bool) 1.0 else 0.0, position) | ||||||
|  |  | ||||||
|  |         fun optimalNumeric(origType1: DataType, origType2: DataType?, value: Number, position: Position) : NumericLiteral { | ||||||
|  |             val optimal = optimalNumeric(value, position) | ||||||
|  |             val largestOrig = if(origType2==null) origType1 else if(origType1.largerThan(origType2)) origType1 else origType2 | ||||||
|  |             if(largestOrig.largerThan(optimal.type)) | ||||||
|  |                 return NumericLiteral(largestOrig, optimal.number, position) | ||||||
|  |             else | ||||||
|  |                 return optimal | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         fun optimalInteger(origType1: DataType, origType2: DataType?, value: Int, position: Position): NumericLiteral { | ||||||
|  |             val optimal = optimalInteger(value, position) | ||||||
|  |             val largestOrig = if(origType2==null) origType1 else if(origType1.largerThan(origType2)) origType1 else origType2 | ||||||
|  |             if(largestOrig.largerThan(optimal.type)) | ||||||
|  |                 return NumericLiteral(largestOrig, optimal.number, position) | ||||||
|  |             else | ||||||
|  |                 return optimal | ||||||
|  |         } | ||||||
|  |  | ||||||
|         fun optimalNumeric(value: Number, position: Position): NumericLiteral { |         fun optimalNumeric(value: Number, position: Position): NumericLiteral { | ||||||
|             val digits = floor(value.toDouble()) - value.toDouble() |             val digits = floor(value.toDouble()) - value.toDouble() | ||||||
|             return if(value is Double && digits!=0.0) { |             return if(value is Double && digits!=0.0) { | ||||||
| @@ -1090,7 +1108,16 @@ data class IdentifierReference(val nameInSource: List<String>, override val posi | |||||||
|         } else if(vardecl.type!= VarDeclType.CONST) { |         } else if(vardecl.type!= VarDeclType.CONST) { | ||||||
|             return null |             return null | ||||||
|         } |         } | ||||||
|         return vardecl.value?.constValue(program) |  | ||||||
|  |         // the value of a variable can (temporarily) be a different type as the vardecl itself. | ||||||
|  |         // don't return the value if the types don't match yet! | ||||||
|  |         val value = vardecl.value?.constValue(program) | ||||||
|  |         if(value==null || value.type==vardecl.datatype) | ||||||
|  |             return value | ||||||
|  |         val optimal = NumericLiteral.optimalNumeric(value.number, value.position) | ||||||
|  |         if(optimal.type==vardecl.datatype) | ||||||
|  |             return optimal | ||||||
|  |         return null | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     override fun toString(): String { |     override fun toString(): String { | ||||||
|   | |||||||
| @@ -1,8 +1,10 @@ | |||||||
| TODO | TODO | ||||||
| ==== | ==== | ||||||
|  |  | ||||||
| wrong answer if cast as uword is not done in: | Should give type error, but seems to make num a word !?: | ||||||
|   const uword W=320;   uword x1 = ((WIDTH-256)/2 as uword) + math.sin8u(i) |     const uword screenwidth = txt.DEFAULT_WIDTH | ||||||
|  |     const ubyte num = (screenwidth-1) / 2 | ||||||
|  |  | ||||||
|  |  | ||||||
| callgraph issue? : if a sub contains another sub and it calls that, the outer sub is never removed even if it doesn't get called? | callgraph issue? : if a sub contains another sub and it calls that, the outer sub is never removed even if it doesn't get called? | ||||||
|  |  | ||||||
|   | |||||||
| @@ -33,9 +33,9 @@ main { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         if fastserial |         if fastserial | ||||||
|             diskio.fastmode(3) |             void diskio.fastmode(3) | ||||||
|         else |         else | ||||||
|             diskio.fastmode(0) |             void diskio.fastmode(0) | ||||||
|  |  | ||||||
|         test_save() |         test_save() | ||||||
|         test_save_blocks() |         test_save_blocks() | ||||||
|   | |||||||
| @@ -3,8 +3,8 @@ | |||||||
| %zeropage basicsafe | %zeropage basicsafe | ||||||
|  |  | ||||||
| main { | main { | ||||||
|     const uword width = 60 |     const ubyte width = 60 | ||||||
|     const uword height = 50 |     const ubyte height = 50 | ||||||
|     const ubyte max_iter = 16 |     const ubyte max_iter = 16 | ||||||
|  |  | ||||||
|     sub start()  { |     sub start()  { | ||||||
|   | |||||||
| @@ -6,8 +6,8 @@ | |||||||
| ; Note: this program can be compiled for multiple target systems. | ; Note: this program can be compiled for multiple target systems. | ||||||
|  |  | ||||||
| main { | main { | ||||||
|     const uword width = 30 |     const ubyte width = 30 | ||||||
|     const uword height = 20 |     const ubyte height = 20 | ||||||
|     const ubyte max_iter = 16 |     const ubyte max_iter = 16 | ||||||
|  |  | ||||||
|     sub start()  { |     sub start()  { | ||||||
|   | |||||||
| @@ -1,61 +1,16 @@ | |||||||
| %import textio | %import textio | ||||||
| %import gfx_lores |  | ||||||
| %import emudbg |  | ||||||
| %zeropage basicsafe | %zeropage basicsafe | ||||||
| %option no_sysinit | %option no_sysinit | ||||||
|  |  | ||||||
| main { | main { | ||||||
|     const uword WIDTH = 320 |  | ||||||
|     const ubyte HEIGHT = 240 |  | ||||||
|  |  | ||||||
|     sub start() { |     sub start() { | ||||||
|         uword clo, chi |         uword @shared large = (320*240/8/8) | ||||||
|  |         const uword WIDTH=320 | ||||||
|         void cx16.set_screen_mode(128) |         uword x1 = ((WIDTH-256)/2 as uword) + 200 | ||||||
|  |         txt.print_uw(x1) | ||||||
|         word x1, y1, x2, y2 |  | ||||||
|         ubyte i |  | ||||||
|         ubyte color = 2 |  | ||||||
|  |  | ||||||
|         sys.set_irqd() |  | ||||||
|         emudbg.reset_cpu_cycles() |  | ||||||
|         for i in 0 to 254 step 4 { |  | ||||||
|             x1 = ((WIDTH-256)/2 as word) + math.sin8u(i) as word |  | ||||||
|             y1 = (HEIGHT-128)/2 + math.cos8u(i)/2 |  | ||||||
|             x2 = ((WIDTH-64)/2 as word) + math.sin8u(i)/4 as word |  | ||||||
|             y2 = (HEIGHT-64)/2 + math.cos8u(i)/4 |  | ||||||
|             cx16.GRAPH_set_colors(color, 0, 1) |  | ||||||
|             cx16.GRAPH_draw_line(x1 as uword, y1 as uword, x2 as uword, y2 as uword) |  | ||||||
|         } |  | ||||||
|         clo, chi = emudbg.cpu_cycles() |  | ||||||
|         sys.clear_irqd() |  | ||||||
|  |  | ||||||
|         txt.print_uwhex(chi, true) |  | ||||||
|         txt.print_uwhex(clo, false) |  | ||||||
|         txt.nl() |         txt.nl() | ||||||
|  |         x1 = ((WIDTH-256)/2) + 200 | ||||||
|         sys.wait(50) |         txt.print_uw(x1) | ||||||
|         cx16.GRAPH_clear() |  | ||||||
|         sys.wait(50) |  | ||||||
|  |  | ||||||
|         sys.set_irqd() |  | ||||||
|         emudbg.reset_cpu_cycles() |  | ||||||
|         color = 5 |  | ||||||
|         for i in 0 to 254 step 4 { |  | ||||||
|             x1 = ((WIDTH-256)/2 as word) + math.sin8u(i) as word |  | ||||||
|             y1 = (HEIGHT-128)/2 + math.cos8u(i)/2 |  | ||||||
|             x2 = ((WIDTH-64)/2 as word) + math.sin8u(i)/4 as word |  | ||||||
|             y2 = (HEIGHT-64)/2 + math.cos8u(i)/4 |  | ||||||
|             gfx_lores.line(x1 as uword, y1 as ubyte, x2 as uword, y2 as ubyte, color) |  | ||||||
|         } |  | ||||||
|         clo, chi = emudbg.cpu_cycles() |  | ||||||
|         sys.clear_irqd() |  | ||||||
|  |  | ||||||
|         txt.print_uwhex(chi, true) |  | ||||||
|         txt.print_uwhex(clo, false) |  | ||||||
|         txt.nl() |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user