1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-01 13:41:34 +00:00

Updated cx16 to match the Commander X16 ROMs and emulator, release 34.

This commit is contained in:
Greg King 2019-11-16 13:11:40 -05:00
parent 4dda5d2173
commit d78133e1f0
37 changed files with 607 additions and 182 deletions

View File

@ -7,18 +7,20 @@
.if .def(__CX16__)
; CX16 extended jump table
GETJOY := $FF06
MOUSE := $FF09
SCRMOD := $FF5F
.endif
.if .def(__C128__)
; C128 extended jump table
C64MODE := $FF4D
SWAPPER := $FF5F
SETBNK := $FF68
.endif
.if .def(__C128__) || .def(__CX16__)
; Extended jump table
CLSALL := $FF4A
SWAPPER := $FF5F
JSRFAR := $FF6E
INDFET := $FF74
INDSTA := $FF77

View File

@ -44,42 +44,55 @@
; ---------------------------------------------------------------------------
; 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
FNAM := $84 ; Pointer to filename
KTEMP2 := $86 ; 2 bytes for temporary storage
SCREEN_PTR := $88 ; Pointer to current row on text screen (16 bits)
IMPARM := $8A ; Pointer for PRIMM function
; BASIC
TXTPTR := $EE ; Pointer into BASIC source code
; Page two
BASIC_BUF := $200 ; Location of command-line
BASIC_BUF_LEN = 89 ; Maximum length of command-line
BASIC_BUF := $0200 ; Location of command-line
BASIC_BUF_LEN = 81 ; Maximum length of command-line
CHARCOLOR := $286
CURS_COLOR := $287 ; Color under the cursor
CURS_COLOR := $027E ; Color under the cursor
CHARCOLOR := $0286 ; Cursor's color nybbles (high: background, low: foreground)
STATUS := $0287 ; Status from previous I/O operation
IN_DEV := $028E ; Current input device number
OUT_DEV := $028F ; Current output device number
TIME := $0292 ; 60 Hz. clock (3 bytes, big-endian)
FNAM_LEN := $0298 ; Length of filename
SECADR := $029A ; Secondary address
DEVNUM := $029B ; Device number
KEY_COUNT := $029E ; Number of keys in input buffer
RVS := $029F ; Reverse flag
CURS_FLAG := $02A3 ; 1 = cursor off
CURS_BLINK := $02A4 ; Blink counter
CURS_CHAR := $02A5 ; Character under the cursor
CURS_STATE := $02A6 ; Cursor blink state
CURS_X := $02A8 ; Cursor column
CURS_Y := $02AB ; Cursor row
LLEN := $02AE ; Line length
NLINES := $02AF ; Number of screen lines
JOY1 := $02BC ; 3 bytes of NES/SNES gamepad data
JOY2 := $02BF
; BASIC
VARTAB := $02DD ; Pointer to start of BASIC variables
MEMSIZE := $02E5 ; Pointer to highest BASIC RAM location (+1)
; Kernal mouse
MSEPAR := $0371 ; mouse: $8x=sprite on, 1/2: scale
MOUSEL := $0372 ; min. x co-ordinate
MOUSER := $0374 ; max. x co-ordinate
MOUSET := $0376 ; min. y co-ordinate
MOUSEB := $0378 ; max. y co-ordinate
MOUSEX := $037A ; x co-ordinate
MOUSEY := $037C ; y co-ordinate
MOUSEBT := $037E ; buttons (bits 2: middle, 1: right, 0: left)
; ---------------------------------------------------------------------------
; Vector and other locations
@ -122,6 +135,12 @@ NMIVec := $0318
INC8192 = 14 << 4
INC16384 = 15 << 4
.endenum
.enum ; Interrupt request flags
VERT_SYNC = %00000001
RASTER = %00000010
SPR_COLLIDED = %00000100
UART_IRQ = %00001000
.endenum
; Internal RAM and registers
VRAM := $000000
.scope COMPOSER ; Display composer
@ -263,7 +282,7 @@ NMIVec := $0318
.endscope
.endscope
; 65c22
; 65C22
.struct VIA1 ; Versatile Interface Adapter
.org $9F60
PRB .byte ; ROM bank, IEC (Port Register B)
@ -281,10 +300,10 @@ NMIVec := $0318
PRA2 .byte ; RAM bank (Port Register A without handshaking)
.endstruct
; 65c22
; 65C22
.struct VIA2
.org $9F70
PRB .byte
PRB .byte ; Mouse communication ?
PRA .byte ; NES controller communication
DDRB .byte
DDRA .byte

View File

@ -6,12 +6,13 @@ SYMBOLS {
__HIMEM__: type = weak, value = $9F00;
}
MEMORY {
ZP: file = "", start = $0004, size = $0090 - $0004, define = yes;
ZP: file = "", start = $0002, size = $0080 - $0002, define = yes;
LOADADDR: file = %O, start = %S - 2, size = $0002;
MAIN: file = %O, start = %S, size = __HIMEM__ - %S;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP, type = zp, optional = yes;
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = MAIN, type = ro, optional = yes;
LOWCODE: load = MAIN, type = ro, optional = yes;

View File

@ -11,7 +11,7 @@ SYMBOLS {
__BANKRAMSIZE__: type = weak, value = $2000; # 8K banked RAM
}
MEMORY {
ZP: file = "", define = yes, start = $0004, size = $0090 - $0004;
ZP: file = "", define = yes, start = $0002, size = $0080 - $0002;
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__;

View File

@ -8,7 +8,7 @@ SYMBOLS {
__HIMEM__: type = weak, value = $9F00;
}
MEMORY {
ZP: file = "", define = yes, start = $0004, size = $0090 - $0004;
ZP: file = "", define = yes, start = $0002, size = $0080 - $0002;
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__;

View File

@ -17,14 +17,14 @@ compiler.
<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.
the ROMs in Commodore's VIC-20 and 64C. It has a couple of I/O chips
(WDC65C22 VIA) that are like the ones 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,
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
Please note that CX16-specific functions just are mentioned here; they might be
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
@ -35,19 +35,20 @@ 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.
is a machine language program that's prepended with a 16-bit load address and 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 program-header
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.
cc65-generated programs with the default setup run with the I/O area, RAM bank
zero, 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:
@ -76,6 +77,9 @@ 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;/.
Those files use 126 bytes in the zero page. (The rest of page zero is reserved
for Kernal and BASIC.)
<sect1>Default config. file (<tt/cx16.cfg/)<p>
@ -138,6 +142,8 @@ url="funcref.html" name="function reference"> for declarations and usage.
<item>get_ostype()
<item>set_tv()
<item>videomode()
<item>vpeek()
<item>vpoke()
<item>waitvsync()
</itemize>
@ -157,6 +163,7 @@ declarations and usage.
<item>cbm_k_ckout()
<item>cbm_k_close()
<item>cbm_k_clrch()
<item>cbm_k_getin()
<item>cbm_k_load()
<item>cbm_k_open()
<item>cbm_k_readst()
@ -217,13 +224,13 @@ 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)/.
point to <tt/cX16-std.joy (cx16_std_joy)/.
<descrip>
<tag><tt/cX16-stdjoy.joy (cX16_stdjoy_joy)/</tag>
Supports up to two NES and SNES controllers connected to the joystick ports
<tag><tt/cX16-std.joy (cX16_std_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.
buttons. Buttons A and B are the primary and secondary fire buttons.
</descrip><p>
@ -248,9 +255,16 @@ any time. Some changes could make old programs fail to work.
<sect>Other hints<p>
<sect1>STOP and RUN codes<p>
The <tt/Esc/ key acts as Commodore's <tt/STOP/ key -- or, you can press the
<tt/Ctrl/ key and the <tt/C/ key together. Pressing the <tt/Shift/ and the
<tt/Esc/ keys together will type Commodore's <tt/RUN/ key.
<sect1>Escape code<p>
For an Esc, press <tt/Ctrl/ and the <tt/[/ key.
For an <tt/Esc/, press the <tt/Ctrl/ key and the <tt/[/ key together.
<sect1>Passing arguments to the program<p>
@ -274,7 +288,7 @@ supported directly by BASIC, the following syntax was chosen:
<sect1>Program return code<p>
The program return code (low byte) is passed back to BASIC by use of the
The program return code (low byte) is passed back to BASIC by the use of its
<tt/ST/ variable.

View File

@ -100,6 +100,9 @@
#define JOY_FIRE2_MASK JOY_BTN_2_MASK
#define JOY_FIRE2(v) ((v) & JOY_FIRE2_MASK)
/* Additional mouse button mask */
#define MOUSE_BTN_MIDDLE 0x02
/* get_tv() return codes
** set_tv() argument codes
*/
@ -113,10 +116,12 @@
#define TV_RGB2 7
/* Video mode defines */
#define VIDEOMODE_40x30 40u
#define VIDEOMODE_80x60 80u
#define VIDEOMODE_40x30 0x00
#define VIDEOMODE_80x60 0x02
#define VIDEOMODE_40COL VIDEOMODE_40x30
#define VIDEOMODE_80COL VIDEOMODE_80x60
#define VIDEOMODE_320x240 0x80
#define VIDEOMODE_SWAP (-1)
/* Define hardware */
@ -157,7 +162,7 @@ struct __emul {
/* The addresses of the static drivers */
extern void cx16_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */
extern void cx16_std_joy[]; /* Referred to by joy_static_stddrv[] */
@ -174,14 +179,20 @@ signed char get_ostype (void);
** Positive -- release build
*/
unsigned char get_tv (void);
/* Return the video type that the machine is using.
** Return a TV_xx constant.
*/
void __fastcall__ set_tv (unsigned char type);
/* Set the video type that 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.
signed char __fastcall__ videomode (signed char mode);
/* Set the video mode, return the old mode.
** Return -1 if Mode isn't valid.
** Call with one of the VIDEOMODE_xx constants.
*/
unsigned char __fastcall__ vpeek (unsigned long addr);

View File

@ -1,6 +1,6 @@
;
; 1998-09-27, Ullrich von Bassewitz
; 2019-09-08, Greg King
; 2019-11-06, Greg King
;
; void __fastcall__ set_brk (unsigned Addr);
; void reset_brk (void);
@ -30,6 +30,7 @@ uservec: jmp $FFFF ; Patched at runtime
.code
; Set the break vector
.proc _set_brk
sta uservec+1
@ -40,9 +41,9 @@ uservec: jmp $FFFF ; Patched at runtime
bne L1 ; Jump if we installed the handler already
lda BRKVec
ldx BRKVec+1
sta oldvec
lda BRKVec+1
sta oldvec+1 ; Save the old vector
stx oldvec+1 ; Save the old vector
L1: lda #<brk_handler ; Set the break vector to our routine
ldx #>brk_handler
@ -54,6 +55,7 @@ L1: lda #<brk_handler ; Set the break vector to our routine
; Reset the break vector
.proc _reset_brk
lda oldvec
@ -61,15 +63,15 @@ L1: lda #<brk_handler ; Set the break vector to our routine
beq @L9 ; Jump if vector not installed
sta BRKVec
stx BRKVec+1
lda #$00
sta oldvec ; Clear the old vector
stx oldvec+1
sta oldvec+1
@L9: rts
.endproc
; Break handler, called if a break occurs
.proc brk_handler
@ -81,14 +83,13 @@ L1: lda #<brk_handler ; Set the break vector to our routine
pla
sta _brk_a
pla
and #$EF ; Clear break bit
sta _brk_sr
pla ; PC low
sec
sbc #2 ; Point to start of brk
sbc #<$0002 ; Point to start of BRK
sta _brk_pc
pla ; PC high
sbc #0
sbc #>$0002
sta _brk_pc+1
jsr uservec ; Call the user's routine
@ -99,11 +100,9 @@ L1: lda #<brk_handler ; Set the break vector to our routine
pha
lda _brk_sr
pha
ldx _brk_x
ldy _brk_y
ldx _brk_x
lda _brk_a
rti ; Jump back...
.endproc

View File

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

View File

@ -19,7 +19,7 @@ _cpeekc:
sta VERA::ADDR+1 ; set row number
stz VERA::ADDR+2
lda CURS_X ; get character column
asl a
asl a ; each character has two bytes
sta VERA::ADDR
lda VERA::DATA0 ; get screen code
plp

View File

@ -21,7 +21,7 @@ _cpeekrevers:
sta VERA::ADDR+1 ; set row number
stz VERA::ADDR+2
lda CURS_X ; get character column
asl a
asl a ; each character has two bytes
sta VERA::ADDR
lda VERA::DATA0 ; get screen code
plp

View File

@ -78,7 +78,7 @@ plot: ldy CURS_X
; Write one screen-code and color to the video RAM without doing anything else.
; Return the x position in Y.
; Return the x position in .Y .
putchar:
ora RVS ; Set revers bit
@ -90,7 +90,7 @@ putchar:
sta VERA::ADDR+2
ldy CURS_X ; Get character column
tya
asl a
asl a ; Each character has two bytes
sta VERA::ADDR
stx VERA::DATA0
lda CHARCOLOR

View File

@ -9,7 +9,6 @@
.import zerobss, callmain
.import CHROUT
.import __MAIN_START__, __MAIN_SIZE__ ; Linker-generated
.importzp ST
.include "zeropage.inc"
.include "cx16.inc"
@ -36,11 +35,18 @@ Start: tsx
jsr callmain
; Back from main() [this is also the exit() entry]. Run the module destructors.
; Back from main() [this is also the exit() entry].
_exit:
; Put the program return code into BASIC's status variable.
sta STATUS
; Run the module destructors.
_exit: pha ; Save the return code on stack
jsr donelib
.if 0 ; We no longer need to preserve zero-page space for cc65's variables.
; Copy back the zero-page stuff.
ldx #zpspace-1
@ -48,11 +54,7 @@ L2: lda zpsave,x
sta sp,x
dex
bpl L2
; Place the program return code into BASIC's status variable.
pla
sta ST
.endif
; Restore the system stuff.
@ -88,6 +90,7 @@ init:
lda #$00 ; Choose RAM bank zero
sta VIA1::PRA2
.if 0 ; We no longer need to preserve zero-page space for cc65's variables.
; Save the zero-page locations that we need.
ldx #zpspace-1
@ -95,6 +98,7 @@ L1: lda sp,x
sta zpsave,x
dex
bpl L1
.endif
; Set up the stack.
@ -121,4 +125,6 @@ L1: lda sp,x
ramsave:
.res 1
spsave: .res 1
.if 0
zpsave: .res zpspace
.endif

View File

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

122
libsrc/cx16/exec.c Normal file
View File

@ -0,0 +1,122 @@
/*
** Program-chaining function for Commodore platforms.
**
** 2019-11-08, Greg King
**
** This function exploits the program-chaining feature in Commander X16 BASIC's ROM.
**
** CC65's CBM programs have a BASIC program stub. We start those programs by
** RUNning that stub; it SYSes to the Machine Language code. Normally, after
** the ML code exits, the BASIC ROM continues running the stub. But, it has
** no more statements; so, the program stops.
**
** This function puts the desired program's name and device number into a LOAD
** statement. Then, it points BASIC to that statement, so that the ROM will run
** that statement after this program quits. The ROM will load the next program,
** and will execute it (because the LOAD will be seen in a running program).
*/
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <device.h>
/* The struct below is a line of BASIC code. It sits in the LOWCODE segment
** to make sure that it won't be hidden by a ROM when BASIC is re-enabled.
** The line is:
** 0 CLR:LOAD""+"" ,01
** After this function has written into the line, it might look like this:
** 0 CLR:LOAD""+"program name" ,08
**
** When BASIC's LOAD command asks the Kernal to load a file, it gives the
** Kernal a pointer to a file-name string. CC65's CBM programs use that
** pointer to give a copy of the program's name to main()'s argv[0] parameter.
** But, when BASIC uses a string literal that is in a program, it points
** directly to that literal -- in the models that don't use banked RAM
** (Pet/CBM, VIC-20, and 64). The literal is overwritten by the next program
** that is loaded. So, argv[0] would point to machine code. String operations
** create a new result string -- even when that operation changes nothing. The
** result is put in the string space at the top of BASIC's memory. So, the ""+
** in this BASIC line guarantees that argv[0] will get a name from a safe place.
*/
#pragma data-name(push, "LOWCODE")
static struct line {
const char end_of_line; /* fake previous line */
const struct line* const next;
const unsigned line_num;
const char CLR_token, colon, LOAD_token, quotes[2], add_token, quote;
char name[21];
const char comma;
char unit[3];
} basic = {
'\0', &basic + 1, /* high byte of link must be non-zero */
0, 0x9C, ':', 0x93, "\"\"", 0xAA, '\"',
"\" ", /* format: "123:1234567890123456\"" */
',', "01"
};
#pragma data-name(pop)
/* These values are platform-specific. */
extern const void* vartab; /* points to BASIC program variables */
extern const void* memsize; /* points to top of BASIC RAM */
extern const struct line* txtptr; /* points to BASIC code */
#pragma zpsym("txtptr")
extern char basbuf[]; /* BASIC's input buffer */
extern void basbuf_len[];
#pragma zpsym("basbuf_len")
int __fastcall__ exec (const char* progname, const char* cmdline)
{
static int fd;
static unsigned char dv, n;
/* Exclude devices that can't load files. */
/* (Use hand optimization, to make smaller code.) */
dv = getcurrentdevice ();
if (dv < 8 && __AX__ != 1 || __AX__ > 30) {
return _mappederrno (9); /* illegal device number */
}
utoa (dv, basic.unit, 10);
/* Don't try to run a program that doesn't exist. */
fd = open (progname, O_RDONLY);
if (fd < 0) {
return _mappederrno (4); /* file not found */
}
close (fd);
n = 0;
do {
if ((basic.name[n] = progname[n]) == '\0') {
break;
}
} while (++n < 20); /* truncate long names */
basic.name[n] = '\"';
/* cc65 program loads might extend beyond the end of the RAM that is allowed
** for BASIC. Then, the LOAD statement would complain that it is "out of
** memory". Some pointers that say where to put BASIC program variables
** must be changed, so that we do not get that error. One pointer is
** changed here; a BASIC CLR statement changes the others.
*/
vartab = (char*)memsize - 256;
/* Build the next program's argument list. */
basbuf[0] = 0x8F; /* REM token */
basbuf[1] = '\0';
if (cmdline != NULL) {
strncat (basbuf, cmdline, (size_t)basbuf_len - 2);
}
/* Tell the ROM where to find that BASIC program. */
txtptr = &basic;
/* (The return code, in STATUS, will be destroyed by LOAD.
** So, don't bother to set it here.)
*/
exit (__AX__);
}

16
libsrc/cx16/execvars.s Normal file
View File

@ -0,0 +1,16 @@
;
; Platform-specific variables for the exec program-chaining function
;
.include "cx16.inc"
; exec() is written in C.
; Provide the spellings that the C compiler wants to use.
.export _vartab := VARTAB
.export _memsize := MEMSIZE
.exportzp _txtptr := TXTPTR
.export _basbuf := BASIC_BUF
.exportzp _basbuf_len = BASIC_BUF_LEN

39
libsrc/cx16/filevars.s Normal file
View File

@ -0,0 +1,39 @@
;
; 2002-11-15, Ullrich von Bassewitz
; 2019-11-08, Greg King
;
; Variables used for CBM file I/O
;
.export curunit
.constructor initcurunit, 30
.destructor updatedevnum, 30
.include "cx16.inc"
.segment "INIT"
curunit:
.res 1
.segment "ONCE"
.proc initcurunit
lda DEVNUM
bne L0
lda #8 ; Default is SD card
sta DEVNUM
L0: sta curunit
rts
.endproc
.code
.proc updatedevnum
lda curunit
sta DEVNUM
rts
.endproc

67
libsrc/cx16/getdevice.s Normal file
View File

@ -0,0 +1,67 @@
;
; 2012-09-04, Oliver Schmidt
; 2019-11-08, Greg King
;
; unsigned char getfirstdevice (void);
; unsigned char __fastcall__ getnextdevice (unsigned char device);
;
.export _getfirstdevice
.export _getnextdevice
.import isdisk
.import opencmdchannel
.import closecmdchannel
.importzp tmp2
.include "cx16.inc"
;------------------------------------------------------------------------------
; getfirstdevice()
_getfirstdevice:
lda #$FF
; Fall through
;------------------------------------------------------------------------------
; getnextdevice()
_getnextdevice:
tax
next: inx
cpx #$FF
beq done
; [open|close]cmdchannel already call isdisk internally; but, they
; interpret a non-disk as a no-op, while we need to interpret it
; as an error here.
jsr isdisk
bcs next
; [open|close]cmdchannel don't call into the Kernal, at all, if they
; only [in|de]crement the reference count of the shared cmdchannel.
; Therefore, we need to initiate STATUS explicitly here.
lda #$00
sta STATUS
stx tmp2
jsr opencmdchannel
ldx tmp2
jsr closecmdchannel
ldx tmp2
; As we had to reference ST above anyway, we can do so, as well,
; here too (instead of calling READST).
lda STATUS
; Either the Kernal calls above were successfull, or there was
; already a cmdchannel to the device open -- which is a pretty
; good indication of its existence. ;-)
bmi next
done: txa
ldx #$00
rts

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

@ -0,0 +1,13 @@
;
; 2019-11-06, Greg King
;
; void fastcall gotox (unsigned char x);
;
.export _gotox
.import plot
.include "cx16.inc"
_gotox: sta CURS_X ; Set new position
jmp plot ; And activate it

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

@ -0,0 +1,18 @@
;
; 2019-11-06, Greg King
;
; void fastcall gotoxy (unsigned char x, unsigned char y);
;
.export gotoxy, _gotoxy
.import popa, plot
.include "cx16.inc"
gotoxy: jsr popa ; Get Y
_gotoxy:
sta CURS_Y ; Set Y
jsr popa ; Get X
sta CURS_X ; Set X
jmp plot ; Set the cursor position

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

@ -0,0 +1,13 @@
;
; 2019-11-06, Greg King
;
; void gotoy (unsigned char y);
;
.export _gotoy
.import plot
.include "cx16.inc"
_gotoy: sta CURS_Y ; Set the new position
jmp plot ; And activate it

View File

@ -1,8 +1,8 @@
;
; Standard joystick driver for the CX16.
; May be used multiple times when statically linked to the application.
; May be installed multiple times when statically linked to the application.
;
; 2019-09-23, Greg King
; 2019-11-15 Greg King
;
.include "joy-kernel.inc"
@ -18,7 +18,7 @@
; ------------------------------------------------------------------------
; Header. Includes jump table
module_header _cx16_stdjoy_joy
module_header _cx16_std_joy
; Driver signature
@ -48,11 +48,10 @@ JOY_COUNT = 2 ; Number of joysticks we support
.code
; ------------------------------------------------------------------------
; INSTALL routine. Is called after the driver is loaded into memory.
; 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.
;
; Must return a JOY_ERR_xx code in .XA .
INSTALL:
lda #<JOY_ERR_OK
@ -60,60 +59,67 @@ INSTALL:
; 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 routine -- is called before the driver is removed from memory.
; Can do clean-up or whatever. Shouldn't return anything.
UNINSTALL:
rts
; ------------------------------------------------------------------------
; COUNT: Return the total number of possible joysticks in a/x.
;
; COUNT: Return the total number of possible joysticks, in .XA .
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: Read a particular joystick passed in .A .
READ: pha
jsr GETJOY
pla
bne pad2
READ: php
bit #JOY_COUNT - $01
sei
bnz pad2
; Read game pad 1
pad1: lda JOY1 + 1
pad1: ldy JOY1 ; Allow JOY1 to be reread between interrupts
sty JOY1 + 2
lda JOY1 + 1
bit #%00001110
beq nes1
asl JOY1 ; Get SNES's B button
bze nes1
asl JOY1 + 2 ; 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 JOY1 + 2 ; Drop SNES's Y button
asl a ; Get back the B button
ror JOY1 + 2
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
ror JOY1 + 2 ; Make byte look like NES pad
nes1: lda JOY1 + 2
plp
eor #%11111111 ; (The controllers use negative logic)
rts
; Read game pad 2
pad2: lda JOY2 + 1
pad2: ldy JOY2
sty JOY2 + 2
lda JOY2 + 1
bit #%00001110
beq nes2
asl JOY2
bze nes2
asl JOY2 + 2
ror a
asl JOY2
asl JOY2 + 2
asl a
ror JOY2
ror JOY2 + 2
asl a
ror JOY2
nes2: lda JOY2
ror JOY2 + 2
nes2: lda JOY2 + 2
plp
eor #%11111111
rts

View File

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

View File

@ -1,7 +1,7 @@
;
; Name of the standard joystick driver
;
; 2019-09-19, Greg King
; 2019-11-10, Greg King
;
; const char joy_stddrv[];
;
@ -10,4 +10,4 @@
.rodata
_joy_stddrv: .asciiz "cx16-stdjoy.joy"
_joy_stddrv: .asciiz "cx16-std.joy"

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

@ -0,0 +1,20 @@
;
; 2019-11-14, Greg King
;
; Link an interrupt handler if joysticks are used by a program.
;
.interruptor joy_libref, 9
.include "cbm_kernal.inc"
.include "cx16.inc"
joy_libref:
lda VERA::IRQ_FLAGS
lsr a
bcc not_vsync
jsr GETJOY ; Bit-bang game controllers
clc ; Let other Jiffy handlers run
not_vsync:
rts

View File

@ -1,5 +1,5 @@
;
; 2019-09-20, Greg King
; 2019-11-06, Greg King
;
; unsigned char kbhit (void);
; /* Returns non-zero (true) if a typed character is waiting. */
@ -11,7 +11,7 @@
.proc _kbhit
ldx #>$0000 ; High byte of return
lda KEY_COUNT ; Get number of characters
rts
tax ; High byte of return (only its zero/nonzero ...
rts ; ... state matters)
.endproc

View File

@ -1,5 +1,5 @@
;
; 2019-09-22, Greg King
; 2019-11-05, Greg King
;
; CX16 Kernal functions
;
@ -7,9 +7,10 @@
.include "cbm_kernal.inc"
.export GETJOY
.export MOUSE
.export SCRMOD
.export CLSALL
.export SWAPPER
.export JSRFAR
.export INDFET
.export INDSTA

View File

@ -1,10 +1,9 @@
;
; 2013-05-31, Oliver Schmidt
; 2019-09-22, Greg King
; 2019-11-14, Greg King
;
.export em_libref
.export joy_libref
.export mouse_libref
.export ser_libref
.export tgi_libref
@ -12,7 +11,6 @@
.import _exit
em_libref := _exit
joy_libref := _exit
mouse_libref := _exit
ser_libref := _exit
tgi_libref := _exit

View File

@ -33,7 +33,7 @@ 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
; which may be reused after the startup code is run.
.segment "ONCE"
@ -64,7 +64,7 @@ L2: lda BASIC_BUF,x
bne L2
ldy #1 * 2
; Find the next argument
; Find the next argument.
next: lda BASIC_BUF,x
beq done ; End of line reached
@ -74,7 +74,7 @@ next: lda BASIC_BUF,x
; 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
; will check now for a quoted argument, in which case, we will have to skip this
; first character.
found: cmp #'"' ; Is the argument quoted?
@ -95,7 +95,7 @@ setterm:sta term ; Set end of argument marker
iny
inc __argc ; Found another arg
; Search for the end of the argument
; Search for the end of the argument.
argloop:lda BASIC_BUF,x
beq done

View File

@ -1,5 +1,5 @@
;
; 2019-09-20, Greg King
; 2019-11-06, Greg King
;
; void __fastcall__ set_tv (unsigned char);
; /* Set the video mode the machine will use. */
@ -12,20 +12,18 @@
.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
ldx #<VERA::COMPOSER::VIDEO
ldy #>VERA::COMPOSER::VIDEO
stx VERA::ADDR
sty VERA::ADDR+1
ldx #^VERA::COMPOSER::VIDEO
stx VERA::ADDR+2
pla
sta VERA::DATA0
plp ; Re-enable interrupts
rts

View File

@ -1,6 +1,16 @@
;
; 2012-09-30, Oliver Schmidt
; 2019-09-08, Greg King
; 2019-11-05, Greg King
;
.exportzp ST := $90 ; IEC status byte
.export ST: zp
.segment "EXTZP": zp
; This is a temporary hack.
; A zero-page copy of the IEC status byte.
; This is needed because the Commander X16's Kernal's status
; variable was moved out of the zero page. But, the common
; CBM file function modules import this as a zero-page variable.
ST: .res 1

View File

@ -0,0 +1,11 @@
;
; Address of the static standard TGI driver
;
; 2019-11-06, Greg King
;
; const void tgi_static_stddrv[];
;
.import _cx16_640x4c_tgi
.export _tgi_static_stddrv := _cx16_640x4c_tgi

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

@ -0,0 +1,13 @@
;
; Name of the standard TGI driver
;
; 2019-11-06, Greg King
;
; const char tgi_stddrv[];
;
.export _tgi_stddrv
.rodata
_tgi_stddrv: .asciiz "cx16-640x4c.tgi"

View File

@ -1,30 +1,44 @@
;
; 2009-09-07, Ullrich von Bassewitz
; 2019-09-23, Greg King
; 2019-11-06, Greg King
;
; unsigned __fastcall__ videomode (unsigned Mode);
; /* Set the video mode, return the old mode. */
; /* Video mode defines */
; #define VIDEOMODE_40x30 0x00
; #define VIDEOMODE_80x60 0x02
; #define VIDEOMODE_320x240 0x80
; #define VIDEOMODE_SWAP (-1)
;
; signed char __fastcall__ videomode (signed char Mode);
; /* Set the video mode, return the old mode.
; ** Return -1 if Mode isn't valid.
; ** Call with one of the VIDEOMODE_xx constants.
; */
;
.export _videomode
.import SWAPPER
.include "cx16.inc"
.import SCRMOD
.proc _videomode
cmp LLEN ; Do we have this mode already?
beq @L9
tax
clc ; (Get old mode)
jsr SCRMOD
pha
txa
lda LLEN ; Get current mode ...
pha ; ... and save it
sec ; (Set new mode)
jsr SCRMOD
jsr SWAPPER ; Toggle the mode
pla ; Get back old mode
bcs @L1
ldx #>$0000 ; Clear high byte
rts
pla ; Get old mode into A
; The new mode is invalid. Go back to the old mode. Return -1.
; Done, old mode is in .A
@L9: ldx #>$0000 ; Clear high byte
@L1: sec
jsr SCRMOD
lda #<-1
tax
rts
.endproc

View File

@ -3,7 +3,7 @@
;
; void waitvsync (void);
;
; VERA's vertical sync. causes IRQs which increment the jiffy clock.
; VERA's vertical sync causes IRQs which increment the jiffy clock.
;
.export _waitvsync

15
libsrc/cx16/wherex.s Normal file
View File

@ -0,0 +1,15 @@
;
; 2019-11-06, Greg King
;
; unsigned char wherex (void);
;
.export _wherex
.include "cx16.inc"
.proc _wherex
lda CURS_X
ldx #>$0000
rts
.endproc

15
libsrc/cx16/wherey.s Normal file
View File

@ -0,0 +1,15 @@
;
; 2019-11-06, Greg King
;
; unsigned char wherey (void);
;
.export _wherey
.include "cx16.inc"
.proc _wherey
lda CURS_Y
ldx #>$0000
rts
.endproc