added atari XEX output format with default $2000 load address

This commit is contained in:
Irmen de Jong 2022-02-26 15:36:22 +01:00
parent c5504c6657
commit df35dfe3bf
24 changed files with 126 additions and 99 deletions

View File

@ -43,9 +43,6 @@ class AsmGen(internal val program: Program,
override fun compileToAssembly(): IAssemblyProgram? {
if(options.compTarget.name=="atari" && options.launcher==LauncherType.CBMBASIC)
throw AssemblyError("atari target cannot use CBM BASIC launcher type")
assemblyLines.clear()
loopEndLabels.clear()

View File

@ -54,6 +54,7 @@ internal class AssemblyProgram(
println("\nCreating raw binary for target ${compTarget.name}.")
binFile
}
else -> throw AssemblyError("invalid output type")
}
command.addAll(listOf("--output", outFile.toString(), assemblyFile.toString()))
assemblerCommand = command
@ -75,7 +76,7 @@ internal class AssemblyProgram(
command.add("--list=$listFile")
val outFile = when (options.output) {
OutputType.PRG -> {
OutputType.XEX -> {
command.add("--atari-xex")
println("\nCreating xex for target ${compTarget.name}.")
xexFile
@ -85,6 +86,7 @@ internal class AssemblyProgram(
println("\nCreating raw binary for target ${compTarget.name}.")
binFile
}
else -> throw AssemblyError("invalid output type")
}
command.addAll(listOf("--output", outFile.toString(), assemblyFile.toString()))
assemblerCommand = command

View File

@ -71,12 +71,27 @@ internal class ProgramAndVarsGen(
program.actualLoadAddress = program.definedLoadAddress
if (program.actualLoadAddress == 0u) {
if (options.launcher == LauncherType.CBMBASIC) {
program.actualLoadAddress = compTarget.machine.BASIC_LOAD_ADDRESS
}
else {
errors.err("load address must be specified with %address when using launcher type ${options.launcher}", program.toplevelModule.position)
return
when(options.output) {
OutputType.RAW -> {
errors.err("load address must be specified with %address when using raw output type", program.toplevelModule.position)
return
}
OutputType.PRG -> {
when(options.launcher) {
CbmPrgLauncherType.BASIC -> {
program.actualLoadAddress = compTarget.machine.PROGRAM_LOAD_ADDRESS
}
CbmPrgLauncherType.NONE -> {
errors.err("load address must be specified with %address when not using basic launcher", program.toplevelModule.position)
return
}
}
}
OutputType.XEX -> {
if(options.launcher!=CbmPrgLauncherType.NONE)
throw AssemblyError("atari xex output can't contain BASIC launcher")
program.actualLoadAddress = compTarget.machine.PROGRAM_LOAD_ADDRESS
}
}
}
@ -89,33 +104,44 @@ internal class ProgramAndVarsGen(
asmgen.out("P8ESTACK_LO = ${compTarget.machine.ESTACK_LO.toHex()}")
asmgen.out("P8ESTACK_HI = ${compTarget.machine.ESTACK_HI.toHex()}")
when {
options.launcher == LauncherType.CBMBASIC -> {
if (program.actualLoadAddress != options.compTarget.machine.BASIC_LOAD_ADDRESS) {
errors.err("BASIC output must have load address ${options.compTarget.machine.BASIC_LOAD_ADDRESS.toHex()}", program.toplevelModule.position)
}
asmgen.out("; ---- basic program with sys call ----")
asmgen.out("* = ${program.actualLoadAddress.toHex()}")
val year = LocalDate.now().year
asmgen.out(" .word (+), $year")
asmgen.out(" .null $9e, format(' %d ', prog8_entrypoint), $3a, $8f, ' prog8'")
asmgen.out("+\t.word 0")
asmgen.out("prog8_entrypoint\t; assembly code starts here\n")
if(!options.noSysInit)
asmgen.out(" jsr ${compTarget.name}.init_system")
asmgen.out(" jsr ${compTarget.name}.init_system_phase2")
}
options.output == OutputType.PRG -> {
asmgen.out("; ---- program without basic sys call ----")
asmgen.out("* = ${program.actualLoadAddress.toHex()}\n")
if(!options.noSysInit)
asmgen.out(" jsr ${compTarget.name}.init_system")
asmgen.out(" jsr ${compTarget.name}.init_system_phase2")
}
options.output == OutputType.RAW -> {
when(options.output) {
OutputType.RAW -> {
asmgen.out("; ---- raw assembler program ----")
asmgen.out("* = ${program.actualLoadAddress.toHex()}\n")
}
OutputType.PRG -> {
when(options.launcher) {
CbmPrgLauncherType.BASIC -> {
if (program.actualLoadAddress != options.compTarget.machine.PROGRAM_LOAD_ADDRESS) {
errors.err("BASIC output must have load address ${options.compTarget.machine.PROGRAM_LOAD_ADDRESS.toHex()}", program.toplevelModule.position)
}
asmgen.out("; ---- basic program with sys call ----")
asmgen.out("* = ${program.actualLoadAddress.toHex()}")
val year = LocalDate.now().year
asmgen.out(" .word (+), $year")
asmgen.out(" .null $9e, format(' %d ', prog8_entrypoint), $3a, $8f, ' prog8'")
asmgen.out("+\t.word 0")
asmgen.out("prog8_entrypoint\t; assembly code starts here\n")
if(!options.noSysInit)
asmgen.out(" jsr ${compTarget.name}.init_system")
asmgen.out(" jsr ${compTarget.name}.init_system_phase2")
}
CbmPrgLauncherType.NONE -> {
asmgen.out("; ---- program without basic sys call ----")
asmgen.out("* = ${program.actualLoadAddress.toHex()}\n")
if(!options.noSysInit)
asmgen.out(" jsr ${compTarget.name}.init_system")
asmgen.out(" jsr ${compTarget.name}.init_system_phase2")
}
}
}
OutputType.XEX -> {
asmgen.out("; ---- atari xex program ----")
asmgen.out("* = ${program.actualLoadAddress.toHex()}\n")
if(!options.noSysInit)
asmgen.out(" jsr ${compTarget.name}.init_system")
asmgen.out(" jsr ${compTarget.name}.init_system_phase2")
}
}
if(options.zeropage !in arrayOf(ZeropageType.BASICSAFE, ZeropageType.DONTUSE)) {

View File

@ -17,7 +17,6 @@ class AtariTarget: ICompilationTarget, IStringEncoding by Encoder, IMemSizer {
override val machine = AtariMachineDefinition()
override val supportedEncodings = setOf(Encoding.ATASCII)
override val defaultEncoding = Encoding.ATASCII
override val defaultLauncherType = LauncherType.NONE
companion object {
const val NAME = "atari"

View File

@ -15,7 +15,6 @@ class C128Target: ICompilationTarget, IStringEncoding by Encoder, IMemSizer by C
override val machine = C128MachineDefinition()
override val supportedEncodings = setOf(Encoding.PETSCII, Encoding.SCREENCODES)
override val defaultEncoding = Encoding.PETSCII
override val defaultLauncherType = LauncherType.CBMBASIC
companion object {
const val NAME = "c128"

View File

@ -15,7 +15,6 @@ class C64Target: ICompilationTarget, IStringEncoding by Encoder, IMemSizer by Cb
override val machine = C64MachineDefinition()
override val supportedEncodings = setOf(Encoding.PETSCII, Encoding.SCREENCODES)
override val defaultEncoding = Encoding.PETSCII
override val defaultLauncherType = LauncherType.CBMBASIC
companion object {
const val NAME = "c64"

View File

@ -15,7 +15,6 @@ class Cx16Target: ICompilationTarget, IStringEncoding by Encoder, IMemSizer by C
override val machine = CX16MachineDefinition()
override val supportedEncodings = setOf(Encoding.PETSCII, Encoding.SCREENCODES, Encoding.ISO)
override val defaultEncoding = Encoding.PETSCII
override val defaultLauncherType = LauncherType.CBMBASIC
companion object {
const val NAME = "cx16"

View File

@ -12,7 +12,7 @@ class AtariMachineDefinition: IMachineDefinition {
override val FLOAT_MAX_POSITIVE = 9.999999999e97
override val FLOAT_MAX_NEGATIVE = -9.999999999e97
override val FLOAT_MEM_SIZE = 6
override val BASIC_LOAD_ADDRESS = 0x2000u
override val PROGRAM_LOAD_ADDRESS = 0x2000u
// the 2*256 byte evaluation stack (on which bytes, words, and even floats are stored during calculations)
override val ESTACK_LO = 0x1a00u // $1a00-$1aff inclusive // TODO
@ -23,7 +23,7 @@ class AtariMachineDefinition: IMachineDefinition {
override fun getFloat(num: Number) = TODO("float from number")
override fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List<String> {
return if (compilerOptions.launcher == LauncherType.CBMBASIC || compilerOptions.output == OutputType.PRG)
return if (compilerOptions.launcher == CbmPrgLauncherType.BASIC || compilerOptions.output == OutputType.PRG)
listOf("syslib")
else
emptyList()

View File

@ -13,7 +13,7 @@ class C128MachineDefinition: IMachineDefinition {
override val FLOAT_MAX_POSITIVE = Mflpt5.FLOAT_MAX_POSITIVE
override val FLOAT_MAX_NEGATIVE = Mflpt5.FLOAT_MAX_NEGATIVE
override val FLOAT_MEM_SIZE = Mflpt5.FLOAT_MEM_SIZE
override val BASIC_LOAD_ADDRESS = 0x1c01u
override val PROGRAM_LOAD_ADDRESS = 0x1c01u
// the 2*256 byte evaluation stack (on which bytes, words, and even floats are stored during calculations)
override val ESTACK_LO = 0x1a00u // $1a00-$1aff inclusive
@ -24,7 +24,7 @@ class C128MachineDefinition: IMachineDefinition {
override fun getFloat(num: Number) = Mflpt5.fromNumber(num)
override fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List<String> {
return if (compilerOptions.launcher == LauncherType.CBMBASIC || compilerOptions.output == OutputType.PRG)
return if (compilerOptions.launcher == CbmPrgLauncherType.BASIC || compilerOptions.output == OutputType.PRG)
listOf("syslib")
else
emptyList()

View File

@ -13,7 +13,7 @@ class C64MachineDefinition: IMachineDefinition {
override val FLOAT_MAX_POSITIVE = Mflpt5.FLOAT_MAX_POSITIVE
override val FLOAT_MAX_NEGATIVE = Mflpt5.FLOAT_MAX_NEGATIVE
override val FLOAT_MEM_SIZE = Mflpt5.FLOAT_MEM_SIZE
override val BASIC_LOAD_ADDRESS = 0x0801u
override val PROGRAM_LOAD_ADDRESS = 0x0801u
// the 2*256 byte evaluation stack (on which bytes, words, and even floats are stored during calculations)
override val ESTACK_LO = 0xce00u // $ce00-$ceff inclusive
@ -24,7 +24,7 @@ class C64MachineDefinition: IMachineDefinition {
override fun getFloat(num: Number) = Mflpt5.fromNumber(num)
override fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List<String> {
return if (compilerOptions.launcher == LauncherType.CBMBASIC || compilerOptions.output == OutputType.PRG)
return if (compilerOptions.launcher == CbmPrgLauncherType.BASIC || compilerOptions.output == OutputType.PRG)
listOf("syslib")
else
emptyList()

View File

@ -12,7 +12,7 @@ class CX16MachineDefinition: IMachineDefinition {
override val FLOAT_MAX_POSITIVE = Mflpt5.FLOAT_MAX_POSITIVE
override val FLOAT_MAX_NEGATIVE = Mflpt5.FLOAT_MAX_NEGATIVE
override val FLOAT_MEM_SIZE = Mflpt5.FLOAT_MEM_SIZE
override val BASIC_LOAD_ADDRESS = 0x0801u
override val PROGRAM_LOAD_ADDRESS = 0x0801u
// the 2*256 byte evaluation stack (on which bytes, words, and even floats are stored during calculations)
override val ESTACK_LO = 0x0400u // $0400-$04ff inclusive
@ -22,7 +22,7 @@ class CX16MachineDefinition: IMachineDefinition {
override fun getFloat(num: Number) = Mflpt5.fromNumber(num)
override fun importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List<String> {
return if (compilerOptions.launcher == LauncherType.CBMBASIC || compilerOptions.output == OutputType.PRG)
return if (compilerOptions.launcher == CbmPrgLauncherType.BASIC || compilerOptions.output == OutputType.PRG)
listOf("syslib")
else
emptyList()

View File

@ -9,7 +9,7 @@ import prog8.codegen.target.Cx16Target
import prog8.compiler.CompilationResult
import prog8.compiler.CompilerArguments
import prog8.compiler.compileProgram
import prog8.compilerinterface.LauncherType
import prog8.compilerinterface.CbmPrgLauncherType
import java.io.File
import java.nio.file.FileSystems
import java.nio.file.Path
@ -169,7 +169,7 @@ private fun compileMain(args: Array<String>): Boolean {
val programNameInPath = outputPath.resolve(compilationResult.programName)
if(startEmulator1==true || startEmulator2==true) {
if (compilationResult.compilationOptions.launcher != LauncherType.NONE || compilationTarget=="atari") {
if (compilationResult.compilationOptions.launcher != CbmPrgLauncherType.NONE || compilationTarget=="atari") {
if (startEmulator1 == true)
compilationResult.compilationOptions.compTarget.machine.launchEmulator(1, programNameInPath)
else if (startEmulator2 == true)

View File

@ -153,7 +153,7 @@ fun compileProgram(args: CompilerArguments): CompilationResult {
val failedProgram = Program("failed", BuiltinFunctionsFacade(BuiltinFunctions), compTarget, compTarget)
val dummyoptions = CompilationOptions(
OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(),
OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.DONTUSE, emptyList(),
floats = false,
noSysInit = true,
compTarget = compTarget
@ -215,9 +215,9 @@ fun parseImports(filepath: Path,
importer.importLibraryModule("math")
importer.importLibraryModule("prog8_lib")
if (compilerOptions.launcher == LauncherType.CBMBASIC && compilerOptions.output != OutputType.PRG)
if (compilerOptions.launcher == CbmPrgLauncherType.BASIC && compilerOptions.output != OutputType.PRG)
errors.err("BASIC launcher requires output type PRG", program.toplevelModule.position)
if(compilerOptions.launcher == LauncherType.CBMBASIC && compTarget.name==AtariTarget.NAME)
if(compilerOptions.launcher == CbmPrgLauncherType.BASIC && compTarget.name==AtariTarget.NAME)
errors.err("atari target cannot use CBM BASIC launcher, use NONE", program.toplevelModule.position)
errors.report()
@ -261,7 +261,12 @@ fun determineCompilationOptions(program: Program, compTarget: ICompilationTarget
.map { it[0].int!!..it[1].int!! }
.toList()
val outputType = if (outputTypeStr == null) OutputType.PRG else {
val outputType = if (outputTypeStr == null) {
if(compTarget is AtariTarget)
OutputType.XEX
else
OutputType.PRG
} else {
try {
OutputType.valueOf(outputTypeStr)
} catch (x: IllegalArgumentException) {
@ -269,12 +274,17 @@ fun determineCompilationOptions(program: Program, compTarget: ICompilationTarget
OutputType.PRG
}
}
val launcherType = if (launcherTypeStr == null) compTarget.defaultLauncherType else {
val launcherType = if (launcherTypeStr == null) {
when(compTarget) {
is AtariTarget -> CbmPrgLauncherType.NONE
else -> CbmPrgLauncherType.BASIC
}
} else {
try {
LauncherType.valueOf(launcherTypeStr)
CbmPrgLauncherType.valueOf(launcherTypeStr)
} catch (x: IllegalArgumentException) {
// set default value; actual check and error handling of invalid option is handled in the AstChecker later
LauncherType.CBMBASIC
CbmPrgLauncherType.BASIC
}
}

View File

@ -20,7 +20,7 @@ import prog8.compiler.astprocessing.VariableExtractor
import prog8.compiler.astprocessing.processAstBeforeAsmGeneration
import prog8.compiler.printProgram
import prog8.compilerinterface.CompilationOptions
import prog8.compilerinterface.LauncherType
import prog8.compilerinterface.CbmPrgLauncherType
import prog8.compilerinterface.OutputType
import prog8.compilerinterface.ZeropageType
import prog8tests.helpers.*
@ -302,7 +302,7 @@ class TestOptimization: FunSpec({
expr.right.inferType(result.program).getOrElse { fail("dt") } shouldBe DataType.UWORD
expr.inferType(result.program).getOrElse { fail("dt") } shouldBe DataType.UBYTE
val options = CompilationOptions(OutputType.RAW, LauncherType.CBMBASIC, ZeropageType.DONTUSE, emptyList(), false, true, C64Target(), outputDir= outputDir)
val options = CompilationOptions(OutputType.PRG, CbmPrgLauncherType.BASIC, ZeropageType.DONTUSE, emptyList(), false, true, C64Target(), outputDir= outputDir)
result.program.processAstBeforeAsmGeneration(options, DummyVarsAndConsts, ErrorReporterForTests())
// assignment is now split into:

View File

@ -43,7 +43,7 @@ class TestAbstractZeropage: FunSpec({
val zp = DummyZeropage(
CompilationOptions(
OutputType.RAW,
LauncherType.NONE,
CbmPrgLauncherType.NONE,
ZeropageType.FULL,
listOf((0x50u..0x5fu)),
false,
@ -64,7 +64,7 @@ class TestC64Zeropage: FunSpec({
val zpdummyscope = GlobalNamespace(emptyList())
test("testNames") {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false, c64target))
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false, c64target))
var result = zp.allocate(emptyList(), DataType.UBYTE, zpdummyscope, null, null, null, errors)
result.onFailure { fail(it.toString()) }
@ -78,33 +78,33 @@ class TestC64Zeropage: FunSpec({
}
test("testZpFloatEnable") {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, c64target))
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, c64target))
var result = zp.allocate(emptyList(), DataType.FLOAT, zpdummyscope, null, null, null, errors)
result.expectError { "should be allocation error due to disabled floats" }
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), true, false, c64target))
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.DONTUSE, emptyList(), true, false, c64target))
result = zp2.allocate(emptyList(), DataType.FLOAT, zpdummyscope, null, null, null, errors)
result.expectError { "should be allocation error due to disabled ZP use" }
val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), true, false, c64target))
val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), true, false, c64target))
zp3.allocate(emptyList(), DataType.FLOAT, zpdummyscope, null, null, null, errors)
}
test("testZpModesWithFloats") {
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, c64target))
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false, false, c64target))
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false, c64target))
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), false, false, c64target))
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, c64target))
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), true, false, c64target))
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, c64target))
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false, false, c64target))
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false, c64target))
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), false, false, c64target))
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, c64target))
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), true, false, c64target))
shouldThrow<InternalCompilerException> {
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), true, false, c64target))
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), true, false, c64target))
}
shouldThrow<InternalCompilerException> {
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), true, false, c64target))
C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), true, false, c64target))
}
}
test("testZpDontuse") {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), false, false, c64target))
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.DONTUSE, emptyList(), false, false, c64target))
println(zp.free)
zp.availableBytes() shouldBe 0
val result = zp.allocate(emptyList(), DataType.BYTE, zpdummyscope, null, null, null, errors)
@ -112,13 +112,13 @@ class TestC64Zeropage: FunSpec({
}
test("testFreeSpacesBytes") {
val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, c64target))
val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, c64target))
zp1.availableBytes() shouldBe 18
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), false, false, c64target))
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), false, false, c64target))
zp2.availableBytes() shouldBe 85
val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false, false, c64target))
val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false, false, c64target))
zp3.availableBytes() shouldBe 125
val zp4 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, c64target))
val zp4 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, c64target))
zp4.availableBytes() shouldBe 239
zp4.allocate(listOf("test"), DataType.UBYTE, zpdummyscope, null, null, null, errors)
zp4.availableBytes() shouldBe 238
@ -127,7 +127,7 @@ class TestC64Zeropage: FunSpec({
}
test("testReservedSpace") {
val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, c64target))
val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, c64target))
zp1.availableBytes() shouldBe 239
50u shouldBeIn zp1.free
100u shouldBeIn zp1.free
@ -136,7 +136,7 @@ class TestC64Zeropage: FunSpec({
200u shouldBeIn zp1.free
255u shouldBeIn zp1.free
199u shouldBeIn zp1.free
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, listOf(50u .. 100u, 200u..255u), false, false, c64target))
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, listOf(50u .. 100u, 200u..255u), false, false, c64target))
zp2.availableBytes() shouldBe 139
50u shouldNotBeIn zp2.free
100u shouldNotBeIn zp2.free
@ -148,7 +148,7 @@ class TestC64Zeropage: FunSpec({
}
test("testBasicsafeAllocation") {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, c64target))
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, c64target))
zp.availableBytes() shouldBe 18
zp.hasByteAvailable() shouldBe true
zp.hasWordAvailable() shouldBe true
@ -170,7 +170,7 @@ class TestC64Zeropage: FunSpec({
}
test("testFullAllocation") {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, c64target))
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, c64target))
zp.availableBytes() shouldBe 239
zp.hasByteAvailable() shouldBe true
zp.hasWordAvailable() shouldBe true
@ -201,7 +201,7 @@ class TestC64Zeropage: FunSpec({
}
test("testEfficientAllocation") {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, c64target))
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, c64target))
zp.availableBytes() shouldBe 18
zp.allocate(emptyList(), DataType.WORD, zpdummyscope, null, null, null, errors).getOrElse{throw it}.first shouldBe 0x04u
zp.allocate(emptyList(), DataType.UBYTE, zpdummyscope, null, null, null, errors).getOrElse{throw it}.first shouldBe 0x06u
@ -219,7 +219,7 @@ class TestC64Zeropage: FunSpec({
}
test("testReservedLocations") {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false, c64target))
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false, c64target))
withClue("zp _B1 and _REG must be next to each other to create a word") {
zp.SCRATCH_B1 + 1u shouldBe zp.SCRATCH_REG
}
@ -233,18 +233,18 @@ class TestCx16Zeropage: FunSpec({
val zpdummyscope = GlobalNamespace(emptyList())
test("testReservedLocations") {
val zp = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false, cx16target))
val zp = CX16Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false, cx16target))
withClue("zp _B1 and _REG must be next to each other to create a word") {
zp.SCRATCH_B1 + 1u shouldBe zp.SCRATCH_REG
}
}
test("testFreeSpacesBytes") {
val zp1 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, cx16target))
val zp1 = CX16Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, cx16target))
zp1.availableBytes() shouldBe 88
val zp2 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false, false, cx16target))
val zp2 = CX16Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false, false, cx16target))
zp2.availableBytes() shouldBe 175
val zp3 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, cx16target))
val zp3 = CX16Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, cx16target))
zp3.availableBytes() shouldBe 216
zp3.allocate(listOf("test"), DataType.UBYTE, zpdummyscope, null, null, null, errors)
zp3.availableBytes() shouldBe 215
@ -253,7 +253,7 @@ class TestCx16Zeropage: FunSpec({
}
test("testReservedSpace") {
val zp1 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, cx16target))
val zp1 = CX16Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, cx16target))
zp1.availableBytes() shouldBe 216
0x22u shouldBeIn zp1.free
0x80u shouldBeIn zp1.free
@ -263,7 +263,7 @@ class TestCx16Zeropage: FunSpec({
}
test("preallocated zp vars") {
val zp1 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, cx16target))
val zp1 = CX16Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, cx16target))
zp1.allocatedVariables[listOf("test")] shouldBe null
zp1.allocatedVariables[listOf("cx16", "r0")] shouldNotBe null
zp1.allocatedVariables[listOf("cx16", "r15")] shouldNotBe null

View File

@ -100,7 +100,7 @@ class TestAsmGenSymbols: StringSpec({
fun createTestAsmGen(program: Program, allocation: IVariablesAndConsts): AsmGen {
val errors = ErrorReporterForTests()
val options = CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, true, C64Target())
val options = CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), false, true, C64Target())
options.compTarget.machine.zeropage = C64Zeropage(options)
return AsmGen(program, errors, allocation, options)
}

View File

@ -53,7 +53,6 @@ internal object DummyCompilationTarget : ICompilationTarget {
get() = throw NotImplementedError("dummy")
override val supportedEncodings = setOf(Encoding.PETSCII, Encoding.SCREENCODES, Encoding.ISO)
override val defaultEncoding = Encoding.PETSCII
override val defaultLauncherType = LauncherType.NONE
override fun encodeString(str: String, encoding: Encoding): List<UByte> {
throw NotImplementedError("dummy")

View File

@ -86,7 +86,7 @@ internal fun generateAssembly(
variables: IVariablesAndConsts,
options: CompilationOptions? = null
): IAssemblyProgram? {
val coptions = options ?: CompilationOptions(OutputType.RAW, LauncherType.CBMBASIC, ZeropageType.DONTUSE, emptyList(), true, true, C64Target(), outputDir = outputDir)
val coptions = options ?: CompilationOptions(OutputType.RAW, CbmPrgLauncherType.BASIC, ZeropageType.DONTUSE, emptyList(), true, true, C64Target(), outputDir = outputDir)
coptions.compTarget.machine.zeropage = C64Zeropage(coptions)
val asmgen = AsmGen(program, ErrorReporterForTests(), variables, coptions)
return asmgen.compileToAssembly()

View File

@ -5,11 +5,12 @@ import kotlin.io.path.Path
enum class OutputType {
RAW,
PRG
PRG,
XEX
}
enum class LauncherType {
CBMBASIC,
enum class CbmPrgLauncherType {
BASIC,
NONE
}
@ -22,7 +23,7 @@ enum class ZeropageType {
}
class CompilationOptions(val output: OutputType,
val launcher: LauncherType,
val launcher: CbmPrgLauncherType,
val zeropage: ZeropageType,
val zpReserved: List<UIntRange>,
val floats: Boolean,

View File

@ -10,7 +10,6 @@ interface ICompilationTarget: IStringEncoding, IMemSizer {
val machine: IMachineDefinition
val supportedEncodings: Set<Encoding>
val defaultEncoding: Encoding
val defaultLauncherType: LauncherType
override fun encodeString(str: String, encoding: Encoding): List<UByte>
override fun decodeString(bytes: List<UByte>, encoding: Encoding): String

View File

@ -19,7 +19,7 @@ interface IMachineDefinition {
val FLOAT_MEM_SIZE: Int
val ESTACK_LO: UInt
val ESTACK_HI: UInt
val BASIC_LOAD_ADDRESS : UInt
val PROGRAM_LOAD_ADDRESS : UInt
val opcodeNames: Set<String>
var zeropage: Zeropage

View File

@ -23,7 +23,6 @@ Future Things and Ideas
^^^^^^^^^^^^^^^^^^^^^^^
Compiler:
- (due to the new atari target:) rework "launcher" option to a better name, include "XEX", and automatically set load address to $2000 in this case so %address can be omitted for atari programs too
- writeAssembly(): make it possible to actually get rid of the VarDecl nodes by fixing the rest of the code mentioned there.
- make everything an expression? (get rid of Statements. Statements are expressions with void return types?).
- allow "xxx" * constexpr (where constexpr is not a number literal), now gives expression error not same type

View File

@ -1,6 +1,5 @@
%import textio
%zeropage basicsafe
%address $2000
; This example computes the first 20 values of the Fibonacci sequence.
; Note: this program is compatible with atari.

View File

@ -1,5 +1,4 @@
%import textio
%address $2000
main {
sub start() {