From d78133e1f00be19929ca6ee920c30f782c502e8b Mon Sep 17 00:00:00 2001
From: Greg King <gregdk@users.sf.net>
Date: Sat, 16 Nov 2019 13:11:40 -0500
Subject: [PATCH 095/170] Updated cx16 to match the Commander X16 ROMs and
emulator, release 34.
---
asminc/cbm_kernal.inc | 4 +-
asminc/cx16.inc | 87 ++++++++-----
cfg/cx16-asm.cfg | 3 +-
cfg/cx16-bank.cfg | 2 +-
cfg/cx16.cfg | 2 +-
doc/cx16.sgml | 50 ++++---
include/cx16.h | 23 +++-
libsrc/cx16/break.s | 21 ++-
libsrc/cx16/conio.s | 9 --
libsrc/cx16/cpeekc.s | 2 +-
libsrc/cx16/cpeekrevers.s | 2 +-
libsrc/cx16/cputc.s | 4 +-
libsrc/cx16/crt0.s | 22 ++--
libsrc/cx16/devnum.s | 8 --
libsrc/cx16/exec.c | 122 ++++++++++++++++++
libsrc/cx16/execvars.s | 16 +++
libsrc/cx16/filevars.s | 39 ++++++
libsrc/cx16/getdevice.s | 67 ++++++++++
libsrc/cx16/gotox.s | 13 ++
libsrc/cx16/gotoxy.s | 18 +++
libsrc/cx16/gotoy.s | 13 ++
libsrc/cx16/joy/{cx16-stdjoy.s => cx16-std.s} | 76 ++++++-----
libsrc/cx16/joy_stat_stddrv.s | 7 +-
libsrc/cx16/joy_stddrv.s | 4 +-
libsrc/cx16/joyref.s | 20 +++
libsrc/cx16/kbhit.s | 6 +-
libsrc/cx16/kernal.s | 5 +-
libsrc/cx16/libref.s | 4 +-
libsrc/cx16/mainargs.s | 8 +-
libsrc/cx16/set_tv.s | 16 +--
libsrc/cx16/status.s | 16 ++-
libsrc/cx16/tgi_stat_stddrv.s | 11 ++
libsrc/cx16/tgi_stddrv.s | 13 ++
libsrc/cx16/videomode.s | 48 ++++---
libsrc/cx16/waitvsync.s | 2 +-
libsrc/cx16/wherex.s | 15 +++
libsrc/cx16/wherey.s | 15 +++
37 files changed, 609 insertions(+), 184 deletions(-)
delete mode 100644 libsrc/cx16/conio.s
delete mode 100644 libsrc/cx16/devnum.s
create mode 100644 libsrc/cx16/exec.c
create mode 100644 libsrc/cx16/execvars.s
create mode 100644 libsrc/cx16/filevars.s
create mode 100644 libsrc/cx16/getdevice.s
create mode 100644 libsrc/cx16/gotox.s
create mode 100644 libsrc/cx16/gotoxy.s
create mode 100644 libsrc/cx16/gotoy.s
rename libsrc/cx16/joy/{cx16-stdjoy.s => cx16-std.s} (58%)
create mode 100644 libsrc/cx16/joyref.s
create mode 100644 libsrc/cx16/tgi_stat_stddrv.s
create mode 100644 libsrc/cx16/tgi_stddrv.s
create mode 100644 libsrc/cx16/wherex.s
create mode 100644 libsrc/cx16/wherey.s
diff --git a/asminc/cbm_kernal.inc b/asminc/cbm_kernal.inc
index 6e1e1604..a38836ce 100644
--- a/asminc/cbm_kernal.inc
+++ b/asminc/cbm_kernal.inc
@@ -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
diff --git a/asminc/cx16.inc b/asminc/cx16.inc
index 5b46908d..1c22c99b 100644
--- a/asminc/cx16.inc
+++ b/asminc/cx16.inc
@@ -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
diff --git a/cfg/cx16-asm.cfg b/cfg/cx16-asm.cfg
index 53f6da17..4228f6da 100644
--- a/cfg/cx16-asm.cfg
+++ b/cfg/cx16-asm.cfg
@@ -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;
diff --git a/cfg/cx16-bank.cfg b/cfg/cx16-bank.cfg
index 52438fba..ff5dded3 100644
--- a/cfg/cx16-bank.cfg
+++ b/cfg/cx16-bank.cfg
@@ -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__;
diff --git a/cfg/cx16.cfg b/cfg/cx16.cfg
index f912e0f8..c72f6c35 100644
--- a/cfg/cx16.cfg
+++ b/cfg/cx16.cfg
@@ -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__;
diff --git a/doc/cx16.sgml b/doc/cx16.sgml
index b739e6a9..16e43db9 100644
--- a/doc/cx16.sgml
+++ b/doc/cx16.sgml
@@ -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 $0800 - $9EFF and $A000 -
-$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 $0800 - $9EFF and
+$A000 - $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 <configfile>/.
+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.
diff --git a/include/cx16.h b/include/cx16.h
index a2f52850..a6f1b78f 100644
--- a/include/cx16.h
+++ b/include/cx16.h
@@ -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);
diff --git a/libsrc/cx16/break.s b/libsrc/cx16/break.s
index ec569b9a..6c79c903 100644
--- a/libsrc/cx16/break.s
+++ b/libsrc/cx16/break.s
@@ -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
-
-
diff --git a/libsrc/cx16/conio.s b/libsrc/cx16/conio.s
deleted file mode 100644
index e760af21..00000000
--- a/libsrc/cx16/conio.s
+++ /dev/null
@@ -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"
diff --git a/libsrc/cx16/cpeekc.s b/libsrc/cx16/cpeekc.s
index 2f02623b..f7a7d208 100644
--- a/libsrc/cx16/cpeekc.s
+++ b/libsrc/cx16/cpeekc.s
@@ -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
diff --git a/libsrc/cx16/cpeekrevers.s b/libsrc/cx16/cpeekrevers.s
index d67dd295..15131d34 100644
--- a/libsrc/cx16/cpeekrevers.s
+++ b/libsrc/cx16/cpeekrevers.s
@@ -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
diff --git a/libsrc/cx16/cputc.s b/libsrc/cx16/cputc.s
index cf0a5fa2..11c4f578 100644
--- a/libsrc/cx16/cputc.s
+++ b/libsrc/cx16/cputc.s
@@ -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
diff --git a/libsrc/cx16/crt0.s b/libsrc/cx16/crt0.s
index 873fd706..bfb4de10 100644
--- a/libsrc/cx16/crt0.s
+++ b/libsrc/cx16/crt0.s
@@ -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
diff --git a/libsrc/cx16/devnum.s b/libsrc/cx16/devnum.s
deleted file mode 100644
index 6a59d6ec..00000000
--- a/libsrc/cx16/devnum.s
+++ /dev/null
@@ -1,8 +0,0 @@
-;
-; 2010-02-14, Oliver Schmidt
-; 2019-09-08, Greg King
-;
-
- .include "cx16.inc"
-
- .exportzp devnum := DEVNUM
diff --git a/libsrc/cx16/exec.c b/libsrc/cx16/exec.c
new file mode 100644
index 00000000..90af4e40
--- /dev/null
+++ b/libsrc/cx16/exec.c
@@ -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__);
+}
diff --git a/libsrc/cx16/execvars.s b/libsrc/cx16/execvars.s
new file mode 100644
index 00000000..2df647a5
--- /dev/null
+++ b/libsrc/cx16/execvars.s
@@ -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
diff --git a/libsrc/cx16/filevars.s b/libsrc/cx16/filevars.s
new file mode 100644
index 00000000..f3fa6466
--- /dev/null
+++ b/libsrc/cx16/filevars.s
@@ -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
diff --git a/libsrc/cx16/getdevice.s b/libsrc/cx16/getdevice.s
new file mode 100644
index 00000000..9b554900
--- /dev/null
+++ b/libsrc/cx16/getdevice.s
@@ -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
diff --git a/libsrc/cx16/gotox.s b/libsrc/cx16/gotox.s
new file mode 100644
index 00000000..1cd7c693
--- /dev/null
+++ b/libsrc/cx16/gotox.s
@@ -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
diff --git a/libsrc/cx16/gotoxy.s b/libsrc/cx16/gotoxy.s
new file mode 100644
index 00000000..1c1b60e2
--- /dev/null
+++ b/libsrc/cx16/gotoxy.s
@@ -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
diff --git a/libsrc/cx16/gotoy.s b/libsrc/cx16/gotoy.s
new file mode 100644
index 00000000..487cfa79
--- /dev/null
+++ b/libsrc/cx16/gotoy.s
@@ -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
diff --git a/libsrc/cx16/joy/cx16-stdjoy.s b/libsrc/cx16/joy/cx16-std.s
similarity index 58%
rename from libsrc/cx16/joy/cx16-stdjoy.s
rename to libsrc/cx16/joy/cx16-std.s
index 8c7ddd2f..b41c6606 100644
--- a/libsrc/cx16/joy/cx16-stdjoy.s
+++ b/libsrc/cx16/joy/cx16-std.s
@@ -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
diff --git a/libsrc/cx16/joy_stat_stddrv.s b/libsrc/cx16/joy_stat_stddrv.s
index 0e1a3e94..08cd2f95 100644
--- a/libsrc/cx16/joy_stat_stddrv.s
+++ b/libsrc/cx16/joy_stat_stddrv.s
@@ -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
diff --git a/libsrc/cx16/joy_stddrv.s b/libsrc/cx16/joy_stddrv.s
index 4edf9afc..ff2f54de 100644
--- a/libsrc/cx16/joy_stddrv.s
+++ b/libsrc/cx16/joy_stddrv.s
@@ -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"
diff --git a/libsrc/cx16/joyref.s b/libsrc/cx16/joyref.s
new file mode 100644
index 00000000..fb21918c
--- /dev/null
+++ b/libsrc/cx16/joyref.s
@@ -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
diff --git a/libsrc/cx16/kbhit.s b/libsrc/cx16/kbhit.s
index 8ceba64b..a73533e2 100644
--- a/libsrc/cx16/kbhit.s
+++ b/libsrc/cx16/kbhit.s
@@ -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
diff --git a/libsrc/cx16/kernal.s b/libsrc/cx16/kernal.s
index faf91385..97443c82 100644
--- a/libsrc/cx16/kernal.s
+++ b/libsrc/cx16/kernal.s
@@ -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
diff --git a/libsrc/cx16/libref.s b/libsrc/cx16/libref.s
index 54ebb91d..0d85c7cd 100644
--- a/libsrc/cx16/libref.s
+++ b/libsrc/cx16/libref.s
@@ -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
diff --git a/libsrc/cx16/mainargs.s b/libsrc/cx16/mainargs.s
index fe4a071c..1764b5e2 100644
--- a/libsrc/cx16/mainargs.s
+++ b/libsrc/cx16/mainargs.s
@@ -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
diff --git a/libsrc/cx16/set_tv.s b/libsrc/cx16/set_tv.s
index 0cf49aff..8b802f32 100644
--- a/libsrc/cx16/set_tv.s
+++ b/libsrc/cx16/set_tv.s
@@ -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
diff --git a/libsrc/cx16/status.s b/libsrc/cx16/status.s
index 6292dc27..e3446637 100644
--- a/libsrc/cx16/status.s
+++ b/libsrc/cx16/status.s
@@ -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
diff --git a/libsrc/cx16/tgi_stat_stddrv.s b/libsrc/cx16/tgi_stat_stddrv.s
new file mode 100644
index 00000000..566a3639
--- /dev/null
+++ b/libsrc/cx16/tgi_stat_stddrv.s
@@ -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
diff --git a/libsrc/cx16/tgi_stddrv.s b/libsrc/cx16/tgi_stddrv.s
new file mode 100644
index 00000000..0f77e734
--- /dev/null
+++ b/libsrc/cx16/tgi_stddrv.s
@@ -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"
diff --git a/libsrc/cx16/videomode.s b/libsrc/cx16/videomode.s
index 4582ec1b..e3a777b8 100644
--- a/libsrc/cx16/videomode.s
+++ b/libsrc/cx16/videomode.s
@@ -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
-
- lda LLEN ; Get current mode ...
- pha ; ... and save it
-
- jsr SWAPPER ; Toggle the mode
-
- pla ; Get old mode into A
+ tax
+ clc ; (Get old mode)
+ jsr SCRMOD
+ pha
+ txa
+
+ sec ; (Set new mode)
+ jsr SCRMOD
+
+ pla ; Get back old mode
+ bcs @L1
+ ldx #>$0000 ; Clear high byte
+ rts
-; Done, old mode is in .A
+; The new mode is invalid. Go back to the old mode. Return -1.
-@L9: ldx #>$0000 ; Clear high byte
+@L1: sec
+ jsr SCRMOD
+ lda #<-1
+ tax
rts
.endproc
diff --git a/libsrc/cx16/waitvsync.s b/libsrc/cx16/waitvsync.s
index 3fb6354f..09d01c6a 100644
--- a/libsrc/cx16/waitvsync.s
+++ b/libsrc/cx16/waitvsync.s
@@ -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
diff --git a/libsrc/cx16/wherex.s b/libsrc/cx16/wherex.s
new file mode 100644
index 00000000..56f42359
--- /dev/null
+++ b/libsrc/cx16/wherex.s
@@ -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
diff --git a/libsrc/cx16/wherey.s b/libsrc/cx16/wherey.s
new file mode 100644
index 00000000..396a2d14
--- /dev/null
+++ b/libsrc/cx16/wherey.s
@@ -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
--
2.26.0