mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 01:29:28 +00:00
finalized zeropage variable allocation
This commit is contained in:
parent
0219c69446
commit
7459896155
@ -41,14 +41,14 @@ fun printWarning(msg: String, position: Position, detailInfo: String?=null) {
|
||||
if(detailInfo==null)
|
||||
print("\n")
|
||||
else
|
||||
println(": $detailInfo")
|
||||
println(": $detailInfo\n")
|
||||
print("\u001b[0m") // normal
|
||||
}
|
||||
|
||||
fun printWarning(msg: String) {
|
||||
print("\u001b[93m") // bright yellow
|
||||
print("Warning: $msg")
|
||||
print("\u001b[0m") // normal
|
||||
print("\u001b[0m\n") // normal
|
||||
}
|
||||
|
||||
private class AstChecker(private val namespace: INameScope,
|
||||
@ -784,7 +784,7 @@ private class AstChecker(private val namespace: INameScope,
|
||||
|
||||
if(target is BuiltinFunctionStatementPlaceholder) {
|
||||
// it's a call to a builtin function.
|
||||
val func = BuiltinFunctions[target.name]!!
|
||||
val func = BuiltinFunctions.getValue(target.name)
|
||||
if(args.size!=func.parameters.size)
|
||||
checkResult.add(SyntaxError("invalid number of arguments", position))
|
||||
else {
|
||||
|
@ -32,7 +32,7 @@ private class DirectedGraph<VT> {
|
||||
println("#vertices: $numVertices")
|
||||
graph.forEach { from, to ->
|
||||
println("$from CALLS:")
|
||||
to.forEach { it -> println(" $it") }
|
||||
to.forEach { println(" $it") }
|
||||
}
|
||||
val cycle = checkForCycle()
|
||||
if(cycle.isNotEmpty()) {
|
||||
|
@ -46,6 +46,8 @@ private class StatementReorderer(private val namespace: INameScope, private val
|
||||
module.statements.removeAll(directives)
|
||||
module.statements.addAll(0, directives)
|
||||
|
||||
// TODO make sure user-defined blocks come BEFORE library blocks
|
||||
|
||||
sortConstantAssignments(module.statements)
|
||||
}
|
||||
|
||||
|
@ -11,49 +11,40 @@ abstract class Zeropage(private val options: CompilationOptions) {
|
||||
private val allocations = mutableMapOf<Int, Pair<String, DataType>>()
|
||||
val free = mutableListOf<Int>() // subclasses must set this to the appropriate free locations.
|
||||
|
||||
val allowedDatatypes = NumericDatatypes
|
||||
|
||||
fun available() = free.size
|
||||
|
||||
fun allocate(name: String, type: DataType) =
|
||||
allocate(VarDecl(VarDeclType.VAR, type, true, null, name, null, Position("",0,0,0)))
|
||||
|
||||
fun allocate(vardecl: VarDecl) : Int {
|
||||
assert(vardecl.name.isEmpty() || !allocations.values.any { it.first==vardecl.name } ) {"same name can't be allocated twice"}
|
||||
assert(vardecl.type== VarDeclType.VAR) {"can only allocate VAR type"}
|
||||
fun allocate(scopedname: String, datatype: DataType, position: Position?): Int {
|
||||
assert(scopedname.isEmpty() || !allocations.values.any { it.first==scopedname } ) {"same scopedname can't be allocated twice"}
|
||||
|
||||
val size =
|
||||
if(vardecl.arrayspec!=null) {
|
||||
printWarning("allocating a large value (arrayspec) in zeropage", vardecl.position)
|
||||
when(vardecl.datatype) {
|
||||
DataType.UBYTE, DataType.BYTE -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!!
|
||||
DataType.UWORD, DataType.UWORD -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!! * 2
|
||||
DataType.FLOAT -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!! * 5
|
||||
else -> throw CompilerException("array can only be of byte, word, float")
|
||||
}
|
||||
} else {
|
||||
when (vardecl.datatype) {
|
||||
when (datatype) {
|
||||
DataType.UBYTE, DataType.BYTE -> 1
|
||||
DataType.UWORD, DataType.WORD -> 2
|
||||
DataType.FLOAT -> {
|
||||
if (options.floats) {
|
||||
printWarning("allocating a large value (float) in zeropage", vardecl.position)
|
||||
if(position!=null)
|
||||
printWarning("allocated a large value (float) in zeropage", position)
|
||||
else
|
||||
printWarning("$scopedname: allocated a large value (float) in zeropage")
|
||||
5
|
||||
} else throw CompilerException("floating point option not enabled")
|
||||
}
|
||||
else -> throw CompilerException("cannot put datatype ${vardecl.datatype} in zeropage")
|
||||
else -> throw CompilerException("cannot put datatype $datatype in zeropage")
|
||||
}
|
||||
}
|
||||
|
||||
if(free.size > 0) {
|
||||
if(size==1) {
|
||||
for(candidate in free.min()!! .. free.max()!!+1) {
|
||||
if(loneByte(candidate))
|
||||
return makeAllocation(candidate, 1, vardecl.datatype, vardecl.name)
|
||||
return makeAllocation(candidate, 1, datatype, scopedname)
|
||||
}
|
||||
return makeAllocation(free[0], 1, vardecl.datatype, vardecl.name)
|
||||
return makeAllocation(free[0], 1, datatype, scopedname)
|
||||
}
|
||||
for(candidate in free.min()!! .. free.max()!!+1) {
|
||||
if (sequentialFree(candidate, size))
|
||||
return makeAllocation(candidate, size, vardecl.datatype, vardecl.name)
|
||||
return makeAllocation(candidate, size, datatype, scopedname)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,10 +45,8 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
||||
if (zpVariables.isNotEmpty()) {
|
||||
for (variable in zpVariables) {
|
||||
try {
|
||||
val address = zeropage.allocate(variable.key, variable.value.type)
|
||||
val address = zeropage.allocate(variable.key, variable.value.type, null)
|
||||
allocatedZeropageVariables[variable.key] = Pair(address, variable.value.type)
|
||||
println("DEBUG: allocated on ZP: $variable @ $address") //TODO
|
||||
block.variablesMarkedForZeropage.remove(variable.key)//TODO weg
|
||||
} catch (x: ZeropageDepletedError) {
|
||||
printWarning(x.toString() + " variable ${variable.key} type ${variable.value.type}")
|
||||
notAllocated++
|
||||
@ -56,7 +54,6 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
||||
}
|
||||
}
|
||||
}
|
||||
println("DEBUG: ${allocatedZeropageVariables.size} variables allocated in Zeropage") // TODO
|
||||
if(notAllocated>0)
|
||||
printWarning("$notAllocated variables marked for Zeropage could not be allocated there")
|
||||
}
|
||||
|
@ -62,6 +62,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
program.blocks.clear()
|
||||
program.blocks.addAll(newblocks)
|
||||
|
||||
val newAllocatedZp = program.allocatedZeropageVariables.map { symname(it.key, null) to it.value}
|
||||
program.allocatedZeropageVariables.clear()
|
||||
program.allocatedZeropageVariables.putAll(newAllocatedZp)
|
||||
|
||||
// make a list of all const floats that are used
|
||||
for(block in program.blocks) {
|
||||
for(ins in block.instructions.filter{it.arg?.type==DataType.FLOAT}) {
|
||||
@ -103,20 +107,27 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
}
|
||||
|
||||
|
||||
private fun symname(scoped: String, block: IntermediateProgram.ProgramBlock): String {
|
||||
private fun symname(scoped: String, block: IntermediateProgram.ProgramBlock?): String {
|
||||
if(' ' in scoped)
|
||||
return scoped
|
||||
|
||||
val blockLocal: Boolean
|
||||
var name = if (scoped.startsWith("${block.shortname}.")) {
|
||||
blockLocal = true
|
||||
scoped.substring(block.shortname.length+1)
|
||||
} else if (scoped.startsWith("block.")) {
|
||||
blockLocal = false
|
||||
scoped
|
||||
} else {
|
||||
blockLocal = false
|
||||
scoped
|
||||
var name = when {
|
||||
block==null -> {
|
||||
blockLocal=true
|
||||
scoped
|
||||
}
|
||||
scoped.startsWith("${block.shortname}.") -> {
|
||||
blockLocal = true
|
||||
scoped.substring(block.shortname.length+1)
|
||||
}
|
||||
scoped.startsWith("block.") -> {
|
||||
blockLocal = false
|
||||
scoped
|
||||
}
|
||||
else -> {
|
||||
blockLocal = false
|
||||
scoped
|
||||
}
|
||||
}
|
||||
name = name.replace("<<<", "prog8_").replace(">>>", "")
|
||||
if(name=="-")
|
||||
@ -203,7 +214,29 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
out("* = ${block.address?.toHex()}")
|
||||
}
|
||||
|
||||
// @TODO allocate variables on the zeropage as long as there is space
|
||||
// deal with zeropage variables
|
||||
for(variable in blk.variables) {
|
||||
val sym = symname(blk.scopedname+"."+variable.key, null)
|
||||
val zpVar = program.allocatedZeropageVariables[sym]
|
||||
if(zpVar==null) {
|
||||
// This var is not on the ZP yet. Attempt to move it there (if it's not a float, those take up too much space)
|
||||
if(variable.value.type in zeropage.allowedDatatypes && variable.value.type != DataType.FLOAT) {
|
||||
try {
|
||||
val address = zeropage.allocate(sym, variable.value.type, null)
|
||||
out("${variable.key} = $address\t; zp ${variable.value.type}")
|
||||
// make sure we add the var to the set of zpvars for this block
|
||||
blk.variablesMarkedForZeropage.add(variable.key)
|
||||
program.allocatedZeropageVariables[sym] = Pair(address, variable.value.type)
|
||||
} catch (x: ZeropageDepletedError) {
|
||||
// leave it as it is.
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// it was already allocated on the zp
|
||||
out("${variable.key} = ${zpVar.first}\t; zp ${zpVar.second}")
|
||||
}
|
||||
}
|
||||
|
||||
out("\n; memdefs and kernel subroutines")
|
||||
memdefs2asm(block)
|
||||
@ -235,7 +268,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
}
|
||||
|
||||
private fun vardecls2asm(block: IntermediateProgram.ProgramBlock) {
|
||||
// these are the non-zeropage variables @todo is this correct now?
|
||||
// these are the non-zeropage variables
|
||||
val sortedVars = block.variables.filter{it.key !in block.variablesMarkedForZeropage}.toList().sortedBy { it.second.type }
|
||||
for (v in sortedVars) {
|
||||
when (v.second.type) {
|
||||
|
@ -25,10 +25,6 @@ const val ESTACK_HI = 0xcf00 // $cf00-$cfff inclusive
|
||||
|
||||
class C64Zeropage(options: CompilationOptions) : Zeropage(options) {
|
||||
|
||||
|
||||
// @todo: actually USE the zero page when allocating variables at code generation time
|
||||
// (ideally, the variables that are used 'most' / inside long loops are allocated in ZP first)
|
||||
|
||||
companion object {
|
||||
const val SCRATCH_B1 = 0x02
|
||||
const val SCRATCH_REG = 0x03 // temp storage for a register
|
||||
|
@ -139,7 +139,7 @@ fun builtinFunctionReturnType(function: String, args: List<IExpression>, namespa
|
||||
throw FatalAstException("function requires one argument which is an arrayspec $function")
|
||||
}
|
||||
|
||||
val func = BuiltinFunctions[function]!!
|
||||
val func = BuiltinFunctions.getValue(function)
|
||||
if(func.returntype!=null)
|
||||
return func.returntype
|
||||
// function has return values, but the return type depends on the arguments
|
||||
|
@ -6,7 +6,6 @@ import prog8.compiler.LauncherType
|
||||
import prog8.compiler.OutputType
|
||||
import prog8.determineCompilationOptions
|
||||
import java.io.InputStream
|
||||
import java.net.URL
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
|
@ -117,36 +117,29 @@ class TestCompiler {
|
||||
}
|
||||
|
||||
|
||||
private val dummypos = Position("test", 0, 0, 0)
|
||||
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class TestZeropage {
|
||||
@Test
|
||||
fun testNames() {
|
||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false))
|
||||
|
||||
zp.allocate("", DataType.UBYTE, null)
|
||||
zp.allocate("", DataType.UBYTE, null)
|
||||
zp.allocate("varname", DataType.UBYTE, null)
|
||||
assertFailsWith<AssertionError> {
|
||||
zp.allocate(VarDecl(VarDeclType.MEMORY, DataType.UBYTE, false, null, "", null, dummypos))
|
||||
zp.allocate("varname", DataType.UBYTE, null)
|
||||
}
|
||||
|
||||
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, "", null, dummypos))
|
||||
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, "", null, dummypos))
|
||||
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, "varname", null, dummypos))
|
||||
assertFailsWith<AssertionError> {
|
||||
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, "varname", null, dummypos))
|
||||
}
|
||||
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, "varname2", null, dummypos))
|
||||
zp.allocate("varname2", DataType.UBYTE, null)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testZpFloatEnable() {
|
||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false))
|
||||
assertFailsWith<CompilerException> {
|
||||
zp.allocate(VarDecl(VarDeclType.VAR, DataType.FLOAT, false, null, "", null, dummypos))
|
||||
zp.allocate("", DataType.FLOAT, null)
|
||||
}
|
||||
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), true))
|
||||
zp2.allocate(VarDecl(VarDeclType.VAR, DataType.FLOAT, false, null, "", null, dummypos))
|
||||
zp2.allocate("", DataType.FLOAT, null)
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -187,22 +180,22 @@ class TestZeropage {
|
||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true))
|
||||
assertEquals(19, zp.available())
|
||||
|
||||
zp.allocate(VarDecl(VarDeclType.VAR, DataType.FLOAT, false, null, "", null, dummypos))
|
||||
zp.allocate("", DataType.FLOAT, null)
|
||||
assertFailsWith<ZeropageDepletedError> {
|
||||
// in regular zp there aren't 5 sequential bytes free after we take the first sequence
|
||||
zp.allocate(VarDecl(VarDeclType.VAR, DataType.FLOAT, false, null, "", null, dummypos))
|
||||
zp.allocate("", DataType.FLOAT, null)
|
||||
}
|
||||
|
||||
for (i in 0 until zp.available()) {
|
||||
val loc = zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, "", null, dummypos))
|
||||
val loc = zp.allocate("", DataType.UBYTE, null)
|
||||
assertTrue(loc > 0)
|
||||
}
|
||||
assertEquals(0, zp.available())
|
||||
assertFailsWith<ZeropageDepletedError> {
|
||||
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, "", null, dummypos))
|
||||
zp.allocate("", DataType.UBYTE, null)
|
||||
}
|
||||
assertFailsWith<ZeropageDepletedError> {
|
||||
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, false, null, "", null, dummypos))
|
||||
zp.allocate("", DataType.UWORD, null)
|
||||
}
|
||||
}
|
||||
|
||||
@ -210,33 +203,33 @@ class TestZeropage {
|
||||
fun testFullAllocation() {
|
||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), true))
|
||||
assertEquals(238, zp.available())
|
||||
val loc = zp.allocate(VarDecl(VarDeclType.VAR, DataType.FLOAT, false, null, "", null, dummypos))
|
||||
val loc = zp.allocate("", DataType.FLOAT, null)
|
||||
assertTrue(loc > 3)
|
||||
assertFalse(loc in zp.free)
|
||||
val num = zp.available() / 5
|
||||
val rest = zp.available() % 5
|
||||
|
||||
for(i in 0..num-4) {
|
||||
zp.allocate(VarDecl(VarDeclType.VAR, DataType.FLOAT, false, null, "", null, dummypos))
|
||||
zp.allocate("", DataType.FLOAT, null)
|
||||
}
|
||||
assertEquals(18,zp.available())
|
||||
|
||||
assertFailsWith<ZeropageDepletedError> {
|
||||
// can't allocate because no more sequential bytes, only fragmented
|
||||
zp.allocate(VarDecl(VarDeclType.VAR, DataType.FLOAT, false, null, "", null, dummypos))
|
||||
zp.allocate("", DataType.FLOAT, null)
|
||||
}
|
||||
|
||||
for(i in 0..13) {
|
||||
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, "", null, dummypos))
|
||||
zp.allocate("", DataType.UBYTE, null)
|
||||
}
|
||||
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, false, null, "", null, dummypos))
|
||||
zp.allocate("", DataType.UWORD, null)
|
||||
|
||||
assertEquals(2, zp.available())
|
||||
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, "", null, dummypos))
|
||||
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, "", null, dummypos))
|
||||
zp.allocate("", DataType.UBYTE, null)
|
||||
zp.allocate("", DataType.UBYTE, null)
|
||||
assertFailsWith<ZeropageDepletedError> {
|
||||
// no more space
|
||||
zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, "", null, dummypos))
|
||||
zp.allocate("", DataType.UBYTE, null)
|
||||
}
|
||||
}
|
||||
|
||||
@ -244,15 +237,15 @@ class TestZeropage {
|
||||
fun testEfficientAllocation() {
|
||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true))
|
||||
assertEquals(19, zp.available())
|
||||
assertEquals(0x04, zp.allocate(VarDecl(VarDeclType.VAR, DataType.FLOAT, false, null, "", null, dummypos)))
|
||||
assertEquals(0x09, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, "", null, dummypos)))
|
||||
assertEquals(0x0d, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, false, null, "", null, dummypos)))
|
||||
assertEquals(0x94, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, false, null, "", null, dummypos)))
|
||||
assertEquals(0xa7, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, false, null, "", null, dummypos)))
|
||||
assertEquals(0xa9, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, false, null, "", null, dummypos)))
|
||||
assertEquals(0xb5, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, false, null, "", null, dummypos)))
|
||||
assertEquals(0xf7, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, false, null, "", null, dummypos)))
|
||||
assertEquals(0xf9, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, "", null, dummypos)))
|
||||
assertEquals(0x04, zp.allocate("", DataType.FLOAT, null))
|
||||
assertEquals(0x09, zp.allocate("", DataType.UBYTE, null))
|
||||
assertEquals(0x0d, zp.allocate("", DataType.UWORD, null))
|
||||
assertEquals(0x94, zp.allocate("", DataType.UWORD, null))
|
||||
assertEquals(0xa7, zp.allocate("", DataType.UWORD, null))
|
||||
assertEquals(0xa9, zp.allocate("", DataType.UWORD, null))
|
||||
assertEquals(0xb5, zp.allocate("", DataType.UWORD, null))
|
||||
assertEquals(0xf7, zp.allocate("", DataType.UWORD, null))
|
||||
assertEquals(0xf9, zp.allocate("", DataType.UBYTE, null))
|
||||
assertEquals(0, zp.available())
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import prog8.ast.LiteralValue
|
||||
import prog8.ast.Position
|
||||
import prog8.compiler.intermediate.Value
|
||||
import prog8.compiler.intermediate.ValueException
|
||||
import prog8.stackvm.VmExecutionException
|
||||
import kotlin.test.*
|
||||
|
||||
|
||||
|
@ -34,16 +34,9 @@ Add more compiler optimizations to the existing ones.
|
||||
Also some library routines and code patterns could perhaps be optimized further
|
||||
|
||||
|
||||
Should use the zeropage for variables
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Variables should be allocated in the zeropage as long as it has space.
|
||||
- add some sort of ``zp`` modifier keyword on vardecls to force them into zeropage?
|
||||
|
||||
|
||||
Misc
|
||||
^^^^
|
||||
|
||||
- sqrt() should have integer implementation as well, instead of relying on float SQRT for all argument types
|
||||
- code generation for POW instruction
|
||||
|
||||
- make sure user-defined blocks come BEFORE library blocks (this helps zeropage variable allocations)
|
||||
|
@ -26,6 +26,7 @@
|
||||
Y++ ; delay for alignment
|
||||
Y++ ; delay for alignment
|
||||
Y++ ; delay for alignment
|
||||
Y++ ; delay for alignment
|
||||
ubyte rasterpos = c64.RASTER
|
||||
if color!=len(colors) {
|
||||
c64.EXTCOL = colors[color]
|
||||
|
@ -56,9 +56,9 @@ sub irq() {
|
||||
c64.EXTCOL--
|
||||
|
||||
; float up & wobble horizontally
|
||||
for ubyte i in 0 to 14 step 2 {
|
||||
for ubyte @zp i in 0 to 14 step 2 {
|
||||
c64.SPXY[i+1]--
|
||||
ubyte r = rnd()
|
||||
ubyte @zp r = rnd()
|
||||
if r>200
|
||||
c64.SPXY[i]++
|
||||
else if r<40
|
||||
|
111
examples/test.p8
111
examples/test.p8
@ -1,102 +1,35 @@
|
||||
%import c64utils
|
||||
%option enable_floats
|
||||
|
||||
~ main {
|
||||
|
||||
ubyte b1 = 42
|
||||
word w = -999
|
||||
|
||||
sub start() {
|
||||
vm_write_num(b1)
|
||||
vm_write_char('\n')
|
||||
vm_write_num(w)
|
||||
vm_write_char('\n')
|
||||
|
||||
; c64scr.print_ub(b1)
|
||||
; c64.CHROUT('\n')
|
||||
; c64scr.print_w(w)
|
||||
; c64.CHROUT('\n')
|
||||
|
||||
b1=0
|
||||
w=0
|
||||
|
||||
vm_write_num(b1)
|
||||
vm_write_char('\n')
|
||||
vm_write_num(w)
|
||||
vm_write_char('\n')
|
||||
|
||||
; c64scr.print_ub(b1)
|
||||
; c64.CHROUT('\n')
|
||||
; c64scr.print_w(w)
|
||||
; c64.CHROUT('\n')
|
||||
derp.derp()
|
||||
|
||||
}
|
||||
}
|
||||
ubyte @zp ub = 22
|
||||
byte @zp b = 22
|
||||
word @zp w = 2222
|
||||
uword @zp uw = 2222
|
||||
|
||||
|
||||
~ derp {
|
||||
|
||||
ubyte b1 = 55
|
||||
|
||||
sub derp() {
|
||||
word w = -999
|
||||
vm_write_num(b1)
|
||||
vm_write_char('\n')
|
||||
vm_write_num(w)
|
||||
vm_write_char('\n')
|
||||
|
||||
; c64scr.print_ub(b1)
|
||||
; c64.CHROUT('\n')
|
||||
; c64scr.print_w(w)
|
||||
; c64.CHROUT('\n')
|
||||
|
||||
b1=0
|
||||
w=0
|
||||
|
||||
vm_write_num(b1)
|
||||
vm_write_char('\n')
|
||||
vm_write_num(w)
|
||||
vm_write_char('\n')
|
||||
|
||||
; c64scr.print_ub(b1)
|
||||
; c64.CHROUT('\n')
|
||||
; c64scr.print_w(w)
|
||||
; c64.CHROUT('\n')
|
||||
|
||||
byte nonzp1 = 42
|
||||
byte nonzp2 = 42
|
||||
byte nonzp3 = 42
|
||||
foo.bar()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
~ foo {
|
||||
|
||||
;~ main {
|
||||
;
|
||||
; sub start() {
|
||||
;
|
||||
; ubyte @zp ub
|
||||
; byte @zp b
|
||||
; word @zp w
|
||||
; uword @zp uw
|
||||
;
|
||||
;
|
||||
; byte nonzp1
|
||||
; byte nonzp2
|
||||
; byte nonzp3
|
||||
; foo.bar()
|
||||
; }
|
||||
;
|
||||
;}
|
||||
;
|
||||
;~ foo {
|
||||
;
|
||||
;sub bar() {
|
||||
; ubyte @zp ub
|
||||
; byte @zp b
|
||||
; word @zp w
|
||||
; uword @zp uw
|
||||
;
|
||||
; word nonzp1
|
||||
; word nonzp2
|
||||
; word nonzp3
|
||||
; A=55
|
||||
;}
|
||||
;}
|
||||
sub bar() {
|
||||
ubyte @zp ub = 33
|
||||
byte @zp b = 33
|
||||
word @zp w = 3333
|
||||
uword @zp uw = 3333
|
||||
|
||||
word nonzp1 = 4444
|
||||
word nonzp2 = 4444
|
||||
word nonzp3 = 4444
|
||||
A=55
|
||||
}
|
||||
}
|
||||
|
@ -53,9 +53,9 @@
|
||||
angle++
|
||||
c64.MSIGX=0
|
||||
|
||||
for ubyte i in 7 to 0 step -1 {
|
||||
uword x = sin8u(angle*2-i*16) as uword + 50
|
||||
ubyte y = cos8u(angle*3-i*16) / 2 + 70
|
||||
for ubyte @zp i in 7 to 0 step -1 {
|
||||
uword @zp x = sin8u(angle*2-i*16) as uword + 50
|
||||
ubyte @zp y = cos8u(angle*3-i*16) / 2 + 70
|
||||
c64.SPXYW[i] = mkword(lsb(x), y)
|
||||
lsl(c64.MSIGX)
|
||||
if msb(x) c64.MSIGX++
|
||||
|
Loading…
Reference in New Issue
Block a user