mirror of
https://github.com/irmen/prog8.git
synced 2025-05-12 19:47:48 +00:00
finalize extracting neo and atari compiler targets into configuration files instead
This commit is contained in:
parent
99ff5dd078
commit
2aeb7a838e
@ -1,4 +1,7 @@
|
||||
[](https://ko-fi.com/H2H6S0FFF)
|
||||
|
||||
PayPal: [](https://paypal.me/irmendejong)
|
||||
|
||||
[](https://prog8.readthedocs.io/)
|
||||
|
||||
Prog8 - Structured Programming Language for 8-bit 6502/65c02 microprocessors
|
||||
@ -14,7 +17,7 @@ which aims to provide many conveniences over raw assembly code (even when using
|
||||
|
||||
This project was created over the last couple of years by dedicating thousands of hours of my free time to it, to make it the best I possibly can.
|
||||
If you like Prog8, and think it's worth a nice cup of hot coffee or a delicious pizza,
|
||||
you can help me out a little bit over at [ko-fi.com/irmen](https://ko-fi.com/irmen).
|
||||
you can help me out a little bit over at [ko-fi.com/irmen](https://ko-fi.com/irmen) or [PayPal](https://paypal.me/irmendejong)
|
||||
|
||||
|
||||
Documentation
|
||||
|
@ -8,13 +8,6 @@ enum class CpuType {
|
||||
VIRTUAL
|
||||
}
|
||||
|
||||
enum class ProgramType {
|
||||
CBMPRG,
|
||||
ATARIXEX,
|
||||
NEORAW,
|
||||
VIRTUALIR
|
||||
}
|
||||
|
||||
interface ICompilationTarget: IStringEncoding, IMemSizer {
|
||||
val name: String
|
||||
|
||||
@ -30,7 +23,6 @@ interface ICompilationTarget: IStringEncoding, IMemSizer {
|
||||
val BSSGOLDENRAM_END: UInt
|
||||
|
||||
val cpu: CpuType
|
||||
val programType: ProgramType
|
||||
var zeropage: Zeropage
|
||||
var golden: GoldenRam
|
||||
val libraryPath: Path?
|
||||
|
@ -1,16 +1,8 @@
|
||||
package prog8.code.target
|
||||
|
||||
import prog8.code.core.CompilationOptions
|
||||
import prog8.code.core.CpuType
|
||||
import prog8.code.core.Encoding
|
||||
import prog8.code.core.GoldenRam
|
||||
import prog8.code.core.ICompilationTarget
|
||||
import prog8.code.core.IMemSizer
|
||||
import prog8.code.core.IStringEncoding
|
||||
import prog8.code.core.ProgramType
|
||||
import prog8.code.core.Zeropage
|
||||
import prog8.code.target.zp.C128Zeropage
|
||||
import prog8.code.core.*
|
||||
import prog8.code.target.encodings.Encoder
|
||||
import prog8.code.target.zp.C128Zeropage
|
||||
import java.nio.file.Path
|
||||
|
||||
|
||||
@ -27,7 +19,6 @@ class C128Target: ICompilationTarget, IStringEncoding by Encoder, IMemSizer by N
|
||||
|
||||
|
||||
override val cpu = CpuType.CPU6502
|
||||
override val programType = ProgramType.CBMPRG
|
||||
|
||||
override val FLOAT_MAX_POSITIVE = Mflpt5.FLOAT_MAX_POSITIVE
|
||||
override val FLOAT_MAX_NEGATIVE = Mflpt5.FLOAT_MAX_NEGATIVE
|
||||
|
@ -22,7 +22,6 @@ class C64Target: ICompilationTarget, IStringEncoding by Encoder, IMemSizer by No
|
||||
|
||||
|
||||
override val cpu = CpuType.CPU6502
|
||||
override val programType = ProgramType.CBMPRG
|
||||
|
||||
override val FLOAT_MAX_POSITIVE = Mflpt5.FLOAT_MAX_POSITIVE
|
||||
override val FLOAT_MAX_NEGATIVE = Mflpt5.FLOAT_MAX_NEGATIVE
|
||||
|
@ -17,7 +17,6 @@ class ConfigFileTarget(
|
||||
override val name: String,
|
||||
override val defaultEncoding: Encoding,
|
||||
override val cpu: CpuType,
|
||||
override val programType: ProgramType,
|
||||
override val PROGRAM_LOAD_ADDRESS: UInt,
|
||||
override val PROGRAM_MEMTOP_ADDRESS: UInt,
|
||||
override val STARTUP_CODE_RESERVED_SIZE: UInt,
|
||||
@ -103,7 +102,7 @@ class ConfigFileTarget(
|
||||
if(!libraryPath.isDirectory())
|
||||
throw IOException("invalid library path: $libraryPath")
|
||||
|
||||
val customLauncherStr = props.getProperty("custom_launcher", null)
|
||||
val customLauncherStr = props.getProperty("custom_launcher_code", null)
|
||||
val customLauncher =
|
||||
if(customLauncherStr?.isNotBlank()==true)
|
||||
(customLauncherStr+"\n").lines().map { it.trimEnd() }
|
||||
@ -115,7 +114,6 @@ class ConfigFileTarget(
|
||||
configfile.nameWithoutExtension,
|
||||
Encoding.entries.first { it.prefix==props.getString("encoding") },
|
||||
cpuType,
|
||||
ProgramType.valueOf(props.getString("program")),
|
||||
props.getInteger("load_address"),
|
||||
props.getInteger("memtop"),
|
||||
0u, // used only in a very specific error condition check in a certain scenario...
|
||||
|
@ -1,14 +1,6 @@
|
||||
package prog8.code.target
|
||||
|
||||
import prog8.code.core.CompilationOptions
|
||||
import prog8.code.core.CpuType
|
||||
import prog8.code.core.Encoding
|
||||
import prog8.code.core.GoldenRam
|
||||
import prog8.code.core.ICompilationTarget
|
||||
import prog8.code.core.IMemSizer
|
||||
import prog8.code.core.IStringEncoding
|
||||
import prog8.code.core.ProgramType
|
||||
import prog8.code.core.Zeropage
|
||||
import prog8.code.core.*
|
||||
import prog8.code.target.encodings.Encoder
|
||||
import prog8.code.target.zp.CX16Zeropage
|
||||
import java.nio.file.Path
|
||||
@ -27,7 +19,6 @@ class Cx16Target: ICompilationTarget, IStringEncoding by Encoder, IMemSizer by N
|
||||
|
||||
|
||||
override val cpu = CpuType.CPU65C02
|
||||
override val programType = ProgramType.CBMPRG
|
||||
|
||||
override val FLOAT_MAX_POSITIVE = Mflpt5.FLOAT_MAX_POSITIVE
|
||||
override val FLOAT_MAX_NEGATIVE = Mflpt5.FLOAT_MAX_NEGATIVE
|
||||
|
@ -1,14 +1,6 @@
|
||||
package prog8.code.target
|
||||
|
||||
import prog8.code.core.CompilationOptions
|
||||
import prog8.code.core.CpuType
|
||||
import prog8.code.core.Encoding
|
||||
import prog8.code.core.GoldenRam
|
||||
import prog8.code.core.ICompilationTarget
|
||||
import prog8.code.core.IMemSizer
|
||||
import prog8.code.core.IStringEncoding
|
||||
import prog8.code.core.ProgramType
|
||||
import prog8.code.core.Zeropage
|
||||
import prog8.code.core.*
|
||||
import prog8.code.target.encodings.Encoder
|
||||
import prog8.code.target.zp.PETZeropage
|
||||
import java.nio.file.Path
|
||||
@ -26,7 +18,6 @@ class PETTarget: ICompilationTarget, IStringEncoding by Encoder, IMemSizer by No
|
||||
}
|
||||
|
||||
override val cpu = CpuType.CPU6502
|
||||
override val programType = ProgramType.CBMPRG
|
||||
|
||||
override val FLOAT_MAX_POSITIVE = Mflpt5.FLOAT_MAX_POSITIVE
|
||||
override val FLOAT_MAX_NEGATIVE = Mflpt5.FLOAT_MAX_NEGATIVE
|
||||
|
@ -20,7 +20,6 @@ class VMTarget: ICompilationTarget, IStringEncoding by Encoder, IMemSizer by Nor
|
||||
}
|
||||
|
||||
override val cpu = CpuType.VIRTUAL
|
||||
override val programType = ProgramType.VIRTUALIR
|
||||
|
||||
override val FLOAT_MAX_POSITIVE = Double.MAX_VALUE.toDouble()
|
||||
override val FLOAT_MAX_NEGATIVE = -Double.MAX_VALUE.toDouble()
|
||||
|
@ -24,11 +24,11 @@ internal class AssemblyProgram(
|
||||
|
||||
val assemblerCommand: List<String>
|
||||
|
||||
when(compTarget.programType) {
|
||||
ProgramType.CBMPRG -> {
|
||||
when(options.output) {
|
||||
OutputType.PRG -> {
|
||||
// CBM machines .prg generation.
|
||||
|
||||
val command = mutableListOf("64tass", "--ascii", "--case-sensitive", "--long-branch",
|
||||
val command = mutableListOf("64tass", "--cbm-prg", "--ascii", "--case-sensitive", "--long-branch",
|
||||
"-Wall", "-Wno-implied-reg", "--no-monitor", "--dump-labels", "--vice-labels", "--labels=$viceMonListFile")
|
||||
|
||||
if(options.warnSymbolShadowing)
|
||||
@ -43,38 +43,15 @@ internal class AssemblyProgram(
|
||||
command.add("--list=$listFile")
|
||||
}
|
||||
|
||||
val outFile = when (options.output) {
|
||||
OutputType.PRG -> {
|
||||
command.add("--cbm-prg")
|
||||
println("\nCreating prg for target ${compTarget.name}.")
|
||||
prgFile
|
||||
}
|
||||
OutputType.RAW -> {
|
||||
command.add("--nostart")
|
||||
println("\nCreating raw binary for target ${compTarget.name}.")
|
||||
binFile
|
||||
}
|
||||
OutputType.LIBRARY -> {
|
||||
if(compTarget.name in listOf(C64Target.NAME, C128Target.NAME, PETTarget.NAME)) {
|
||||
println("\nCreating binary library file with header for target ${compTarget.name}.")
|
||||
command.add("--cbm-prg")
|
||||
} else {
|
||||
println("\nCreating binary library file without header for target ${compTarget.name}.")
|
||||
command.add("--nostart") // should be headerless bin, because basic has problems doing a normal LOAD"lib",8,1 - need to use BLOAD
|
||||
}
|
||||
binFile
|
||||
}
|
||||
else -> throw AssemblyError("invalid output type")
|
||||
}
|
||||
|
||||
command.addAll(listOf("--output", outFile.toString(), assemblyFile.toString()))
|
||||
command.addAll(listOf("--output", prgFile.toString(), assemblyFile.toString()))
|
||||
assemblerCommand = command
|
||||
|
||||
println("\nCreating prg for target ${compTarget.name}.")
|
||||
}
|
||||
ProgramType.ATARIXEX -> {
|
||||
OutputType.XEX -> {
|
||||
// Atari800XL .xex generation.
|
||||
|
||||
val command = mutableListOf("64tass", "--case-sensitive", "--long-branch", "-Wall", "-Wno-implied-reg", "--no-monitor")
|
||||
val command = mutableListOf("64tass", "--atari-xex", "--case-sensitive", "--long-branch",
|
||||
"-Wall", "-Wno-implied-reg", "--no-monitor", "--dump-labels", "--vice-labels", "--labels=$viceMonListFile")
|
||||
|
||||
if(options.warnSymbolShadowing)
|
||||
command.add("-Wshadow")
|
||||
@ -87,30 +64,14 @@ internal class AssemblyProgram(
|
||||
if(options.asmListfile)
|
||||
command.add("--list=$listFile")
|
||||
|
||||
val outFile = when (options.output) {
|
||||
OutputType.XEX -> {
|
||||
command.add("--atari-xex")
|
||||
println("\nCreating xex for target ${compTarget.name}.")
|
||||
xexFile
|
||||
}
|
||||
OutputType.RAW -> {
|
||||
command.add("--nostart")
|
||||
println("\nCreating raw binary for target ${compTarget.name}.")
|
||||
binFile
|
||||
}
|
||||
else -> throw AssemblyError("invalid output type")
|
||||
}
|
||||
command.addAll(listOf("--output", outFile.toString(), assemblyFile.toString()))
|
||||
command.addAll(listOf("--output", xexFile.toString(), assemblyFile.toString()))
|
||||
assemblerCommand = command
|
||||
println("\nCreating xex for target ${compTarget.name}.")
|
||||
}
|
||||
ProgramType.NEORAW -> {
|
||||
// Neo6502 raw program generation.
|
||||
|
||||
if(options.output!=OutputType.RAW || options.loadAddress!=0x0800u || options.launcher!=CbmPrgLauncherType.NONE) {
|
||||
throw AssemblyError("invalid program compilation options. Neo6502 requires %output raw, %launcher none, %address $0800")
|
||||
}
|
||||
|
||||
val command = mutableListOf("64tass", "--case-sensitive", "--long-branch", "-Wall", "-Wno-implied-reg", "--no-monitor")
|
||||
OutputType.RAW -> {
|
||||
// Neo6502/headerless raw program generation.
|
||||
val command = mutableListOf("64tass", "--nostart", "--case-sensitive", "--long-branch",
|
||||
"-Wall", "-Wno-implied-reg", "--no-monitor", "--dump-labels", "--vice-labels", "--labels=$viceMonListFile")
|
||||
|
||||
if(options.warnSymbolShadowing)
|
||||
command.add("-Wshadow")
|
||||
@ -123,18 +84,38 @@ internal class AssemblyProgram(
|
||||
if(options.asmListfile)
|
||||
command.add("--list=$listFile")
|
||||
|
||||
val outFile = when (options.output) {
|
||||
OutputType.RAW -> {
|
||||
command.add("--nostart")
|
||||
println("\nCreating raw binary for target ${compTarget.name}.")
|
||||
binFile
|
||||
}
|
||||
else -> throw AssemblyError("invalid output type, need 'raw'")
|
||||
command.addAll(listOf("--output", binFile.toString(), assemblyFile.toString()))
|
||||
assemblerCommand = command
|
||||
println("\nCreating raw binary for target ${compTarget.name}.")
|
||||
}
|
||||
OutputType.LIBRARY -> {
|
||||
// CBM machines library (.bin) generation (with or without 2 byte load address header depending on the compilation target machine)
|
||||
|
||||
val command = mutableListOf("64tass", "--ascii", "--case-sensitive", "--long-branch",
|
||||
"-Wall", "-Wno-implied-reg", "--no-monitor", "--dump-labels", "--vice-labels", "--labels=$viceMonListFile")
|
||||
|
||||
if(options.warnSymbolShadowing)
|
||||
command.add("-Wshadow")
|
||||
else
|
||||
command.add("-Wno-shadow")
|
||||
|
||||
if(options.asmQuiet)
|
||||
command.add("--quiet")
|
||||
|
||||
if(options.asmListfile)
|
||||
command.add("--list=$listFile")
|
||||
|
||||
if(compTarget.name in listOf(C64Target.NAME, C128Target.NAME, PETTarget.NAME)) {
|
||||
println("\nCreating binary library file with header for target ${compTarget.name}.")
|
||||
command.add("--cbm-prg")
|
||||
} else {
|
||||
println("\nCreating binary library file without header for target ${compTarget.name}.")
|
||||
command.add("--nostart") // should be headerless bin, because basic has problems doing a normal LOAD"lib",8,1 - need to use BLOAD
|
||||
}
|
||||
command.addAll(listOf("--output", outFile.toString(), assemblyFile.toString()))
|
||||
|
||||
command.addAll(listOf("--output", binFile.toString(), assemblyFile.toString()))
|
||||
assemblerCommand = command
|
||||
}
|
||||
else -> throw AssemblyError("invalid program type")
|
||||
}
|
||||
|
||||
if(options.compTarget.additionalAssemblerOptions!=null)
|
||||
|
@ -70,7 +70,7 @@ private fun compileMain(args: Array<String>): Boolean {
|
||||
val includeSourcelines by cli.option(ArgType.Boolean, fullName = "sourcelines", description = "include original Prog8 source lines in generated asm code")
|
||||
val dontSplitWordArrays by cli.option(ArgType.Boolean, fullName = "dontsplitarrays", description = "don't store any word array as split lsb/msb in memory, as if all of those have @nosplit")
|
||||
val sourceDirs by cli.option(ArgType.String, fullName="srcdirs", description = "list of extra paths, separated with ${File.pathSeparator}, to search in for imported modules").multiple().delimiter(File.pathSeparator)
|
||||
val compilationTarget by cli.option(ArgType.String, fullName = "target", description = "target output of the compiler (one of ${CompilationTargets.joinToString(",")}) (required)")
|
||||
val compilationTarget by cli.option(ArgType.String, fullName = "target", description = "target output of the compiler (one of ${CompilationTargets.joinToString(",")} or a custom target properties file) (required)")
|
||||
val varsGolden by cli.option(ArgType.Boolean, fullName = "varsgolden", description = "put uninitialized variables in 'golden ram' memory area instead of at the end of the program. On the cx16 target this is $0400-07ff. This is unavailable on other systems.")
|
||||
val varsHighBank by cli.option(ArgType.Int, fullName = "varshigh", description = "put uninitialized variables in high memory area instead of at the end of the program. On the cx16 target the value specifies the HiRAM bank to use, on other systems this value is ignored.")
|
||||
val startVm by cli.option(ArgType.Boolean, fullName = "vm", description = "run a .p8ir IR source file in the embedded VM")
|
||||
|
@ -243,34 +243,12 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
|
||||
internal fun determineProgramLoadAddress(program: Program, options: CompilationOptions, errors: IErrorReporter) {
|
||||
val specifiedAddress = program.toplevelModule.loadAddress
|
||||
var loadAddress: UInt? = null
|
||||
if(specifiedAddress!=null) {
|
||||
if(specifiedAddress!=null)
|
||||
loadAddress = specifiedAddress.first
|
||||
}
|
||||
else {
|
||||
when(options.output) {
|
||||
OutputType.PRG -> {
|
||||
if(options.launcher==CbmPrgLauncherType.BASIC) {
|
||||
loadAddress = options.compTarget.PROGRAM_LOAD_ADDRESS
|
||||
}
|
||||
}
|
||||
OutputType.XEX -> {
|
||||
if(options.launcher!=CbmPrgLauncherType.NONE)
|
||||
throw AssemblyError("atari xex output can't contain BASIC launcher")
|
||||
loadAddress = options.compTarget.PROGRAM_LOAD_ADDRESS
|
||||
}
|
||||
OutputType.LIBRARY -> {
|
||||
if(options.launcher!=CbmPrgLauncherType.NONE)
|
||||
throw AssemblyError("library output can't contain BASIC launcher")
|
||||
if(options.zeropage!=ZeropageType.DONTUSE)
|
||||
throw AssemblyError("library output can't use zeropage")
|
||||
if(options.noSysInit==false)
|
||||
throw AssemblyError("library output can't have sysinit")
|
||||
// LIBRARY has no predefined load address.
|
||||
}
|
||||
else
|
||||
loadAddress = options.compTarget.PROGRAM_LOAD_ADDRESS
|
||||
|
||||
|
||||
OutputType.RAW -> { }
|
||||
}
|
||||
}
|
||||
|
||||
if(options.output==OutputType.PRG && options.launcher==CbmPrgLauncherType.BASIC && options.compTarget.customLauncher.isEmpty()) {
|
||||
val expected = options.compTarget.PROGRAM_LOAD_ADDRESS
|
||||
@ -279,11 +257,6 @@ internal fun determineProgramLoadAddress(program: Program, options: CompilationO
|
||||
}
|
||||
}
|
||||
|
||||
if(loadAddress==null) {
|
||||
errors.err("load address must be specified for the selected output/launcher options", program.toplevelModule.position)
|
||||
return
|
||||
}
|
||||
|
||||
options.loadAddress = loadAddress
|
||||
|
||||
options.memtopAddress = program.toplevelModule.memtopAddress?.first ?: options.compTarget.PROGRAM_MEMTOP_ADDRESS
|
||||
|
@ -124,8 +124,8 @@ class TestCompilerOnExamplesCx16: FunSpec({
|
||||
"zsmkit_v1/demo2",
|
||||
"zsmkit_v2/demo",
|
||||
"banking/program",
|
||||
// "fileselector/main.p8",
|
||||
// "fileselector/standalone.p8",
|
||||
// "fileselector/main.p8",
|
||||
"amiga",
|
||||
"audioroutines",
|
||||
"automatons",
|
||||
|
@ -26,9 +26,8 @@ You can compile programs for various machines that are built in into the compile
|
||||
* Commodore 64
|
||||
* Commodore 128 (limited support)
|
||||
* Commodore PET (limited support)
|
||||
* Atari 800 XL (very limited support)
|
||||
* Neo6502 (very imited support)
|
||||
* any other 65(C)02 target machine or setup can be configured to a great extent in a user written configuration file.
|
||||
There are some examples included for the Atari 800 XL, NEO6502 and such.
|
||||
|
||||
Some language features are mentioned below, and you can also read :ref:`comparingprog8` if you
|
||||
want to quickly read about how Prog8 compares to well-known other languages.
|
||||
@ -57,7 +56,7 @@ Want to buy me a coffee or a pizza perhaps?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
This project was created over the last couple of years by dedicating thousands of hours of my free time to it, to make it the best I possibly can.
|
||||
If you like Prog8, and think it's worth a nice cup of hot coffee or a delicious pizza,
|
||||
you can help me out a little bit over at https://ko-fi.com/irmen .
|
||||
you can help me out a little bit over at https://ko-fi.com/irmen or https://paypal.me/irmendejong .
|
||||
|
||||
|
||||
.. image:: _static/cube3d.png
|
||||
|
@ -995,13 +995,13 @@ sys (part of syslib)
|
||||
system when the program is running.
|
||||
The following return values are currently defined:
|
||||
|
||||
- 7 = Neo6502
|
||||
- 8 = Atari 8 bits
|
||||
- 16 = Commander X16
|
||||
- 64 = Commodore 64
|
||||
- 128 = Commodore 128
|
||||
- 255 = Virtual machine
|
||||
|
||||
|
||||
``exit (returncode)``
|
||||
Immediately stops the program and exits it, with the returncode in the A register.
|
||||
Note: custom interrupt handlers remain active unless manually cleared first!
|
||||
|
@ -1,20 +1,16 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
- (WIP) Make neo and atari targets external via configs? They are very bare bones atm so easier to contribute to if they're configurable externally? What about the pet32 target
|
||||
|
||||
- add Adiee5's NES target and example to the docs (or the custom targets examples) somewhere https://github.com/adiee5/prog8-nes-target
|
||||
|
||||
- add paypal donation button as well?
|
||||
- announce prog8 on the 6502.org site?
|
||||
|
||||
...
|
||||
|
||||
|
||||
Future Things and Ideas
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Improve compilation target configurability: the program type (CBMPRG, ATARIXEX etc) is still hardcoded into the compiler (AssemblyProgram.kt) + emulator binary
|
||||
- Improve compilation target configurability: emulator binary/cmdline?
|
||||
neo6502 emulator: "neo hello.bin@800 cold"
|
||||
atari emulators: "atari800 -xl -xl-rev 2 -nobasic -run hello.xex >/dev/null 2>/dev/null" or second one: "Altirra64.exe hello.xex"
|
||||
|
||||
- Look at github PR for improved romability
|
||||
- Kotlin: can we use inline value classes in certain spots?
|
||||
- add float support to the configurable compiler targets
|
||||
|
@ -1,76 +0,0 @@
|
||||
package prog8.code.target
|
||||
|
||||
import prog8.code.core.*
|
||||
import prog8.code.target.encodings.Encoder
|
||||
import prog8.code.target.zp.AtariZeropage
|
||||
import java.nio.file.Path
|
||||
|
||||
|
||||
|
||||
class AtariTarget: ICompilationTarget, IStringEncoding by Encoder, IMemSizer by NormalMemSizer(FLOAT_MEM_SIZE) {
|
||||
override val name = NAME
|
||||
override val defaultEncoding = Encoding.ATASCII
|
||||
override val libraryPath = null
|
||||
override val customLauncher: List<String> = emptyList()
|
||||
override val additionalAssemblerOptions = null
|
||||
|
||||
companion object {
|
||||
const val NAME = "atari"
|
||||
const val FLOAT_MEM_SIZE = 6
|
||||
}
|
||||
|
||||
override val cpu = CpuType.CPU6502
|
||||
override val programType = ProgramType.ATARIXEX
|
||||
|
||||
override val FLOAT_MAX_POSITIVE = 9.999999999e97
|
||||
override val FLOAT_MAX_NEGATIVE = -9.999999999e97
|
||||
override val FLOAT_MEM_SIZE = AtariTarget.FLOAT_MEM_SIZE
|
||||
override val STARTUP_CODE_RESERVED_SIZE = 20u
|
||||
override val PROGRAM_LOAD_ADDRESS = 0x2000u
|
||||
override val PROGRAM_MEMTOP_ADDRESS = 0xffffu // TODO what's memtop?
|
||||
|
||||
override val BSSHIGHRAM_START = 0u // TODO
|
||||
override val BSSHIGHRAM_END = 0u // TODO
|
||||
override val BSSGOLDENRAM_START = 0u // TODO
|
||||
override val BSSGOLDENRAM_END = 0u // TODO
|
||||
|
||||
override lateinit var zeropage: Zeropage
|
||||
override lateinit var golden: GoldenRam
|
||||
|
||||
override fun getFloatAsmBytes(num: Number) = TODO("atari float asm bytes from number")
|
||||
override fun convertFloatToBytes(num: Double): List<UByte> = TODO("atari float to bytes")
|
||||
override fun convertBytesToFloat(bytes: List<UByte>): Double = TODO("atari bytes to float")
|
||||
|
||||
override fun launchEmulator(selectedEmulator: Int, programNameWithPath: Path) {
|
||||
val emulatorName: String
|
||||
val cmdline: List<String>
|
||||
when(selectedEmulator) {
|
||||
1 -> {
|
||||
emulatorName = "atari800"
|
||||
cmdline = listOf(emulatorName, "-xl", "-xl-rev", "2", "-nobasic", "-run", "${programNameWithPath}.xex")
|
||||
}
|
||||
2 -> {
|
||||
emulatorName = "altirra"
|
||||
cmdline = listOf("Altirra64.exe", "${programNameWithPath.normalize()}.xex")
|
||||
}
|
||||
else -> {
|
||||
System.err.println("Atari target only supports atari800 and altirra emulators.")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// TODO monlist?
|
||||
|
||||
println("\nStarting Atari800XL emulator $emulatorName...")
|
||||
val processb = ProcessBuilder(cmdline) // no inheritIO because the emulator destroys the terminal configuration somehow
|
||||
val process: Process = processb.start()
|
||||
process.waitFor()
|
||||
}
|
||||
|
||||
override fun isIOAddress(address: UInt): Boolean = address==0u || address==1u || address in 0xd000u..0xdfffu // TODO
|
||||
|
||||
override fun initializeMemoryAreas(compilerOptions: CompilationOptions) {
|
||||
zeropage = AtariZeropage(compilerOptions)
|
||||
golden = GoldenRam(compilerOptions, UIntRange.EMPTY)
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
package prog8.code.target.zp
|
||||
|
||||
import prog8.code.core.CompilationOptions
|
||||
import prog8.code.core.InternalCompilerException
|
||||
import prog8.code.core.Zeropage
|
||||
import prog8.code.core.ZeropageType
|
||||
|
||||
class AtariZeropage(options: CompilationOptions) : Zeropage(options) {
|
||||
|
||||
override val SCRATCH_B1 = 0xcbu // temp storage for a single byte
|
||||
override val SCRATCH_REG = 0xccu // temp storage for a register byte, must be B1+1
|
||||
override val SCRATCH_W1 = 0xcdu // temp storage 1 for a word $cd+$ce
|
||||
override val SCRATCH_W2 = 0xcfu // temp storage 2 for a word $cf+$d0 TODO is $d0 okay to use?
|
||||
|
||||
init {
|
||||
if (options.floats) {
|
||||
throw InternalCompilerException("Atari target doesn't yet support floating point routines")
|
||||
}
|
||||
|
||||
if (options.floats && options.zeropage !in arrayOf(
|
||||
ZeropageType.FLOATSAFE,
|
||||
ZeropageType.BASICSAFE,
|
||||
ZeropageType.DONTUSE
|
||||
))
|
||||
throw InternalCompilerException("when floats are enabled, zero page type should be 'floatsafe' or 'basicsafe' or 'dontuse'")
|
||||
|
||||
when (options.zeropage) {
|
||||
ZeropageType.FULL -> {
|
||||
// TODO all atari usable zero page locations, except the ones used by the system's IRQ routine
|
||||
free.addAll(0x00u..0xffu)
|
||||
// TODO atari free.removeAll(arrayOf(0xa0u, 0xa1u, 0xa2u, 0x91u, 0xc0u, 0xc5u, 0xcbu, 0xf5u, 0xf6u)) // these are updated by IRQ
|
||||
}
|
||||
ZeropageType.KERNALSAFE -> {
|
||||
free.addAll(0x80u..0xffu) // TODO
|
||||
}
|
||||
ZeropageType.BASICSAFE,
|
||||
ZeropageType.FLOATSAFE -> {
|
||||
free.addAll(0x80u..0xffu) // TODO
|
||||
free.removeAll(0xd4u .. 0xefu) // floating point storage
|
||||
}
|
||||
ZeropageType.DONTUSE -> {
|
||||
free.clear() // don't use zeropage at all
|
||||
}
|
||||
}
|
||||
|
||||
val distinctFree = free.distinct()
|
||||
free.clear()
|
||||
free.addAll(distinctFree)
|
||||
|
||||
removeReservedFromFreePool()
|
||||
retainAllowed()
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
package prog8.code.target
|
||||
|
||||
import prog8.code.core.*
|
||||
import prog8.code.target.encodings.Encoder
|
||||
import prog8.code.target.zp.Neo6502Zeropage
|
||||
import java.nio.file.Path
|
||||
|
||||
|
||||
class Neo6502Target: ICompilationTarget, IStringEncoding by Encoder, IMemSizer by NormalMemSizer(FLOAT_MEM_SIZE) {
|
||||
override val name = NAME
|
||||
override val defaultEncoding = Encoding.ISO
|
||||
override val libraryPath = null
|
||||
override val customLauncher: List<String> = emptyList()
|
||||
override val additionalAssemblerOptions = null
|
||||
|
||||
companion object {
|
||||
const val NAME = "neo"
|
||||
const val FLOAT_MEM_SIZE = 6
|
||||
}
|
||||
|
||||
|
||||
override val cpu = CpuType.CPU65C02
|
||||
override val programType = ProgramType.NEORAW
|
||||
|
||||
override val FLOAT_MAX_POSITIVE = 9.999999999e97
|
||||
override val FLOAT_MAX_NEGATIVE = -9.999999999e97
|
||||
override val FLOAT_MEM_SIZE = Neo6502Target.FLOAT_MEM_SIZE
|
||||
override val STARTUP_CODE_RESERVED_SIZE = 20u
|
||||
override val PROGRAM_LOAD_ADDRESS = 0x0800u
|
||||
override val PROGRAM_MEMTOP_ADDRESS = 0xfc00u // kernal starts here
|
||||
|
||||
override val BSSHIGHRAM_START = 0u // TODO
|
||||
override val BSSHIGHRAM_END = 0u // TODO
|
||||
override val BSSGOLDENRAM_START = 0u // TODO
|
||||
override val BSSGOLDENRAM_END = 0u // TODO
|
||||
|
||||
override lateinit var zeropage: Zeropage
|
||||
override lateinit var golden: GoldenRam
|
||||
|
||||
override fun getFloatAsmBytes(num: Number) = TODO("atari float asm bytes from number")
|
||||
override fun convertFloatToBytes(num: Double): List<UByte> = TODO("atari float to bytes")
|
||||
override fun convertBytesToFloat(bytes: List<UByte>): Double = TODO("atari bytes to float")
|
||||
|
||||
override fun launchEmulator(selectedEmulator: Int, programNameWithPath: Path) {
|
||||
if(selectedEmulator!=1) {
|
||||
System.err.println("The neo target only supports the main emulator (neo).")
|
||||
return
|
||||
}
|
||||
|
||||
val cmdline = listOf("neo", "${programNameWithPath}.bin@800", "cold")
|
||||
|
||||
println("\nStarting Neo6502 emulator...")
|
||||
val processb = ProcessBuilder(cmdline).inheritIO()
|
||||
val process: Process = processb.start()
|
||||
process.waitFor()
|
||||
}
|
||||
|
||||
override fun isIOAddress(address: UInt): Boolean = address in 0xff00u..0xff0fu
|
||||
|
||||
override fun initializeMemoryAreas(compilerOptions: CompilationOptions) {
|
||||
zeropage = Neo6502Zeropage(compilerOptions)
|
||||
golden = GoldenRam(compilerOptions, UIntRange.EMPTY)
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
package prog8.code.target.zp
|
||||
|
||||
import prog8.code.core.*
|
||||
|
||||
class Neo6502Zeropage(options: CompilationOptions) : Zeropage(options) {
|
||||
|
||||
override val SCRATCH_B1 = 0xfau // temp storage for a single byte
|
||||
override val SCRATCH_REG = 0xfbu // temp storage for a register byte, must be B1+1
|
||||
override val SCRATCH_W1 = 0xfcu // temp storage 1 for a word $fc+$fd
|
||||
override val SCRATCH_W2 = 0xfeu // temp storage 2 for a word $fe+$ff
|
||||
|
||||
init {
|
||||
if (options.floats) {
|
||||
throw InternalCompilerException("Neo6502 target doesn't support floating point routines")
|
||||
}
|
||||
|
||||
when (options.zeropage) {
|
||||
ZeropageType.DONTUSE -> {
|
||||
free.clear() // don't use zeropage at all
|
||||
}
|
||||
else -> {
|
||||
free.addAll(0x22u..0xffu)
|
||||
}
|
||||
}
|
||||
|
||||
val distinctFree = free.distinct()
|
||||
free.clear()
|
||||
free.addAll(distinctFree)
|
||||
|
||||
removeReservedFromFreePool()
|
||||
allocateCx16VirtualRegisters()
|
||||
retainAllowed()
|
||||
}
|
||||
|
||||
private fun allocateCx16VirtualRegisters() {
|
||||
// Note: the 16 virtual registers R0-R15 are not regular allocated variables, they're *memory mapped* elsewhere to fixed addresses.
|
||||
// However, to be able for the compiler to "see" them as zeropage variables, we have to register them here as well.
|
||||
// This is important because the compiler sometimes treats ZP variables more efficiently (for example if it's a pointer)
|
||||
for(reg in 0..15) {
|
||||
allocatedVariables["cx16.r${reg}"] = VarAllocation((2+reg*2).toUInt(), DataType.forDt(BaseDataType.UWORD), 2) // cx16.r0 .. cx16.r15
|
||||
allocatedVariables["cx16.r${reg}s"] = VarAllocation((2+reg*2).toUInt(), DataType.forDt(BaseDataType.WORD), 2) // cx16.r0s .. cx16.r15s
|
||||
allocatedVariables["cx16.r${reg}L"] = VarAllocation((2+reg*2).toUInt(), DataType.forDt(BaseDataType.UBYTE), 1) // cx16.r0L .. cx16.r15L
|
||||
allocatedVariables["cx16.r${reg}H"] = VarAllocation((3+reg*2).toUInt(), DataType.forDt(BaseDataType.UBYTE), 1) // cx16.r0H .. cx16.r15H
|
||||
allocatedVariables["cx16.r${reg}sL"] = VarAllocation((2+reg*2).toUInt(), DataType.forDt(BaseDataType.BYTE), 1) // cx16.r0sL .. cx16.r15sL
|
||||
allocatedVariables["cx16.r${reg}sH"] = VarAllocation((3+reg*2).toUInt(), DataType.forDt(BaseDataType.BYTE), 1) // cx16.r0sH .. cx16.r15sH
|
||||
}
|
||||
}
|
||||
}
|
@ -2,3 +2,9 @@ Various examples for configurable target machines, such as the NEO6502, Atari 80
|
||||
and "tiny" example configurations for the X16 or C64 that provide more example materials.
|
||||
|
||||
Look in the Makefile to see how to build or run the various programs.
|
||||
|
||||
The user 'adiee5' has been working on a Nintendo Entertainment System (NES) compilation target
|
||||
and example program, you can find those efforts here on GitHub: https://github.com/adiee5/prog8-nes-target
|
||||
Note that the NES is a very alien architecture for Prog8 still and the support is very limited
|
||||
(for example, prog8 is not aware that the program code usually is going to end up in a ROM cartridge,
|
||||
and currently still generates code that might nog work in ROM.)
|
||||
|
@ -1,6 +1,7 @@
|
||||
%import textio
|
||||
%zeropage basicsafe
|
||||
%launcher none
|
||||
%output xex
|
||||
|
||||
; This example computes the first 20 values of the Fibonacci sequence.
|
||||
; Note: this program is compatible with atari.
|
||||
|
@ -1,6 +1,7 @@
|
||||
%import textio
|
||||
%zeropage basicsafe
|
||||
%launcher none
|
||||
%output xex
|
||||
|
||||
; hello world test for Atari 8-bit
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
# configuration file for a C64 like Prog8 compilation target
|
||||
|
||||
cpu = 6502
|
||||
program = ATARIXEX
|
||||
encoding = atascii
|
||||
load_address = $2000
|
||||
memtop = $ffff
|
||||
@ -23,8 +22,9 @@ zp_scratch_w2 = $cf
|
||||
# free zeropage locations for the various zp usage methods
|
||||
# zero or more zeropage address ranges (inclusive).
|
||||
zp_fullsafe = $00-$ff
|
||||
zp_kernalsafe = $00-$ff
|
||||
zp_basicsafe = $00-$ff
|
||||
zp_kernalsafe = $80-$ff
|
||||
zp_basicsafe = $80-$ff
|
||||
# TODO zp_floatsafe = $80-$d3,$f0-$ff
|
||||
|
||||
# the start of the 32 bytes used by the R0-R15 virtual registers. Can be in Zeropage or elsewhere.
|
||||
virtual_registers = $1b00
|
||||
@ -32,9 +32,9 @@ virtual_registers = $1b00
|
||||
# Where can we find the standard library (syslib.p8). You can still add more paths manually using -srcdirs
|
||||
library = ./libraries/atari
|
||||
|
||||
# if a non-empty custom launcher string is supplied, the compiler won't output ANY launcher / init code by itself,
|
||||
# if a non-empty custom launcher code string is supplied, the compiler won't output ANY launcher / init code by itself,
|
||||
# and instead outputs whatever is specified here. (You can use \n here for newline and \ for line continuantions)
|
||||
custom_launcher =
|
||||
custom_launcher_code =
|
||||
|
||||
# additional options passed to the assembler program
|
||||
assembler_options =
|
||||
|
@ -1,7 +1,6 @@
|
||||
# configuration file for a C64 like Prog8 compilation target
|
||||
|
||||
cpu = 65C02
|
||||
program = NEORAW
|
||||
encoding = iso
|
||||
load_address = $0800
|
||||
memtop = $fc00
|
||||
@ -32,9 +31,9 @@ virtual_registers = $02
|
||||
# Where can we find the standard library (syslib.p8). You can still add more paths manually using -srcdirs
|
||||
library = ./libraries/neo6502
|
||||
|
||||
# if a non-empty custom launcher string is supplied, the compiler won't output ANY launcher / init code by itself,
|
||||
# if a non-empty custom launcher code string is supplied, the compiler won't output ANY launcher / init code by itself,
|
||||
# and instead outputs whatever is specified here. (You can use \n here for newline and \ for line continuantions)
|
||||
custom_launcher =
|
||||
custom_launcher_code =
|
||||
|
||||
# additional options passed to the assembler program
|
||||
assembler_options =
|
||||
|
@ -1,7 +1,6 @@
|
||||
# configuration file for a C64 like Prog8 compilation target
|
||||
|
||||
cpu = 6502
|
||||
program = CBMPRG
|
||||
encoding = petscii
|
||||
load_address = $0801
|
||||
memtop = $cfe0
|
||||
@ -32,9 +31,9 @@ virtual_registers = $cfe0
|
||||
# Where can we find the standard library (syslib.p8). You can still add more paths manually using -srcdirs
|
||||
library = ./libraries/tinyc64
|
||||
|
||||
# if a non-empty custom launcher string is supplied, the compiler won't output ANY launcher / init code by itself,
|
||||
# if a non-empty custom launcher code string is supplied, the compiler won't output ANY launcher / init code by itself,
|
||||
# and instead outputs whatever is specified here. (You can use \n here for newline and \ for line continuantions)
|
||||
custom_launcher =
|
||||
custom_launcher_code =
|
||||
|
||||
# additional options passed to the assembler program
|
||||
assembler_options =
|
||||
|
@ -1,7 +1,6 @@
|
||||
# configuration file for a Commander X16 like Prog8 compilation target
|
||||
|
||||
cpu = 65C02
|
||||
program = CBMPRG
|
||||
encoding = petscii
|
||||
load_address = $0801
|
||||
memtop = $9f00
|
||||
@ -32,9 +31,9 @@ virtual_registers = $02
|
||||
# Where can we find the standard library (syslib.p8). You can still add more paths manually using -srcdirs
|
||||
library = ./libraries/tinycx16
|
||||
|
||||
# if a non-empty custom launcher string is supplied, the compiler won't output ANY launcher / init code by itself,
|
||||
# if a non-empty custom launcher code string is supplied, the compiler won't output ANY launcher / init code by itself,
|
||||
# and instead outputs whatever is specified here. (You can use \n here for newline and \ for line continuantions)
|
||||
custom_launcher =
|
||||
custom_launcher_code =
|
||||
|
||||
# additional options passed to the assembler program
|
||||
assembler_options =
|
||||
|
@ -1,7 +1,6 @@
|
||||
# configuration file for a PET like Prog8 compilation target
|
||||
|
||||
cpu = 6502
|
||||
program = CBMPRG
|
||||
encoding = petscii
|
||||
load_address = $0401
|
||||
memtop = $8000
|
||||
@ -32,9 +31,9 @@ virtual_registers = $7fe0
|
||||
# Where can we find the standard library (syslib.p8). You can still add more paths manually using -srcdirs
|
||||
library = ./libraries/tinypet
|
||||
|
||||
# if a non-empty custom launcher string is supplied, the compiler won't output ANY launcher / init code by itself,
|
||||
# if a non-empty custom launcher code string is supplied, the compiler won't output ANY launcher / init code by itself,
|
||||
# and instead outputs whatever is specified here. (You can use \n here for newline and \ for line continuantions)
|
||||
custom_launcher =
|
||||
custom_launcher_code =
|
||||
|
||||
# additional options passed to the assembler program
|
||||
assembler_options =
|
||||
|
Loading…
x
Reference in New Issue
Block a user