mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
fix inlining subroutines multiple times
This commit is contained in:
parent
9e2b8a2aa9
commit
d582d1cc42
6
.idea/compiler.xml
generated
Normal file
6
.idea/compiler.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="CompilerConfiguration">
|
||||||
|
<option name="BUILD_PROCESS_HEAP_SIZE" value="1200" />
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -96,7 +96,7 @@ fun compileProgram(filepath: Path,
|
|||||||
importedFiles = imported
|
importedFiles = imported
|
||||||
processAst(programAst, errors, compilationOptions)
|
processAst(programAst, errors, compilationOptions)
|
||||||
if (compilationOptions.optimize)
|
if (compilationOptions.optimize)
|
||||||
optimizeAst(programAst, errors, BuiltinFunctionsFacade(BuiltinFunctions), compTarget)
|
optimizeAst(programAst, errors, BuiltinFunctionsFacade(BuiltinFunctions), compTarget, compilationOptions)
|
||||||
postprocessAst(programAst, errors, compilationOptions)
|
postprocessAst(programAst, errors, compilationOptions)
|
||||||
|
|
||||||
// printAst(programAst)
|
// printAst(programAst)
|
||||||
@ -253,7 +253,7 @@ private fun processAst(programAst: Program, errors: IErrorReporter, compilerOpti
|
|||||||
errors.report()
|
errors.report()
|
||||||
programAst.addTypecasts(errors)
|
programAst.addTypecasts(errors)
|
||||||
errors.report()
|
errors.report()
|
||||||
programAst.variousCleanups(programAst, errors, compilerOptions)
|
programAst.variousCleanups(errors)
|
||||||
errors.report()
|
errors.report()
|
||||||
programAst.checkValid(compilerOptions, errors, compilerOptions.compTarget)
|
programAst.checkValid(compilerOptions, errors, compilerOptions.compTarget)
|
||||||
errors.report()
|
errors.report()
|
||||||
@ -261,7 +261,7 @@ private fun processAst(programAst: Program, errors: IErrorReporter, compilerOpti
|
|||||||
errors.report()
|
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
|
// optimize the parse tree
|
||||||
println("Optimizing...")
|
println("Optimizing...")
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -275,16 +275,24 @@ private fun optimizeAst(programAst: Program, errors: IErrorReporter, functions:
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
val remover = UnusedCodeRemover(programAst, errors, compTarget, ::loadAsmIncludeFile)
|
val inliner = SubroutineInliner(programAst, errors, options)
|
||||||
remover.visit(programAst)
|
inliner.visit(programAst)
|
||||||
remover.applyModifications()
|
errors.report()
|
||||||
|
if(errors.noErrors()) {
|
||||||
|
inliner.applyModifications()
|
||||||
|
inliner.fixCallsToInlinedSubroutines()
|
||||||
|
val remover = UnusedCodeRemover(programAst, errors, compTarget, ::loadAsmIncludeFile)
|
||||||
|
remover.visit(programAst)
|
||||||
|
remover.applyModifications()
|
||||||
|
}
|
||||||
|
|
||||||
errors.report()
|
errors.report()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun postprocessAst(programAst: Program, errors: IErrorReporter, compilerOptions: CompilationOptions) {
|
private fun postprocessAst(programAst: Program, errors: IErrorReporter, compilerOptions: CompilationOptions) {
|
||||||
programAst.addTypecasts(errors)
|
programAst.addTypecasts(errors)
|
||||||
errors.report()
|
errors.report()
|
||||||
programAst.variousCleanups(programAst, errors, compilerOptions)
|
programAst.variousCleanups(errors)
|
||||||
programAst.checkValid(compilerOptions, errors, compilerOptions.compTarget) // check if final tree is still valid
|
programAst.checkValid(compilerOptions, errors, compilerOptions.compTarget) // check if final tree is still valid
|
||||||
errors.report()
|
errors.report()
|
||||||
val callGraph = CallGraph(programAst, ::loadAsmIncludeFile)
|
val callGraph = CallGraph(programAst, ::loadAsmIncludeFile)
|
||||||
|
@ -56,8 +56,8 @@ internal fun Program.checkIdentifiers(errors: IErrorReporter, compTarget: ICompi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Program.variousCleanups(program: Program, errors: IErrorReporter, options: CompilationOptions) {
|
internal fun Program.variousCleanups(errors: IErrorReporter) {
|
||||||
val process = VariousCleanups(program, errors, options)
|
val process = VariousCleanups(errors)
|
||||||
process.visit(this)
|
process.visit(this)
|
||||||
if(errors.noErrors())
|
if(errors.noErrors())
|
||||||
process.applyModifications()
|
process.applyModifications()
|
||||||
|
@ -3,19 +3,16 @@ package prog8.compiler.astprocessing
|
|||||||
import prog8.ast.IFunctionCall
|
import prog8.ast.IFunctionCall
|
||||||
import prog8.ast.INameScope
|
import prog8.ast.INameScope
|
||||||
import prog8.ast.Node
|
import prog8.ast.Node
|
||||||
import prog8.ast.Program
|
|
||||||
import prog8.ast.base.FatalAstException
|
import prog8.ast.base.FatalAstException
|
||||||
import prog8.ast.base.Position
|
import prog8.ast.base.Position
|
||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
import prog8.ast.walk.AstWalker
|
import prog8.ast.walk.AstWalker
|
||||||
import prog8.ast.walk.IAstModification
|
import prog8.ast.walk.IAstModification
|
||||||
import prog8.compiler.CompilationOptions
|
|
||||||
import prog8.compiler.IErrorReporter
|
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<IAstModification>()
|
private val noModifications = emptyList<IAstModification>()
|
||||||
|
|
||||||
override fun before(nopStatement: NopStatement, parent: Node): Iterable<IAstModification> {
|
override fun before(nopStatement: NopStatement, parent: Node): Iterable<IAstModification> {
|
||||||
@ -58,33 +55,24 @@ internal class VariousCleanups(private val program: Program, val errors: IErrorR
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun before(functionCall: IFunctionCall, parent: Node, position: Position): Iterable<IAstModification> {
|
private fun before(functionCall: IFunctionCall, parent: Node, position: Position): Iterable<IAstModification> {
|
||||||
|
|
||||||
val modifications = mutableListOf<IAstModification>()
|
|
||||||
|
|
||||||
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")) {
|
if(functionCall.target.nameInSource==listOf("peek")) {
|
||||||
// peek(a) is synonymous with @(a)
|
// peek(a) is synonymous with @(a)
|
||||||
val memread = DirectMemoryRead(functionCall.args.single(), position)
|
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")) {
|
if(functionCall.target.nameInSource==listOf("poke")) {
|
||||||
// poke(a, v) is synonymous with @(a) = v
|
// poke(a, v) is synonymous with @(a) = v
|
||||||
val tgt = AssignTarget(null, null, DirectMemoryWrite(functionCall.args[0], position), position)
|
val tgt = AssignTarget(null, null, DirectMemoryWrite(functionCall.args[0], position), position)
|
||||||
val assign = Assignment(tgt, functionCall.args[1], 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<IAstModification> {
|
||||||
|
if(subroutine.parent!==parent)
|
||||||
|
throw FatalAstException("parent node mismatch at $subroutine")
|
||||||
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun after(assignment: Assignment, parent: Node): Iterable<IAstModification> {
|
override fun after(assignment: Assignment, parent: Node): Iterable<IAstModification> {
|
||||||
@ -128,61 +116,4 @@ internal class VariousCleanups(private val program: Program, val errors: IErrorR
|
|||||||
throw FatalAstException("parent node mismatch at $identifier")
|
throw FatalAstException("parent node mismatch at $identifier")
|
||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun annotateInlinedSubroutineIdentifiers(sub: Subroutine): Pair<List<IAstModification>, 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<IAstModification> {
|
|
||||||
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<IAstModification> {
|
|
||||||
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<IAstModification> {
|
|
||||||
numReturns++
|
|
||||||
if(parent !== sub || sub.indexOfChild(returnStmt)<sub.statements.size-1)
|
|
||||||
errors.err("return statement must be the very last statement in the inlined subroutine", sub.position)
|
|
||||||
return noModifications
|
|
||||||
}
|
|
||||||
|
|
||||||
fun theModifications(): List<IAstModification> {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
109
compiler/src/prog8/optimizer/SubroutineInliner.kt
Normal file
109
compiler/src/prog8/optimizer/SubroutineInliner.kt
Normal file
@ -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<IAstModification>()
|
||||||
|
private var callsToInlinedSubroutines = mutableListOf<Pair<IFunctionCall, Node>>()
|
||||||
|
|
||||||
|
fun fixCallsToInlinedSubroutines() {
|
||||||
|
for((call, parent) in callsToInlinedSubroutines) {
|
||||||
|
val sub = call.target.targetSubroutine(program)!!
|
||||||
|
val intermediateReturnValueVar = sub.statements.filterIsInstance<VarDecl>().singleOrNull { it.name.endsWith(retvarName) }
|
||||||
|
if(intermediateReturnValueVar!=null) {
|
||||||
|
val scope = parent.definingScope()
|
||||||
|
if(!scope.statements.filterIsInstance<VarDecl>().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<IAstModification> {
|
||||||
|
return if(compilerOptions.optimize && subroutine.inline && !subroutine.isAsmSubroutine)
|
||||||
|
annotateInlinedSubroutineIdentifiers(subroutine)
|
||||||
|
else
|
||||||
|
noModifications
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun after(functionCallStatement: FunctionCallStatement, parent: Node): Iterable<IAstModification> {
|
||||||
|
return after(functionCallStatement as IFunctionCall, parent, functionCallStatement.position)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun after(functionCall: FunctionCall, parent: Node): Iterable<IAstModification> {
|
||||||
|
return after(functionCall as IFunctionCall, parent, functionCall.position)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun after(functionCall: IFunctionCall, parent: Node, position: Position): Iterable<IAstModification> {
|
||||||
|
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<IAstModification> {
|
||||||
|
// 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<IAstModification> {
|
||||||
|
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<IAstModification> {
|
||||||
|
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<IAstModification> {
|
||||||
|
numReturns++
|
||||||
|
if(parent !== sub || sub.indexOfChild(returnStmt)<sub.statements.size-1)
|
||||||
|
errors.err("return statement must be the very last statement in the inlined subroutine", sub.position)
|
||||||
|
return noModifications
|
||||||
|
}
|
||||||
|
|
||||||
|
fun theModifications(): List<IAstModification> {
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -658,6 +658,7 @@ class Subroutine(override val name: String,
|
|||||||
override lateinit var parent: Node
|
override lateinit var parent: Node
|
||||||
val asmGenInfo = AsmGenInfo()
|
val asmGenInfo = AsmGenInfo()
|
||||||
val scopedname: String by lazy { makeScopedName(name) }
|
val scopedname: String by lazy { makeScopedName(name) }
|
||||||
|
var inlineAnnotated: Boolean = false
|
||||||
|
|
||||||
override fun linkParents(parent: Node) {
|
override fun linkParents(parent: Node) {
|
||||||
this.parent = parent
|
this.parent = parent
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
- fix multiple cals to inlined subroutines
|
|
||||||
|
|
||||||
- allow inlining of subroutines with params
|
- allow inlining of subroutines with params
|
||||||
- optimize several inner loops in gfx2
|
- 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)
|
- 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)
|
||||||
|
415
examples/cx16/multipalette.p8
Normal file
415
examples/cx16/multipalette.p8
Normal file
@ -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))
|
||||||
|
}
|
||||||
|
}
|
@ -6,9 +6,14 @@ main {
|
|||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
ubyte thing = otherblock.othersub()
|
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(thing) ; should print 41!
|
||||||
;txt.print_ub(thing2) ; should print 41!
|
|
||||||
|
|
||||||
; str filename = "titlescreen.bin"
|
; str filename = "titlescreen.bin"
|
||||||
; ubyte success = cx16.vload(filename, 8, 0, $0000)
|
; ubyte success = cx16.vload(filename, 8, 0, $0000)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user