1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-17 16:29:32 +00:00

Created a target and a library for the Commander X16 prototype computer.

This commit is contained in:
Greg King 2019-09-27 03:38:51 -04:00
parent 0896deedef
commit 18afc7c703
49 changed files with 2440 additions and 59 deletions

View File

@ -1,30 +1,45 @@
;
; Olli Savia <ops@iki.fi>
;
; Commodore kernal functions
; Commodore Kernal functions
;
.if .def(__CX16__)
; CX16 extended jump table
GETJOY := $FF06
.endif
.if .def(__C128__)
; C128 Extended jump table
; C128 extended jump table
C64MODE := $FF4D
SWAPPER := $FF5F
SETBNK := $FF68
.endif
.if .def(__C64__) || .def(__C128__) || .def(__C16__)
.if .def(__C128__) || .def(__CX16__)
; Extended jump table
CLSALL := $FF4A
SWAPPER := $FF5F
JSRFAR := $FF6E
INDFET := $FF74
INDSTA := $FF77
INDCMP := $FF7A
PRIMM := $FF7D
.endif
.if .def(__C64__) || .def(__C128__) || .def(__C16__) || .def(__CX16__)
CINT := $FF81
IOINIT := $FF84
RAMTAS := $FF87
.elseif .def(__VIC20__)
CINT := $E518 ; No entries are in the kernal jump table of the Vic20 for these three (3) functions.
CINT := $E518 ; No entries are in the Kernal jump table of the VIC-20 for these three (3) functions.
IOINIT := $FDF9 ; The entries for these functions have been set to point directly to the functions
RAMTAS := $FD8D ; in the kernal to maintain compatibility with the other Commodore platforms.
RAMTAS := $FD8D ; in the Kernal, to maintain compatibility with the other Commodore platforms.
.elseif .def(__CBM510__) || .def(__CBM610__)
IOINIT := $FF7B
CINT := $FF7E
.endif
.if .def(__VIC20__) || .def(__C64__) || .def(__C128__) || .def(__C16__)
.if .def(__VIC20__) || .def(__C64__) || .def(__C128__) || .def(__C16__) || .def(__CX16__)
RESTOR := $FF8A
VECTOR := $FF8D
.elseif .def(__CBM510__) || .def(__CBM610__)
@ -32,7 +47,7 @@
RESTOR := $FF87
.endif
.if .def(__CBM510__) || .def(__CBM610__) || .def(__VIC20__) || .def(__C64__) || .def(__C128__) || .def(__C16__)
.if .def(__CBM510__) || .def(__CBM610__) || .def(__VIC20__) || .def(__C64__) || .def(__C128__) || .def(__C16__) || .def(__CX16__)
SETMSG := $FF90
SECOND := $FF93
TKSA := $FF96
@ -64,7 +79,7 @@ CHRIN := $FFCF
BSOUT := $FFD2
CHROUT := $FFD2
.if .def(__CBM510__) || .def(__CBM610__) || .def(__VIC20__) || .def(__C64__) || .def(__C128__) || .def(__C16__)
.if .def(__CBM510__) || .def(__CBM610__) || .def(__VIC20__) || .def(__C64__) || .def(__C128__) || .def(__C16__) || .def(__CX16__)
LOAD := $FFD5
SAVE := $FFD8
SETTIM := $FFDB
@ -77,7 +92,7 @@ GETIN := $FFE4
CLALL := $FFE7
UDTIM := $FFEA
.if .def(__CBM510__) || .def(__CBM610__) || .def(__VIC20__) || .def(__C64__) || .def(__C128__) || .def(__C16__)
.if .def(__CBM510__) || .def(__CBM610__) || .def(__VIC20__) || .def(__C64__) || .def(__C128__) || .def(__C16__) || .def(__CX16__)
SCREEN := $FFED
PLOT := $FFF0
IOBASE := $FFF3
@ -102,7 +117,6 @@ UDTIM := $FFEA
CURS_SET := $CD57
CURS_ON := $CD6F
CURS_OFF := $CD9F
INDFET := $FF74
.elseif .def(__C16__)
CLRSCR := $D88B
KBDREAD := $D8C1

316
asminc/cx16.inc Normal file
View File

@ -0,0 +1,316 @@
;
; CX16 definitions
;
; ---------------------------------------------------------------------------
; Constants
.enum COLOR
BLACK = $00
WHITE
RED
CYAN
VIOLET
PURPLE = VIOLET
GREEN
BLUE
YELLOW
ORANGE
BROWN
LIGHTRED
GRAY1
GRAY2
LIGHTGREEN
LIGHTBLUE
GRAY3
.endenum
; Special keys
.enum KEY
F1 = $85
F3
F5
F7
F2
F4
F6
F8
F9 = $10
F10 = $15
F11
F12
.endenum
; ---------------------------------------------------------------------------
; Zero page
; BASIC
VARTAB := $2D ; Pointer to start of BASIC variables
MEMSIZE := $37 ; Pointer to highest BASIC RAM location (+1)
TXTPTR := $7A ; Pointer into BASIC source code
; Kernal
IN_DEV := $99 ; Current input device number
OUT_DEV := $9A ; Current output device number
IMPARM := $9B ; Pointer for PRIMM function
TIME := $A0 ; 60 Hz. clock
FNAM_LEN := $B7 ; Length of filename
SECADR := $B9 ; Secondary address
DEVNUM := $BA ; Device number
FNAM := $BB ; Pointer to filename
KEY_COUNT := $C6 ; Number of keys in input buffer
RVS := $C7 ; Reverse flag
CURS_FLAG := $CC ; 1 = cursor off
CURS_BLINK := $CD ; Blink counter
CURS_CHAR := $CE ; Character under the cursor
CURS_STATE := $CF ; Cursor blink state
SCREEN_PTR := $D1 ; Pointer to current row on text screen (16 bits)
CURS_X := $D3 ; Cursor column
CURS_Y := $D6 ; Cursor row
LLEN := $D9 ; Line length
NLINES := $DA ; Number of screen lines
JOY1 := $EF ; 3 bytes of NES/SNES gamepad data
JOY2 := $F2
FREKZP := $FB ; Five unused bytes
; Page two
BASIC_BUF := $200 ; Location of command-line
BASIC_BUF_LEN = 89 ; Maximum length of command-line
CHARCOLOR := $286
CURS_COLOR := $287 ; Color under the cursor
; ---------------------------------------------------------------------------
; Vector and other locations
IRQVec := $0314
BRKVec := $0316
NMIVec := $0318
; ---------------------------------------------------------------------------
; I/O locations
; Video Enhanced Retro Adapter
; Has audio, SPI, and UART.
.scope VERA
; External registers
.struct
.org $9F20
ADDR .faraddr ; Address for data port access
DATA0 .byte ; First data port
DATA1 .byte ; Second data port
CTRL .byte ; Control register
IRQ_EN .byte ; Interrupt enable bits
IRQ_FLAGS .byte ; Interrupt flags
.endstruct
.enum ; Address automatic increment amounts
INC0 = 0 << 4
INC1 = 1 << 4
INC2 = 2 << 4
INC4 = 3 << 4
INC8 = 4 << 4
INC16 = 5 << 4
INC32 = 6 << 4
INC64 = 7 << 4
INC128 = 8 << 4
INC256 = 9 << 4
INC512 = 10 << 4
INC1024 = 11 << 4
INC2048 = 12 << 4
INC4096 = 13 << 4
INC8192 = 14 << 4
INC16384 = 15 << 4
.endenum
; Internal RAM and registers
VRAM := $000000
.scope COMPOSER ; Display composer
.struct
.org $0F0000
VIDEO .byte
HSCALE .byte
VSCALE .byte
FRAME .byte
HSTART_LO .byte
HSTOP_LO .byte
VSTART_LO .byte
VSTOP_LO .byte
STRTSTOP_HI .byte
IRQ_LINE .word
.endstruct
.enum MODE ; Output mode
DISABLE = 0
VGA
NTSC
RGB ; Interlaced, composite sync
.endenum
.enum
ENABLE_COLOR = 0 << 2
DISABLE_COLOR = 1 << 2 ; NTSC monochrome
.endenum
.endscope
PALETTE := $0F1000
.struct L0 ; Layer 0 registers
.org $0F2000
CTRL0 .byte ; Display mode control
CTRL1 .byte ; Geometry control
MAP_BASE .addr
TILE_BASE .addr
HSCROLL .word ; Horizontal scroll
VSCROLL .word ; Vertical scroll
.endstruct
.struct L1 ; Layer 1 registers (same as layer 0)
.org $0F3000
CTRL0 .byte
CTRL1 .byte
MAP_BASE .addr
TILE_BASE .addr
HSCROLL .word
VSCROLL .word
.endstruct
.enum MAP ; Map geometry
WIDTH32 = 0
WIDTH64
WIDTH128
WIDTH256
HEIGHT32 = 0 << 2
HEIGHT64 = 1 << 2
HEIGHT128 = 2 << 2
HEIGHT256 = 3 << 2
.endenum
.scope TILE ; Tile geometry
.enum
WIDTH8 = 0 << 4
WIDTH16 = 1 << 4
WIDTH320 = WIDTH8
WIDTH640 = WIDTH16
HEIGHT8 = 0 << 5
HEIGHT16 = 1 << 5
.endenum
.enum FLIP
NONE = 0 << 2
HORIZ = 1 << 2
VERT = 2 << 2
BOTH = 3 << 2
.endenum
.endscope
.enum DMODE ; Display modes
TEXT16 = 0 << 5
TEXT256 = 1 << 5
TILE4 = 2 << 5
TILE16 = 3 << 5
TILE256 = 4 << 5
BITMAP4 = 5 << 5
BITMAP16 = 6 << 5
BITMAP256 = 7 << 5
.endenum
.scope SPRITE
.struct
.org $0F4000
CTRL .byte ; Enables sprites
COLLISION .byte
.endstruct
.enum FLIP
NONE = 0
HORIZ
VERT
BOTH
.endenum
.enum ; Sprite geometry
WIDTH8 = 0 << 4
WIDTH16 = 1 << 4
WIDTH32 = 2 << 4
WIDTH64 = 3 << 4
HEIGHT8 = 0 << 6
HEIGHT16 = 1 << 6
HEIGHT32 = 2 << 6
HEIGHT64 = 3 << 6
COLORS16 = 0 << 7
COLORS256 = 1 << 7
.endenum
.enum DEPTH
DISABLE = 0 << 2
CANVAS = 1 << 2
LAYER0 = 2 << 2
LAYER1 = 3 << 2
.endenum
ATTRIB := $0F5000 ; Sprite attributes
.endscope
AUDIO := $0F6000
.scope SPI
.struct
.org $0F7000
DATA .byte
CONTROL .byte
.endstruct
.enum
DESELECT = 0
SELECT
BUSY_MASK = 1 << 1
.endenum
.endscope
.scope UART ; Universal Asyncronous Receiver Transmitter
.struct
.org $0F8000
DATA .byte
STATUS .byte
BPS_DIV .word
.endstruct
.enum MASK
RECEIVE = 1 << 0
TRANSMIT = 1 << 1
.endenum
.endscope
.endscope
; 65c22
.struct VIA1 ; Versatile Interface Adapter
.org $9F60
PRB .byte ; ROM bank, IEC (Port Register B)
PRA .byte ; RAM bank (Port Register A)
DDRB .byte ; (Data Direction Register B)
DDRA .byte ; (Data Direction Register A)
T1 .word ; (Timer 1)
T1L .word ; (Timer 1 Latch)
T2 .word ; (Timer 2)
SR .byte ; (Shift Register)
ACR .byte ; (Auxiliary Control Register)
PCR .byte ; (Peripheral Control Register)
IFR .byte ; (Interrupt Flags Register)
IER .byte ; (Interrupt Enable Register)
PRA2 .byte ; RAM bank (Port Register A without handshaking)
.endstruct
; 65c22
.struct VIA2
.org $9F70
PRB .byte
PRA .byte ; NES controller communication
DDRB .byte
DDRA .byte
T1 .word
T1L .word
T2 .word
SR .byte
ACR .byte
PCR .byte
IFR .byte
IER .byte
PRA2 .byte
.endstruct
; Real-Time Clock
; X16 Emulator device
; This device doesn't exist on the real machine.
.struct EMULATOR
.org $9FB0
DEBUG .byte ; Boolean: debugging enabled
VIDACCESSLOG .byte ; Boolean: log VERA activity
KEYBOARDLOG .byte ; Boolean: log keyboard data
ECHO .byte ; Boolean: echo enabled
SAVEXIT .byte ; Boolean: save on exit
.res $D - $5
KEYMAP .byte ; Current keyboard layout number
DETECT .byte 2 ; If is "16" string, then running on emulator
.endstruct

37
cfg/cx16-asm.cfg Normal file
View File

@ -0,0 +1,37 @@
FEATURES {
STARTADDRESS: default = $0801;
}
SYMBOLS {
__LOADADDR__: type = import;
__HIMEM__: type = weak, value = $9F00;
}
MEMORY {
ZP: file = "", start = $0004, size = $0090 - $0004, define = yes;
LOADADDR: file = %O, start = %S - 2, size = $0002;
MAIN: file = %O, start = %S, size = __HIMEM__ - %S;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = MAIN, type = ro, optional = yes;
LOWCODE: load = MAIN, type = ro, optional = yes;
CODE: load = MAIN, type = ro;
RODATA: load = MAIN, type = ro;
DATA: load = MAIN, type = rw;
BSS: load = MAIN, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
segment = RODATA;
CONDES: type = interruptor,
label = __INTERRUPTOR_TABLE__,
count = __INTERRUPTOR_COUNT__,
segment = RODATA,
import = __CALLIRQ__;
}

112
cfg/cx16-bank.cfg Normal file
View File

@ -0,0 +1,112 @@
FEATURES {
STARTADDRESS: default = $0801;
}
SYMBOLS {
__LOADADDR__: type = import;
__EXEHDR__: type = import;
__BANKRAMADDR__: type = import;
__STACKSIZE__: type = weak, value = $0800; # 2K stack
__HIMEM__: type = weak, value = $9F00;
__BANKRAMSTART__: type = export, value = $A000;
__BANKRAMSIZE__: type = weak, value = $2000; # 8K banked RAM
}
MEMORY {
ZP: file = "", define = yes, start = $0004, size = $0090 - $0004;
LOADADDR: file = %O, start = %S - 2, size = $0002;
HEADER: file = %O, define = yes, start = %S, size = $000D;
MAIN: file = %O, define = yes, start = __HEADER_LAST__, size = __HIMEM__ - __HEADER_LAST__;
BSS: file = "", start = __ONCE_RUN__, size = __HIMEM__ - __ONCE_RUN__ - __STACKSIZE__;
BRAM00ADDR: file = "%O.00", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM00: file = "%O.00", start = __BANKRAMSTART__, size = __BANKRAMSIZE__;
BRAM01ADDR: file = "%O.01", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM01: file = "%O.01", start = __BANKRAMSTART__, size = __BANKRAMSIZE__;
BRAM02ADDR: file = "%O.02", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM02: file = "%O.02", start = __BANKRAMSTART__, size = __BANKRAMSIZE__;
BRAM03ADDR: file = "%O.03", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM03: file = "%O.03", start = __BANKRAMSTART__, size = __BANKRAMSIZE__;
BRAM04ADDR: file = "%O.04", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM04: file = "%O.04", start = __BANKRAMSTART__, size = __BANKRAMSIZE__;
BRAM05ADDR: file = "%O.05", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM05: file = "%O.05", start = __BANKRAMSTART__, size = __BANKRAMSIZE__;
BRAM06ADDR: file = "%O.06", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM06: file = "%O.06", start = __BANKRAMSTART__, size = __BANKRAMSIZE__;
BRAM07ADDR: file = "%O.07", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM07: file = "%O.07", start = __BANKRAMSTART__, size = __BANKRAMSIZE__;
BRAM08ADDR: file = "%O.08", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM08: file = "%O.08", start = __BANKRAMSTART__, size = __BANKRAMSIZE__;
BRAM09ADDR: file = "%O.09", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM09: file = "%O.09", start = __BANKRAMSTART__, size = __BANKRAMSIZE__;
BRAM0AADDR: file = "%O.0a", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM0A: file = "%O.0a", start = __BANKRAMSTART__, size = __BANKRAMSIZE__;
BRAM0BADDR: file = "%O.0b", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM0B: file = "%O.0b", start = __BANKRAMSTART__, size = __BANKRAMSIZE__;
BRAM0CADDR: file = "%O.0c", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM0C: file = "%O.0c", start = __BANKRAMSTART__, size = __BANKRAMSIZE__;
BRAM0DADDR: file = "%O.0d", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM0D: file = "%O.0d", start = __BANKRAMSTART__, size = __BANKRAMSIZE__;
BRAM0EADDR: file = "%O.0e", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM0E: file = "%O.0e", start = __BANKRAMSTART__, size = __BANKRAMSIZE__;
BRAM0FADDR: file = "%O.0f", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM0F: file = "%O.0f", start = __BANKRAMSTART__, size = __BANKRAMSIZE__;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP, type = zp, optional = yes;
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = HEADER, type = ro;
STARTUP: load = MAIN, type = ro;
LOWCODE: load = MAIN, type = ro, optional = yes;
CODE: load = MAIN, type = ro;
RODATA: load = MAIN, type = ro;
DATA: load = MAIN, type = rw;
INIT: load = MAIN, type = rw;
ONCE: load = MAIN, type = ro, define = yes;
BSS: load = BSS, type = bss, define = yes;
BRAM00ADDR: load = BRAM00ADDR, type = ro, optional = yes;
BANKRAM00: load = BRAM00, type = rw, define = yes, optional = yes;
BRAM01ADDR: load = BRAM01ADDR, type = ro, optional = yes;
BANKRAM01: load = BRAM01, type = rw, define = yes, optional = yes;
BRAM02ADDR: load = BRAM02ADDR, type = ro, optional = yes;
BANKRAM02: load = BRAM02, type = rw, define = yes, optional = yes;
BRAM03ADDR: load = BRAM03ADDR, type = ro, optional = yes;
BANKRAM03: load = BRAM03, type = rw, define = yes, optional = yes;
BRAM04ADDR: load = BRAM04ADDR, type = ro, optional = yes;
BANKRAM04: load = BRAM04, type = rw, define = yes, optional = yes;
BRAM05ADDR: load = BRAM05ADDR, type = ro, optional = yes;
BANKRAM05: load = BRAM05, type = rw, define = yes, optional = yes;
BRAM06ADDR: load = BRAM06ADDR, type = ro, optional = yes;
BANKRAM06: load = BRAM06, type = rw, define = yes, optional = yes;
BRAM07ADDR: load = BRAM07ADDR, type = ro, optional = yes;
BANKRAM07: load = BRAM07, type = rw, define = yes, optional = yes;
BRAM08ADDR: load = BRAM08ADDR, type = ro, optional = yes;
BANKRAM08: load = BRAM08, type = rw, define = yes, optional = yes;
BRAM09ADDR: load = BRAM09ADDR, type = ro, optional = yes;
BANKRAM09: load = BRAM09, type = rw, define = yes, optional = yes;
BRAM0AADDR: load = BRAM0AADDR, type = ro, optional = yes;
BANKRAM0A: load = BRAM0A, type = rw, define = yes, optional = yes;
BRAM0BADDR: load = BRAM0BADDR, type = ro, optional = yes;
BANKRAM0B: load = BRAM0B, type = rw, define = yes, optional = yes;
BRAM0CADDR: load = BRAM0CADDR, type = ro, optional = yes;
BANKRAM0C: load = BRAM0C, type = rw, define = yes, optional = yes;
BRAM0DADDR: load = BRAM0DADDR, type = ro, optional = yes;
BANKRAM0D: load = BRAM0D, type = rw, define = yes, optional = yes;
BRAM0EADDR: load = BRAM0EADDR, type = ro, optional = yes;
BANKRAM0E: load = BRAM0E, type = rw, define = yes, optional = yes;
BRAM0FADDR: load = BRAM0FADDR, type = ro, optional = yes;
BANKRAM0F: load = BRAM0F, type = rw, define = yes, optional = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
segment = RODATA;
CONDES: type = interruptor,
label = __INTERRUPTOR_TABLE__,
count = __INTERRUPTOR_COUNT__,
segment = RODATA,
import = __CALLIRQ__;
}

45
cfg/cx16.cfg Normal file
View File

@ -0,0 +1,45 @@
FEATURES {
STARTADDRESS: default = $0801;
}
SYMBOLS {
__LOADADDR__: type = import;
__EXEHDR__: type = import;
__STACKSIZE__: type = weak, value = $0800; # 2k stack
__HIMEM__: type = weak, value = $9F00;
}
MEMORY {
ZP: file = "", define = yes, start = $0004, size = $0090 - $0004;
LOADADDR: file = %O, start = %S - 2, size = $0002;
HEADER: file = %O, define = yes, start = %S, size = $000D;
MAIN: file = %O, define = yes, start = __HEADER_LAST__, size = __HIMEM__ - __HEADER_LAST__;
BSS: file = "", start = __ONCE_RUN__, size = __HIMEM__ - __ONCE_RUN__ - __STACKSIZE__;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP, type = zp, optional = yes;
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = HEADER, type = ro;
STARTUP: load = MAIN, type = ro;
LOWCODE: load = MAIN, type = ro, optional = yes;
CODE: load = MAIN, type = ro;
RODATA: load = MAIN, type = ro;
DATA: load = MAIN, type = rw;
INIT: load = MAIN, type = rw;
ONCE: load = MAIN, type = ro, define = yes;
BSS: load = BSS, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
segment = RODATA;
CONDES: type = interruptor,
label = __INTERRUPTOR_TABLE__,
count = __INTERRUPTOR_COUNT__,
segment = RODATA,
import = __CALLIRQ__;
}

View File

@ -4653,9 +4653,10 @@ compiler, depending on the target system selected:
<item><tt/__C128__/ - Target system is <tt/c128/
<item><tt/__C16__/ - Target system is <tt/c16/ or <tt/plus4/
<item><tt/__C64__/ - Target system is <tt/c64/
<item><tt/__CBM__/ - Target is a Commodore system
<item><tt/__CBM__/ - Target is a Commodore or Commodore-alike system
<item><tt/__CBM510__/ - Target system is <tt/cbm510/
<item><tt/__CBM610__/ - Target system is <tt/cbm610/
<item><tt/__CX16__/ - Target system is <tt/cx16/
<item><tt/__GEOS__/ - Target is a GEOS system
<item><tt/__GEOS_APPLE__/ - Target system is <tt/geos-apple/
<item><tt/__GEOS_CBM__/ - Target system is <tt/geos-cbm/

View File

@ -901,6 +901,10 @@ The compiler defines several macros at startup:
<item><tt/__CC65_STD_CC65__/
</itemize>
<tag><tt>__CX16__</tt></tag>
This macro is defined if the target is the Commander X16 (-t cx16).
<tag><tt>__DATE__</tt></tag>
This macro expands to the date of translation of the preprocessing

311
doc/cx16.sgml Normal file
View File

@ -0,0 +1,311 @@
<!doctype linuxdoc system>
<article>
<title>Commander X16-specific information for cc65
<author><url url="mailto:greg.king5@verizon.net" name="Greg King">
<abstract>
An overview over the CX16 run-time system as it's implemented for the cc65 C
compiler.
</abstract>
<!-- Table of contents -->
<toc>
<!-- Begin the document -->
<sect>Overview<p>
The Commander X16 is a modern small computer with firmware that is based on
the ROMs in Commodore's VIC-20 and 64C. It has a couple of the I/O chips that
are in the VIC-20.
This file contains an overview of the CX16 run-time system as it comes with the
cc65 C compiler. It describes the memory layout, CX16-specific header files,
available drivers, and any pitfalls specific to that platform.
Please note that CX16-specific functions just are mentioned here; they are
described in detail in the separate <url url="funcref.html" name="function
reference">. Even functions marked as "platform dependent" may be available on
more than one platform. Please see the function reference for more
information.
<sect>Binary format<p>
The standard binary output format generated by the linker for the CX16 target
is a machine language program with a one-line BASIC stub which calls the
machine language part via SYS. That means that a program can be loaded as a
BASIC program, and started with RUN. It is, of course, possible to change that
behaviour by using a modified start-up file and linker config.
<sect>Memory layout<p>
cc65-generated programs with the default setup run with the I/O area and the
Kernal ROM visible. That means that Kernal entry points can be called directly.
The usable memory ranges are &dollar;0800 - &dollar;9EFF and &dollar;A000 -
&dollar;BFFF.
Special locations:
<descrip>
<tag/Stack/
The C run-time stack is located at &dollar;9EFF, and grows downward.
<tag/Heap/
The C heap is located at the end of the program, and grows toward the C
run-time stack.
<tag/Bank RAM/
Bank RAM is located at &dollar;A000 - &dollar;BFFF. It's an eight-Kibibyte
window into a half Mibibyte or two Mibibytes of banked RAM.
<tag/Bank ROM/
Bank ROM is located at &dollar;C000 - &dollar;FFFF. It's a sixteen-Kibibyte
window into 128 Kibibytes of banked ROM.
</descrip><p>
<sect>Linker configurations<p>
The ld65 linker comes with a default config. file for the Commander X16, which
is used via <tt/-t cx16/. The cx16 package comes with additional secondary
linker config. files which are used via <tt/-t cx16 -C &lt;configfile&gt;/.
<sect1>Default config. file (<tt/cx16.cfg/)<p>
The default configuration is tailored to C programs. It supplies the load
address and a small BASIC stub that starts the compiled program using a SYS
command.
<sect1><tt/cx16-asm.cfg/<p>
This configuration is made for Assembly programmers who don't need a special
setup. The default start address is &dollar;0801. It can be changed with the
linker command-line option <tt/--start-addr/ or <tt/-S/. All standard segments,
with the exception of <tt/ZEROPAGE/, are written to the output file;
and, a two-byte load address is prepended.
To use that config. file, assemble with <tt/-t cx16/, and link with <tt/-C
cx16-asm.cfg/. The former will make sure that the correct character
translations are in effect, while the latter supplies the actual config.
When using <tt/cl65/, use both command-line options.
Sample command line for <tt/cl65/:
<tscreen><verb>
cl65 -o file.prg -t cx16 -C cx16-asm.cfg source.s
</verb></tscreen>
To generate code that loads to &dollar;A000:
<tscreen><verb>
cl65 -o file.prg -Wl -S,$A000 -t cX16 -C cX16-asm.cfg source.s
</verb></tscreen>
It also is possible to add a small BASIC header to the program, that uses SYS
to jump to the program entry point (which is the start of the code segment).
The advantage is that the program can be started using RUN.
To generate a program with a BASIC SYS header, use
<tscreen><verb>
cl65 -o file.prg -u __EXEHDR__ -t cx16 -C cx16-asm.cfg source.s
</verb></tscreen>
Please note that, in this case, a changed start address doesn't make sense,
because the program must be loaded to BASIC's start address.
<sect>Platform-specific header files<p>
Programs containing CX16-specific code may use the <tt/cx16.h/ or <tt/cbm.h/
header files. Using the later may be an option when writing code for more than
one CBM-like platform, because it includes <tt/cx16.h/, and declares several
functions common to all CBM-like platforms.
<sect1>CX16-specific functions<p>
The functions listed below are special for the CX16. See the <url
url="funcref.html" name="function reference"> for declarations and usage.
<itemize>
<item>get_ostype()
<item>set_tv()
<item>videomode()
<item>waitvsync()
</itemize>
<sect1>CBM-specific functions<p>
Some functions are available for all (or, at least most) of the Commodore-like
machines. See the <url url="funcref.html" name="function reference"> for
declarations and usage.
<itemize>
<item>cbm_close()
<item>cbm_closedir()
<item>cbm_k_basin()
<item>cbm_k_bsout()
<item>cbm_k_chkin()
<item>cbm_k_ckout()
<item>cbm_k_close()
<item>cbm_k_clrch()
<item>cbm_k_load()
<item>cbm_k_open()
<item>cbm_k_readst()
<item>cbm_k_save()
<item>cbm_k_second()
<item>cbm_k_setlfs()
<item>cbm_k_setnam()
<item>cbm_k_tksa()
<item>cbm_load()
<item>cbm_open()
<item>cbm_opendir()
<item>cbm_read()
<item>cbm_readdir()
<item>cbm_save()
<item>cbm_write()
<item>get_tv()
</itemize>
<sect1>Hardware access<p>
The following pseudo variables declared in the <tt/cx16.h/ header file do allow
access to hardware located in the address space. Some variables are
structures, accessing the struct fields will access the chip registers.
<descrip>
<tag><tt/VERA/</tag>
The <tt/VERA/ structure allows access
to the Video Enhanced Retro Adapter chip.
<tag><tt/VIA1, VIA2/</tag>
Access to the two VIA (Versatile Interface Adapter) chips is available via
the <tt/VIA1/ and <tt/VIA2/ variables. The structure behind those variables
is explained in <tt/_6522.h/.
<tag><tt/BANK_RAM/</tag>
A character array that mirrors the eight-Kibibyte window, at &dollar;A000,
into banked RAM.
</descrip><p>
<sect>Loadable drivers<p>
The names in the parentheses denote the symbols to be used for static linking of the drivers.
<sect1>Graphics drivers<p>
No graphics drivers are available currently for the CX16.
<sect1>Extended memory drivers<p>
No extended memory drivers are available currently for the CX16.
<sect1>Joystick drivers<p>
The default drivers, <tt/joy_stddrv (joy_static_stddrv)/,
point to <tt/cX16-stdjoy.joy (cx16_stdjoy_joy)/.
<descrip>
<tag><tt/cX16-stdjoy.joy (cX16_stdjoy_joy)/</tag>
Supports up to two NES and SNES controllers connected to the joystick ports
of the CX16. It reads the four directions, and the A, B, Select, and Start
buttons. Button A is the primary fire button.
</descrip><p>
<sect1>Mouse drivers<p>
No mouse drivers are available currently for the CX16.
<sect1>RS232 device drivers<p>
No serial drivers are available currently for the CX16.
<sect>Limitations<p>
The Commander X16 still is being designed. It's configuration can change at
any time. Some changes could make old programs fail to work.
<sect>Other hints<p>
<sect1>Escape code<p>
For an Esc, press <tt/Ctrl/ and the <tt/[/ key.
<sect1>Passing arguments to the program<p>
Command-line arguments can be passed to <tt/main()/. Because that is not
supported directly by BASIC, the following syntax was chosen:
<tscreen><verb>
RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5
</verb></tscreen>
<enum>
<item>Arguments are separated by spaces.
<item>Arguments may be quoted.
<item>Leading and trailing spaces around an argument are ignored. Spaces within
a quoted argument are allowed.
<item>The first argument passed to <tt/main()/ is the program name.
<item>A maximum number of 10 arguments (including the program name) are
supported.
</enum>
<sect1>Program return code<p>
The program return code (low byte) is passed back to BASIC by use of the
<tt/ST/ variable.
<sect1>Interrupts<p>
The run-time for the CX16 uses routines marked as <tt/.INTERRUPTOR/ for
interrupt handlers. Such routines must be written as simple machine language
subroutines, and will be called automatically by the interrupt handler code
if they are linked into a program. See the discussion of the <tt/.CONDES/
feature in the <url url="ca65.html" name="assembler manual">.
<sect>License<p>
This software is provided "as-is", without any expressed or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
<enum>
<item> The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated, but is not required.
<item> Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
<item> This notice may not be removed or altered from any source
distribution.
</enum>
</article>

View File

@ -145,6 +145,9 @@
<tag><htmlurl url="creativision.html" name="creativision.html"></tag>
Topics specific to the Creativision Console.
<tag><htmlurl url="cx16.html" name="cx16.html"></tag>
Topics specific to the Commander X16.
<tag><htmlurl url="gamate.html" name="gamate.html"></tag>
Topics specific to the Bit Corporation Gamate Console.

View File

@ -402,11 +402,36 @@ RUN
The emulation, also, supports that method.
<sect1>Commander X16
<sect2>x16-emulator<p>
Available at <url
url="https://github.com/commanderx16/x16-emulator/releases">:
Emulates the Commander X16 Single Board Computer, with sound, SD card images,
VGA and NTSC video, and a NES game controller emulation. Includes a monitor.
It runs on all SDL2 platforms.
Compile the tutorial with
<tscreen><verb>
cl65 -O -t cx16 hello.c text.s
</verb></tscreen>
Start the emulator. Then, type
<tscreen><verb>
LOAD"HELLO",1
RUN
</verb></tscreen>
(Type those lines in lower-case; but, they will appear as upper-case.)
On a real computer, you would type an <tt/8/ instead of a <tt/1/.
<sect1>Commodore
<sect2>VICE<p>
Available at <url
url="http://vice-emu.sourceforge.net/">:
url="https://vice-emu.sourceforge.net/">:
Emulates Commodore 64/128/VIC-20/PET/CBM II/Plus 4 computers. Supports
printers, serial port and adapters, stereo sound, disk drives and images, RAM expansions,

View File

@ -65,6 +65,8 @@
# include <cbm610.h>
#elif defined(__PET__) && !defined(_PET_H)
# include <pet.h>
#elif defined(__CX16__) && !defined(_CX16_H)
# include <cx16.h>
#endif
/* Include definitions for CBM file types */
@ -300,5 +302,3 @@ void __fastcall__ cbm_closedir (unsigned char lfn);
/* End of cbm.h */
#endif

189
include/cx16.h Normal file
View File

@ -0,0 +1,189 @@
/*****************************************************************************/
/* */
/* cx16.h */
/* */
/* CX16 system-specific definitions */
/* */
/* */
/* This software is provided "as-is", without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated, but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef _CX16_H
#define _CX16_H
/* Check for errors */
#ifndef __CX16__
# error This module may be used only when compiling for the CX16!
#endif
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Additional key defines */
#define CH_F1 0x85
#define CH_F2 0x89
#define CH_F3 0x86
#define CH_F4 0x8A
#define CH_F5 0x87
#define CH_F6 0x8B
#define CH_F7 0x88
#define CH_F8 0x8C
#define CH_F9 0x10
#define CH_F10 0x15
#define CH_F11 0x16
#define CH_F12 0x17
/* Color defines */
#define COLOR_BLACK 0x00
#define COLOR_WHITE 0x01
#define COLOR_RED 0x02
#define COLOR_CYAN 0x03
#define COLOR_VIOLET 0x04
#define COLOR_PURPLE COLOR_VIOLET
#define COLOR_GREEN 0x05
#define COLOR_BLUE 0x06
#define COLOR_YELLOW 0x07
#define COLOR_ORANGE 0x08
#define COLOR_BROWN 0x09
#define COLOR_LIGHTRED 0x0A
#define COLOR_GRAY1 0x0B
#define COLOR_GRAY2 0x0C
#define COLOR_LIGHTGREEN 0x0D
#define COLOR_LIGHTBLUE 0x0E
#define COLOR_GRAY3 0x0F
/* Masks for joy_read() */
#define JOY_BTN_1_MASK 0x80
#define JOY_BTN_2_MASK 0x40
#define JOY_BTN_3_MASK 0x20
#define JOY_BTN_4_MASK 0x10
#define JOY_UP_MASK 0x08
#define JOY_DOWN_MASK 0x04
#define JOY_LEFT_MASK 0x02
#define JOY_RIGHT_MASK 0x01
#define JOY_BTN_A_MASK JOY_BTN_1_MASK
#define JOY_BTN_B_MASK JOY_BTN_2_MASK
#define JOY_SELECT_MASK JOY_BTN_3_MASK
#define JOY_START_MASK JOY_BTN_4_MASK
#define JOY_BTN_A(v) ((v) & JOY_BTN_A_MASK)
#define JOY_BTN_B(v) ((v) & JOY_BTN_B_MASK)
#define JOY_SELECT(v) ((v) & JOY_SELECT_MASK)
#define JOY_START(v) ((v) & JOY_START_MASK)
#define JOY_FIRE2_MASK JOY_BTN_2_MASK
#define JOY_FIRE2(v) ((v) & JOY_FIRE2_MASK)
/* get_tv() return codes
** set_tv() argument codes
*/
#define TV_NONE 0
#define TV_VGA 1
#define TV_NTSC_COLOR 2
#define TV_RGB 3
#define TV_NONE2 4
#define TV_VGA2 5
#define TV_NTSC_MONO 6
#define TV_RGB2 7
/* Video mode defines */
#define VIDEOMODE_40x30 40u
#define VIDEOMODE_80x60 80u
#define VIDEOMODE_40COL VIDEOMODE_40x30
#define VIDEOMODE_80COL VIDEOMODE_80x60
/* Define hardware */
/* Define a structure with the Video Enhanced Retro Adapter's
** external registers.
*/
struct __vera {
unsigned short address; /* Address for data ports */
unsigned char address_hi;
unsigned char data0; /* Data port 0 */
unsigned char data1; /* Data port 1 */
unsigned char control; /* Control register */
unsigned char irq_enable; /* Interrupt enable bits */
unsigned char irq_flags; /* Interrupt flags */
};
#define VERA (*(volatile struct __vera *)0x9F20)
#include <_6522.h>
#define VIA1 (*(volatile struct __6522 *)0x9F60)
#define VIA2 (*(volatile struct __6522 *)0x9F70)
/* Define a structure with the x16emu's settings registers. */
struct __emul {
unsigned char debug; /* Boolean: debugging enabled */
unsigned char vera_action; /* Boolean: displaying VERA activity */
unsigned char keyboard; /* Boolean: displaying typed keys */
unsigned char echo; /* Boolean: Kernal output echoed to host */
unsigned char save_on_exit; /* Boolean: save SD card when quitting */
unsigned char unused[0xD - 0x5];
unsigned char keymap; /* Keyboard layout number */
const char detect[2]; /* "16" if running on x16emu */
};
#define EMULATOR (*(volatile struct __emul)0x9FB0)
/* The addresses of the static drivers */
extern void cx16_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */
/*****************************************************************************/
/* Code */
/*****************************************************************************/
signed char get_ostype (void);
/* Get the ROM build version.
** -1 -- custom build
** Negative -- prerelease build
** Positive -- release build
*/
void __fastcall__ set_tv (unsigned char);
/* Set the video mode the machine will use.
** Call with a TV_xx constant.
*/
unsigned char __fastcall__ videomode (unsigned char Mode);
/* Set the video mode, return the old mode. Call with one of the VIDEOMODE_xx
** constants.
*/
/* End of cX16.h */
#endif

View File

@ -7,6 +7,7 @@ CBMS = c128 \
c64 \
cbm510 \
cbm610 \
cx16 \
pet \
plus4 \
vic20

14
libsrc/cx16/_scrsize.s Normal file
View File

@ -0,0 +1,14 @@
;
; 2019-09-16, Greg King
;
; Screen size info
;
.export screensize
.include "cx16.inc"
screensize:
ldx LLEN
ldy NLINES
rts

50
libsrc/cx16/bankramaddr.s Normal file
View File

@ -0,0 +1,50 @@
;
; 2019-09-16, Greg King
;
; This module supplies the load addresses that are expected
; by a Commander X16 in the first two bytes of banked RAM load files.
;
; The following symbol is used by a linker config. to force
; this module to get included into the output files.
.export __BANKRAMADDR__: abs = 1
.segment "BRAM00ADDR"
.addr *+2
.segment "BRAM01ADDR"
.addr *+2
.segment "BRAM02ADDR"
.addr *+2
.segment "BRAM03ADDR"
.addr *+2
.segment "BRAM04ADDR"
.addr *+2
.segment "BRAM05ADDR"
.addr *+2
.segment "BRAM06ADDR"
.addr *+2
.segment "BRAM07ADDR"
.addr *+2
.segment "BRAM08ADDR"
.addr *+2
.segment "BRAM09ADDR"
.addr *+2

27
libsrc/cx16/bordercolor.s Normal file
View File

@ -0,0 +1,27 @@
;
; 2019-09-23, Greg King
;
; unsigned char __fastcall__ bordercolor (unsigned char color);
; /* Set the color for the border. The old color setting is returned. */
;
.export _bordercolor
.include "cx16.inc"
_bordercolor:
tax
; Point to the border color register.
stz VERA::CTRL ; Use port 0
lda #<VERA::COMPOSER::FRAME
sta VERA::ADDR
lda #>VERA::COMPOSER::FRAME
sta VERA::ADDR+1
ldy #^VERA::COMPOSER::FRAME | VERA::INC0
sty VERA::ADDR+2
lda VERA::DATA0 ; get old value
stx VERA::DATA0 ; set new value
rts

109
libsrc/cx16/break.s Normal file
View File

@ -0,0 +1,109 @@
;
; 1998-09-27, Ullrich von Bassewitz
; 2019-09-08, Greg King
;
; void __fastcall__ set_brk (unsigned Addr);
; void reset_brk (void);
;
.export _set_brk, _reset_brk
.destructor _reset_brk
.export _brk_a, _brk_x, _brk_y, _brk_sr, _brk_pc
.include "cx16.inc"
.bss
_brk_a: .res 1
_brk_x: .res 1
_brk_y: .res 1
_brk_sr: .res 1
_brk_pc: .res 2
oldvec: .res 2 ; Old vector
.data
uservec: jmp $FFFF ; Patched at runtime
.code
; Set the break vector
.proc _set_brk
sta uservec+1
stx uservec+2 ; Set the user vector
lda oldvec
ora oldvec+1 ; Did we save the vector already?
bne L1 ; Jump if we installed the handler already
lda BRKVec
sta oldvec
lda BRKVec+1
sta oldvec+1 ; Save the old vector
L1: lda #<brk_handler ; Set the break vector to our routine
ldx #>brk_handler
sta BRKVec
stx BRKVec+1
rts
.endproc
; Reset the break vector
.proc _reset_brk
lda oldvec
ldx oldvec+1
beq @L9 ; Jump if vector not installed
sta BRKVec
stx BRKVec+1
lda #$00
sta oldvec ; Clear the old vector
stx oldvec+1
@L9: rts
.endproc
; Break handler, called if a break occurs
.proc brk_handler
pla
sta _brk_y
pla
sta _brk_x
pla
sta _brk_a
pla
and #$EF ; Clear break bit
sta _brk_sr
pla ; PC low
sec
sbc #2 ; Point to start of brk
sta _brk_pc
pla ; PC high
sbc #0
sta _brk_pc+1
jsr uservec ; Call the user's routine
lda _brk_pc+1
pha
lda _brk_pc
pha
lda _brk_sr
pha
ldx _brk_x
ldy _brk_y
lda _brk_a
rti ; Jump back...
.endproc

72
libsrc/cx16/cgetc.s Normal file
View File

@ -0,0 +1,72 @@
;
; 2019-09-23, Greg King
;
; char cgetc (void);
; /* Return a character from the keyboard. */
;
.export _cgetc
.import cursor, GETIN
.include "cx16.inc"
.macpack generic
_cgetc: ldx KEY_COUNT ; Get number of characters
bnz L3 ; Jump if there are already chars waiting
; Switch the cursor on if wanted.
lda CURS_FLAG ; Save cursor's current enable flag
tay
lda cursor
jsr setcursor
L1: lda KEY_COUNT
bze L1 ; Wait for key
tya
eor #%00000001 ; (Cursor flag uses negative logic)
jsr setcursor ; Restore previous cursor condition
; An internal Kernal function can't be used because it might be moved in future
; revisions. Use an official function; but, make sure that it reads
; the keyboard.
L3: ldy IN_DEV ; Save current input device
stz IN_DEV ; Keyboard
jsr GETIN ; Read char, and return in .A
sty IN_DEV ; Restore input device
ldx #>$0000
rts
; Switch the cursor on or off.
setcursor:
tax ; On or off?
bnz seton ; Go set it on
lda CURS_FLAG ; Is the cursor currently off?
bnz crs9 ; Jump if yes
inc CURS_FLAG ; Mark it as off
ldx CURS_STATE ; Cursor currently displayed?
bze crs9 ; Jump if not
; Restore the current character in video RAM.
; Restore that character's colors.
stz VERA::CTRL ; Use port 0
lda CURS_Y
sta VERA::ADDR+1 ; Set row number
lda #VERA::INC1 ; Increment address by one
sta VERA::ADDR+2
lda CURS_X ; Get character column
asl a
sta VERA::ADDR
ldx CURS_CHAR
stx VERA::DATA0
ldx CURS_COLOR
stx VERA::DATA0
stz CURS_STATE ; Cursor not displayed
crs9: rts
seton: stz CURS_FLAG
rts

26
libsrc/cx16/clrscr.s Normal file
View File

@ -0,0 +1,26 @@
;
; 2019-09-22, Greg King
;
; void clrscr (void);
; /* Clear the screen. */
;
.export _clrscr
.import CHROUT
.include "cx16.inc"
; An internal Kernal function can't be used because it might be moved in future
; revisions. Use an official function; but, make sure that it prints
; to the screen.
_clrscr:
ldy OUT_DEV ; Save current output device
ldx #$03 ; Screen device
stx OUT_DEV
lda #$93
jsr CHROUT ; Print clear-screen character
sty OUT_DEV ; Restore output device
rts

43
libsrc/cx16/color.s Normal file
View File

@ -0,0 +1,43 @@
;
; 2019-09-16, Greg King
;
; unsigned char __fastcall__ textcolor (unsigned char color);
; unsigned char __fastcall__ bgcolor (unsigned char color);
;
.export _textcolor, _bgcolor
.importzp tmp1
.include "cx16.inc"
_textcolor:
and #$0F
sta tmp1
ldx CHARCOLOR ; get old values
txa
and #<~$0F ; keep screen color, remove text color
ora tmp1
sta CHARCOLOR ; set new values
txa
and #$0F
rts
_bgcolor:
asl a ; move number to screen-color nybble
asl a
asl a
asl a
sta tmp1
ldx CHARCOLOR ; get old values
txa
and #<~$F0 ; remove screen color, keep text color
ora tmp1
sta CHARCOLOR ; set new values
txa
lsr a ; get screen color
lsr a
lsr a
lsr a
rts

9
libsrc/cx16/conio.s Normal file
View File

@ -0,0 +1,9 @@
;
; 2019-09-23, Greg King
;
; Low-level stuff for screen output/console input
;
.exportzp CURS_X, CURS_Y
.include "cx16.inc"

48
libsrc/cx16/cpeekc.s Normal file
View File

@ -0,0 +1,48 @@
;
; 2016-02-28, Groepaz
; 2019-09-25, Greg King
;
; char cpeekc (void);
; /* Return the character from the current cursor position. */
;
.export _cpeekc
.include "cx16.inc"
_cpeekc:
php
sei ; don't let cursor blinking interfere
stz VERA::CTRL ; use port 0
lda CURS_Y
sta VERA::ADDR+1 ; set row number
stz VERA::ADDR+2
lda CURS_X ; get character column
asl a
sta VERA::ADDR
lda VERA::DATA0 ; get screen code
plp
ldx #>$0000
and #<~%10000000 ; remove reverse bit
; Convert the screen code into a PetSCII code.
; $00 - $1F: +$40
; $20 - $3F
; $40 - $5f: +$20
; $60 - $7F: +$40
cmp #$20
bcs @sk1 ;(bge)
ora #$40
rts
@sk1: cmp #$40
bcc @end ;(blt)
cmp #$60
bcc @sk2 ;(blt)
;sec
adc #$20 - $01
@sk2: ;clc ; both above cmp and adc clear carry flag
adc #$20
@end: rts

27
libsrc/cx16/cpeekcolor.s Normal file
View File

@ -0,0 +1,27 @@
;
; 2019-09-25, Greg King
;
; unsigned char cpeekcolor (void);
; /* Return the colors from the current cursor position. */
;
.export _cpeekcolor
.include "cx16.inc"
_cpeekcolor:
php
sei ; don't let cursor blinking interfere
stz VERA::CTRL ; use port 0
lda CURS_Y
sta VERA::ADDR+1 ; set row number
stz VERA::ADDR+2
lda CURS_X ; get character column
sec ; color attribute is second byte
rol a
sta VERA::ADDR
lda VERA::DATA0 ; get color
plp
ldx #>$0000
rts

32
libsrc/cx16/cpeekrevers.s Normal file
View File

@ -0,0 +1,32 @@
;
; 2016-02-28, Groepaz
; 2019-09-25, Greg King
;
; unsigned char cpeekrevers (void);
; /* Return the reverse attribute from the current cursor position.
; ** If the character is reversed, then return 1; return 0 otherwise.
; */
;
.export _cpeekrevers
.include "cx16.inc"
_cpeekrevers:
php
sei ; don't let cursor blinking interfere
stz VERA::CTRL ; use port 0
lda CURS_Y
sta VERA::ADDR+1 ; set row number
stz VERA::ADDR+2
lda CURS_X ; get character column
asl a
sta VERA::ADDR
lda VERA::DATA0 ; get screen code
plp
and #%10000000 ; get reverse bit
asl a
tax ; ldx #>$0000
rol a ; return boolean value
rts

0
libsrc/cx16/cpeeks.s Normal file
View File

98
libsrc/cx16/cputc.s Normal file
View File

@ -0,0 +1,98 @@
;
; 2019-09-23, Greg King
;
; void __fastcall__ cputcxy (unsigned char x, unsigned char y, char c);
; void __fastcall__ cputc (char c);
;
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot
.import gotoxy, PLOT
.include "cx16.inc"
.macpack generic
; First, move to a new position.
_cputcxy:
pha ; Save C
jsr gotoxy ; Set cursor, drop x and y
pla ; Restore C
; Print a character.
_cputc: cmp #$0D ; LF?
beq newline
cmp #$0A ; CR?
beq plotx0
; Printable char of some sort
cmp #' '
blt cputdirect ; Other control char
tay
bmi L10
cmp #$60
blt L2
and #<~%00100000
bra cputdirect
; Handle character if high bit set
L10: and #<~%10000000 ; Remove high bit
ora #%01000000
bra cputdirect
L2: and #<~%01000000
cputdirect:
jsr putchar ; Write character to screen, return .Y
; Advance cursor position.
iny
cpy LLEN ; Reached end of line?
bne L3
jsr newline ; Next line
ldy #$00 ; + CR
L3: sty CURS_X
rts
; Move down.
newline:
inc SCREEN_PTR+1
inc CURS_Y
rts
; Set the cursor's position, calculate RAM pointer.
plotx0: stz CURS_X
plot: ldy CURS_X
ldx CURS_Y
clc
jmp PLOT ; Set the new cursor
; Write one screen-code and color to the video RAM without doing anything else.
; Return the x position in Y.
putchar:
ora RVS ; Set revers bit
tax
stz VERA::CTRL ; Use port 0
lda CURS_Y
sta VERA::ADDR+1 ; Set row number
lda #VERA::INC1 ; Increment address by one
sta VERA::ADDR+2
ldy CURS_X ; Get character column
tya
asl a
sta VERA::ADDR
stx VERA::DATA0
lda CHARCOLOR
sta VERA::DATA0
rts

115
libsrc/cx16/crt0.s Normal file
View File

@ -0,0 +1,115 @@
;
; Start-up code for cc65 (CX16 version)
;
.export _exit
.export __STARTUP__ : absolute = 1 ; Mark as start-up
.import initlib, donelib
.import zerobss, callmain
.import BSOUT
.import __MAIN_START__, __MAIN_SIZE__ ; Linker-generated
.importzp ST
.include "zeropage.inc"
.include "cx16.inc"
; ------------------------------------------------------------------------
; Start-up code
.segment "STARTUP"
Start: tsx
stx spsave ; Save the system stack ptr
; Save space by putting some of the start-up code in the ONCE segment,
; which will be re-used by the BSS segment, the heap, and the C stack.
jsr init
; Clear the BSS data.
jsr zerobss
; Push the command-line arguments; and, call main().
jsr callmain
; Back from main() [this is also the exit() entry]. Run the module destructors.
_exit: pha ; Save the return code on stack
jsr donelib
; Copy back the zero-page stuff.
ldx #zpspace-1
L2: lda zpsave,x
sta sp,x
dex
bpl L2
; Place the program return code into BASIC's status variable.
pla
sta ST
; Restore the system stuff.
ldx spsave
txs ; Restore stack pointer
ldx banksave
stx VIA1::PRA2 ; Restore former RAM bank
; Back to BASIC.
rts
; ------------------------------------------------------------------------
.segment "ONCE"
init:
; Change to the first RAM bank.
lda VIA1::PRA2
sta banksave ; Save the current bank number
lda #$00 ; Choose RAM bank zero
sta VIA1::PRA2
; Save the zero-page locations that we need.
ldx #zpspace-1
L1: lda sp,x
sta zpsave,x
dex
bpl L1
; Set up the stack.
lda #<(__MAIN_START__ + __MAIN_SIZE__)
ldx #>(__MAIN_START__ + __MAIN_SIZE__)
sta sp
stx sp+1 ; Set argument stack ptr
; Switch to the second charset.
lda #$0E
jsr BSOUT
; Call the module constructors.
jmp initlib
; ------------------------------------------------------------------------
; Data
.segment "INIT"
banksave:
.res 1
spsave: .res 1
zpsave: .res zpspace

8
libsrc/cx16/devnum.s Normal file
View File

@ -0,0 +1,8 @@
;
; 2010-02-14, Oliver Schmidt
; 2019-09-08, Greg King
;
.include "cx16.inc"
.exportzp devnum := DEVNUM

20
libsrc/cx16/get_ostype.s Normal file
View File

@ -0,0 +1,20 @@
;
; 2019-09-09, Greg King
;
; signed char get_ostype(void)
; /* Return a "build version". */
;
; Positive number -- release build
; Negative number -- prerelease build
; -1 -- custom build
;
.export _get_ostype
.proc _get_ostype
ldx #>$0000
lda $ff80
bpl :+
dex ; negative
: rts
.endproc

31
libsrc/cx16/get_tv.s Normal file
View File

@ -0,0 +1,31 @@
;
; 2019-09-20, Greg King
;
; unsigned char get_tv (void);
; /* Return the video mode the machine is using. */
;
.export _get_tv
.include "cx16.inc"
.proc _get_tv
php
sei ; Don't let interrupts interfere
; Point to the video output register.
stz VERA::CTRL ; Use port 0
lda #<VERA::COMPOSER::VIDEO
ldx #>VERA::COMPOSER::VIDEO
ldy #^VERA::COMPOSER::VIDEO
sta VERA::ADDR
stx VERA::ADDR+1
sty VERA::ADDR+2
lda VERA::DATA0
plp ; Re-enable interrupts
and #$07 ; Get the type of output signal
rts
.endproc

48
libsrc/cx16/irq.s Normal file
View File

@ -0,0 +1,48 @@
;
; IRQ handling (CX16 version)
;
.export initirq, doneirq
.import callirq
.include "cx16.inc"
; ------------------------------------------------------------------------
.segment "ONCE"
initirq:
lda IRQVec
ldx IRQVec+1
sta IRQInd+1
stx IRQInd+2
lda #<IRQStub
ldx #>IRQStub
jmp setvec
; ------------------------------------------------------------------------
.code
doneirq:
lda IRQInd+1
ldx IRQInd+2
setvec: sei
sta IRQVec
stx IRQVec+1
cli
rts
; ------------------------------------------------------------------------
.segment "LOWCODE"
IRQStub:
jsr callirq ; Call the functions
jmp IRQInd ; Jump to the saved IRQ vector
; ------------------------------------------------------------------------
.data
IRQInd: jmp $0000

View File

@ -0,0 +1,119 @@
;
; Standard joystick driver for the CX16.
; May be used multiple times when statically linked to the application.
;
; 2019-09-23, Greg King
;
.include "joy-kernel.inc"
.include "joy-error.inc"
.include "cbm_kernal.inc"
.include "cx16.inc"
.macpack generic
.macpack module
; ------------------------------------------------------------------------
; Header. Includes jump table
module_header _cx16_stdjoy_joy
; Driver signature
.byte $6A, $6F, $79 ; ASCII "joy"
.byte JOY_API_VERSION ; Driver API version number
; Library reference
.addr $0000
; Jump table.
.addr INSTALL
.addr UNINSTALL
.addr COUNT
.addr READ
; ------------------------------------------------------------------------
; Constant
JOY_COUNT = 2 ; Number of joysticks we support
; ------------------------------------------------------------------------
; Data.
.code
; ------------------------------------------------------------------------
; INSTALL routine. Is called after the driver is loaded into memory.
; If possible, check if the hardware is present, and determine the amount
; of memory available.
; Must return a JOY_ERR_xx code in a/x.
;
INSTALL:
lda #<JOY_ERR_OK
ldx #>JOY_ERR_OK
; rts ; Run into UNINSTALL instead
; ------------------------------------------------------------------------
; UNINSTALL routine. Is called before the driver is removed from memory.
; Can do clean-up or whatever. Must not return anything.
;
UNINSTALL:
rts
; ------------------------------------------------------------------------
; COUNT: Return the total number of possible joysticks in a/x.
;
COUNT: lda #<JOY_COUNT
ldx #>JOY_COUNT
rts
; ------------------------------------------------------------------------
; READ: Read a particular joystick passed in A.
;
; TODO: Find a way to report the SNES controller's extra four lines.
;
READ: pha
jsr GETJOY
pla
bne pad2
; Read game pad 1
pad1: lda JOY1 + 1
bit #%00001110
beq nes1
asl JOY1 ; Get SNES's B button
ror a ; Put it next to the A button
asl JOY1 ; Drop SNES's Y button
asl a ; Get the B button
ror JOY1
asl a ; Get SNES's A button
ror JOY1 ; Make byte look like NES pad
nes1: lda JOY1
eor #%11111111 ; We don't want the pad's negative logic
rts
; Read game pad 2
pad2: lda JOY2 + 1
bit #%00001110
beq nes2
asl JOY2
ror a
asl JOY2
asl a
ror JOY2
asl a
ror JOY2
nes2: lda JOY2
eor #%11111111
rts

View File

@ -0,0 +1,10 @@
;
; Address of the static standard joystick driver
;
; 2019-09-19, Greg King
;
; const void joy_static_stddrv[];
;
.import _cx16_stdjoy_joy
.export _joy_static_stddrv := _cx16_stdjoy_joy

13
libsrc/cx16/joy_stddrv.s Normal file
View File

@ -0,0 +1,13 @@
;
; Name of the standard joystick driver
;
; 2019-09-19, Greg King
;
; const char joy_stddrv[];
;
.export _joy_stddrv
.rodata
_joy_stddrv: .asciiz "cx16-stdjoy.joy"

17
libsrc/cx16/kbhit.s Normal file
View File

@ -0,0 +1,17 @@
;
; 2019-09-20, Greg King
;
; unsigned char kbhit (void);
; /* Returns non-zero (true) if a typed character is waiting. */
;
.export _kbhit
.include "cx16.inc"
.proc _kbhit
ldx #>$0000 ; High byte of return
lda KEY_COUNT ; Get number of characters
rts
.endproc

59
libsrc/cx16/kernal.s Normal file
View File

@ -0,0 +1,59 @@
;
; 2019-09-22, Greg King
;
; CX16 Kernal functions
;
.include "cbm_kernal.inc"
.export GETJOY
.export CLSALL
.export SWAPPER
.export JSRFAR
.export INDFET
.export INDSTA
.export INDCMP
.export PRIMM
.export CINT
.export IOINIT
.export RAMTAS
.export RESTOR
.export VECTOR
.export SETMSG
.export SECOND
.export TKSA
.export MEMTOP
.export MEMBOT
.export SCNKEY
.export SETTMO
.export ACPTR
.export CIOUT
.export UNTLK
.export UNLSN
.export LISTEN
.export TALK
.export READST
.export SETLFS
.export SETNAM
.export OPEN
.export CLOSE
.export CHKIN
.export CKOUT
.export CLRCH
.export BASIN
.export CHRIN
.export BSOUT
.export CHROUT
.export LOAD
.export SAVE
.export SETTIM
.export RDTIM
.export STOP
.export GETIN
.export CLALL
.export UDTIM
.export SCREEN
.export PLOT
.export IOBASE

18
libsrc/cx16/libref.s Normal file
View File

@ -0,0 +1,18 @@
;
; 2013-05-31, Oliver Schmidt
; 2019-09-22, Greg King
;
.export em_libref
.export joy_libref
.export mouse_libref
.export ser_libref
.export tgi_libref
.import _exit
em_libref := _exit
joy_libref := _exit
mouse_libref := _exit
ser_libref := _exit
tgi_libref := _exit

137
libsrc/cx16/mainargs.s Normal file
View File

@ -0,0 +1,137 @@
; mainargs.s
;
; Ullrich von Bassewitz, 2003-03-07
; Based on code from Stefan A. Haubenthal, <polluks@web.de>
; 2005-02-26, Ullrich von Bassewitz
; 2019-09-08, Greg King
;
; Scan a group of arguments that are in BASIC's input-buffer.
; Build an array that points to the beginning of each argument.
; Send, to main(), that array and the count of the arguments.
;
; Command-lines look like these lines:
;
; run
; run : rem
; run:rem arg1 " arg 2 is quoted " arg3 "" arg5
;
; "run" and "rem" are entokenned; the args. are not. Leading and trailing
; spaces outside of quotes are ignored.
;
; TO-DO:
; - The "file-name" might be a path-name; don't copy the directory-components.
; - Add a control-character quoting mechanism.
.constructor initmainargs, 24
.import __argc, __argv
.include "cx16.inc"
MAXARGS = 10 ; Maximum number of arguments allowed
REM = $8f ; BASIC token-code
NAME_LEN = 16 ; Maximum length of command-name
; Get possible command-line arguments. Goes into the special ONCE segment,
; which may be reused after the startup code is run
.segment "ONCE"
initmainargs:
; Assume that the program was loaded, a moment ago, by the traditional LOAD
; statement. Save the "most-recent filename" as argument #0.
lda #0 ; The terminating NUL character
ldy FNAM_LEN
cpy #NAME_LEN + 1
bcc L1
ldy #NAME_LEN ; Limit the length
bne L1 ; Branch always
L0: lda (FNAM),y
L1: sta name,y
dey
bpl L0
inc __argc ; argc always is equal to, at least, 1
; Find the "rem" token.
ldx #0
L2: lda BASIC_BUF,x
beq done ; No "rem," no args.
inx
cmp #REM
bne L2
ldy #1 * 2
; Find the next argument
next: lda BASIC_BUF,x
beq done ; End of line reached
inx
cmp #' ' ; Skip leading spaces
beq next
; Found start of next argument. We've incremented the pointer in X already, so
; it points to the second character of the argument. This is useful since we
; will check now for a quoted argument, in which case we will have to skip this
; first character.
found: cmp #'"' ; Is the argument quoted?
beq setterm ; Jump if so
dex ; Reset pointer to first argument character
lda #' ' ; A space ends the argument
setterm:sta term ; Set end of argument marker
; Now store a pointer to the argument into the next slot. Since the BASIC
; input buffer is located at the start of a RAM page, no calculations are
; necessary.
txa ; Get low byte
sta argv,y ; argv[y]= &arg
iny
lda #>BASIC_BUF
sta argv,y
iny
inc __argc ; Found another arg
; Search for the end of the argument
argloop:lda BASIC_BUF,x
beq done
inx
cmp term
bne argloop
; We've found the end of the argument. X points one character behind it, and
; A contains the terminating character. To make the argument a valid C string,
; replace the terminating character by a zero.
lda #0
sta BASIC_BUF-1,x
; Check if the maximum number of command line arguments is reached. If not,
; parse the next one.
lda __argc ; Get low byte of argument count
cmp #MAXARGS ; Maximum number of arguments reached?
bcc next ; Parse next one if not
; (The last vector in argv[] already is NULL.)
done: lda #<argv
ldx #>argv
sta __argv
stx __argv + 1
rts
.segment "INIT"
term: .res 1
name: .res NAME_LEN + 1
.data
; char* argv[MAXARGS+1]={name};
argv: .addr name
.res MAXARGS * 2

23
libsrc/cx16/revers.s Normal file
View File

@ -0,0 +1,23 @@
;
; 2019-09-16, Greg King
;
; unsigned char __fastcall__ revers (unsigned char onoff);
;
.export _revers
.include "cx16.inc"
.proc _revers
ldy #$00 ; Assume revers off
tax ; Test on/off
beq :+ ; Jump if off
ldy #$80 ; Load "on" value
ldx #>$0000 ; Zero high byte of result
: lda RVS ; Load old value
sty RVS ; Set new value
clc
rol a ; Convert bit-mask into boolean
rol a
rts
.endproc

32
libsrc/cx16/set_tv.s Normal file
View File

@ -0,0 +1,32 @@
;
; 2019-09-20, Greg King
;
; void __fastcall__ set_tv (unsigned char);
; /* Set the video mode the machine will use. */
;
.export _set_tv
.include "cx16.inc"
.proc _set_tv
php
pha
sei ; Don't let interrupts interfere
; Point to the video output register.
stz VERA::CTRL ; Use port 0
lda #<VERA::COMPOSER::VIDEO
ldx #>VERA::COMPOSER::VIDEO
ldy #^VERA::COMPOSER::VIDEO
sta VERA::ADDR
stx VERA::ADDR+1
sty VERA::ADDR+2
pla
sta VERA::DATA0
plp ; Re-enable interrupts
rts
.endproc

6
libsrc/cx16/status.s Normal file
View File

@ -0,0 +1,6 @@
;
; 2012-09-30, Oliver Schmidt
; 2019-09-08, Greg King
;
.exportzp ST := $90 ; IEC status byte

37
libsrc/cx16/sysuname.s Normal file
View File

@ -0,0 +1,37 @@
;
; 2003-08-12, Ullrich von Bassewitz
; 2019-09-08, Greg King
;
; unsigned char __fastcall__ _sysuname (struct utsname* buf);
;
.export __sysuname, utsdata
.import utscopy
__sysuname := utscopy
;--------------------------------------------------------------------------
; Data. We define a fixed utsname struct here, and just copy it.
.rodata
utsdata:
; sysname
.asciiz "cc65"
; nodename
.asciiz ""
; release
.byte ((.VERSION >> 8) & $0F) + '0'
.byte '.'
.byte ((.VERSION >> 4) & $0F) + '0'
.byte $00
; version
.byte (.VERSION & $0F) + '0'
.byte $00
; machine
.asciiz "Commander X16"

30
libsrc/cx16/videomode.s Normal file
View File

@ -0,0 +1,30 @@
;
; 2009-09-07, Ullrich von Bassewitz
; 2019-09-23, Greg King
;
; unsigned __fastcall__ videomode (unsigned Mode);
; /* Set the video mode, return the old mode. */
;
.export _videomode
.import SWAPPER
.include "cx16.inc"
.proc _videomode
cmp LLEN ; Do we have this mode already?
beq @L9
lda LLEN ; Get current mode ...
pha ; ... and save it
jsr SWAPPER ; Toggle the mode
pla ; Get old mode into A
; Done, old mode is in .A
@L9: ldx #>$0000 ; Clear high byte
rts
.endproc

17
libsrc/cx16/waitvsync.s Normal file
View File

@ -0,0 +1,17 @@
;
; 2019-09-26, Greg King
;
; void waitvsync (void);
;
; VERA's vertical sync. causes IRQs which increment the jiffy clock.
;
.export _waitvsync
.include "cx16.inc"
_waitvsync:
lda TIME + 2
: cmp TIME + 2
beq :- ; Wait for next jiffy
rts

View File

@ -296,7 +296,7 @@ static void SetSys (const char* Sys)
case TGT_ATMOS:
NewSymbol ("__ATMOS__", 1);
break;
break;
case TGT_TELESTRAT:
NewSymbol ("__TELESTRAT__", 1);
@ -330,6 +330,10 @@ static void SetSys (const char* Sys)
NewSymbol ("__PCE__", 1);
break;
case TGT_CX16:
CBMSystem ("__CX16__");
break;
default:
AbEnd ("Invalid target name: '%s'", Sys);

View File

@ -285,6 +285,10 @@ static void SetSys (const char* Sys)
DefineNumericMacro ("__PCE__", 1);
break;
case TGT_CX16:
cbmsys ("__CX16__");
break;
default:
AbEnd ("Unknown target system type %d", Target);
}

View File

@ -135,11 +135,11 @@ static const unsigned char CTPET[256] = {
typedef struct TargetEntry TargetEntry;
struct TargetEntry {
char Name[13]; /* Target name */
target_t Id; /* Target id */
target_t Id; /* Target ID */
};
/* Table that maps target names to ids. Sorted alphabetically for bsearch.
** Allows multiple entries for one target id (target name aliases).
/* Table that maps target names to IDs. Sorted alphabetically for bsearch().
** Allows multiple entries for one target ID (target name aliases).
*/
static const TargetEntry TargetMap[] = {
{ "apple2", TGT_APPLE2 },
@ -157,6 +157,7 @@ static const TargetEntry TargetMap[] = {
{ "cbm510", TGT_CBM510 },
{ "cbm610", TGT_CBM610 },
{ "creativision", TGT_CREATIVISION },
{ "cx16", TGT_CX16 },
{ "gamate", TGT_GAMATE },
{ "geos", TGT_GEOS_CBM },
{ "geos-apple", TGT_GEOS_APPLE },
@ -179,7 +180,7 @@ static const TargetEntry TargetMap[] = {
#define MAP_ENTRY_COUNT (sizeof (TargetMap) / sizeof (TargetMap[0]))
/* Table with target properties by target id */
/* Table with target properties by target ID */
static const TargetProperties PropertyTable[TGT_COUNT] = {
{ "none", CPU_6502, BINFMT_BINARY, CTNone },
{ "module", CPU_6502, BINFMT_O65, CTNone },
@ -213,6 +214,7 @@ static const TargetProperties PropertyTable[TGT_COUNT] = {
{ "pce", CPU_HUC6280, BINFMT_BINARY, CTNone },
{ "gamate", CPU_6502, BINFMT_BINARY, CTNone },
{ "c65", CPU_4510, BINFMT_BINARY, CTPET },
{ "cx16", CPU_65C02, BINFMT_BINARY, CTPET },
};
/* Target system */
@ -235,7 +237,7 @@ static int Compare (const void* Key, const void* Entry)
target_t FindTarget (const char* Name)
/* Find a target by name and return the target id. TGT_UNKNOWN is returned if
/* Find a target by name and return the target ID. TGT_UNKNOWN is returned if
** the given name is no valid target.
*/
{
@ -243,7 +245,7 @@ target_t FindTarget (const char* Name)
const TargetEntry* T;
T = bsearch (Name, TargetMap, MAP_ENTRY_COUNT, sizeof (TargetMap[0]), Compare);
/* Return the target id */
/* Return the target ID */
return (T == 0)? TGT_UNKNOWN : T->Id;
}
@ -252,7 +254,7 @@ target_t FindTarget (const char* Name)
const TargetProperties* GetTargetProperties (target_t Target)
/* Return the properties for a target */
{
/* Must have a valid target id */
/* Must have a valid target ID */
PRECONDITION (Target >= 0 && Target < TGT_COUNT);
/* Return the array entry */

View File

@ -84,6 +84,7 @@ typedef enum {
TGT_PCENGINE,
TGT_GAMATE,
TGT_C65,
TGT_CX16,
TGT_COUNT /* Number of target systems */
} target_t;
@ -102,7 +103,7 @@ extern target_t Target;
/* Types of available output formats */
#define BINFMT_DEFAULT 0 /* Default (binary) */
#define BINFMT_BINARY 1 /* Straight binary format */
#define BINFMT_O65 2 /* Andre Fachats o65 format */
#define BINFMT_O65 2 /* Andre Fachat's o65 format */
#define BINFMT_ATARIEXE 3 /* Standard Atari binary load */
@ -127,5 +128,4 @@ const char* GetTargetName (target_t Target);
/* End of target.h */
#endif

View File

@ -1,4 +1,3 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
@ -14,16 +13,15 @@
# define DYN_DRV 0
/*
** link existing drivers like this:
** Link existing drivers this way:
**
** cl65 -DJOYSTICK_DRIVER=c64_hitjoy_joy -o joy-test.prg joy-test.c
**
** for testing a new driver you will have to uncomment the define below, and
** link your driver like this:
** For testing a new driver, you need to uncomment the declaration below,
** and link your driver this way:
**
** co65 ../../target/c64/drv/joy/c64-hitjoy.joy -o hitjoy.s --code-label _hitjoy
** cl65 -DJOYSTICK_DRIVER=hitjoy -o joy-test.prg joy-test.c hitjoy.s
**
*/
/* extern char JOYSTICK_DRIVER; */
@ -40,10 +38,8 @@
int main (void)
{
unsigned char j;
unsigned char count;
unsigned char i;
unsigned char i, count;
unsigned char Res;
unsigned char ch, kb;
clrscr ();
@ -58,47 +54,69 @@ int main (void)
if (Res != JOY_ERR_OK) {
cprintf ("Error in joy_load_driver: %u\r\n", Res);
#if DYN_DRV
cprintf ("os: %u, %s\r\n", _oserror, _stroserror (_oserror));
cprintf ("OS: %u, %s\r\n", _oserror, _stroserror (_oserror));
#endif
exit (EXIT_FAILURE);
return EXIT_FAILURE;
}
count = joy_count ();
#if defined(__ATARI5200__) || defined(__CREATIVISION__)
cprintf ("JOYSTICKS: %d", count);
cprintf ("JOYSTICKS: %u.", count);
#else
cprintf ("Driver supports %d joystick(s)", count);
cprintf ("Driver supports %u joystick%s", count, count == 1 ? "." : "s.");
#endif
while (1) {
for (i = 0; i < count; ++i) {
gotoxy (0, i+1);
j = joy_read (i);
#if defined(__ATARI5200__) || defined(__CREATIVISION__)
cprintf ("%1d:%-3s%-3s%-3s%-3s%-3s %02x",
#if defined(__NES__) || defined(__CX16__)
/* two lines for each device */
gotoxy (0, i * 2 +1);
cprintf ("%2u:%-6s%-6s%-6s%-6s\r\n"
" %-6s%-6s%-6s%-6s $%02X",
i,
JOY_UP(j)? " U " : " - ",
JOY_DOWN(j)? " D " : " - ",
JOY_LEFT(j)? " L " : " - ",
JOY_RIGHT(j)? " R " : " - ",
JOY_BTN_1(j)? " 1 " : " - ", j);
JOY_UP(j) ? " up " : " ---- ",
JOY_DOWN(j) ? " down " : " ---- ",
JOY_LEFT(j) ? " left " : " ---- ",
JOY_RIGHT(j) ? " right" : " ---- ",
JOY_BTN_1(j) ? "btn A " : " ---- ",
JOY_BTN_2(j) ? "btn B " : " ---- ",
JOY_BTN_3(j) ? "select" : " ---- ",
JOY_BTN_4(j) ? " start" : " ---- ",
j);
#else
cprintf ("%2d: %-6s%-6s%-6s%-6s%-6s %02x",
/* one line for each device */
gotoxy (0, i + 1);
# if defined(__ATARI5200__) || defined(__CREATIVISION__)
cprintf ("%1u:%-3s%-3s%-3s%-3s%-3s %02X",
i,
JOY_UP(j)? " up " : " ---- ",
JOY_DOWN(j)? " down " : " ---- ",
JOY_LEFT(j)? " left " : " ---- ",
JOY_RIGHT(j)? "right " : " ---- ",
JOY_BTN_1(j)? "button" : " ---- ", j);
JOY_UP(j) ? " U " : " - ",
JOY_DOWN(j) ? " D " : " - ",
JOY_LEFT(j) ? " L " : " - ",
JOY_RIGHT(j) ? " R " : " - ",
JOY_BTN_1(j) ? " 1 " : " - ",
j);
# else
cprintf ("%2u: %-6s%-6s%-6s%-6s%-6s $%02X",
i,
JOY_UP(j) ? " up " : " ---- ",
JOY_DOWN(j) ? " down " : " ---- ",
JOY_LEFT(j) ? " left " : " ---- ",
JOY_RIGHT(j) ? "right " : " ---- ",
JOY_BTN_1(j) ? "button" : " ---- ",
j);
# endif
#endif
}
/* show pressed key, so we can verify keyboard is working */
kb = kbhit ();
ch = kb ? cgetc () : ' ';
gotoxy (1, i+2);
revers (kb);
cprintf ("kbd: %c", ch);
revers (0);
/* Show any pressed keys; so that we can verify that the keyboard is working. */
if (kbhit ()) {
#if defined(__NES__) || defined(__CX16__)
gotoxy (1, i * 2 + 2);
#else
gotoxy (1, i + 2);
#endif
cprintf ("keyboard: $%02X", cgetc ());
}
}
return 0;
return EXIT_SUCCESS;
}