finalize extracting neo and atari compiler targets into configuration files instead

This commit is contained in:
Irmen de Jong 2025-02-12 12:07:25 +01:00
parent 99ff5dd078
commit 2aeb7a838e
27 changed files with 86 additions and 410 deletions

View File

@ -1,4 +1,7 @@
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/H2H6S0FFF)
PayPal: [![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://paypal.me/irmendejong)
[![Documentation](https://readthedocs.org/projects/prog8/badge/?version=latest)](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

View File

@ -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?

View File

@ -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

View File

@ -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

View File

@ -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...

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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)

View File

@ -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")

View File

@ -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

View File

@ -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",

View File

@ -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

View File

@ -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!

View File

@ -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

View File

@ -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)
}
}

View File

@ -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()
}
}

View File

@ -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)
}
}

View File

@ -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
}
}
}

View File

@ -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.)

View File

@ -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.

View File

@ -1,6 +1,7 @@
%import textio
%zeropage basicsafe
%launcher none
%output xex
; hello world test for Atari 8-bit

View File

@ -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 =

View File

@ -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 =

View File

@ -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 =

View File

@ -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 =

View File

@ -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 =