diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 000000000..a39e0f0fb
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt
index 0201bd107..759c067d6 100644
--- a/compiler/src/prog8/compiler/Compiler.kt
+++ b/compiler/src/prog8/compiler/Compiler.kt
@@ -96,7 +96,7 @@ fun compileProgram(filepath: Path,
importedFiles = imported
processAst(programAst, errors, compilationOptions)
if (compilationOptions.optimize)
- optimizeAst(programAst, errors, BuiltinFunctionsFacade(BuiltinFunctions), compTarget)
+ optimizeAst(programAst, errors, BuiltinFunctionsFacade(BuiltinFunctions), compTarget, compilationOptions)
postprocessAst(programAst, errors, compilationOptions)
// printAst(programAst)
@@ -253,7 +253,7 @@ private fun processAst(programAst: Program, errors: IErrorReporter, compilerOpti
errors.report()
programAst.addTypecasts(errors)
errors.report()
- programAst.variousCleanups(programAst, errors, compilerOptions)
+ programAst.variousCleanups(errors)
errors.report()
programAst.checkValid(compilerOptions, errors, compilerOptions.compTarget)
errors.report()
@@ -261,7 +261,7 @@ private fun processAst(programAst: Program, errors: IErrorReporter, compilerOpti
errors.report()
}
-private fun optimizeAst(programAst: Program, errors: IErrorReporter, functions: IBuiltinFunctions, compTarget: ICompilationTarget) {
+private fun optimizeAst(programAst: Program, errors: IErrorReporter, functions: IBuiltinFunctions, compTarget: ICompilationTarget, options: CompilationOptions) {
// optimize the parse tree
println("Optimizing...")
while (true) {
@@ -275,16 +275,24 @@ private fun optimizeAst(programAst: Program, errors: IErrorReporter, functions:
break
}
- val remover = UnusedCodeRemover(programAst, errors, compTarget, ::loadAsmIncludeFile)
- remover.visit(programAst)
- remover.applyModifications()
+ val inliner = SubroutineInliner(programAst, errors, options)
+ inliner.visit(programAst)
+ errors.report()
+ if(errors.noErrors()) {
+ inliner.applyModifications()
+ inliner.fixCallsToInlinedSubroutines()
+ val remover = UnusedCodeRemover(programAst, errors, compTarget, ::loadAsmIncludeFile)
+ remover.visit(programAst)
+ remover.applyModifications()
+ }
+
errors.report()
}
private fun postprocessAst(programAst: Program, errors: IErrorReporter, compilerOptions: CompilationOptions) {
programAst.addTypecasts(errors)
errors.report()
- programAst.variousCleanups(programAst, errors, compilerOptions)
+ programAst.variousCleanups(errors)
programAst.checkValid(compilerOptions, errors, compilerOptions.compTarget) // check if final tree is still valid
errors.report()
val callGraph = CallGraph(programAst, ::loadAsmIncludeFile)
diff --git a/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt b/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt
index 099e6e5d5..b8201b028 100644
--- a/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt
+++ b/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt
@@ -56,8 +56,8 @@ internal fun Program.checkIdentifiers(errors: IErrorReporter, compTarget: ICompi
}
}
-internal fun Program.variousCleanups(program: Program, errors: IErrorReporter, options: CompilationOptions) {
- val process = VariousCleanups(program, errors, options)
+internal fun Program.variousCleanups(errors: IErrorReporter) {
+ val process = VariousCleanups(errors)
process.visit(this)
if(errors.noErrors())
process.applyModifications()
diff --git a/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt b/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt
index bb8abf760..1bcf1da09 100644
--- a/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt
+++ b/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt
@@ -3,19 +3,16 @@ package prog8.compiler.astprocessing
import prog8.ast.IFunctionCall
import prog8.ast.INameScope
import prog8.ast.Node
-import prog8.ast.Program
import prog8.ast.base.FatalAstException
import prog8.ast.base.Position
import prog8.ast.expressions.*
import prog8.ast.statements.*
import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification
-import prog8.compiler.CompilationOptions
import prog8.compiler.IErrorReporter
-import prog8.optimizer.retvarName
-internal class VariousCleanups(private val program: Program, val errors: IErrorReporter, private val compilerOptions: CompilationOptions): AstWalker() {
+internal class VariousCleanups(val errors: IErrorReporter): AstWalker() {
private val noModifications = emptyList()
override fun before(nopStatement: NopStatement, parent: Node): Iterable {
@@ -58,33 +55,24 @@ internal class VariousCleanups(private val program: Program, val errors: IErrorR
}
private fun before(functionCall: IFunctionCall, parent: Node, position: Position): Iterable {
-
- val modifications = mutableListOf()
-
- if(compilerOptions.optimize) {
- val sub = functionCall.target.targetSubroutine(program)
- if(sub!=null && sub.inline && !sub.isAsmSubroutine) {
- val (annotations, intermediateReturnValueVar) = annotateInlinedSubroutineIdentifiers(sub)
- modifications.addAll(annotations)
- if(intermediateReturnValueVar!=null) {
- val decl=intermediateReturnValueVar.copy()
- modifications.add(IAstModification.InsertFirst(decl, parent.definingScope()))
- }
- }
- }
-
if(functionCall.target.nameInSource==listOf("peek")) {
// peek(a) is synonymous with @(a)
val memread = DirectMemoryRead(functionCall.args.single(), position)
- modifications.add(IAstModification.ReplaceNode(functionCall as Node, memread, parent))
+ return listOf(IAstModification.ReplaceNode(functionCall as Node, memread, parent))
}
if(functionCall.target.nameInSource==listOf("poke")) {
// poke(a, v) is synonymous with @(a) = v
val tgt = AssignTarget(null, null, DirectMemoryWrite(functionCall.args[0], position), position)
val assign = Assignment(tgt, functionCall.args[1], position)
- modifications.add(IAstModification.ReplaceNode(functionCall as Node, assign, parent))
+ return listOf(IAstModification.ReplaceNode(functionCall as Node, assign, parent))
}
- return modifications
+ return noModifications
+ }
+
+ override fun after(subroutine: Subroutine, parent: Node): Iterable {
+ if(subroutine.parent!==parent)
+ throw FatalAstException("parent node mismatch at $subroutine")
+ return noModifications
}
override fun after(assignment: Assignment, parent: Node): Iterable {
@@ -128,61 +116,4 @@ internal class VariousCleanups(private val program: Program, val errors: IErrorR
throw FatalAstException("parent node mismatch at $identifier")
return noModifications
}
-
- private fun annotateInlinedSubroutineIdentifiers(sub: Subroutine): Pair, VarDecl?> {
- // this adds full name prefixes to all identifiers used in the subroutine,
- // so that the statements can be inlined (=copied) in the call site and still reference
- // the correct symbols as seen from the scope of the subroutine.
-
- if(sub.containsDefinedVariables())
- errors.warn("inlining a subroutine with variables, this could result in large code/memory size", sub.position)
-
- var intermediateReturnVar: VarDecl? = null
-
- class Annotator: AstWalker() {
- var numReturns=0
-
- override fun before(identifier: IdentifierReference, parent: Node): Iterable {
- val stmt = identifier.targetStatement(program)!!
- val subroutine = identifier.definingSubroutine()
- return if(stmt is VarDecl && stmt.parent === subroutine) {
- val prefixed = stmt.makeScopedName(identifier.nameInSource.last()).replace('.','_')
- val withPrefix = IdentifierReference(listOf(prefixed), identifier.position)
- listOf(IAstModification.ReplaceNode(identifier, withPrefix, parent))
- } else {
- val prefixed = stmt.makeScopedName(identifier.nameInSource.last()).split('.')
- val withPrefix = IdentifierReference(prefixed, identifier.position)
- listOf(IAstModification.ReplaceNode(identifier, withPrefix, parent))
- }
- }
-
- override fun after(decl: VarDecl, parent: Node): Iterable {
- val prefixed = decl.makeScopedName(decl.name).replace('.','_')
- val newdecl = VarDecl(decl.type, decl.datatype, decl.zeropage, decl.arraysize, prefixed, decl.struct?.name, decl.value, decl.isArray, decl.autogeneratedDontRemove, decl.position)
- if(decl.name == retvarName)
- intermediateReturnVar = newdecl
- return listOf(IAstModification.ReplaceNode(decl, newdecl, parent))
- }
-
- override fun before(returnStmt: Return, parent: Node): Iterable {
- numReturns++
- if(parent !== sub || sub.indexOfChild(returnStmt) {
- return this.modifications.map { it.first }.toList()
- }
- }
-
- val annotator = Annotator()
- sub.accept(annotator, sub.parent)
- if(annotator.numReturns>1) {
- errors.err("inlined subroutine can only have one return statement", sub.position)
- return Pair(noModifications, intermediateReturnVar)
- }
- return Pair(annotator.theModifications(), intermediateReturnVar)
- }
-
}
diff --git a/compiler/src/prog8/optimizer/SubroutineInliner.kt b/compiler/src/prog8/optimizer/SubroutineInliner.kt
new file mode 100644
index 000000000..2dd4aab2b
--- /dev/null
+++ b/compiler/src/prog8/optimizer/SubroutineInliner.kt
@@ -0,0 +1,109 @@
+package prog8.optimizer
+
+import prog8.ast.IFunctionCall
+import prog8.ast.Node
+import prog8.ast.Program
+import prog8.ast.base.Position
+import prog8.ast.expressions.*
+import prog8.ast.statements.*
+import prog8.ast.walk.AstWalker
+import prog8.ast.walk.IAstModification
+import prog8.compiler.CompilationOptions
+import prog8.compiler.IErrorReporter
+
+
+internal class SubroutineInliner(private val program: Program, val errors: IErrorReporter, private val compilerOptions: CompilationOptions): AstWalker() {
+ private val noModifications = emptyList()
+ private var callsToInlinedSubroutines = mutableListOf>()
+
+ fun fixCallsToInlinedSubroutines() {
+ for((call, parent) in callsToInlinedSubroutines) {
+ val sub = call.target.targetSubroutine(program)!!
+ val intermediateReturnValueVar = sub.statements.filterIsInstance().singleOrNull { it.name.endsWith(retvarName) }
+ if(intermediateReturnValueVar!=null) {
+ val scope = parent.definingScope()
+ if(!scope.statements.filterIsInstance().any { it.name==intermediateReturnValueVar.name}) {
+ val decl = intermediateReturnValueVar.copy()
+ scope.statements.add(0, decl)
+ decl.linkParents(scope as Node)
+ }
+ }
+ }
+ }
+
+ override fun after(subroutine: Subroutine, parent: Node): Iterable {
+ return if(compilerOptions.optimize && subroutine.inline && !subroutine.isAsmSubroutine)
+ annotateInlinedSubroutineIdentifiers(subroutine)
+ else
+ noModifications
+ }
+
+ override fun after(functionCallStatement: FunctionCallStatement, parent: Node): Iterable {
+ return after(functionCallStatement as IFunctionCall, parent, functionCallStatement.position)
+ }
+
+ override fun after(functionCall: FunctionCall, parent: Node): Iterable {
+ return after(functionCall as IFunctionCall, parent, functionCall.position)
+ }
+
+ private fun after(functionCall: IFunctionCall, parent: Node, position: Position): Iterable {
+ val sub = functionCall.target.targetSubroutine(program)
+ if(sub != null && compilerOptions.optimize && sub.inline && !sub.isAsmSubroutine)
+ callsToInlinedSubroutines.add(Pair(functionCall, parent))
+
+ return noModifications
+ }
+
+ private fun annotateInlinedSubroutineIdentifiers(sub: Subroutine): List {
+ // this adds full name prefixes to all identifiers used in the subroutine,
+ // so that the statements can be inlined (=copied) in the call site and still reference
+ // the correct symbols as seen from the scope of the subroutine.
+
+ if(sub.containsDefinedVariables())
+ errors.warn("inlining a subroutine with variables, this could result in large code/memory size", sub.position)
+
+ class Annotator: AstWalker() {
+ var numReturns=0
+
+ override fun before(identifier: IdentifierReference, parent: Node): Iterable {
+ val stmt = identifier.targetStatement(program)!!
+ val subroutine = identifier.definingSubroutine()
+ return if(stmt is VarDecl && stmt.parent === subroutine) {
+ val prefixed = stmt.makeScopedName(identifier.nameInSource.last()).replace('.','_')
+ val withPrefix = IdentifierReference(listOf(prefixed), identifier.position)
+ listOf(IAstModification.ReplaceNode(identifier, withPrefix, parent))
+ } else {
+ val prefixed = stmt.makeScopedName(identifier.nameInSource.last()).split('.')
+ val withPrefix = IdentifierReference(prefixed, identifier.position)
+ listOf(IAstModification.ReplaceNode(identifier, withPrefix, parent))
+ }
+ }
+
+ override fun after(decl: VarDecl, parent: Node): Iterable {
+ val prefixed = decl.makeScopedName(decl.name).replace('.','_')
+ val newdecl = VarDecl(decl.type, decl.datatype, decl.zeropage, decl.arraysize, prefixed, decl.struct?.name, decl.value, decl.isArray, decl.autogeneratedDontRemove, decl.position)
+ return listOf(IAstModification.ReplaceNode(decl, newdecl, parent))
+ }
+
+ override fun before(returnStmt: Return, parent: Node): Iterable {
+ numReturns++
+ if(parent !== sub || sub.indexOfChild(returnStmt) {
+ return this.modifications.map { it.first }.toList()
+ }
+ }
+
+ val annotator = Annotator()
+ sub.accept(annotator, sub.parent)
+ if(annotator.numReturns>1) {
+ errors.err("inlined subroutine can only have one return statement", sub.position)
+ return noModifications
+ }
+ return annotator.theModifications()
+ }
+
+}
diff --git a/compilerAst/src/prog8/ast/statements/AstStatements.kt b/compilerAst/src/prog8/ast/statements/AstStatements.kt
index 32bcf099c..c9fdd9cba 100644
--- a/compilerAst/src/prog8/ast/statements/AstStatements.kt
+++ b/compilerAst/src/prog8/ast/statements/AstStatements.kt
@@ -658,6 +658,7 @@ class Subroutine(override val name: String,
override lateinit var parent: Node
val asmGenInfo = AsmGenInfo()
val scopedname: String by lazy { makeScopedName(name) }
+ var inlineAnnotated: Boolean = false
override fun linkParents(parent: Node) {
this.parent = parent
diff --git a/docs/source/todo.rst b/docs/source/todo.rst
index 9b08db37c..80b226d18 100644
--- a/docs/source/todo.rst
+++ b/docs/source/todo.rst
@@ -2,8 +2,6 @@
TODO
====
-- fix multiple cals to inlined subroutines
-
- allow inlining of subroutines with params
- optimize several inner loops in gfx2
- hoist all variable declarations up to the subroutine scope *before* even the constant folding takes place (to avoid undefined symbol errors when referring to a variable from another nested scope in the subroutine)
diff --git a/examples/cx16/multipalette.p8 b/examples/cx16/multipalette.p8
new file mode 100644
index 000000000..d09b202c0
--- /dev/null
+++ b/examples/cx16/multipalette.p8
@@ -0,0 +1,415 @@
+%target cx16
+%import palette
+%import gfx2
+%option no_sysinit
+
+main {
+
+ sub start() {
+ ; palette.set_rgb(&colors, len(colors))
+ void cx16.screen_set_mode(128) ; low-res bitmap 256 colors
+
+ cx16.FB_init()
+
+ cx16.VERA_DC_VIDEO = (cx16.VERA_DC_VIDEO & %11001111) | %00010000 ; enable only layer 0
+ cx16.VERA_L0_CONFIG = %00000110 ; 4 bpp = 16 colors
+ ;cx16.VERA_L0_MAPBASE = 0
+ ;cx16.VERA_L0_TILEBASE = 0
+
+ ubyte pix=0
+ ubyte ypos
+ cx16.FB_cursor_position(0, 0)
+ for ypos in 0 to 199 {
+ repeat 320/2 {
+ cx16.FB_set_pixel((pix&15)<<4 | (pix&15))
+ pix++
+ }
+ pix=0
+ }
+
+ ; color index 0 can't be swapped - set it to black in both ranges
+ palette.set_color(0, 0)
+ palette.set_color(16, 0)
+
+ cx16.set_rasterirq(&irq.irq, 0)
+
+ repeat {
+ ; don't exit
+ }
+ }
+}
+
+
+irq {
+ ubyte phase = 0
+ uword next_rasterline = 0
+ const ubyte increment = 4 ; 4 scanlines = 2 lores pixels per color swap (2 scanlines is too tight)
+
+ sub irq() {
+ if phase & 1 == 0 {
+ %asm {{
+ lda #0 ; activate palette #0 (first set of colors)
+ sta cx16.VERA_L0_HSCROLL_H
+
+ stz cx16.VERA_CTRL
+ lda #<$fa00+32+2
+ sta cx16.VERA_ADDR_L
+ lda #>$fa00+32+2
+ sta cx16.VERA_ADDR_M
+ lda #%00010001
+ sta cx16.VERA_ADDR_H
+
+ ; change 15 palette entries 1..15 (0 is fixed)
+ lda #<$e000
+ sta $02
+ lda #>$e000
+ sta $02
+ ldy #0
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+
+
+
+; lda #$0f
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$0f
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$0f
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$0f
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$0f
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$0f
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$0f
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$0f
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$0f
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$0f
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$0f
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$0f
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$0f
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$0f
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$0f
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+
+ }}
+ }
+ else {
+ %asm {{
+ lda #1 ; activate palette #1 (second set of colors)
+ sta cx16.VERA_L0_HSCROLL_H
+
+ stz cx16.VERA_CTRL
+ lda #<$fa00+2
+ sta cx16.VERA_ADDR_L
+ lda #>$fa00+2
+ sta cx16.VERA_ADDR_M
+ lda #%00010001
+ sta cx16.VERA_ADDR_H
+
+ ; change 15 palette entries 1..15 (0 is fixed)
+
+ lda #<$f000
+ sta $02
+ lda #>$f000
+ sta $02
+ ldy #0
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+ iny
+ lda (2),y
+ sta cx16.VERA_DATA0
+
+
+; lda #$ff
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$ff
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$ff
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$ff
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$ff
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$ff
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$ff
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$ff
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$ff
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$ff
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$ff
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$ff
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$ff
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$ff
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+; lda #$ff
+; sta cx16.VERA_DATA0
+; lda #0
+; sta cx16.VERA_DATA0
+
+ }}
+ }
+
+ phase++
+ next_rasterline += increment
+
+ if next_rasterline > 400 {
+ next_rasterline = 0
+ phase = 0
+ }
+
+ cx16.set_rasterline(next_rasterline)
+
+;
+; uword[16] colors1 = 0
+; uword[16] colors2 = 200
+;
+; palette.set_rgb(colors1, len(colors1))
+; palette.set_rgb(colors2, len(colors2))
+ }
+}
diff --git a/examples/test.p8 b/examples/test.p8
index ecbc2c820..07f19c150 100644
--- a/examples/test.p8
+++ b/examples/test.p8
@@ -6,9 +6,14 @@ main {
sub start() {
ubyte thing = otherblock.othersub()
- ;ubyte thing2 = otherblock.othersub()
+ thing = otherblock.othersub()
+ thing = otherblock.othersub()
+ thing = otherblock.othersub()
+ thing = otherblock.othersub()
+ thing = otherblock.othersub()
+ thing = otherblock.othersub()
+ thing = otherblock.othersub()
txt.print_ub(thing) ; should print 41!
- ;txt.print_ub(thing2) ; should print 41!
; str filename = "titlescreen.bin"
; ubyte success = cx16.vload(filename, 8, 0, $0000)