initial neo6502 target

This commit is contained in:
Irmen de Jong 2024-04-25 01:17:44 +02:00
parent 688dce6145
commit a50400b7d1
19 changed files with 1241 additions and 31 deletions

View File

@ -27,6 +27,7 @@ val CompilationTargets = listOf(
Cx16Target.NAME,
PETTarget.NAME,
AtariTarget.NAME,
Neo6502Target.NAME,
VMTarget.NAME
)
@ -37,5 +38,6 @@ fun getCompilationTargetByName(name: String) = when(name.lowercase()) {
PETTarget.NAME -> PETTarget()
AtariTarget.NAME -> AtariTarget()
VMTarget.NAME -> VMTarget()
Neo6502Target.NAME -> Neo6502Target()
else -> throw IllegalArgumentException("invalid compilation target")
}
}

View File

@ -0,0 +1,30 @@
package prog8.code.target
import prog8.code.core.*
import prog8.code.target.neo6502.Neo6502MachineDefinition
class Neo6502Target: ICompilationTarget, IStringEncoding by Encoder, IMemSizer {
override val name = NAME
override val machine = Neo6502MachineDefinition()
override val defaultEncoding = Encoding.ISO
companion object {
const val NAME = "neo"
}
override fun memorySize(dt: DataType): Int {
return when(dt) {
in ByteDatatypesWithBoolean -> 1
in WordDatatypes, in PassByReferenceDatatypes -> 2
DataType.FLOAT -> machine.FLOAT_MEM_SIZE
else -> throw IllegalArgumentException("invalid datatype")
}
}
override fun memorySize(arrayDt: DataType, numElements: Int) =
if(arrayDt== DataType.UWORD)
numElements // pointer to bytes.
else
memorySize(ArrayToElementTypes.getValue(arrayDt)) * numElements
}

View File

@ -0,0 +1,52 @@
package prog8.code.target.neo6502
import prog8.code.core.*
import java.nio.file.Path
class Neo6502MachineDefinition: IMachineDefinition {
override val cpu = CpuType.CPU65c02
override val FLOAT_MAX_POSITIVE = 9.999999999e97
override val FLOAT_MAX_NEGATIVE = -9.999999999e97
override val FLOAT_MEM_SIZE = 6
override val PROGRAM_LOAD_ADDRESS = 0x0800u
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 importLibs(compilerOptions: CompilationOptions, compilationTargetName: String): List<String> {
return listOf("syslib")
}
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

@ -0,0 +1,48 @@
package prog8.code.target.neo6502
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, 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()
}
override 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 zero page 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.UWORD, 2) // cx16.r0 .. cx16.r15
allocatedVariables["cx16.r${reg}s"] = VarAllocation((2+reg*2).toUInt(), DataType.WORD, 2) // cx16.r0s .. cx16.r15s
allocatedVariables["cx16.r${reg}L"] = VarAllocation((2+reg*2).toUInt(), DataType.UBYTE, 1) // cx16.r0L .. cx16.r15L
allocatedVariables["cx16.r${reg}H"] = VarAllocation((3+reg*2).toUInt(), DataType.UBYTE, 1) // cx16.r0H .. cx16.r15H
allocatedVariables["cx16.r${reg}sL"] = VarAllocation((2+reg*2).toUInt(), DataType.BYTE, 1) // cx16.r0sL .. cx16.r15sL
allocatedVariables["cx16.r${reg}sH"] = VarAllocation((3+reg*2).toUInt(), DataType.BYTE, 1) // cx16.r0sH .. cx16.r15sH
}
}
}

View File

@ -1,7 +1,9 @@
package prog8.codegen.cpu6502
import prog8.code.core.*
import prog8.code.target.AtariTarget
import prog8.code.target.C64Target
import prog8.code.target.Neo6502Target
import java.nio.file.Path
@ -16,6 +18,7 @@ internal class AssemblyProgram(
private val binFile = outputDir.resolve("$name.bin")
private val viceMonListFile = outputDir.resolve(C64Target.viceMonListName(name))
private val listFile = outputDir.resolve("$name.list")
private val targetWithoutBreakpointsForEmulator = setOf(AtariTarget.NAME, Neo6502Target.NAME)
override fun assemble(options: CompilationOptions, errors: IErrorReporter): Boolean {
@ -96,12 +99,47 @@ internal class AssemblyProgram(
command.addAll(listOf("--output", outFile.toString(), assemblyFile.toString()))
assemblerCommand = command
}
"neo" -> {
// 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")
}
// TODO are these options okay for neo?
val command = mutableListOf("64tass", "--case-sensitive", "--long-branch",
"-Wall", // "-Werror", "-Wno-strict-bool"
"--no-monitor"
)
if(options.warnSymbolShadowing)
command.add("-Wshadow")
else
command.add("-Wno-shadow")
if(options.asmQuiet)
command.add("--quiet")
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", outFile.toString(), assemblyFile.toString()))
assemblerCommand = command
}
else -> throw AssemblyError("invalid compilation target")
}
val proc = ProcessBuilder(assemblerCommand).inheritIO().start()
val result = proc.waitFor()
if (result == 0 && compTarget.name!="atari") {
if (result == 0 && compTarget.name !in targetWithoutBreakpointsForEmulator) {
removeGeneratedLabelsFromMonlist()
generateBreakpointList()
}

View File

@ -21,7 +21,7 @@ atari {
sys {
; ------- lowlevel system routines --------
const ubyte target = 8 ; compilation target specifier. 64 = C64, 128 = C128, 16 = CommanderX16, 8 = atari800XL
const ubyte target = 8 ; compilation target specifier. 255=virtual, 128=C128, 64=C64, 32=PET, 16=CommanderX16, 8=atari800XL, 7=Neo6502
const ubyte sizeof_bool = 1
const ubyte sizeof_byte = 1

View File

@ -402,7 +402,7 @@ asmsub x16jsrfar() {
sys {
; ------- lowlevel system routines --------
const ubyte target = 128 ; compilation target specifier. 64 = C64, 128 = C128, 16 = CommanderX16.
const ubyte target = 128 ; compilation target specifier. 255=virtual, 128=C128, 64=C64, 32=PET, 16=CommanderX16, 8=atari800XL, 7=Neo6502
const ubyte sizeof_bool = 1
const ubyte sizeof_byte = 1

View File

@ -432,7 +432,7 @@ _jmpfar jmp $0000 ; modified
sys {
; ------- lowlevel system routines --------
const ubyte target = 64 ; compilation target specifier. 64 = C64, 128 = C128, 16 = CommanderX16.
const ubyte target = 64 ; compilation target specifier. 255=virtual, 128=C128, 64=C64, 32=PET, 16=CommanderX16, 8=atari800XL, 7=Neo6502
const ubyte sizeof_bool = 1
const ubyte sizeof_byte = 1

View File

@ -332,7 +332,7 @@ cx16 {
&ubyte VERA_FX_X_POS_S = VERA_BASE + $0009
&ubyte VERA_FX_Y_POS_S = VERA_BASE + $000a
&ubyte VERA_FX_POLY_FILL_L = VERA_BASE + $000b
&ubyte VERA_FX_POLY_FILL_H = VERA_BASE + $000c
&ubyte VERA_FX_POLY_FILL_H = VERA_BASE + $000cF
&uword VERA_FX_POLY_FILL = VERA_BASE + $000b
&ubyte VERA_FX_CACHE_L = VERA_BASE + $0009
&ubyte VERA_FX_CACHE_M = VERA_BASE + $000a
@ -1372,7 +1372,7 @@ _continue iny
sys {
; ------- lowlevel system routines --------
const ubyte target = 16 ; compilation target specifier. 64 = C64, 128 = C128, 16 = CommanderX16.
const ubyte target = 16 ; compilation target specifier. 255=virtual, 128=C128, 64=C64, 32=PET, 16=CommanderX16, 8=atari800XL, 7=Neo6502
const ubyte sizeof_bool = 1
const ubyte sizeof_byte = 1

View File

@ -0,0 +1,500 @@
; Convenience macros for Neo6502 applications programming
; SPDX-License-Identifier: CC0-1.0
; obtained from https://github.com/paulscottrobson/neo6502-firmware
;-----------------------------------------------------;
; Neo6502 Kernel jump vectors (see kernel/kernel.asm) ;
;-----------------------------------------------------;
ChainBasicOnlyProgram = $ffdf
ChainBasicProgram = $ffe2
WriteCharacterInline = $ffe5
LoadExtended = $ffe8
ReadLine = $FFEB
ReadCharacter = $FFEE
WriteCharacter = $FFF1
WaitMessage = $FFF4
SendMessage = $FFF7
;--------------------------------------;
; Neo6502 Kernel API control addresses ;
;--------------------------------------;
ControlPort = $FF00
API_COMMAND = ControlPort + 0 ; function group address
API_FUNCTION = ControlPort + 1 ; function address
API_ERROR = ControlPort + 2 ; function error codes
API_STATUS = ControlPort + 3 ; misc hardware status codes (bit-field)
API_PARAMETERS = ControlPort + 4 ; function parameters base address (+0-7)
;------------------------------------------------;
; Neo6502 Kernel API control codes (see api.pdf) ;
;------------------------------------------------;
; Status Information
API_ERROR_NONE = #$00 ; error code
API_STATUS_ESC = #$07 ; flag
; System functions (Group 1)
API_GROUP_SYSTEM = #$01 ; API function group
API_FN_TIMER = #$01 ; API function
API_FN_KEY_STATUS = #$02 ; API function
API_FN_BASIC = #$03 ; API function
API_FN_CREDITS = #$04 ; API function
API_FN_SERIAL_STATUS = #$05 ; API function
API_FN_LOCALE = #$06 ; API function
API_FN_RESET = #$07 ; API function
API_FN_MOS = #$08 ; API function
API_FN_SWEET16 = #$09 ; API function
; Console functions (Group 2)
API_GROUP_CONSOLE = #$02 ; API function group
API_FN_READ_CHAR = #$01 ; API function
API_FN_CONSOLE_STATUS = #$02 ; API function
API_FN_READ_LINE = #$03 ; API function
API_FN_DEFINE_HOTKEY = #$04 ; API function
API_FN_DEFINE_CHAR = #$05 ; API function
API_FN_WRITE_CHAR = #$06 ; API function
API_FN_SET_CURSOR_POS = #$07 ; API function
API_FN_LIST_HOTKEYS = #$08 ; API function
API_FN_SCREEN_SIZE = #$09 ; API function
API_FN_INSERT_LINE = #$0A ; API function
API_FN_DELETE_LINE = #$0B ; API function
API_FN_CLEAR_SCREEN = #$0C ; API function
API_FN_CURSOR_POS = #$0D ; API function
API_FN_CLEAR_REGIION = #$0E ; API function
API_FN_SET_TEXT_COLOR = #$0F ; API function
API_FN_CURSOR_INVERSE = #$10 ; API function
; Console results (Group 2 Function 2)
API_QUEUE_EMPTY = #$FF ; API result (status code)
; File I/O functions (Group 3)
API_GROUP_FILEIO = #$03 ; API function group
API_FN_LIST_DIRECTORY = #$01 ; API function
API_FN_LOAD_FILENAME = #$02 ; API function
API_FN_STORE_FILENAME = #$03 ; API function
API_FN_FILE_OPEN = #$04 ; API function
API_FN_FILE_CLOSE = #$05 ; API function
API_FN_FILE_SEEK = #$06 ; API function
API_FN_FILE_TELL = #$07 ; API function
API_FN_FILE_READ = #$08 ; API function
API_FN_FILE_WRITE = #$09 ; API function
API_FN_FILE_SIZE = #$0A ; API function
API_FN_FILE_SET_SIZE = #$0B ; API function
API_FN_FILE_RENAME = #$0C ; API function
API_FN_FILE_DELETE = #$0D ; API function
API_FN_DIR_CHDIR = #$0E ; API function
API_FN_DIR_MKDIR = #$0F ; API function
API_FN_FILE_STAT = #$10 ; API function
API_FN_DIR_OPEN = #$11 ; API function
API_FN_DIR_READ = #$12 ; API function
API_FN_DIR_CLOSE = #$13 ; API function
API_FN_FILE_COPY = #$14 ; API function
API_FN_SET_ATTR = #$15 ; API function
API_FN_LIST_FILTERED = #$20 ; API function
; File I/O parameters (Group 3 Function 2)
API_FILE_TO_SCREEN = #$FFFF ; API parameter
; Mathematics functions (Group 4)
API_GROUP_MATH = #$04 ; API function group
API_FN_ADD = #$00 ; API function
API_FN_SUB = #$01 ; API function
API_FN_MUL = #$02 ; API function
API_FN_DIV_DEC = #$03 ; API function
API_FN_DIV_INT = #$04 ; API function
API_FN_MOD = #$05 ; API function
API_FN_COMP = #$06 ; API function
API_FN_NEG = #$10 ; API function
API_FN_FLOOR = #$11 ; API function
API_FN_SQRT = #$12 ; API function
API_FN_SINE = #$13 ; API function
API_FN_COS = #$14 ; API function
API_FN_TAN = #$15 ; API function
API_FN_ATAN = #$16 ; API function
API_FN_EXP = #$17 ; API function
API_FN_LOG = #$18 ; API function
API_FN_ABS = #$19 ; API function
API_FN_SIGN = #$1A ; API function
API_FN_RND_DEC = #$1B ; API function
API_FN_RND_INT = #$1C ; API function
API_FN_INT_TO_DEC = #$20 ; API function
API_FN_STR_TO_NUM = #$21 ; API function
API_FN_NUM_TO_STR = #$22 ; API function
API_FN_SET_DEG_RAD_MODE = #$23 ; API function
; Graphics functions (Group 5)
API_GROUP_GRAPHICS = #$05 ; API function group
API_FN_SET_GFX = #$01 ; API function
API_FN_DRAW_LINE = #$02 ; API function
API_FN_DRAW_RECT = #$03 ; API function
API_FN_DRAW_ELLIPSE = #$04 ; API function
API_FN_DRAW_PIXEL = #$05 ; API function
API_FN_DRAW_TEXT = #$06 ; API function
API_FN_DRAW_IMG = #$07 ; API function
API_FN_DRAW_TILEMAP = #$08 ; API function
API_FN_SET_PALETTE = #$20 ; API function
API_FN_READ_PIXEL = #$21 ; API function
API_FN_RESET_PALETTE = #$22 ; API function
API_FN_SET_TILEMAP = #$23 ; API function
API_FN_READ_SPRITE_PXL = #$24 ; API function
API_FN_FRAME_COUNT = #$25 ; API function
API_FN_GET_PALETTE = #$26 ; API function
API_FN_WRITE_PIXEL = #$27 ; API function
API_FN_SET_COLOR = #$40 ; API function
API_FN_SET_SOLID = #$41 ; API function
API_FN_SET_DRAW_SIZE = #$42 ; API function
API_FN_SET_FLIP = #$43 ; API function
; Graphics parameters (Group 5, Function 1 - Group 6, Function 2)
API_FLIP_HORZ = #$00 ; API parameter (flag)
API_FLIP_VERT = #$01 ; API parameter (flag)
; Graphics results (Group 5, Functions 33,36)
API_PIXEL_TRANSPARENT = #$00 ; API result (flag)
; Sprites functions (Group 6)
API_GROUP_SPRITES = #$06 ; API function group
API_FN_SPRITE_RESET = #$01 ; API function
API_FN_SPRITE_SET = #$02 ; API function
API_FN_SPRITE_HIDE = #$03 ; API function
API_FN_SPRITE_COLLISION = #$04 ; API function
API_FN_SPRITE_POS = #$05 ; API function
; Sprites parameters (Group 6, Function 2)
API_SPRITE_TURTLE = #$00 ; API parameter (sprite index)
API_SPRITE_32BIT = #$40 ; API parameter (bit-mask)
API_SPRITE_CLEAR = #$80 ; API parameter (bit-mask)
API_ANCHOR_BL = #$01 ; API parameter (anchor position)
API_ANCHOR_B = #$02 ; API parameter (anchor position)
API_ANCHOR_BR = #$03 ; API parameter (anchor position)
API_ANCHOR_L = #$04 ; API parameter (anchor position)
API_ANCHOR_C = #$05 ; API parameter (anchor position)
API_ANCHOR_R = #$06 ; API parameter (anchor position)
API_ANCHOR_TL = #$07 ; API parameter (anchor position)
API_ANCHOR_T = #$08 ; API parameter (anchor position)
API_ANCHOR_TR = #$09 ; API parameter (anchor position)
; Sprites results (Group 6, Function 4)
API_COLLISION_NONE = #$00 ; API result (flag)
; Controller functions (Group 7)
API_GROUP_CONTROLLER = #$07 ; API function group
API_FN_READ_DEFAULT_CONTROLLER = #$01 ; API function
API_FN_READ_CONTROLLER_COUNT = #$02 ; API function
API_FN_READ_CONTROLLER = #$03 ; API function
; Controller results (Group 7, Function 1)
API_CONTROLLER_LEFT = #$01 ; API result (status bit-mask)
API_CONTROLLER_RIGHT = #$02 ; API result (status bit-mask)
API_CONTROLLER_UP = #$04 ; API result (status bit-mask)
API_CONTROLLER_DOWN = #$08 ; API result (status bit-mask)
API_CONTROLLER_BTNA = #$10 ; API result (status bit-mask)
API_CONTROLLER_BTNB = #$20 ; API result (status bit-mask)
; Sound functions (Group 8)
API_GROUP_SOUND = #$08 ; API function group
API_FN_RESET_SOUND = #$01 ; API function
API_FN_RESET_CHANNEL = #$02 ; API function
API_FN_BEEP = #$03 ; API function
API_FN_QUEUE_SOUND = #$04 ; API function
API_FN_PLAY_SOUND = #$05 ; API function
API_FN_SOUND_STATUS = #$06 ; API function
; Sound parameters (Group 8, Functions 2,4,5)
API_SOUND_CH_00 = #$00 ; API parameter (channel index)
; Sound parameters (Group 8, Function 4)
API_NOTE_REST = #$0000 ; API parameter (musical rest)
API_NOTE_C0 = #$0010 ; API parameter (musical note)
API_NOTE_Cs0 = #$0011 ; API parameter (musical note)
API_NOTE_Df0 = #$0011 ; API parameter (musical note)
API_NOTE_D0 = #$0012 ; API parameter (musical note)
API_NOTE_Ds0 = #$0013 ; API parameter (musical note)
API_NOTE_Ef0 = #$0013 ; API parameter (musical note)
API_NOTE_E0 = #$0015 ; API parameter (musical note)
API_NOTE_F0 = #$0016 ; API parameter (musical note)
API_NOTE_Fs0 = #$0017 ; API parameter (musical note)
API_NOTE_Gf0 = #$0017 ; API parameter (musical note)
API_NOTE_G0 = #$0018 ; API parameter (musical note)
API_NOTE_Af0 = #$001A ; API parameter (musical note)
API_NOTE_Gs0 = #$001A ; API parameter (musical note)
API_NOTE_A0 = #$001C ; API parameter (musical note)
API_NOTE_As0 = #$001D ; API parameter (musical note)
API_NOTE_Bf0 = #$001D ; API parameter (musical note)
API_NOTE_B0 = #$001F ; API parameter (musical note)
API_NOTE_C1 = #$0021 ; API parameter (musical note)
API_NOTE_Cs1 = #$0023 ; API parameter (musical note)
API_NOTE_Df1 = #$0023 ; API parameter (musical note)
API_NOTE_D1 = #$0025 ; API parameter (musical note)
API_NOTE_Ds1 = #$0027 ; API parameter (musical note)
API_NOTE_Ef1 = #$0027 ; API parameter (musical note)
API_NOTE_E1 = #$0029 ; API parameter (musical note)
API_NOTE_F1 = #$002C ; API parameter (musical note)
API_NOTE_Fs1 = #$002E ; API parameter (musical note)
API_NOTE_Gf1 = #$002E ; API parameter (musical note)
API_NOTE_G1 = #$0031 ; API parameter (musical note)
API_NOTE_Af1 = #$0034 ; API parameter (musical note)
API_NOTE_Gs1 = #$0034 ; API parameter (musical note)
API_NOTE_A1 = #$0037 ; API parameter (musical note)
API_NOTE_As1 = #$003A ; API parameter (musical note)
API_NOTE_Bf1 = #$003A ; API parameter (musical note)
API_NOTE_B1 = #$003E ; API parameter (musical note)
API_NOTE_C2 = #$0041 ; API parameter (musical note)
API_NOTE_Cs2 = #$0045 ; API parameter (musical note)
API_NOTE_Df2 = #$0045 ; API parameter (musical note)
API_NOTE_D2 = #$0049 ; API parameter (musical note)
API_NOTE_Ds2 = #$004E ; API parameter (musical note)
API_NOTE_Ef2 = #$004E ; API parameter (musical note)
API_NOTE_E2 = #$0052 ; API parameter (musical note)
API_NOTE_F2 = #$0057 ; API parameter (musical note)
API_NOTE_Fs2 = #$005C ; API parameter (musical note)
API_NOTE_Gf2 = #$005C ; API parameter (musical note)
API_NOTE_G2 = #$0062 ; API parameter (musical note)
API_NOTE_Af2 = #$0068 ; API parameter (musical note)
API_NOTE_Gs2 = #$0068 ; API parameter (musical note)
API_NOTE_A2 = #$006E ; API parameter (musical note)
API_NOTE_As2 = #$0075 ; API parameter (musical note)
API_NOTE_Bf2 = #$0075 ; API parameter (musical note)
API_NOTE_B2 = #$007B ; API parameter (musical note)
API_NOTE_C3 = #$0083 ; API parameter (musical note)
API_NOTE_Cs3 = #$008B ; API parameter (musical note)
API_NOTE_Df3 = #$008B ; API parameter (musical note)
API_NOTE_D3 = #$0093 ; API parameter (musical note)
API_NOTE_Ds3 = #$009C ; API parameter (musical note)
API_NOTE_Ef3 = #$009C ; API parameter (musical note)
API_NOTE_E3 = #$00A5 ; API parameter (musical note)
API_NOTE_F3 = #$00AF ; API parameter (musical note)
API_NOTE_Fs3 = #$00B9 ; API parameter (musical note)
API_NOTE_Gf3 = #$00B9 ; API parameter (musical note)
API_NOTE_G3 = #$00C4 ; API parameter (musical note)
API_NOTE_Af3 = #$00D0 ; API parameter (musical note)
API_NOTE_Gs3 = #$00D0 ; API parameter (musical note)
API_NOTE_A3 = #$00DC ; API parameter (musical note)
API_NOTE_As3 = #$00E9 ; API parameter (musical note)
API_NOTE_Bf3 = #$00E9 ; API parameter (musical note)
API_NOTE_B3 = #$00F7 ; API parameter (musical note)
API_NOTE_C4 = #$0106 ; API parameter (musical note)
API_NOTE_Cs4 = #$0115 ; API parameter (musical note)
API_NOTE_Df4 = #$0115 ; API parameter (musical note)
API_NOTE_D4 = #$0126 ; API parameter (musical note)
API_NOTE_Ds4 = #$0137 ; API parameter (musical note)
API_NOTE_Ef4 = #$0137 ; API parameter (musical note)
API_NOTE_E4 = #$014A ; API parameter (musical note)
API_NOTE_F4 = #$015D ; API parameter (musical note)
API_NOTE_Fs4 = #$0172 ; API parameter (musical note)
API_NOTE_Gf4 = #$0172 ; API parameter (musical note)
API_NOTE_G4 = #$0188 ; API parameter (musical note)
API_NOTE_Af4 = #$019F ; API parameter (musical note)
API_NOTE_Gs4 = #$019F ; API parameter (musical note)
API_NOTE_A4 = #$01B8 ; API parameter (musical note)
API_NOTE_As4 = #$01D2 ; API parameter (musical note)
API_NOTE_Bf4 = #$01D2 ; API parameter (musical note)
API_NOTE_B4 = #$01EE ; API parameter (musical note)
API_NOTE_C5 = #$020B ; API parameter (musical note)
API_NOTE_Cs5 = #$022A ; API parameter (musical note)
API_NOTE_Df5 = #$022A ; API parameter (musical note)
API_NOTE_D5 = #$024B ; API parameter (musical note)
API_NOTE_Ds5 = #$026E ; API parameter (musical note)
API_NOTE_Ef5 = #$026E ; API parameter (musical note)
API_NOTE_E5 = #$0293 ; API parameter (musical note)
API_NOTE_F5 = #$02BA ; API parameter (musical note)
API_NOTE_Fs5 = #$02E4 ; API parameter (musical note)
API_NOTE_Gf5 = #$02E4 ; API parameter (musical note)
API_NOTE_G5 = #$0310 ; API parameter (musical note)
API_NOTE_Af5 = #$033F ; API parameter (musical note)
API_NOTE_Gs5 = #$033F ; API parameter (musical note)
API_NOTE_A5 = #$0370 ; API parameter (musical note)
API_NOTE_As5 = #$03A4 ; API parameter (musical note)
API_NOTE_Bf5 = #$03A4 ; API parameter (musical note)
API_NOTE_B5 = #$03DC ; API parameter (musical note)
API_NOTE_C6 = #$0417 ; API parameter (musical note)
API_NOTE_Cs6 = #$0455 ; API parameter (musical note)
API_NOTE_Df6 = #$0455 ; API parameter (musical note)
API_NOTE_D6 = #$0497 ; API parameter (musical note)
API_NOTE_Ds6 = #$04DD ; API parameter (musical note)
API_NOTE_Ef6 = #$04DD ; API parameter (musical note)
API_NOTE_E6 = #$0527 ; API parameter (musical note)
API_NOTE_F6 = #$0575 ; API parameter (musical note)
API_NOTE_Fs6 = #$05C8 ; API parameter (musical note)
API_NOTE_Gf6 = #$05C8 ; API parameter (musical note)
API_NOTE_G6 = #$0620 ; API parameter (musical note)
API_NOTE_Af6 = #$067D ; API parameter (musical note)
API_NOTE_Gs6 = #$067D ; API parameter (musical note)
API_NOTE_A6 = #$06E0 ; API parameter (musical note)
API_NOTE_As6 = #$0749 ; API parameter (musical note)
API_NOTE_Bf6 = #$0749 ; API parameter (musical note)
API_NOTE_B6 = #$07B8 ; API parameter (musical note)
API_NOTE_C7 = #$082D ; API parameter (musical note)
API_NOTE_Cs7 = #$08A9 ; API parameter (musical note)
API_NOTE_Df7 = #$08A9 ; API parameter (musical note)
API_NOTE_D7 = #$092D ; API parameter (musical note)
API_NOTE_Ds7 = #$09B9 ; API parameter (musical note)
API_NOTE_Ef7 = #$09B9 ; API parameter (musical note)
API_NOTE_E7 = #$0A4D ; API parameter (musical note)
API_NOTE_F7 = #$0AEA ; API parameter (musical note)
API_NOTE_Fs7 = #$0B90 ; API parameter (musical note)
API_NOTE_Gf7 = #$0B90 ; API parameter (musical note)
API_NOTE_G7 = #$0C40 ; API parameter (musical note)
API_NOTE_Af7 = #$0CFA ; API parameter (musical note)
API_NOTE_Gs7 = #$0CFA ; API parameter (musical note)
API_NOTE_A7 = #$0DC0 ; API parameter (musical note)
API_NOTE_As7 = #$0E91 ; API parameter (musical note)
API_NOTE_Bf7 = #$0E91 ; API parameter (musical note)
API_NOTE_B7 = #$0F6F ; API parameter (musical note)
API_NOTE_C8 = #$105A ; API parameter (musical note)
API_NOTE_Cs8 = #$1153 ; API parameter (musical note)
API_NOTE_Df8 = #$1153 ; API parameter (musical note)
API_NOTE_D8 = #$125B ; API parameter (musical note)
API_NOTE_Ds8 = #$1372 ; API parameter (musical note)
API_NOTE_Ef8 = #$1372 ; API parameter (musical note)
API_NOTE_E8 = #$149A ; API parameter (musical note)
API_NOTE_F8 = #$15D4 ; API parameter (musical note)
API_NOTE_Fs8 = #$1720 ; API parameter (musical note)
API_NOTE_Gf8 = #$1720 ; API parameter (musical note)
API_NOTE_G8 = #$1880 ; API parameter (musical note)
API_NOTE_Af8 = #$19F5 ; API parameter (musical note)
API_NOTE_Gs8 = #$19F5 ; API parameter (musical note)
API_NOTE_A8 = #$1B80 ; API parameter (musical note)
API_NOTE_As8 = #$1D23 ; API parameter (musical note)
API_NOTE_Bf8 = #$1D23 ; API parameter (musical note)
API_NOTE_B8 = #$1EDE ; API parameter (musical note)
API_NOTE_C9 = #$20B4 ; API parameter (musical note)
API_NOTE_Cs9 = #$22A6 ; API parameter (musical note)
API_NOTE_Df9 = #$22A6 ; API parameter (musical note)
API_NOTE_D9 = #$24B5 ; API parameter (musical note)
API_NOTE_Ds9 = #$26E4 ; API parameter (musical note)
API_NOTE_Ef9 = #$26E4 ; API parameter (musical note)
API_NOTE_E9 = #$2934 ; API parameter (musical note)
API_NOTE_F9 = #$2BA7 ; API parameter (musical note)
API_NOTE_Fs9 = #$2E40 ; API parameter (musical note)
API_NOTE_Gf9 = #$2E40 ; API parameter (musical note)
API_NOTE_G9 = #$3100 ; API parameter (musical note)
API_NOTE_Af9 = #$33EA ; API parameter (musical note)
API_NOTE_Gs9 = #$33EA ; API parameter (musical note)
API_NOTE_A9 = #$3700 ; API parameter (musical note)
API_NOTE_As9 = #$3A45 ; API parameter (musical note)
API_NOTE_Bf9 = #$3A45 ; API parameter (musical note)
API_NOTE_B9 = #$3DBC ; API parameter (musical note)
API_NOTE_C10 = #$4168 ; API parameter (musical note)
API_NOTE_Cs10 = #$454C ; API parameter (musical note)
API_NOTE_Df10 = #$454C ; API parameter (musical note)
API_NOTE_D10 = #$496B ; API parameter (musical note)
API_NOTE_Ds10 = #$4DC8 ; API parameter (musical note)
API_NOTE_Ef10 = #$4DC8 ; API parameter (musical note)
API_TEMPO_60 = #$0064 ; API parameter (musical note duration, 60BPM)
API_TEMPO_80 = #$004B ; API parameter (musical note duration, 80BPM)
API_TEMPO_90 = #$0042 ; API parameter (musical note duration, 90BPM)
API_TEMPO_120 = #$0032 ; API parameter (musical note duration, 120BPM)
API_SLIDE_NONE = #$0000 ; API parameter (slide value)
API_SLIDE_SLOW = #$0004 ; API parameter (slide range)
API_SLIDE_MED = #$0008 ; API parameter (slide range)
API_SLIDE_FAST = #$0010 ; API parameter (slide range)
API_SOUND_SRC_BEEP = #$00 ; API parameter (sound generator)
; Sound parameters (Group 8, Function 5)
API_SFX_POSITIVE = #$00 ; API parameter (sound effect)
API_SFX_NEGATIVE = #$01 ; API parameter (sound effect)
API_SFX_ERROR = #$02 ; API parameter (sound effect)
API_SFX_CONFIRM = #$03 ; API parameter (sound effect)
API_SFX_REJECT = #$04 ; API parameter (sound effect)
API_SFX_SWEEP = #$05 ; API parameter (sound effect)
API_SFX_COIN = #$06 ; API parameter (sound effect)
API_SFX_LASER_LONG = #$07 ; API parameter (sound effect)
API_SFX_POWERUP = #$08 ; API parameter (sound effect)
API_SFX_VICTORY = #$09 ; API parameter (sound effect)
API_SFX_DEFEAT = #$0A ; API parameter (sound effect)
API_SFX_FANFARE = #$0B ; API parameter (sound effect)
API_SFX_ALARM1 = #$0C ; API parameter (sound effect)
API_SFX_ALARM2 = #$0D ; API parameter (sound effect)
API_SFX_ALARM3 = #$0E ; API parameter (sound effect)
API_SFX_RING1 = #$0F ; API parameter (sound effect)
API_SFX_RING2 = #$10 ; API parameter (sound effect)
API_SFX_RING3 = #$11 ; API parameter (sound effect)
API_SFX_DANGER = #$12 ; API parameter (sound effect)
API_SFX_EXPL_LONG = #$13 ; API parameter (sound effect)
API_SFX_EXPL_MEDIUM = #$14 ; API parameter (sound effect)
API_SFX_EXPL_SHORT = #$15 ; API parameter (sound effect)
API_SFX_LASER_MEDIUM = #$16 ; API parameter (sound effect)
API_SFX_LASER_SHORT = #$17 ; API parameter (sound effect)
; Turtle Graphics functions (Group 9)
API_GROUP_TURTLE = #$09 ; API function group
API_FN_TURTLE_INIT = #$01 ; API function
API_FN_TURTLE_TURN = #$02 ; API function
API_FN_TURTLE_MOVE = #$03 ; API function
API_FN_TURTLE_HIDE = #$04 ; API function
API_FN_TURTLE_HOME = #$05 ; API function
; Turtle Graphics parameters (Group 9, Function 2)
API_TURTLE_LEFT = #$010E ; API parameter (turn -90 degrees)
API_TURTLE_RIGHT = #$005A ; API parameter (turn +90 degrees)
API_TURTLE_FLIP = #$00B4 ; API parameter (turn 180 degrees)
; Turtle Graphics parameters (Group 9, Function 3)
API_PEN_UP = #$00 ; API parameter (turtle tracks on)
API_PEN_DOWN = #$01 ; API parameter (turtle tracks off)
; UExt functions (Group 10)
API_GROUP_UEXT = #$09 ; API function group
API_FN_UEXT_INIT = #$01 ; API function
API_FN_GPIO_WRITE = #$02 ; API function
API_FN_GPIO_READ = #$03 ; API function
API_FN_SET_PORT_DIR = #$04 ; API function
API_FN_I2C_WRITE = #$05 ; API function
API_FN_I2C_READ = #$06 ; API function
API_FN_ANALOG_READ = #$07 ; API function
API_FN_I2C_STATUS = #$08 ; API function
API_FN_I2C_READ_BLOCK = #$09 ; API function
API_FN_I2C_WRITE_BLCOK = #$0a ; API function
API_FN_SPI_READ_BLOCK = #$0b ; API function
API_FN_SPI_WRITE_BLOCK = #$0c ; API function
API_FN_UART_READ_BLOCK = #$0d ; API function
API_FN_UART_WRITE_BLOPCK= #$0e ; API function
API_FN_UART_SET_SPEED = #$0f ; API function
API_FN_UART_WRITE = #$10 ; API function
API_FN_UART_READ = #$11 ; API function
API_FN_UART_CHECK_BYTE_AVAILABLE = #$12 ; API function
; TODO group 11 MOUSE
; TODO group 12 BLITTER
; TODO group 13 EDITOR
;--------;
; colors ;
;--------;
COLOR_BLACK = #$80
COLOR_RED = #$81
COLOR_GREEN = #$82
COLOR_YELLOW = #$83
COLOR_BLUE = #$84
COLOR_MAGENTA = #$85
COLOR_CYAN = #$86
COLOR_WHITE = #$87
COLOR_ALT_BLACK = #$88
COLOR_DARK_GREY = #$89
COLOR_DARK_GREEN = #$8A
COLOR_ORANGE = #$8B
COLOR_DARK_ORANGE = #$8C
COLOR_BROWN = #$8D
COLOR_PINK = #$8E
COLOR_LIGHT_GREY = #$8F
;---------------------------------;
; limited-case convenience macros ;
;---------------------------------;
DoSendMessage .macro
jsr neo.SendMessage
.endm
DoWaitMessage .macro
jsr neo.WaitMessage
.endm

View File

@ -0,0 +1,439 @@
; Prog8 definitions for the Neo6502
%option no_symbol_prefixing, ignore_unused
neo {
&uword NMI_VEC = $FFFA ; 6502 nmi vector, determined by the kernal if banked in
&uword RESET_VEC = $FFFC ; 6502 reset vector, determined by the kernal if banked in
&uword IRQ_VEC = $FFFE ; 6502 interrupt vector, determined by the kernal if banked in
%asminclude "library:neo/neo6502.asm"
}
sys {
; ------- lowlevel system routines --------
const ubyte target = 7 ; compilation target specifier. 255=virtual, 128=C128, 64=C64, 32=PET, 16=CommanderX16, 8=atari800XL, 7=Neo6502
asmsub init_system() {
; Initializes the machine to a sane starting state.
; Called automatically by the loader program logic.
%asm {{
sei
cld
clc
; TODO reset screen mode etc etc?
clv
; TODO what about IRQ handler? cli
rts
}}
}
asmsub init_system_phase2() {
%asm {{
rts ; no phase 2 steps on the Neo6502
}}
}
asmsub reset_system() {
; Soft-reset the system back to initial power-on status
; TODO
%asm {{
sei
jmp (neo.RESET_VEC)
}}
}
sub wait(uword jiffies) {
; --- wait approximately the given number of jiffies (1/60th seconds)
; TODO
}
asmsub waitvsync() clobbers(A) {
; --- busy wait till the next vsync has occurred (approximately), without depending on custom irq handling.
; TODO
%asm {{
nop
rts
}}
}
asmsub internal_stringcopy(uword source @R0, uword target @AY) clobbers (A,Y) {
; Called when the compiler wants to assign a string value to another string.
%asm {{
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
lda cx16.r0
ldy cx16.r0+1
jmp prog8_lib.strcpy
}}
}
asmsub memcopy(uword source @R0, uword target @R1, uword count @AY) clobbers(A,X,Y) {
; note: only works for NON-OVERLAPPING memory regions!
; note: can't be inlined because is called from asm as well
%asm {{
ldx cx16.r0
stx P8ZP_SCRATCH_W1 ; source in ZP
ldx cx16.r0+1
stx P8ZP_SCRATCH_W1+1
ldx cx16.r1
stx P8ZP_SCRATCH_W2 ; target in ZP
ldx cx16.r1+1
stx P8ZP_SCRATCH_W2+1
cpy #0
bne _longcopy
; copy <= 255 bytes
tay
bne _copyshort
rts ; nothing to copy
_copyshort
dey
beq +
- lda (P8ZP_SCRATCH_W1),y
sta (P8ZP_SCRATCH_W2),y
dey
bne -
+ lda (P8ZP_SCRATCH_W1),y
sta (P8ZP_SCRATCH_W2),y
rts
_longcopy
sta P8ZP_SCRATCH_B1 ; lsb(count) = remainder in last page
tya
tax ; x = num pages (1+)
ldy #0
- lda (P8ZP_SCRATCH_W1),y
sta (P8ZP_SCRATCH_W2),y
iny
bne -
inc P8ZP_SCRATCH_W1+1
inc P8ZP_SCRATCH_W2+1
dex
bne -
ldy P8ZP_SCRATCH_B1
bne _copyshort
rts
}}
}
asmsub memset(uword mem @R0, uword numbytes @R1, ubyte value @A) clobbers(A,X,Y) {
%asm {{
ldy cx16.r0
sty P8ZP_SCRATCH_W1
ldy cx16.r0+1
sty P8ZP_SCRATCH_W1+1
ldx cx16.r1
ldy cx16.r1+1
jmp prog8_lib.memset
}}
}
asmsub memsetw(uword mem @R0, uword numwords @R1, uword value @AY) clobbers(A,X,Y) {
%asm {{
ldx cx16.r0
stx P8ZP_SCRATCH_W1
ldx cx16.r0+1
stx P8ZP_SCRATCH_W1+1
ldx cx16.r1
stx P8ZP_SCRATCH_W2
ldx cx16.r1+1
stx P8ZP_SCRATCH_W2+1
jmp prog8_lib.memsetw
}}
}
inline asmsub read_flags() -> ubyte @A {
%asm {{
php
pla
}}
}
inline asmsub clear_carry() {
%asm {{
clc
}}
}
inline asmsub set_carry() {
%asm {{
sec
}}
}
inline asmsub clear_irqd() {
%asm {{
cli
}}
}
inline asmsub set_irqd() {
%asm {{
sei
}}
}
inline asmsub irqsafe_set_irqd() {
%asm {{
php
sei
}}
}
inline asmsub irqsafe_clear_irqd() {
%asm {{
plp
}}
}
sub disable_caseswitch() {
; no-op
}
sub enable_caseswitch() {
; no-op
}
asmsub save_prog8_internals() {
%asm {{
lda P8ZP_SCRATCH_B1
sta save_SCRATCH_ZPB1
lda P8ZP_SCRATCH_REG
sta save_SCRATCH_ZPREG
lda P8ZP_SCRATCH_W1
sta save_SCRATCH_ZPWORD1
lda P8ZP_SCRATCH_W1+1
sta save_SCRATCH_ZPWORD1+1
lda P8ZP_SCRATCH_W2
sta save_SCRATCH_ZPWORD2
lda P8ZP_SCRATCH_W2+1
sta save_SCRATCH_ZPWORD2+1
rts
save_SCRATCH_ZPB1 .byte 0
save_SCRATCH_ZPREG .byte 0
save_SCRATCH_ZPWORD1 .word 0
save_SCRATCH_ZPWORD2 .word 0
}}
}
asmsub restore_prog8_internals() {
%asm {{
lda save_prog8_internals.save_SCRATCH_ZPB1
sta P8ZP_SCRATCH_B1
lda save_prog8_internals.save_SCRATCH_ZPREG
sta P8ZP_SCRATCH_REG
lda save_prog8_internals.save_SCRATCH_ZPWORD1
sta P8ZP_SCRATCH_W1
lda save_prog8_internals.save_SCRATCH_ZPWORD1+1
sta P8ZP_SCRATCH_W1+1
lda save_prog8_internals.save_SCRATCH_ZPWORD2
sta P8ZP_SCRATCH_W2
lda save_prog8_internals.save_SCRATCH_ZPWORD2+1
sta P8ZP_SCRATCH_W2+1
rts
}}
}
asmsub exit(ubyte returnvalue @A) {
; -- immediately exit the program with a return code in the A register
; TODO where to store A as exit code?
%asm {{
ldx prog8_lib.orig_stackpointer
txs
rts ; return to original caller
}}
}
asmsub exit2(ubyte resulta @A, ubyte resultx @X, ubyte resulty @Y) {
; -- immediately exit the program with result values in the A, X and Y registers.
; TODO where to store A,X,Y as exit code?
%asm {{
jmp exit
}}
}
asmsub exit3(ubyte resulta @A, ubyte resultx @X, ubyte resulty @Y, bool carry @Pc) {
; -- immediately exit the program with result values in the A, X and Y registers, and the Carry flag in the status register.
; TODO where to store A,X,Y,Carry as exit code?
%asm {{
jmp exit
}}
}
inline asmsub progend() -> uword @AY {
%asm {{
lda #<prog8_program_end
ldy #>prog8_program_end
}}
}
inline asmsub push(ubyte value @A) {
%asm {{
pha
}}
}
inline asmsub pushw(uword value @AY) {
%asm {{
pha
tya
pha
}}
}
inline asmsub pop() -> ubyte @A {
%asm {{
pla
}}
}
inline asmsub popw() -> uword @AY {
%asm {{
pla
tay
pla
}}
}
}
cx16 {
; the sixteen virtual 16-bit registers that the CX16 has defined in the zeropage
; the sixteen virtual 16-bit registers in both normal unsigned mode and signed mode (s)
&uword r0 = $0002
&uword r1 = $0004
&uword r2 = $0006
&uword r3 = $0008
&uword r4 = $000a
&uword r5 = $000c
&uword r6 = $000e
&uword r7 = $0010
&uword r8 = $0012
&uword r9 = $0014
&uword r10 = $0016
&uword r11 = $0018
&uword r12 = $001a
&uword r13 = $001c
&uword r14 = $001e
&uword r15 = $0020
&word r0s = $0002
&word r1s = $0004
&word r2s = $0006
&word r3s = $0008
&word r4s = $000a
&word r5s = $000c
&word r6s = $000e
&word r7s = $0010
&word r8s = $0012
&word r9s = $0014
&word r10s = $0016
&word r11s = $0018
&word r12s = $001a
&word r13s = $001c
&word r14s = $001e
&word r15s = $0020
&ubyte r0L = $0002
&ubyte r1L = $0004
&ubyte r2L = $0006
&ubyte r3L = $0008
&ubyte r4L = $000a
&ubyte r5L = $000c
&ubyte r6L = $000e
&ubyte r7L = $0010
&ubyte r8L = $0012
&ubyte r9L = $0014
&ubyte r10L = $0016
&ubyte r11L = $0018
&ubyte r12L = $001a
&ubyte r13L = $001c
&ubyte r14L = $001e
&ubyte r15L = $0020
&ubyte r0H = $0003
&ubyte r1H = $0005
&ubyte r2H = $0007
&ubyte r3H = $0009
&ubyte r4H = $000b
&ubyte r5H = $000d
&ubyte r6H = $000f
&ubyte r7H = $0011
&ubyte r8H = $0013
&ubyte r9H = $0015
&ubyte r10H = $0017
&ubyte r11H = $0019
&ubyte r12H = $001b
&ubyte r13H = $001d
&ubyte r14H = $001f
&ubyte r15H = $0021
&byte r0sL = $0002
&byte r1sL = $0004
&byte r2sL = $0006
&byte r3sL = $0008
&byte r4sL = $000a
&byte r5sL = $000c
&byte r6sL = $000e
&byte r7sL = $0010
&byte r8sL = $0012
&byte r9sL = $0014
&byte r10sL = $0016
&byte r11sL = $0018
&byte r12sL = $001a
&byte r13sL = $001c
&byte r14sL = $001e
&byte r15sL = $0020
&byte r0sH = $0003
&byte r1sH = $0005
&byte r2sH = $0007
&byte r3sH = $0009
&byte r4sH = $000b
&byte r5sH = $000d
&byte r6sH = $000f
&byte r7sH = $0011
&byte r8sH = $0013
&byte r9sH = $0015
&byte r10sH = $0017
&byte r11sH = $0019
&byte r12sH = $001b
&byte r13sH = $001d
&byte r14sH = $001f
&byte r15sH = $0021
asmsub save_virtual_registers() clobbers(A,Y) {
%asm {{
ldy #31
- lda cx16.r0,y
sta _cx16_vreg_storage,y
dey
bpl -
rts
_cx16_vreg_storage
.word 0,0,0,0,0,0,0,0
.word 0,0,0,0,0,0,0,0
}}
}
asmsub restore_virtual_registers() clobbers(A,Y) {
%asm {{
ldy #31
- lda save_virtual_registers._cx16_vreg_storage,y
sta cx16.r0,y
dey
bpl -
rts
}}
}
sub cpu_is_65816() -> bool {
; Returns true when you have a 65816 cpu, false when it's a 6502.
return false
}
}

View File

@ -96,7 +96,7 @@ asmsub kbdbuf_clear() {
sys {
; ------- lowlevel system routines --------
const ubyte target = 32 ; compilation target specifier. 64 = C64, 128 = C128, 16 = CommanderX16, 32=PET
const ubyte target = 32 ; compilation target specifier. 255=virtual, 128=C128, 64=C64, 32=PET, 16=CommanderX16, 8=atari800XL, 7=Neo6502
const ubyte sizeof_bool = 1
const ubyte sizeof_byte = 1

View File

@ -5,7 +5,7 @@
sys {
; ------- lowlevel system routines --------
const ubyte target = 255 ; compilation target specifier. 64 = C64, 128 = C128, 16 = CommanderX16, 8 = atari800XL, 255 = virtual
const ubyte target = 255 ; compilation target specifier. 255=virtual, 128=C128, 64=C64, 32=PET, 16=CommanderX16, 8=atari800XL, 7=Neo6502
const ubyte sizeof_bool = 1
const ubyte sizeof_byte = 1

View File

@ -292,7 +292,7 @@ private fun compileMain(args: Array<String>): Boolean {
val programNameInPath = outputPath.resolve(compilationResult.compilerAst.name)
if(startEmulator1==true || startEmulator2==true) {
if (compilationResult.compilationOptions.launcher != CbmPrgLauncherType.NONE || compilationTarget=="atari") {
if (compilationResult.compilationOptions.launcher != CbmPrgLauncherType.NONE || compilationTarget=="atari" || compilationTarget=="neo") {
if (startEmulator1 == true)
compilationResult.compilationOptions.compTarget.machine.launchEmulator(1, programNameInPath)
else if (startEmulator2 == true)

View File

@ -15,10 +15,7 @@ import prog8.code.ast.printAst
import prog8.code.ast.verifyFinalAstBeforeAsmGen
import prog8.code.core.*
import prog8.code.optimize.optimizeIntermediateAst
import prog8.code.target.AtariTarget
import prog8.code.target.Cx16Target
import prog8.code.target.VMTarget
import prog8.code.target.getCompilationTargetByName
import prog8.code.target.*
import prog8.codegen.vm.VmCodeGen
import prog8.compiler.astprocessing.*
import prog8.optimizer.*
@ -236,7 +233,11 @@ internal fun determineProgramLoadAddress(program: Program, options: CompilationO
}
else {
when(options.output) {
OutputType.RAW -> { /* no predefined load address */ }
OutputType.RAW -> {
if(options.compTarget.name==Neo6502Target.NAME)
loadAddress = options.compTarget.machine.PROGRAM_LOAD_ADDRESS
// for all other targets, RAW has no predefined load address.
}
OutputType.PRG -> {
if(options.launcher==CbmPrgLauncherType.BASIC) {
loadAddress = options.compTarget.machine.PROGRAM_LOAD_ADDRESS

View File

@ -136,7 +136,7 @@ One or more .p8 module files
``-target <compilation target>``
Sets the target output of the compiler. This option is required.
``c64`` = Commodore 64, ``c128`` = Commodore 128, ``cx16`` = Commander X16, ``pet32`` - Commodore PET model 4032,
``atari`` = Atari 800 XL, ``virtual`` = builtin virtual machine.
``atari`` = Atari 800 XL, ``neo`` = Neo6502, ``virtual`` = builtin virtual machine.
``-srcdirs <pathlist>``
Specify a list of extra paths (separated with ':'), to search in for imported modules.

View File

@ -235,6 +235,7 @@ Grouped per compilation target.
* `c128 <_static/symboldumps/skeletons-c128.txt>`_
* `cx16 <_static/symboldumps/skeletons-cx16.txt>`_
* `pet32 <_static/symboldumps/skeletons-pet32.txt>`_
* `neo <_static/symboldumps/skeletons-neo.txt>`_
* `virtual <_static/symboldumps/skeletons-virtual.txt>`_

View File

@ -16,6 +16,7 @@ Currently these machines can be selected as a compilation target (via the ``-tar
- 'c128': the Commodore 128 (*limited support*)
- 'pet32': the Commodore PET 4032 (*limited support*)
- 'atari': the Atari 800 XL (*experimental support*)
- 'neo': the `Neo6502 <https://github.com/paulscottrobson/neo6502-firmware/wiki>`_ (*experimental*)
- 'virtual': a builtin virtual machine
This chapter explains some relevant system details of the c64 and cx16 machines.

View File

@ -1,20 +1,118 @@
%import textio
%import floats
%option no_sysinit
%zeropage basicsafe
%output raw
%launcher none
main {
sub start() {
float @shared fl1 = 4444.234
float @shared fl2 = -9999.111
float @shared fl3 = fl1+fl2
floats.print(fl1)
txt.spc()
floats.print(fl2)
txt.spc()
floats.print(fl3)
txt.nl()
txt.print_w(fl3 as word)
txt.nl()
romsub $fff1 = WriteCharacter(ubyte character @A)
for cx16.r0L in "\n\n\n.... Hello from Prog8 :-)"
WriteCharacter(cx16.r0L)
repeat {
}
}
sub start2() {
%asm {{
; Program constants
CURSOR_POS_X = #0 ; character display 'X' coordinate
CURSOR_POS_Y = #21 ; character display 'Y' coordinate
NEWLINE_CHAR = #13 ; ASCII character code
;--------------;
; Main Program ;
;--------------;
start:
;-----------------------------------------------;
; Play sound effect - (API Group 8, Function 5) ;
;-----------------------------------------------;
lda neo.API_SOUND_CH_00 ; sound channel (API::sound->play->channel)
sta neo.API_PARAMETERS + 0 ; set API 'Parameter0' (API::sound->play->channel)
lda neo.API_SFX_COIN ; sound effect index (API::sound->play->effect)
sta neo.API_PARAMETERS + 1 ; set API 'Parameter1' (API::sound->play->effect)
lda neo.API_FN_PLAY_SOUND ; sound effect function (API::sound->play)
sta neo.API_FUNCTION ; set API 'Function' (API::sound->play)
lda neo.API_GROUP_SOUND ; 'Sound' API function group (API::sound)
sta neo.API_COMMAND ; trigger 'Sound' API routine (API::sound)
;--------------------------------------------------;
; Set cursor position - (API Group 2, Function 7) ;
;--------------------------------------------------;
; reposition the cursor to overwrite the default welcome text
lda neo.API_FN_SET_CURSOR_POS ; set cursor position function (API::console->cursor)
sta neo.API_FUNCTION ; set API 'Function' (API::console->cursor)
lda CURSOR_POS_X ; cursor 'X' coordinate (API::console->cursor->x)
sta neo.API_PARAMETERS + 0 ; set API 'Parameter0' (API::console->cursor->x)
lda CURSOR_POS_Y ; cursor 'Y' coordinate (API::console->cursor->y)
sta neo.API_PARAMETERS + 1 ; set API 'Parameter1' (API::console->cursor->y)
lda neo.API_GROUP_CONSOLE ; 'Console' API function group (API::console)
sta neo.API_COMMAND ; trigger 'Console' API routine (API::console)
; this simply repeats the same routine as the previous block,
; but using the generic convenience macro, for the sake of demonstration
lda CURSOR_POS_X
sta neo.API_PARAMETERS + 0
lda CURSOR_POS_Y
sta neo.API_PARAMETERS + 1
#neo.DoSendMessage ; send command 2,7
.byte 2,7
;--------------------------------------------------------;
; Write character to console - (API Group 2, Function 6) ;
;--------------------------------------------------------;
; first, write a single newline character, using the special convenience macro
lda NEWLINE_CHAR
jsr neo.WriteCharacter
; the text foreground color can also be set by injecting a control character
lda neo.COLOR_DARK_GREEN
jsr neo.WriteCharacter
; next, print the welcome message (a string of characters), using the API
ldx #0 ; initialize string iteration index
lda neo.API_FN_WRITE_CHAR ; console write function (API::console->write)
sta neo.API_FUNCTION ; set API 'Function' (API::console->write)
print_next_char:
lda neo.API_COMMAND ; previous API routine status
bne print_next_char ; wait for previous API routine to complete
lda hello_msg , x ; next character of 'hello_msg' (API::console->write->char)
beq end ; test for string end null byte
sta neo.API_PARAMETERS + 0 ; set API 'Parameter0' (API::console->write->char)
lda neo.API_GROUP_CONSOLE ; 'Console' API function group (API::console)
sta neo.API_COMMAND ; trigger 'Console' API routine (API::console)
inx ; increment iteration index
jmp print_next_char ; continue 'hello_msg' print loop
end:
jmp end ; infinite loop
;--------------;
; Program data ;
;--------------;
hello_msg:
.text " Hello Neo6502" ; line 1 to display
.text 13 ; newline
.text " " ; 53 blanks
.text 13 ; newline
.text " Now you're playing with Neo Power!" ; line 2 to display
.text 13 ; newline
.text " (Some assembly required)" ; line 3 to display
.text 0 ; null-terminated
}}
}
}