removed the automatic system reset at program exit, this did't work with the new init code

This commit is contained in:
Irmen de Jong 2020-09-25 22:11:06 +02:00
parent 14d091e60a
commit d7ceda4d82
18 changed files with 43 additions and 133 deletions

View File

@ -251,8 +251,7 @@ asmsub init_system() {
sta c64.COLOR sta c64.COLOR
lda #0 lda #0
sta c64.BGCOL0 sta c64.BGCOL0
tax jsr disable_runstop_and_charsetswitch
tay
clc clc
clv clv
cli cli
@ -272,7 +271,6 @@ asmsub reset_system() {
asmsub disable_runstop_and_charsetswitch() { asmsub disable_runstop_and_charsetswitch() {
%asm {{ %asm {{
lda #$80
lda #$80 lda #$80
sta 657 ; disable charset switching sta 657 ; disable charset switching
lda #239 lda #239

View File

@ -8,7 +8,6 @@ import prog8.ast.expressions.*
import prog8.ast.processing.AstWalker import prog8.ast.processing.AstWalker
import prog8.ast.processing.IAstModification import prog8.ast.processing.IAstModification
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.compiler.target.c64.codegen.programInitializationRoutineName
internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: ErrorReporter) : AstWalker() { internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: ErrorReporter) : AstWalker() {
@ -107,16 +106,6 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: E
&& outerScope !is Block) { && outerScope !is Block) {
mods += IAstModification.InsertAfter(outerStatements[subroutineStmtIdx - 1], returnStmt, outerScope as Node) mods += IAstModification.InsertAfter(outerStatements[subroutineStmtIdx - 1], returnStmt, outerScope as Node)
} }
// if it's the program's start subroutine, insert a call to the initalization logic (if it's not there already)
if(subroutine.name=="start" && subroutine.definingBlock().name=="main") {
val first = subroutine.statements.firstOrNull() as? FunctionCallStatement
if(first==null || first.target.nameInSource != listOf(programInitializationRoutineName)) {
val call = FunctionCallStatement(IdentifierReference(listOf(programInitializationRoutineName), subroutine.position), mutableListOf(), true, subroutine.position)
mods += IAstModification.InsertFirst(call, subroutine)
}
}
return mods return mods
} }

View File

@ -70,12 +70,4 @@ abstract class Zeropage(protected val options: CompilationOptions) {
private fun loneByte(address: Int) = address in free && address-1 !in free && address+1 !in free private fun loneByte(address: Int) = address in free && address-1 !in free && address+1 !in free
private fun sequentialFree(address: Int, size: Int) = free.containsAll((address until address+size).toList()) private fun sequentialFree(address: Int, size: Int) = free.containsAll((address until address+size).toList())
enum class ExitProgramStrategy {
CLEAN_EXIT,
SYSTEM_RESET
}
abstract val exitProgramStrategy: ExitProgramStrategy
} }

View File

@ -17,9 +17,6 @@ internal interface CompilationTarget {
fun encodeString(str: String, altEncoding: Boolean): List<Short> fun encodeString(str: String, altEncoding: Boolean): List<Short>
fun decodeString(bytes: List<Short>, altEncoding: Boolean): String fun decodeString(bytes: List<Short>, altEncoding: Boolean): String
fun asmGenerator(program: Program, errors: ErrorReporter, zp: Zeropage, options: CompilationOptions, path: Path): IAssemblyGenerator fun asmGenerator(program: Program, errors: ErrorReporter, zp: Zeropage, options: CompilationOptions, path: Path): IAssemblyGenerator
val initProcName: String?
val resetProcName: String?
val disableRunStopProcName: String?
companion object { companion object {
lateinit var instance: CompilationTarget lateinit var instance: CompilationTarget
@ -36,9 +33,6 @@ internal object C64Target: CompilationTarget {
if(altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true) if(altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true)
override fun asmGenerator(program: Program, errors: ErrorReporter, zp: Zeropage, options: CompilationOptions, path: Path) = override fun asmGenerator(program: Program, errors: ErrorReporter, zp: Zeropage, options: CompilationOptions, path: Path) =
AsmGen(program, errors, zp, options, path) AsmGen(program, errors, zp, options, path)
override val initProcName = "c64.init_system"
override val resetProcName = "c64.reset_system"
override val disableRunStopProcName = "c64.disable_runstop_and_charsetswitch"
} }
internal object Cx16Target: CompilationTarget { internal object Cx16Target: CompilationTarget {
@ -50,7 +44,4 @@ internal object Cx16Target: CompilationTarget {
if(altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true) if(altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true)
override fun asmGenerator(program: Program, errors: ErrorReporter, zp: Zeropage, options: CompilationOptions, path: Path) = override fun asmGenerator(program: Program, errors: ErrorReporter, zp: Zeropage, options: CompilationOptions, path: Path) =
AsmGen(program, errors, zp, options, path) AsmGen(program, errors, zp, options, path)
override val initProcName = "cx16.init_system"
override val resetProcName = "cx16.reset_system"
override val disableRunStopProcName = null
} }

View File

@ -113,12 +113,6 @@ internal object C64MachineDefinition: IMachineDefinition {
override val SCRATCH_W2 = 0xfd // temp storage 2 for a word $fb+$fc override val SCRATCH_W2 = 0xfd // temp storage 2 for a word $fb+$fc
override val exitProgramStrategy: ExitProgramStrategy = when (options.zeropage) {
ZeropageType.BASICSAFE, ZeropageType.DONTUSE -> ExitProgramStrategy.CLEAN_EXIT
ZeropageType.FLOATSAFE, ZeropageType.KERNALSAFE, ZeropageType.FULL -> ExitProgramStrategy.SYSTEM_RESET
}
init { init {
if (options.floats && options.zeropage !in setOf(ZeropageType.FLOATSAFE, ZeropageType.BASICSAFE, ZeropageType.DONTUSE )) if (options.floats && options.zeropage !in setOf(ZeropageType.FLOATSAFE, ZeropageType.BASICSAFE, ZeropageType.DONTUSE ))
throw CompilerException("when floats are enabled, zero page type should be 'floatsafe' or 'basicsafe' or 'dontuse'") throw CompilerException("when floats are enabled, zero page type should be 'floatsafe' or 'basicsafe' or 'dontuse'")

View File

@ -29,9 +29,6 @@ import java.util.*
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
internal const val programInitializationRoutineName = "prog8_initialize_program"
internal class AsmGen(private val program: Program, internal class AsmGen(private val program: Program,
val errors: ErrorReporter, val errors: ErrorReporter,
val zeropage: Zeropage, val zeropage: Zeropage,
@ -54,12 +51,10 @@ internal class AsmGen(private val program: Program,
private val expressionsAsmGen = ExpressionsAsmGen(program, this) private val expressionsAsmGen = ExpressionsAsmGen(program, this)
internal val loopEndLabels = ArrayDeque<String>() internal val loopEndLabels = ArrayDeque<String>()
private val blockLevelVarInits = mutableMapOf<Block, MutableSet<VarDecl>>() private val blockLevelVarInits = mutableMapOf<Block, MutableSet<VarDecl>>()
private val programInitLines = mutableListOf<String>()
override fun compileToAssembly(optimize: Boolean): IAssemblyProgram { override fun compileToAssembly(optimize: Boolean): IAssemblyProgram {
assemblyLines.clear() assemblyLines.clear()
loopEndLabels.clear() loopEndLabels.clear()
programInitLines.clear()
println("Generating assembly code... ") println("Generating assembly code... ")
@ -126,63 +121,25 @@ internal class AsmGen(private val program: Program,
out(" .null $9e, format(' %d ', _prog8_entrypoint), $3a, $8f, ' prog8 by idj'") out(" .null $9e, format(' %d ', _prog8_entrypoint), $3a, $8f, ' prog8 by idj'")
out("+\t.word 0") out("+\t.word 0")
out("_prog8_entrypoint\t; assembly code starts here\n") out("_prog8_entrypoint\t; assembly code starts here\n")
if(!options.noSysInit && !CompilationTarget.instance.initProcName.isNullOrEmpty()) if(!options.noSysInit)
out(" jsr ${CompilationTarget.instance.initProcName}") out(" jsr ${CompilationTarget.instance.name}.init_system")
} }
options.output == OutputType.PRG -> { options.output == OutputType.PRG -> {
out("; ---- program without basic sys call ----") out("; ---- program without basic sys call ----")
out("* = ${program.actualLoadAddress.toHex()}\n") out("* = ${program.actualLoadAddress.toHex()}\n")
if(!options.noSysInit && !CompilationTarget.instance.initProcName.isNullOrEmpty()) if(!options.noSysInit)
out(" jsr ${CompilationTarget.instance.initProcName}") out(" jsr ${CompilationTarget.instance.name}.init_system")
} }
options.output == OutputType.RAW -> { options.output == OutputType.RAW -> {
out("; ---- raw assembler program ----") out("; ---- raw assembler program ----")
out("* = ${program.actualLoadAddress.toHex()}\n") out("* = ${program.actualLoadAddress.toHex()}\n")
} }
} }
out(" jmp main.start ; start program / force start proc to be included")
if (zeropage.exitProgramStrategy != Zeropage.ExitProgramStrategy.CLEAN_EXIT) { out(" jmp main.start ; start program / force start proc to be included")
if(!CompilationTarget.instance.disableRunStopProcName.isNullOrEmpty())
programInitLines.add(" jsr ${CompilationTarget.instance.disableRunStopProcName}")
}
programInitLines.add(" ; initialize the variables in each block that has globals")
programInitLines.add(" cld")
programInitLines.add(" clv")
program.allBlocks().forEach {
if(it.statements.filterIsInstance<VarDecl>().any { vd->vd.value!=null && vd.type==VarDeclType.VAR && vd.datatype in NumericDatatypes})
programInitLines.add(" jsr ${it.name}.prog8_init_vars")
}
if (zeropage.exitProgramStrategy == Zeropage.ExitProgramStrategy.SYSTEM_RESET) {
// push the reset routine onto the cpu stack so that it is executed when the program does an rts
programInitLines.addAll(listOf(
" tsx",
" lda $0102,x",
" pha",
" lda $0103,x",
" pha",
" lda #>(${CompilationTarget.instance.resetProcName}-1)",
" sta $0102,x",
" lda #<(${CompilationTarget.instance.resetProcName}-1)",
" sta $0103,x",
))
}
programInitLines.add(" ldx #\$ff\t; init estack pointer")
programInitLines.add(" rts")
} }
private fun footer() { private fun footer() {
// the program preamble or initialization code
out("")
out("; program initialization")
out(programInitializationRoutineName)
for(line in programInitLines) {
out(line)
}
out("")
// the global list of all floating point constants for the whole program // the global list of all floating point constants for the whole program
out("; global float constants") out("; global float constants")
for (flt in globalFloatConsts) { for (flt in globalFloatConsts) {
@ -632,25 +589,18 @@ $save .byte 0
is InlineAssembly -> translate(stmt) is InlineAssembly -> translate(stmt)
is FunctionCallStatement -> { is FunctionCallStatement -> {
val functionName = stmt.target.nameInSource.last() val functionName = stmt.target.nameInSource.last()
if(functionName == programInitializationRoutineName) { val builtinFunc = BuiltinFunctions[functionName]
out(""" if (builtinFunc != null) {
tsx builtinFunctionsAsmGen.translateFunctioncallStatement(stmt, builtinFunc)
stx prog8_lib.orig_stackpointer
jsr $functionName""")
} else { } else {
val builtinFunc = BuiltinFunctions[functionName] functioncallAsmGen.translateFunctionCall(stmt)
if (builtinFunc != null) { // discard any results from the stack:
builtinFunctionsAsmGen.translateFunctioncallStatement(stmt, builtinFunc) val sub = stmt.target.targetSubroutine(program.namespace)!!
} else { val returns = sub.returntypes.zip(sub.asmReturnvaluesRegisters)
functioncallAsmGen.translateFunctionCall(stmt) for ((t, reg) in returns) {
// discard any results from the stack: if (reg.stack) {
val sub = stmt.target.targetSubroutine(program.namespace)!! if (t in IntegerDatatypes || t in PassByReferenceDatatypes) out(" inx")
val returns = sub.returntypes.zip(sub.asmReturnvaluesRegisters) else if (t == DataType.FLOAT) out(" inx | inx | inx")
for ((t, reg) in returns) {
if (reg.stack) {
if (t in IntegerDatatypes || t in PassByReferenceDatatypes) out(" inx")
else if (t == DataType.FLOAT) out(" inx | inx | inx")
}
} }
} }
} }
@ -811,6 +761,23 @@ $save .byte 0
out("${sub.name}\t.proc") out("${sub.name}\t.proc")
zeropagevars2asm(sub.statements) zeropagevars2asm(sub.statements)
memdefs2asm(sub.statements) memdefs2asm(sub.statements)
// the main.start subroutine is the program's entrypoint and should perform some initialization logic
if(sub.name=="start" && sub.definingBlock().name=="main") {
out("; program startup initialization")
out(" cld")
program.allBlocks().forEach {
if(it.statements.filterIsInstance<VarDecl>().any { vd->vd.value!=null && vd.type==VarDeclType.VAR && vd.datatype in NumericDatatypes})
out(" jsr ${it.name}.prog8_init_vars")
}
out("""
tsx
stx prog8_lib.orig_stackpointer ; required for func_exit
ldx #255 ; init estack ptr
clv
clc""")
}
out("; statements") out("; statements")
sub.statements.forEach{ translate(it) } sub.statements.forEach{ translate(it) }
out("; variables") out("; variables")

View File

@ -78,13 +78,6 @@ internal object CX16MachineDefinition: IMachineDefinition {
override val SCRATCH_W2 = 0x7e // temp storage 2 for a word $7e+$7f override val SCRATCH_W2 = 0x7e // temp storage 2 for a word $7e+$7f
override val exitProgramStrategy: ExitProgramStrategy = when (options.zeropage) {
ZeropageType.BASICSAFE, ZeropageType.DONTUSE -> ExitProgramStrategy.CLEAN_EXIT
ZeropageType.KERNALSAFE, ZeropageType.FULL -> ExitProgramStrategy.SYSTEM_RESET
else -> ExitProgramStrategy.SYSTEM_RESET
}
init { init {
if (options.floats && options.zeropage !in setOf(ZeropageType.BASICSAFE, ZeropageType.DONTUSE )) if (options.floats && options.zeropage !in setOf(ZeropageType.BASICSAFE, ZeropageType.DONTUSE ))
throw CompilerException("when floats are enabled, zero page type should be 'basicsafe' or 'dontuse'") throw CompilerException("when floats are enabled, zero page type should be 'basicsafe' or 'dontuse'")

View File

@ -67,7 +67,8 @@ Directives
- style ``kernalsafe`` -- use the part of the ZP that is 'free' or only used by BASIC routines, - style ``kernalsafe`` -- use the part of the ZP that is 'free' or only used by BASIC routines,
and don't change anything else. This allows full use of KERNAL ROM routines (but not BASIC routines), and don't change anything else. This allows full use of KERNAL ROM routines (but not BASIC routines),
including default IRQs during normal system operation. including default IRQs during normal system operation.
When the program exits, a system reset is performed (because BASIC will be in a corrupt state). It's not possible to return cleanly to BASIC when the program exits. The only choice is
to perform a system reset. (A ``system_reset`` subroutine is available in the syslib to help you do this)
- style ``floatsafe`` -- like the previous one but also reserves the addresses that - style ``floatsafe`` -- like the previous one but also reserves the addresses that
are required to perform floating point operations (from the BASIC kernel). No clean exit is possible. are required to perform floating point operations (from the BASIC kernel). No clean exit is possible.
- style ``basicsafe`` -- the most restricted mode; only use the handful 'free' addresses in the ZP, and don't - style ``basicsafe`` -- the most restricted mode; only use the handful 'free' addresses in the ZP, and don't
@ -78,9 +79,10 @@ Directives
except the few addresses mentioned above that are used by the system's IRQ routine. except the few addresses mentioned above that are used by the system's IRQ routine.
Even though the default IRQ routine is still active, it is impossible to use most BASIC and KERNAL ROM routines. Even though the default IRQ routine is still active, it is impossible to use most BASIC and KERNAL ROM routines.
This includes many floating point operations and several utility routines that do I/O, such as ``print_string``. This includes many floating point operations and several utility routines that do I/O, such as ``print_string``.
As with ``kernalsafe``, it is not possible to cleanly exit the program, other than to reset the machine.
This option makes programs smaller and faster because even more variables can This option makes programs smaller and faster because even more variables can
be stored in the ZP (which allows for more efficient assembly code). be stored in the ZP (which allows for more efficient assembly code).
It's not possible to return cleanly to BASIC when the program exits. The only choice is
to perform a system reset. (A ``system_reset`` subroutine is available in the syslib to help you do this)
- style ``dontuse`` -- don't use *any* location in the zeropage. - style ``dontuse`` -- don't use *any* location in the zeropage.
Also read :ref:`zeropage`. Also read :ref:`zeropage`.

View File

@ -2,8 +2,6 @@
%import textio %import textio
%import syslib %import syslib
; TODO fix crash it's caused by commit 2b9316c4fff5ef33340676da96a9c7ef57237bc0 reworked program init logic
main { main {
sub start() { sub start() {

View File

@ -3,8 +3,6 @@
; Note: this program is compatible with C64 and CX16. ; Note: this program is compatible with C64 and CX16.
; TODO fix crash
main { main {
; vertices ; vertices

View File

@ -2,8 +2,6 @@
%import syslib %import syslib
%import textio %import textio
; TODO fix crash
spritedata $2000 { spritedata $2000 {
; this memory block contains the sprite data ; this memory block contains the sprite data
; it must start on an address aligned to 64 bytes. ; it must start on an address aligned to 64 bytes.

View File

@ -2,8 +2,6 @@
; Note: this program is compatible with C64 and CX16. ; Note: this program is compatible with C64 and CX16.
; TODO fix crash
main { main {
sub start() { sub start() {

View File

@ -8,9 +8,6 @@
; Note: this program is compatible with C64 and CX16. ; Note: this program is compatible with C64 and CX16.
; TODO fix problem that it freezes or doesn't draw anything anymore
main { main {
const ubyte width = 255 const ubyte width = 255
const ubyte height = 200 const ubyte height = 200

View File

@ -13,8 +13,6 @@
;** ** ;** **
;\*****************************************************************************/ ;\*****************************************************************************/
; TODO fix problem
main { main {
const uword SCREEN1 = $E000 const uword SCREEN1 = $E000

View File

@ -7,8 +7,7 @@
; staged speed increase ; staged speed increase
; some simple sound effects ; some simple sound effects
; TODO fix crash ; TODO fix auto dropping of blocks (first fix testarrays)
%target c64 %target c64
%import syslib %import syslib
@ -34,7 +33,8 @@ main {
sub start() { sub start() {
@(650) = 128 ; set all keys to repeat c64.disable_runstop_and_charsetswitch()
;@(650) = 128 ; set all keys to repeat
sound.init() sound.init()
newGame() newGame()
drawBoard() drawBoard()

View File

@ -5,9 +5,6 @@
; Note: this program is compatible with C64 and CX16. ; Note: this program is compatible with C64 and CX16.
; TODO fix byte var in arrayvar fail
main { main {
; this is only a parser/compiler test, there's no actual working program ; this is only a parser/compiler test, there's no actual working program

View File

@ -3,6 +3,8 @@
; Note: this program is compatible with C64 and CX16. ; Note: this program is compatible with C64 and CX16.
; TODO fix byte var in arrayvar fail
main { main {
sub start() { sub start() {

View File

@ -3,8 +3,6 @@
%import graphics %import graphics
%zeropage floatsafe %zeropage floatsafe
; TODO fix crash
main { main {
sub start() { sub start() {