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
lda #0
sta c64.BGCOL0
tax
tay
jsr disable_runstop_and_charsetswitch
clc
clv
cli
@ -272,7 +271,6 @@ asmsub reset_system() {
asmsub disable_runstop_and_charsetswitch() {
%asm {{
lda #$80
lda #$80
sta 657 ; disable charset switching
lda #239

View File

@ -8,7 +8,6 @@ import prog8.ast.expressions.*
import prog8.ast.processing.AstWalker
import prog8.ast.processing.IAstModification
import prog8.ast.statements.*
import prog8.compiler.target.c64.codegen.programInitializationRoutineName
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) {
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
}

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 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 decodeString(bytes: List<Short>, altEncoding: Boolean): String
fun asmGenerator(program: Program, errors: ErrorReporter, zp: Zeropage, options: CompilationOptions, path: Path): IAssemblyGenerator
val initProcName: String?
val resetProcName: String?
val disableRunStopProcName: String?
companion object {
lateinit var instance: CompilationTarget
@ -36,9 +33,6 @@ internal object C64Target: CompilationTarget {
if(altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true)
override fun asmGenerator(program: Program, errors: ErrorReporter, zp: Zeropage, options: CompilationOptions, path: 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 {
@ -50,7 +44,4 @@ internal object Cx16Target: CompilationTarget {
if(altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true)
override fun asmGenerator(program: Program, errors: ErrorReporter, zp: Zeropage, options: CompilationOptions, path: 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 exitProgramStrategy: ExitProgramStrategy = when (options.zeropage) {
ZeropageType.BASICSAFE, ZeropageType.DONTUSE -> ExitProgramStrategy.CLEAN_EXIT
ZeropageType.FLOATSAFE, ZeropageType.KERNALSAFE, ZeropageType.FULL -> ExitProgramStrategy.SYSTEM_RESET
}
init {
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'")

View File

@ -29,9 +29,6 @@ import java.util.*
import kotlin.math.absoluteValue
internal const val programInitializationRoutineName = "prog8_initialize_program"
internal class AsmGen(private val program: Program,
val errors: ErrorReporter,
val zeropage: Zeropage,
@ -54,12 +51,10 @@ internal class AsmGen(private val program: Program,
private val expressionsAsmGen = ExpressionsAsmGen(program, this)
internal val loopEndLabels = ArrayDeque<String>()
private val blockLevelVarInits = mutableMapOf<Block, MutableSet<VarDecl>>()
private val programInitLines = mutableListOf<String>()
override fun compileToAssembly(optimize: Boolean): IAssemblyProgram {
assemblyLines.clear()
loopEndLabels.clear()
programInitLines.clear()
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("+\t.word 0")
out("_prog8_entrypoint\t; assembly code starts here\n")
if(!options.noSysInit && !CompilationTarget.instance.initProcName.isNullOrEmpty())
out(" jsr ${CompilationTarget.instance.initProcName}")
if(!options.noSysInit)
out(" jsr ${CompilationTarget.instance.name}.init_system")
}
options.output == OutputType.PRG -> {
out("; ---- program without basic sys call ----")
out("* = ${program.actualLoadAddress.toHex()}\n")
if(!options.noSysInit && !CompilationTarget.instance.initProcName.isNullOrEmpty())
out(" jsr ${CompilationTarget.instance.initProcName}")
if(!options.noSysInit)
out(" jsr ${CompilationTarget.instance.name}.init_system")
}
options.output == OutputType.RAW -> {
out("; ---- raw assembler program ----")
out("* = ${program.actualLoadAddress.toHex()}\n")
}
}
out(" jmp main.start ; start program / force start proc to be included")
if (zeropage.exitProgramStrategy != Zeropage.ExitProgramStrategy.CLEAN_EXIT) {
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")
out(" jmp main.start ; start program / force start proc to be included")
}
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
out("; global float constants")
for (flt in globalFloatConsts) {
@ -632,25 +589,18 @@ $save .byte 0
is InlineAssembly -> translate(stmt)
is FunctionCallStatement -> {
val functionName = stmt.target.nameInSource.last()
if(functionName == programInitializationRoutineName) {
out("""
tsx
stx prog8_lib.orig_stackpointer
jsr $functionName""")
val builtinFunc = BuiltinFunctions[functionName]
if (builtinFunc != null) {
builtinFunctionsAsmGen.translateFunctioncallStatement(stmt, builtinFunc)
} else {
val builtinFunc = BuiltinFunctions[functionName]
if (builtinFunc != null) {
builtinFunctionsAsmGen.translateFunctioncallStatement(stmt, builtinFunc)
} else {
functioncallAsmGen.translateFunctionCall(stmt)
// discard any results from the stack:
val sub = stmt.target.targetSubroutine(program.namespace)!!
val returns = sub.returntypes.zip(sub.asmReturnvaluesRegisters)
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")
}
functioncallAsmGen.translateFunctionCall(stmt)
// discard any results from the stack:
val sub = stmt.target.targetSubroutine(program.namespace)!!
val returns = sub.returntypes.zip(sub.asmReturnvaluesRegisters)
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")
zeropagevars2asm(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")
sub.statements.forEach{ translate(it) }
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 exitProgramStrategy: ExitProgramStrategy = when (options.zeropage) {
ZeropageType.BASICSAFE, ZeropageType.DONTUSE -> ExitProgramStrategy.CLEAN_EXIT
ZeropageType.KERNALSAFE, ZeropageType.FULL -> ExitProgramStrategy.SYSTEM_RESET
else -> ExitProgramStrategy.SYSTEM_RESET
}
init {
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'")

View File

@ -67,7 +67,8 @@ Directives
- 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),
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
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
@ -78,9 +79,10 @@ Directives
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.
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
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.
Also read :ref:`zeropage`.

View File

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

View File

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

View File

@ -2,8 +2,6 @@
%import syslib
%import textio
; TODO fix crash
spritedata $2000 {
; this memory block contains the sprite data
; 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.
; TODO fix crash
main {
sub start() {

View File

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

View File

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

View File

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

View File

@ -5,9 +5,6 @@
; Note: this program is compatible with C64 and CX16.
; TODO fix byte var in arrayvar fail
main {
; 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.
; TODO fix byte var in arrayvar fail
main {
sub start() {

View File

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