more forloop asm

This commit is contained in:
Irmen de Jong 2019-08-24 16:21:05 +02:00
parent 9edc92ec29
commit 5e854c2cf8
5 changed files with 559 additions and 216 deletions

View File

@ -43,7 +43,7 @@ dependencies {
compileKotlin {
kotlinOptions {
jvmTarget = "1.8"
verbose = true
// verbose = true
// freeCompilerArgs += "-XXLanguage:+NewInference"
}
}

View File

@ -8,10 +8,14 @@ import prog8.ast.expressions.RangeExpr
import prog8.ast.statements.AssignTarget
import prog8.ast.statements.Assignment
import prog8.ast.statements.ForLoop
import prog8.compiler.target.c64.MachineDefinition
import prog8.compiler.target.c64.MachineDefinition.ESTACK_LO_HEX
import prog8.compiler.target.c64.MachineDefinition.ESTACK_LO_PLUS1_HEX
import prog8.compiler.target.c64.MachineDefinition.ESTACK_HI_PLUS1_HEX
import prog8.compiler.toHex
import kotlin.math.absoluteValue
// todo choose more efficient comparisons to avoid needless lda's
internal class ForLoopsAsmGen(private val program: Program, private val asmgen: AsmGen) {
@ -25,8 +29,6 @@ internal class ForLoopsAsmGen(private val program: Program, private val asmgen:
if(range==null) {
translateForOverNonconstRange(stmt, iterableDt.typeOrElse(DataType.STRUCT), stmt.iterable as RangeExpr)
} else {
if (range.isEmpty())
throw AssemblyError("empty range")
translateForOverConstRange(stmt, iterableDt.typeOrElse(DataType.STRUCT), range)
}
}
@ -41,68 +43,132 @@ internal class ForLoopsAsmGen(private val program: Program, private val asmgen:
val loopLabel = asmgen.makeLabel("for_loop")
val endLabel = asmgen.makeLabel("for_end")
val continueLabel = asmgen.makeLabel("for_continue")
val counterLabel = asmgen.makeLabel("for_counter")
asmgen.loopEndLabels.push(endLabel)
asmgen.loopContinueLabels.push(continueLabel)
val stepsize=range.step.constValue(program)?.number
when (stepsize) {
1 -> {
when(iterableDt) {
DataType.ARRAY_B, DataType.ARRAY_UB -> {
if (stmt.loopRegister != null) {
// loop register over range
if(stmt.loopRegister!= Register.A)
throw AssemblyError("can only use A")
asmgen.translateExpression(range.to)
asmgen.translateExpression(range.from)
asmgen.out("""
inx
lda ${MachineDefinition.ESTACK_LO_HEX},x
sta $loopLabel+1
inx
lda ${MachineDefinition.ESTACK_LO_HEX},x
sec
sbc $loopLabel+1
adc #0
sta $counterLabel
$loopLabel lda #0 ; modified""")
asmgen.translate(stmt.body)
asmgen.out("""
$continueLabel dec $counterLabel
beq $endLabel
inc $loopLabel+1
jmp $loopLabel
$counterLabel .byte 0
$endLabel""")
} else {
// loop over byte range via loopvar
val varname = asmgen.asmIdentifierName(stmt.loopVar!!)
asmgen.translateExpression(range.to)
asmgen.translateExpression(range.from)
asmgen.out("""
inx
lda ${MachineDefinition.ESTACK_LO_HEX},x
sta $varname
inx
lda ${MachineDefinition.ESTACK_LO_HEX},x
sec
sbc $varname
adc #0
sta $counterLabel
$loopLabel""")
asmgen.translate(stmt.body)
asmgen.out("""
$continueLabel dec $counterLabel
beq $endLabel
inc $varname
jmp $loopLabel
$counterLabel .byte 0
$endLabel""")
}
}
DataType.ARRAY_UW, DataType.ARRAY_W -> {
val stepsize=range.step.constValue(program)!!.number.toInt()
when(iterableDt) {
DataType.ARRAY_B, DataType.ARRAY_UB -> {
if (stepsize==1 || stepsize==-1) {
// bytes, step 1 or -1
val incdec = if(stepsize==1) "inc" else "dec"
if (stmt.loopRegister != null) {
// loop register over range
if(stmt.loopRegister!= Register.A)
throw AssemblyError("can only use A")
asmgen.translateExpression(range.to)
asmgen.translateExpression(range.from)
asmgen.out("""
inx
lda ${ESTACK_LO_HEX},x
sta $loopLabel+1
$loopLabel lda #0 ; modified""")
asmgen.translate(stmt.body)
asmgen.out("""
$continueLabel lda $loopLabel+1
cmp $ESTACK_LO_PLUS1_HEX,x
beq $endLabel
$incdec $loopLabel+1
jmp $loopLabel
$endLabel inx""")
} else {
// loop over byte range via loopvar
val varname = asmgen.asmIdentifierName(stmt.loopVar!!)
asmgen.translateExpression(range.to)
asmgen.translateExpression(range.from)
asmgen.out("""
inx
lda ${ESTACK_LO_HEX},x
sta $varname
$loopLabel""")
asmgen.translate(stmt.body)
asmgen.out("""
$continueLabel lda $varname
cmp $ESTACK_LO_PLUS1_HEX,x
beq $endLabel
$incdec $varname
jmp $loopLabel
$endLabel inx""")
}
}
else {
// bytes, step >= 2 or <= -2
if (stmt.loopRegister != null) {
// loop register over range
if(stmt.loopRegister!= Register.A)
throw AssemblyError("can only use A")
asmgen.translateExpression(range.to)
asmgen.translateExpression(range.from)
asmgen.out("""
inx
lda ${ESTACK_LO_HEX},x
sta $loopLabel+1
$loopLabel lda #0 ; modified""")
asmgen.translate(stmt.body)
asmgen.out("""
$continueLabel lda $loopLabel+1""")
if(stepsize>0) {
asmgen.out("""
clc
adc #$stepsize
sta $loopLabel+1
cmp $ESTACK_LO_PLUS1_HEX,x
bcc $loopLabel
beq $loopLabel""")
} else {
asmgen.out("""
sec
sbc #${stepsize.absoluteValue}
sta $loopLabel+1
cmp $ESTACK_LO_PLUS1_HEX,x
bcs $loopLabel""")
}
asmgen.out("""
$endLabel inx""")
} else {
// loop over byte range via loopvar
val varname = asmgen.asmIdentifierName(stmt.loopVar!!)
asmgen.translateExpression(range.to)
asmgen.translateExpression(range.from)
asmgen.out("""
inx
lda ${ESTACK_LO_HEX},x
sta $varname
$loopLabel""")
asmgen.translate(stmt.body)
asmgen.out("""
$continueLabel lda $varname""")
if(stepsize>0) {
asmgen.out("""
clc
adc #$stepsize
sta $varname
cmp $ESTACK_LO_PLUS1_HEX,x
bcc $loopLabel
beq $loopLabel""")
} else {
asmgen.out("""
sec
sbc #${stepsize.absoluteValue}
sta $varname
cmp $ESTACK_LO_PLUS1_HEX,x
bcs $loopLabel""")
}
asmgen.out("""
$endLabel inx""")
}
}
}
DataType.ARRAY_W, DataType.ARRAY_UW -> {
when {
// words, step 1 or -1
stepsize == 1 || stepsize == -1 -> {
asmgen.translateExpression(range.to)
asmgen.out(" inc ${MachineDefinition.ESTACK_LO_HEX}+1,x | bne + | inc ${MachineDefinition.ESTACK_HI_HEX}+1,x |+ ")
val varname = asmgen.asmIdentifierName(stmt.loopVar!!)
val assignLoopvar = Assignment(AssignTarget(null, stmt.loopVar, null, null, stmt.loopVar!!.position),
null, range.from, range.position)
@ -111,81 +177,34 @@ $endLabel""")
asmgen.out(loopLabel)
asmgen.translate(stmt.body)
asmgen.out("""
inc $varname
lda $varname+1
cmp $ESTACK_HI_PLUS1_HEX,x
bne +
lda $varname
cmp $ESTACK_LO_PLUS1_HEX,x
beq $endLabel""")
if(stepsize==1) {
asmgen.out("""
+ inc $varname
bne +
inc $varname+1
+ lda ${MachineDefinition.ESTACK_HI_HEX}+1,x
cmp $varname+1
""")
} else {
asmgen.out("""
+ lda $varname
bne +
lda ${MachineDefinition.ESTACK_LO_HEX}+1,x
cmp $varname
beq $endLabel
dec $varname+1
+ dec $varname""")
}
asmgen.out("""
+ jmp $loopLabel
$endLabel inx""")
}
else -> throw AssemblyError("range expression can only be byte or word")
}
}
-1 -> {
when(iterableDt){
DataType.ARRAY_B, DataType.ARRAY_UB -> {
if (stmt.loopRegister != null) {
// loop register over range
if(stmt.loopRegister!= Register.A)
throw AssemblyError("can only use A")
asmgen.translateExpression(range.from)
asmgen.translateExpression(range.to)
asmgen.out("""
inx
lda ${MachineDefinition.ESTACK_LO_HEX}+1,x
sta $loopLabel+1
sec
sbc ${MachineDefinition.ESTACK_LO_HEX},x
adc #0
sta $counterLabel
inx
$loopLabel lda #0 ; modified""")
asmgen.translate(stmt.body)
asmgen.out("""
$continueLabel dec $counterLabel
beq $endLabel
dec $loopLabel+1
jmp $loopLabel
$counterLabel .byte 0
$endLabel""")
} else {
// loop over byte range via loopvar
val varname = asmgen.asmIdentifierName(stmt.loopVar!!)
asmgen.translateExpression(range.from)
asmgen.translateExpression(range.to)
asmgen.out("""
inx
lda ${MachineDefinition.ESTACK_LO_HEX}+1,x
sta $varname
sec
sbc ${MachineDefinition.ESTACK_LO_HEX},x
adc #0
sta $counterLabel
inx
$loopLabel""")
asmgen.translate(stmt.body)
asmgen.out("""
$continueLabel dec $counterLabel
beq $endLabel
dec $varname
jmp $loopLabel
$counterLabel .byte 0
$endLabel""")
}
}
DataType.ARRAY_UW, DataType.ARRAY_W -> {
stepsize > 0 -> {
// (u)words, step >= 2
asmgen.translateExpression(range.to)
asmgen.out("""
lda ${MachineDefinition.ESTACK_LO_HEX}+1,x
bne +
dec ${MachineDefinition.ESTACK_HI_HEX}+1,x
+ dec ${MachineDefinition.ESTACK_LO_HEX}+1,x
""")
val varname = asmgen.asmIdentifierName(stmt.loopVar!!)
val assignLoopvar = Assignment(AssignTarget(null, stmt.loopVar, null, null, stmt.loopVar!!.position),
null, range.from, range.position)
@ -193,29 +212,97 @@ $endLabel""")
asmgen.translate(assignLoopvar)
asmgen.out(loopLabel)
asmgen.translate(stmt.body)
asmgen.out("""
if (iterableDt == DataType.ARRAY_UW) {
asmgen.out("""
lda $varname
bne +
dec $varname+1
+ dec $varname
lda ${MachineDefinition.ESTACK_HI_HEX}+1,x
clc
adc #<$stepsize
sta $varname
lda $varname+1
adc #>$stepsize
sta $varname+1
lda $ESTACK_HI_PLUS1_HEX,x
cmp $varname+1
bne +
lda ${MachineDefinition.ESTACK_LO_HEX}+1,x
cmp $varname
beq $endLabel
+ jmp $loopLabel
bcc $endLabel
bne $loopLabel
lda $varname
cmp $ESTACK_LO_PLUS1_HEX,x
bcc $endLabel
bcs $loopLabel
$endLabel inx""")
} else {
asmgen.out("""
lda $varname
clc
adc #<$stepsize
sta $varname
lda $varname+1
adc #>$stepsize
sta $varname+1
lda $ESTACK_LO_PLUS1_HEX,x
cmp $varname
lda $ESTACK_HI_PLUS1_HEX,x
sbc $varname+1
bvc +
eor #$80
+ bpl $loopLabel
$endLabel inx""")
}
}
else -> {
// (u)words, step <= -2
asmgen.translateExpression(range.to)
val varname = asmgen.asmIdentifierName(stmt.loopVar!!)
val assignLoopvar = Assignment(AssignTarget(null, stmt.loopVar, null, null, stmt.loopVar!!.position),
null, range.from, range.position)
assignLoopvar.linkParents(stmt)
asmgen.translate(assignLoopvar)
asmgen.out(loopLabel)
asmgen.translate(stmt.body)
if(iterableDt==DataType.ARRAY_UW) {
asmgen.out("""
lda $varname
sec
sbc #<${stepsize.absoluteValue}
sta $varname
lda $varname+1
sbc #>${stepsize.absoluteValue}
sta $varname+1
cmp $ESTACK_HI_PLUS1_HEX,x
bcc $endLabel
bne $loopLabel
lda $varname
cmp $ESTACK_LO_PLUS1_HEX,x
bcs $loopLabel
$endLabel inx""")
} else {
asmgen.out("""
lda $varname
sec
sbc #<${stepsize.absoluteValue}
sta $varname
pha
lda $varname+1
sbc #>${stepsize.absoluteValue}
sta $varname+1
pla
cmp $ESTACK_LO_PLUS1_HEX,x
lda $varname+1
sbc $ESTACK_HI_PLUS1_HEX,x
bvc +
eor #$80
+ bpl $loopLabel
$endLabel inx""")
}
}
else -> throw AssemblyError("range expression can only be byte or word")
}
}
else -> when (iterableDt) {
DataType.ARRAY_UB, DataType.ARRAY_B -> TODO("non-const forloop bytes, step >1: $stepsize")
DataType.ARRAY_UW, DataType.ARRAY_W -> TODO("non-const forloop words, step >1: $stepsize")
else -> throw AssemblyError("range expression can only be byte or word")
}
else -> throw AssemblyError("range expression can only be byte or word")
}
asmgen.loopEndLabels.pop()
asmgen.loopContinueLabels.pop()
}
@ -322,6 +409,8 @@ $endLabel""")
private fun translateForOverConstRange(stmt: ForLoop, iterableDt: DataType, range: IntProgression) {
// TODO: optimize loop code when the range is < 256 iterations, don't need a separate counter in such cases
if (range.isEmpty())
throw AssemblyError("empty range")
val loopLabel = asmgen.makeLabel("for_loop")
val endLabel = asmgen.makeLabel("for_end")
val continueLabel = asmgen.makeLabel("for_continue")
@ -544,11 +633,59 @@ $endLabel""")
}
range.step >= 2 -> {
// word, step >= 2
TODO("for, word, step>=2")
// note: range.last has already been adjusted by kotlin itself to actually be the last value of the sequence
val lastValue = range.last+range.step
asmgen.out("""
lda #<${range.first}
ldy #>${range.first}
sta $varname
sty $varname+1
$loopLabel""")
asmgen.translate(stmt.body)
asmgen.out("""
$continueLabel clc
lda $varname
adc #<${range.step}
sta $varname
lda $varname+1
adc #>${range.step}
sta $varname+1
lda $varname
cmp #<$lastValue
bne +
lda $varname+1
cmp #>$lastValue
beq $endLabel
+ jmp $loopLabel
$endLabel""")
}
else -> {
// step <= -2
TODO("for, word, step<=-2")
// note: range.last has already been adjusted by kotlin itself to actually be the last value of the sequence
val lastValue = range.last+range.step
asmgen.out("""
lda #<${range.first}
ldy #>${range.first}
sta $varname
sty $varname+1
$loopLabel""")
asmgen.translate(stmt.body)
asmgen.out("""
$continueLabel sec
lda $varname
sbc #<${range.step.absoluteValue}
sta $varname
lda $varname+1
sbc #>${range.step.absoluteValue}
sta $varname+1
lda $varname
cmp #<$lastValue
bne +
lda $varname+1
cmp #>$lastValue
beq $endLabel
+ jmp $loopLabel
$endLabel""")
}
}
}

View File

@ -106,6 +106,39 @@ main {
else
c64scr.print("error in -222>=-222!\n")
v1 = 1000
v2 = 1000
if v1==v2
c64scr.print("ok: 1000 == 1000\n")
else
c64scr.print("error in 1000==1000!\n")
if v1!=v2
c64scr.print("error in 1000!=1000!\n")
else
c64scr.print("ok: 1000 is not != 1000\n")
if v1<v2
c64scr.print("error in 1000<1000!\n")
else
c64scr.print("ok: 1000 is not < 1000\n")
if v1<=v2
c64scr.print("ok: 1000 <= 1000\n")
else
c64scr.print("error in 1000<=1000!\n")
if v1>v2
c64scr.print("error in 1000>1000!\n")
else
c64scr.print("ok: 1000 is not > 1000\n")
if v1>=v2
c64scr.print("ok: 1000 >= 1000\n")
else
c64scr.print("error in 1000>=1000!\n")
ubyte endX = X
if endX == 255
c64scr.print("stack x ok!\n")

View File

@ -1,90 +1,263 @@
%import c64lib
%import c64utils
%import c64flt
%zeropage basicsafe
; TODO implement asm generation for all loops here
main {
str str1 = "irmen"
str str2 = "test"
str_s strs1 = "irmen"
str_s strs2 = "test"
sub start() {
str str1x = "irmen"
str str2x = "test"
str_s strs1x = "irmen"
str_s strs2x = "test"
byte bvar
ubyte var2
c64scr.print(str1)
c64.CHROUT('\n')
c64scr.print(str2)
c64.CHROUT('\n')
c64scr.print(str1x)
c64.CHROUT('\n')
c64scr.print(str2x)
c64.CHROUT('\n')
ubyte[] barr = [22,33,44,55,66]
word[] warr = [-111,222,-333,444]
str1[0]='a'
str2[0]='a'
str1x[0]='a'
str2x[0]='a'
strs1x[0]='a'
strs2x[0]='a'
strs1[0]='a'
strs2[0]='a'
c64scr.print(str1)
c64.CHROUT('\n')
c64scr.print(str2)
c64.CHROUT('\n')
c64scr.print(str1x)
c64.CHROUT('\n')
c64scr.print(str2x)
c64.CHROUT('\n')
byte[] barr = [1,2,3]
word[] warr = [1000,2000,3000]
float[] farr = [1.1, 2.2, 3.3]
; for A in "hello" {
; c64scr.print_ub(A)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for A in [1,3,5,99] {
; c64scr.print_ub(A)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for A in 10 to 20 {
; c64scr.print_ub(A)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for A in 20 to 10 step -1 {
; c64scr.print_ub(A)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for A in 10 to 21 step 3 {
; c64scr.print_ub(A)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for A in 24 to 10 step -3 {
; c64scr.print_ub(A)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for A in barr {
; c64scr.print_ub(A)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
; c64.CHROUT('\n')
;
; ubyte cc
; for cc in "hello" {
; c64scr.print_ub(cc)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for cc in [1,3,5,99] {
; c64scr.print_ub(cc)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for cc in 10 to 20 {
; c64scr.print_ub(cc)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for cc in 20 to 10 step -1 {
; c64scr.print_ub(cc)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for cc in 10 to 21 step 3 {
; c64scr.print_ub(cc)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for cc in 24 to 10 step -3 {
; c64scr.print_ub(cc)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for cc in barr {
; c64scr.print_ub(cc)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
; c64.CHROUT('\n')
;
; uword uw
; for uw in [1111, 2222, 3333] {
; c64scr.print_uw(uw)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for ww in warr {
; c64scr.print_w(ww)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for uw in 1111 to 1117 {
; c64scr.print_uw(uw)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for uw in 2000 to 1995 step -1 {
; c64scr.print_uw(uw)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for uw in 1111 to 50000 step 4444 {
; c64scr.print_uw(uw)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
word endw1 = 999
uword enduw1 = 2600
word endw2 = -999
byte endb1 = 100
byte endb2 = -100
byte bb
word ww
float ff
for bb in barr {
c64scr.print_b(bb)
c64.CHROUT(',')
}
c64.CHROUT('\n')
for ww in warr {
uword uw
ubyte ub
ubyte ubb
; for A in 95 to endb1 step 1 {
; c64scr.print_ub(A)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for bb in 95 to endb1 step 1 {
; c64scr.print_b(bb)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for A in endb1 to 95 step -1 {
; c64scr.print_ub(A)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for bb in -95 to endb2 step -1 {
; c64scr.print_b(bb)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; c64.CHROUT('\n')
;
; for ww in 995 to endw1 step 1 {
; c64scr.print_w(ww)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for ww in -995 to endw2 step -1 {
; c64scr.print_w(ww)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
; c64.CHROUT('\n')
;
; for A in 90 to endb1 step 3 {
; c64scr.print_ub(A)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for bb in 90 to endb1 step 3 {
; c64scr.print_b(bb)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; ubb = 10
; for A in 20 to ubb step -3 {
; c64scr.print_ub(A)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for bb in -90 to endb2 step -3 {
; c64scr.print_b(bb)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
; c64.CHROUT('\n')
;
; for uw in 999 to enduw1 step 500 {
; c64scr.print_uw(uw)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for uw in enduw1 to 999 step -500 {
; c64scr.print_uw(uw)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
for ww in -999 to endw1 step 500 { ; TODO fix loop asm
c64scr.print_w(ww)
c64.CHROUT(',')
}
c64.CHROUT('\n')
for bb in 0 to len(farr)-1 {
c64flt.print_f(farr[bb])
c64.CHROUT(',')
}
c64.CHROUT('\n')
barr[0] = 99
warr[0] = 99
farr[0] = 99.9
for bb in barr {
c64scr.print_b(bb)
c64.CHROUT(',')
}
c64.CHROUT('\n')
for ww in warr {
; for ww in 999 to endw2 step -500 {
; c64scr.print_w(ww)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
; c64.CHROUT('\n')
;
; enduw1 = 2000
; for uw in 500 to enduw1 step 500 {
; c64scr.print_uw(uw)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
;
; for uw in enduw1 to 500 step -500 {
; c64scr.print_uw(uw)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
endw1 = 1000
for ww in -1000 to endw1 step 500 { ; TODO fix loop asm
c64scr.print_w(ww)
c64.CHROUT(',')
}
c64.CHROUT('\n')
for bb in 0 to len(farr)-1 {
c64flt.print_f(farr[bb])
for ww in 3000 to endw1 step -500 {
c64scr.print_w(ww)
c64.CHROUT(',')
}
c64.CHROUT('\n')
c64.CHROUT('\n')
ubb=X
c64scr.print_ub(ubb)
}
}

View File

@ -4,4 +4,4 @@ org.gradle.parallel=true
org.gradle.jvmargs=-Xmx2500M
org.gradle.daemon=true
kotlinVersion=1.3.41
kotlinVersion=1.3.50