Blob Blame History Raw
From 3fa253d31fbec8602e791345125e33efadd98cbf Mon Sep 17 00:00:00 2001
From: Greg King <gregdk@users.sf.net>
Date: Wed, 25 Dec 2019 10:56:32 -0500
Subject: [PATCH 130/170] Updated the cx16 library to the Commander X16
 Kernal's prerelease 35.

---
 asminc/cbm_kernal.inc            |  40 +++++-
 asminc/cx16.inc                  | 217 ++++++++++++++++++++++++-------
 cfg/cx16-asm.cfg                 |   2 +-
 cfg/cx16-bank.cfg                |  10 +-
 cfg/cx16.cfg                     |   2 +-
 doc/cx16.sgml                    |  10 +-
 include/cbm.h                    |   2 +-
 include/cx16.h                   |  14 +-
 libsrc/cbm/clock.s               |  19 ++-
 libsrc/cx16/_scrsize.s           |   6 +-
 libsrc/cx16/bankramaddr.s        |   6 +-
 libsrc/cx16/cgetc.s              |   8 +-
 libsrc/cx16/clock.s              |  36 +++++
 libsrc/cx16/crt0.s               |  12 +-
 libsrc/cx16/get_tv.s             |   6 +-
 libsrc/cx16/joy/cx16-std.s       |  60 +++------
 libsrc/cx16/joyref.s             |   4 +-
 libsrc/cx16/kbhit.s              |   7 +-
 libsrc/cx16/kernal.s             | 136 +++++++++++--------
 libsrc/cx16/mcbdefault.s         |  48 ++++---
 libsrc/cx16/mou/cx16-std.s       |  64 ++++-----
 libsrc/cx16/mouse_stat_stddrv.s  |   2 +-
 libsrc/cx16/set_tv.s             |   6 +-
 libsrc/cx16/sysuname.s           |   2 +-
 libsrc/cx16/tgi_stat_stddrv.s    |   7 +-
 libsrc/cx16/tgi_stddrv.s         |   5 +-
 libsrc/cx16/{vset.s => vaddr0.s} |   9 +-
 libsrc/cx16/vpeek.s              |   8 +-
 libsrc/cx16/vpoke.s              |   8 +-
 libsrc/cx16/waitvsync.s          |  12 +-
 src/ca65/struct.c                |   9 +-
 31 files changed, 507 insertions(+), 270 deletions(-)
 create mode 100644 libsrc/cx16/clock.s
 rename libsrc/cx16/{vset.s => vaddr0.s} (60%)

diff --git a/asminc/cbm_kernal.inc b/asminc/cbm_kernal.inc
index a38836ce..86a60d49 100644
--- a/asminc/cbm_kernal.inc
+++ b/asminc/cbm_kernal.inc
@@ -6,9 +6,40 @@
 
 .if .def(__CX16__)
   ; CX16 extended jump table
-  GETJOY       := $FF06
-  MOUSE        := $FF09
-  SCRMOD       := $FF5F
+  FB_INIT                       := $FEF6
+  FB_GET_INFO                   := $FEF9
+  FB_SET_PALETTE                := $FEFC
+  FB_CURSOR_POSITION            := $FEFF
+  FB_CURSOR_NEXT_LINE           := $FF02
+  FB_GET_PIXEL                  := $FF05
+  FB_GET_PIXELS                 := $FF08
+  FB_SET_PIXEL                  := $FF0B
+  FB_SET_PIXELS                 := $FF0E
+  FB_SET_8_PIXELS               := $FF11
+  FB_SET_8_PIXELS_OPAQUE        := $FF14
+  FB_FILL_PIXELS                := $FF17
+  FB_FILTER_PIXELS              := $FF1A
+  FB_MOVE_PIXELS                := $FF1D
+  GRAPH_INIT                    := $FF20
+  GRAPH_CLEAR                   := $FF23
+  GRAPH_SET_WINDOW              := $FF26
+  GRAPH_SET_COLORS              := $FF29
+  GRAPH_DRAW_LINE               := $FF2C
+  GRAPH_DRAW_RECT               := $FF2F
+  GRAPH_MOVE_RECT               := $FF32
+  GRAPH_DRAW_OVAL               := $FF35
+  GRAPH_DRAW_IMAGE              := $FF38
+  GRAPH_SET_FONT                := $FF3B
+  GRAPH_GET_CHAR_SIZE           := $FF3E
+  GRAPH_PUT_CHAR                := $FF41
+  RESTORE_BASIC                 := $FF47
+  CLOCK_SET_DATE_TIME           := $FF4D
+  CLOCK_GET_DATE_TIME           := $FF50
+  JOYSTICK_SCAN                 := $FF53
+  JOYSTICK_GET                  := $FF56
+  SCRMOD                        := $FF5F
+  MOUSE_CONFIG                  := $FF68
+  MOUSE_GET                     := $FF6B
 .endif
 
 .if .def(__C128__)
@@ -21,6 +52,9 @@
 .if .def(__C128__) || .def(__CX16__)
   ; Extended jump table
   CLSALL       := $FF4A
+  LKUPLA       := $FF59
+  LKUPSA       := $FF5C
+  PFKEY        := $FF65
   JSRFAR       := $FF6E
   INDFET       := $FF74
   INDSTA       := $FF77
diff --git a/asminc/cx16.inc b/asminc/cx16.inc
index 1c22c99b..e08215df 100644
--- a/asminc/cx16.inc
+++ b/asminc/cx16.inc
@@ -1,5 +1,5 @@
 ;
-; CX16 definitions
+; CX16 r35 definitions
 ;
 
 ; ---------------------------------------------------------------------------
@@ -44,11 +44,128 @@
 ; ---------------------------------------------------------------------------
 ; Zero page
 
+; GEOS and graphics pseudo-registers
+.struct gREG
+                .org    $02
+  .union
+  r0            .word
+  .struct
+  r0L           .byte
+  r0H           .byte
+  .endstruct
+  .endunion
+  .union
+  r1            .word
+  .struct
+  r1L           .byte
+  r1H           .byte
+  .endstruct
+  .endunion
+  .union
+  r2            .word
+  .struct
+  r2L           .byte
+  r2H           .byte
+  .endstruct
+  .endunion
+  .union
+  r3            .word
+  .struct
+  r3L           .byte
+  r3H           .byte
+  .endstruct
+  .endunion
+  .union
+  r4            .word
+  .struct
+  r4L           .byte
+  r4H           .byte
+  .endstruct
+  .endunion
+  .union
+  r5            .word
+  .struct
+  r5L           .byte
+  r5H           .byte
+  .endstruct
+  .endunion
+  .union
+  r6            .word
+  .struct
+  r6L           .byte
+  r6H           .byte
+  .endstruct
+  .endunion
+  .union
+  r7            .word
+  .struct
+  r7L           .byte
+  r7H           .byte
+  .endstruct
+  .endunion
+  .union
+  r8            .word
+  .struct
+  r8L           .byte
+  r8H           .byte
+  .endstruct
+  .endunion
+  .union
+  r9            .word
+  .struct
+  r9L           .byte
+  r9H           .byte
+  .endstruct
+  .endunion
+  .union
+  r10           .word
+  .struct
+  r10L          .byte
+  r10H          .byte
+  .endstruct
+  .endunion
+  .union
+  r11           .word
+  .struct
+  r11L          .byte
+  r11H          .byte
+  .endstruct
+  .endunion
+  .union
+  r12           .word
+  .struct
+  r12L          .byte
+  r12H          .byte
+  .endstruct
+  .endunion
+  .union
+  r13           .word
+  .struct
+  r13L          .byte
+  r13H          .byte
+  .endstruct
+  .endunion
+  .union
+  r14           .word
+  .struct
+  r14L          .byte
+  r14H          .byte
+  .endstruct
+  .endunion
+  .union
+  r15           .word
+  .struct
+  r15L          .byte
+  r15H          .byte
+  .endstruct
+  .endunion
+.endstruct
+
 ; Kernal
 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
+IMPARM          := $88          ; Pointer for PRIMM function
+SCREEN_PTR      := $90          ; Pointer to current row on text screen (16 bits)
 
 ; BASIC
 TXTPTR          := $EE          ; Pointer into BASIC source code
@@ -58,41 +175,27 @@ TXTPTR          := $EE          ; Pointer into BASIC source code
 BASIC_BUF       := $0200        ; Location of command-line
 BASIC_BUF_LEN   = 81            ; Maximum length of command-line
 
-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
+STATUS          := $0275        ; Status from previous I/O operation
+IN_DEV          := $0279        ; Current input device number
+OUT_DEV         := $027A        ; Current output device number
+FNAM_LEN        := $027D        ; Length of filename
+SECADR          := $027F        ; Secondary address
+DEVNUM          := $0280        ; Device number
+CURS_COLOR      := $0373        ; Color under the cursor
+CHARCOLOR       := $0377        ; Cursor's color nybbles (high: background, low: foreground)
+RVS             := $0378        ; Reverse flag
+CURS_FLAG       := $037C        ; 1 = cursor off
+CURS_BLINK      := $037D        ; Blink counter
+CURS_CHAR       := $037E        ; Character under the cursor
+CURS_STATE      := $037F        ; Cursor blink state
+CURS_X          := $0381        ; Cursor column
+CURS_Y          := $0384        ; Cursor row
+LLEN            := $0387        ; Line length
+NLINES          := $0388        ; Number of screen lines
 
 ; 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)
+VARTAB          := $03E3        ; Pointer to start of BASIC variables
+MEMSIZE         := $03EB        ; Pointer to highest BASIC RAM location (+1)
 
 ; ---------------------------------------------------------------------------
 ; Vector and other locations
@@ -141,8 +244,13 @@ NMIVec          := $0318
   SPR_COLLIDED  =       %00000100
   UART_IRQ      =       %00001000
   .endenum
+
   ; Internal RAM and registers
-  VRAM          :=      $000000
+
+  .struct
+                .org    $000000
+  VRAM          .res    $020000 ; 128 Kibibytes
+  .endstruct
   .scope        COMPOSER        ; Display composer
     .struct
                 .org    $0F0000
@@ -226,15 +334,29 @@ NMIVec          := $0318
   .scope        SPRITE
     .struct
                 .org    $0F4000
-    CTRL        .byte           ; Enables sprites
+    CTRL        .byte           ; Enables sprite engine
     COLLISION   .byte
     .endstruct
+    .struct     ATTRIB          ; Sprite attributes
+                .org    $0F5000
+      ADDR      .addr           ; Address and color mode
+      XX        .word
+      YY        .word
+      Z_FLIP    .byte
+      SIZE_PAL  .byte
+    .endstruct
     .enum       FLIP
       NONE      =       0
       HORIZ
       VERT
       BOTH
     .endenum
+    .enum       DEPTH
+      DISABLE   =       0 << 2
+      CANVAS    =       1 << 2
+      LAYER0    =       2 << 2
+      LAYER1    =       3 << 2
+    .endenum
     .enum                       ; Sprite geometry
     WIDTH8      =       0 << 4
     WIDTH16     =       1 << 4
@@ -247,13 +369,6 @@ NMIVec          := $0318
     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
@@ -334,3 +449,15 @@ NMIVec          := $0318
   KEYMAP        .byte           ; Current keyboard layout number (Read-Only)
   DETECT        .byte   2       ; If is "16" string, then running on emulator (RO)
 .endstruct
+
+; ---------------------------------------------------------------------------
+; Banked RAM and ROM
+
+KEY_COUNT       := $A00A        ; (bank 0) Number of keys in input buffer
+TIMER           := $A03E        ; (bank 0) 60 Hz. timer (3 bytes, big-endian)
+
+.struct BANK
+        .org    $A000
+  RAM   .res    $2000           ; 8 Kibibyte window into 512 Kibibytes or 2048 Kibibytes
+  ROM   .res    $4000           ; 16 Kibibyte window into 128 Kibibytes
+.endstruct
diff --git a/cfg/cx16-asm.cfg b/cfg/cx16-asm.cfg
index 4228f6da..3c24bd56 100644
--- a/cfg/cx16-asm.cfg
+++ b/cfg/cx16-asm.cfg
@@ -6,7 +6,7 @@ SYMBOLS {
     __HIMEM__:    type = weak, value = $9F00;
 }
 MEMORY {
-    ZP:       file = "", start = $0002,  size = $0080 - $0002, define = yes;
+    ZP:       file = "", start = $0022,  size = $0080 - $0022, define = yes;
     LOADADDR: file = %O, start = %S - 2, size = $0002;
     MAIN:     file = %O, start = %S,     size = __HIMEM__ - %S;
 }
diff --git a/cfg/cx16-bank.cfg b/cfg/cx16-bank.cfg
index ff5dded3..1f998f18 100644
--- a/cfg/cx16-bank.cfg
+++ b/cfg/cx16-bank.cfg
@@ -11,13 +11,13 @@ SYMBOLS {
     __BANKRAMSIZE__:  type = weak,   value = $2000; # 8K banked RAM
 }
 MEMORY {
-    ZP:         file = "", define = yes,  start = $0002,                size = $0080 - $0002;
+    ZP:         file = "", define = yes,  start = $0022,                size = $0080 - $0022;
     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__;
+#   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;
@@ -62,8 +62,8 @@ SEGMENTS {
     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;
+#   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;
diff --git a/cfg/cx16.cfg b/cfg/cx16.cfg
index c72f6c35..72fc2fe9 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 = $0002,                size = $0080 - $0002;
+    ZP:       file = "", define = yes, start = $0022,                size = $0080 - $0022;
     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 2136265b..ca9a50ed 100644
--- a/doc/cx16.sgml
+++ b/doc/cx16.sgml
@@ -62,7 +62,7 @@ Special locations:
 
   <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.
+  window into a half Mebibyte or two Mebibytes of banked RAM.
 
   <tag/Bank ROM/
   Bank ROM is located at &dollar;C000 - &dollar;FFFF.  It's a sixteen-Kibibyte
@@ -229,8 +229,9 @@ point to <tt/cX16-std.joy (cx16_std_joy)/.
 <descrip>
   <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.  Buttons A and B are the primary and secondary fire buttons.
+  of the CX16.  It reads the four directions, and the <bf/A/, <bf/B/,
+  <bf/Select/, and <bf/Start/ buttons.  Buttons <bf/A/ and <bf/B/ are
+  the first and second fire buttons.
 </descrip><p>
 
 
@@ -243,6 +244,9 @@ point to <tt/cX16-std.mou (cx16_std_mou)/.
   <tag><tt/cX16-std.mou (cX16_std_mou)/</tag>
   Supports a standard 3-button mouse connected to the PS/2 mouse port of the
   Commander X16.
+
+  Currently (r35), this driver doesn't support <tt/mouse_move()/
+  and <tt/mouse_setbox()/.
 </descrip><p>
 
 
diff --git a/include/cbm.h b/include/cbm.h
index 96eb675c..56b5b294 100644
--- a/include/cbm.h
+++ b/include/cbm.h
@@ -168,7 +168,7 @@ unsigned char __fastcall__ kbrepeat (unsigned char mode);
 
 #if !defined(__CBM610__) && !defined(__PET__)
 void waitvsync (void);
-/* Wait for the start of the next frame */
+/* Wait for the start of the next video field. */
 #endif
 
 /*****************************************************************************/
diff --git a/include/cx16.h b/include/cx16.h
index d7ed15d2..c6638cef 100644
--- a/include/cx16.h
+++ b/include/cx16.h
@@ -44,7 +44,19 @@
 
 
 
+/* Additional output character codes */
+#define CH_COLOR_SWAP           0x01
+#define CH_UNDERLINE            0x04
+#define CH_BOLD                 0x06
+#define CH_BACKSPACE            0x08
+#define CH_ITALIC               0x0B
+#define CH_OUTLINE              0x0C
+#define CH_FONT_ISO             0x0F
+#define CH_FONT_PET             0x8F
+
 /* Additional key defines */
+#define CH_SHIFT_TAB            0x18
+#define CH_HELP                 0x84
 #define CH_F1                   0x85
 #define CH_F2                   0x89
 #define CH_F3                   0x86
@@ -163,7 +175,7 @@ struct __emul {
 };
 #define EMULATOR        (*(volatile struct __emul)0x9FB0)
 
-/* An array window into the half Mibibyte or two Mibibytes of banked RAM */
+/* An array window into the half Mebibyte or two Mebibytes of banked RAM */
 #define BANK_RAM        ((unsigned char[0x2000])0xA000)
 
 
diff --git a/libsrc/cbm/clock.s b/libsrc/cbm/clock.s
index b5fa6e89..90e4263a 100644
--- a/libsrc/cbm/clock.s
+++ b/libsrc/cbm/clock.s
@@ -1,19 +1,28 @@
 ;
-; Ullrich von Bassewitz, 21.09.1998
+; 1998-09-21, Ullrich von Bassewitz
+; 2019-12-25, Greg King
 ;
 ; clock_t clock (void);
 ;
 
-        .include        "cbm.inc"
-
         .export         _clock
         .importzp       sreg
 
+        .include        "cbm.inc"
+        .macpack        cpu
+
 
 .proc   _clock
 
-        lda     #0              ; Byte 3 is always zero
-        sta     sreg+1
+; Some accelerator adaptors have CMOS ICs.
+
+.if (.cpu & ::CPU_ISET_65SC02)
+        stz     sreg + 1
+.else
+        lda     #$00            ; Byte 3 always is zero
+        sta     sreg + 1
+.endif
+
         jsr     RDTIM
         sty     sreg
         rts
diff --git a/libsrc/cx16/_scrsize.s b/libsrc/cx16/_scrsize.s
index f240b1e5..6b848078 100644
--- a/libsrc/cx16/_scrsize.s
+++ b/libsrc/cx16/_scrsize.s
@@ -1,10 +1,6 @@
 ;
-; Ullrich von Bassewitz, 26.10.2000
-;
 ; Screen size variables
 ;
 
-        .export         screensize
         .import         SCREEN
-
-screensize      := SCREEN
+        .export         screensize := SCREEN
diff --git a/libsrc/cx16/bankramaddr.s b/libsrc/cx16/bankramaddr.s
index 53d96e91..7736f869 100644
--- a/libsrc/cx16/bankramaddr.s
+++ b/libsrc/cx16/bankramaddr.s
@@ -1,7 +1,7 @@
 ;
-; 2019-09-16, Greg King
+; 2019-12-21, Greg King
 ;
-; This module supplies the load addresses that are expected
+; This module supplies some load addresses that are expected
 ; by a Commander X16 in the first two bytes of banked RAM load files.
 ;
 
@@ -9,9 +9,11 @@
         ; this module to get included into the output files.
         .export         __BANKRAMADDR__: abs = 1
 
+.if 0 ; bank 0 is used by Kernal
 .segment        "BRAM00ADDR"
 
         .addr   *+2
+.endif
 
 .segment        "BRAM01ADDR"
 
diff --git a/libsrc/cx16/cgetc.s b/libsrc/cx16/cgetc.s
index 2c5ea76d..2372b431 100644
--- a/libsrc/cx16/cgetc.s
+++ b/libsrc/cx16/cgetc.s
@@ -1,5 +1,5 @@
 ;
-; 2019-10-01, Greg King
+; 2019-12-22, Greg King
 ;
 ; char cgetc (void);
 ; /* Return a character from the keyboard. */
@@ -7,13 +7,13 @@
 
         .export         _cgetc
 
-        .import         cursor, GETIN
+        .import         _kbhit, cursor, GETIN
 
         .include        "cx16.inc"
         .macpack        generic
 
 
-_cgetc: ldx     KEY_COUNT       ; Get number of characters
+_cgetc: jsr     _kbhit
         bnz     L3              ; Jump if there are already chars waiting
 
 ; Switch the cursor on if wanted.
@@ -22,7 +22,7 @@ _cgetc: ldx     KEY_COUNT       ; Get number of characters
         tay
         lda     cursor
         jsr     setcursor
-L1:     lda     KEY_COUNT
+L1:     jsr     _kbhit
         bze     L1              ; Wait for key
         tya
         eor     #%00000001      ; (Cursor flag uses negative logic)
diff --git a/libsrc/cx16/clock.s b/libsrc/cx16/clock.s
new file mode 100644
index 00000000..9af215e0
--- /dev/null
+++ b/libsrc/cx16/clock.s
@@ -0,0 +1,36 @@
+;
+; 1998-09-21, Ullrich von Bassewitz
+; 2019-12-25, Greg King
+;
+; clock_t clock (void);
+;
+
+        .constructor    initclock
+        .export         _clock
+
+        .import         SETTIM, RDTIM
+        .importzp       sreg
+
+
+; clock() counts the amount of time that the process has run.
+; Therefore, reset it when the program begins.
+
+.proc   initclock
+
+        lda     #$00
+        tax
+        tay
+        jmp     SETTIM
+
+.endproc
+
+
+
+.proc   _clock
+
+        stz     sreg + 1        ; Byte 3 always is zero
+        jsr     RDTIM
+        sty     sreg
+        rts
+
+.endproc
diff --git a/libsrc/cx16/crt0.s b/libsrc/cx16/crt0.s
index bfb4de10..52deeb76 100644
--- a/libsrc/cx16/crt0.s
+++ b/libsrc/cx16/crt0.s
@@ -1,5 +1,5 @@
 ;
-; Start-up code for cc65 (CX16 version)
+; Start-up code for cc65 (CX16 r35 version)
 ;
 
         .export         _exit
@@ -46,7 +46,7 @@ _exit:
 
         jsr     donelib
 
-.if 0   ; We no longer need to preserve zero-page space for cc65's variables.
+.if 0   ; We don't need to preserve zero-page space for cc65's variables.
 ; Copy back the zero-page stuff.
 
         ldx     #zpspace-1
@@ -83,14 +83,14 @@ init:
         and     #<~$07
         sta     VIA1::PRB
 
-; Change to the first RAM bank.
+; Change to the second RAM bank.
 
         lda     VIA1::PRA2
         sta     ramsave         ; Save the current RAM bank number
-        lda     #$00            ; Choose RAM bank zero
+        lda     #$01
         sta     VIA1::PRA2
 
-.if 0   ; We no longer need to preserve zero-page space for cc65's variables.
+.if 0   ; We don't need to preserve zero-page space for cc65's variables.
 ; Save the zero-page locations that we need.
 
         ldx     #zpspace-1
@@ -107,7 +107,7 @@ L1:     lda     sp,x
         sta     sp
         stx     sp+1            ; Set argument stack ptr
 
-; Switch to the second charset.
+; Switch to the lower/UPPER PetSCII charset.
 
         lda     #$0E
         jsr     CHROUT
diff --git a/libsrc/cx16/get_tv.s b/libsrc/cx16/get_tv.s
index 79a577df..291a32cd 100644
--- a/libsrc/cx16/get_tv.s
+++ b/libsrc/cx16/get_tv.s
@@ -1,5 +1,5 @@
 ;
-; 2019-09-20, Greg King
+; 2019-12-22, Greg King
 ;
 ; unsigned char get_tv (void);
 ; /* Return the video mode the machine is using. */
@@ -11,9 +11,6 @@
 
 
 .proc   _get_tv
-        php
-        sei                             ; Don't let interrupts interfere
-
         ; Point to the video output register.
 
         stz     VERA::CTRL              ; Use port 0
@@ -25,7 +22,6 @@
         sty     VERA::ADDR+2
 
         lda     VERA::DATA0
-        plp                             ; Re-enable interrupts
         and     #$07                    ; Get the type of output signal
         rts
 .endproc
diff --git a/libsrc/cx16/joy/cx16-std.s b/libsrc/cx16/joy/cx16-std.s
index b41c6606..5c10c059 100644
--- a/libsrc/cx16/joy/cx16-std.s
+++ b/libsrc/cx16/joy/cx16-std.s
@@ -1,8 +1,8 @@
 ;
 ; Standard joystick driver for the CX16.
-; May be installed multiple times when statically linked to the application.
+; May be installed multiple times when statically linked to an application.
 ;
-; 2019-11-15 Greg King
+; 2019-12-24, Greg King
 ;
 
         .include        "joy-kernel.inc"
@@ -14,6 +14,8 @@
         .macpack        generic
         .macpack        module
 
+        .importzp       tmp1
+
 
 ; ------------------------------------------------------------------------
 ; Header. Includes jump table
@@ -75,51 +77,21 @@ COUNT:  lda     #<JOY_COUNT
 ; ------------------------------------------------------------------------
 ; READ: Read a particular joystick passed in .A .
 
-READ:   php
-        bit     #JOY_COUNT - $01
-        sei
-        bnz     pad2
-
-; Read game pad 1
-
-pad1:   ldy     JOY1            ; Allow JOY1 to be reread between interrupts
-        sty     JOY1 + 2
+READ:   and     #%00000001
+        jsr     JOYSTICK_GET
+        sta     tmp1
+        txa
+        bit     #%00001110      ; Is it NES or SNES controller?
+        bze     nes
 
-        lda     JOY1 + 1
-        bit     #%00001110
-        bze     nes1
-
-        asl     JOY1 + 2        ; Get SNES's B button
+        asl     tmp1            ; Get SNES's B button
         ror     a               ; Put it next to the A button
-        asl     JOY1 + 2        ; Drop SNES's Y button
+        asl     tmp1            ; Drop SNES's Y button
         asl     a               ; Get back the B button
-        ror     JOY1 + 2
+        ror     tmp1
         asl     a               ; Get SNES's A button
-        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:   ldy     JOY2
-        sty     JOY2 + 2
-
-        lda     JOY2 + 1
-        bit     #%00001110
-        bze     nes2
-
-        asl     JOY2 + 2
-        ror     a
-        asl     JOY2 + 2
-        asl     a
-        ror     JOY2 + 2
-        asl     a
-        ror     JOY2 + 2
+        ror     tmp1            ; Make byte look like NES pad
 
-nes2:   lda     JOY2 + 2
-        plp
-        eor     #%11111111
+nes:    lda     tmp1            ; The controllers give zeroes for "pressed"
+        eor     #%11111111      ; We want ones for "pressed"
         rts
diff --git a/libsrc/cx16/joyref.s b/libsrc/cx16/joyref.s
index fb21918c..edd89fba 100644
--- a/libsrc/cx16/joyref.s
+++ b/libsrc/cx16/joyref.s
@@ -1,5 +1,5 @@
 ;
-; 2019-11-14, Greg King
+; 2019-12-22, Greg King
 ;
 ; Link an interrupt handler if joysticks are used by a program.
 ;
@@ -14,7 +14,7 @@ joy_libref:
         lda     VERA::IRQ_FLAGS
         lsr     a
         bcc     not_vsync
-        jsr     GETJOY          ; Bit-bang game controllers
+        jsr     JOYSTICK_SCAN   ; 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 a73533e2..34afdeba 100644
--- a/libsrc/cx16/kbhit.s
+++ b/libsrc/cx16/kbhit.s
@@ -1,5 +1,5 @@
 ;
-; 2019-11-06, Greg King
+; 2019-12-22, Greg King
 ;
 ; unsigned char kbhit (void);
 ; /* Returns non-zero (true) if a typed character is waiting. */
@@ -11,7 +11,10 @@
 
 
 .proc   _kbhit
+        ldy     VIA1::PRA2      ; (KEY_COUNT is in RAM bank 0)
+        stz     VIA1::PRA2
         lda     KEY_COUNT       ; Get number of characters
+        sty     VIA1::PRA2
         tax                     ; High byte of return (only its zero/nonzero ...
-        rts			; ... state matters)
+        rts                     ; ... state matters)
 .endproc
diff --git a/libsrc/cx16/kernal.s b/libsrc/cx16/kernal.s
index 97443c82..ccd52d63 100644
--- a/libsrc/cx16/kernal.s
+++ b/libsrc/cx16/kernal.s
@@ -1,60 +1,94 @@
 ;
-; 2019-11-05, Greg King
+; 2019-12-22, Greg King
 ;
 ; CX16 Kernal functions
 ;
 
         .include        "cbm_kernal.inc"
 
-        .export         GETJOY
-        .export         MOUSE
-        .export         SCRMOD
+        .export FB_INIT
+        .export FB_GET_INFO
+        .export FB_SET_PALETTE
+        .export FB_CURSOR_POSITION
+        .export FB_CURSOR_NEXT_LINE
+        .export FB_GET_PIXEL
+        .export FB_GET_PIXELS
+        .export FB_SET_PIXEL
+        .export FB_SET_PIXELS
+        .export FB_SET_8_PIXELS
+        .export FB_SET_8_PIXELS_OPAQUE
+        .export FB_FILL_PIXELS
+        .export FB_FILTER_PIXELS
+        .export FB_MOVE_PIXELS
+        .export GRAPH_INIT
+        .export GRAPH_CLEAR
+        .export GRAPH_SET_WINDOW
+        .export GRAPH_SET_COLORS
+        .export GRAPH_DRAW_LINE
+        .export GRAPH_DRAW_RECT
+        .export GRAPH_MOVE_RECT
+        .export GRAPH_DRAW_OVAL
+        .export GRAPH_DRAW_IMAGE
+        .export GRAPH_SET_FONT
+        .export GRAPH_GET_CHAR_SIZE
+        .export GRAPH_PUT_CHAR
+        .export RESTORE_BASIC
+        .export CLOCK_SET_DATE_TIME
+        .export CLOCK_GET_DATE_TIME
+        .export JOYSTICK_SCAN
+        .export JOYSTICK_GET
+        .export SCRMOD
+        .export MOUSE_CONFIG
+        .export MOUSE_GET
 
-        .export         CLSALL
-        .export         JSRFAR
-        .export         INDFET
-        .export         INDSTA
-        .export         INDCMP
-        .export         PRIMM
+        .export CLSALL
+        .export LKUPLA
+        .export LKUPSA
+        .export PFKEY
+        .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
+        .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
diff --git a/libsrc/cx16/mcbdefault.s b/libsrc/cx16/mcbdefault.s
index d817b9ae..3dda1c71 100644
--- a/libsrc/cx16/mcbdefault.s
+++ b/libsrc/cx16/mcbdefault.s
@@ -1,53 +1,63 @@
 ;
 ; Default mouse callbacks for the CX16
 ;
-; 2019-11-09, Greg King
+; 2019-12-25, Greg King
 ;
-; All functions in this module should be interrupt safe
+; All functions in this module should be interrupt-safe
 ; because they might be called from an interrupt handler.
 ;
 
         .export         _mouse_def_callbacks
 
-        .include        "cbm_kernal.inc"
         .include        "cx16.inc"
 
-; --------------------------------------------------------------------------
-; Hide the mouse pointer. Always called with interrupts disabled.
 
-.code
+msprite:
+        stz     VERA::CTRL      ; set address for VERA's data port zero
+        lda     #<(VERA::SPRITE::ATTRIB::Z_FLIP + 0 * 8)
+        ldx     #>(VERA::SPRITE::ATTRIB::Z_FLIP + 0 * 8)
+        ldy     #^(VERA::SPRITE::ATTRIB::Z_FLIP + 0 * 8) | VERA::INC0
+        sta     VERA::ADDR
+        stx     VERA::ADDR+1
+        sty     VERA::ADDR+2
+        rts
+
+; --------------------------------------------------------------------------
+; Hide the mouse pointer.
 
-hide:   ldx     #$00            ; Don't change sprite's scale
-        lda     #$00            ; Disable sprite
-        jmp     MOUSE
+hide:   jsr     msprite
+        lda     VERA::DATA0
+        and     #<~VERA::SPRITE::DEPTH::LAYER1
+        sta     VERA::DATA0
+        rts
 
 ; --------------------------------------------------------------------------
-; Show the mouse pointer. Always called with interrupts disabled.
+; Show the mouse pointer.
 
-show:   ldx     #$00
-        lda     #<-$01          ; Enable sprite
-        jmp     MOUSE
+show:   jsr     msprite
+        lda     VERA::DATA0
+        ora     #VERA::SPRITE::DEPTH::LAYER1
+        sta     VERA::DATA0
+        rts
 
 ; --------------------------------------------------------------------------
-; Prepare to move the mouse pointer. Always called with interrupts disabled.
+; Prepare to move the mouse pointer.
 
 prep:   ; Fall through
 
 ; --------------------------------------------------------------------------
-; Draw the mouse pointer. Always called with interrupts disabled.
+; Draw the mouse pointer.
 
 draw:   ; Fall through
 
 ; --------------------------------------------------------------------------
-; Move the mouse pointer X position to the value in .XA .  Always called with
-; interrupts disabled.
+; Move the mouse pointer X position to the value in .XA .
 
 movex:                          ; Already set by drivers
         ; Fall through
 
 ; --------------------------------------------------------------------------
-; Move the mouse pointer Y position to the value in .XA .  Always called with
-; interrupts disabled.
+; Move the mouse pointer Y position to the value in .XA .
 
 movey:  rts                     ; Already set by drivers
 
diff --git a/libsrc/cx16/mou/cx16-std.s b/libsrc/cx16/mou/cx16-std.s
index eb3f8316..0d046bbc 100644
--- a/libsrc/cx16/mou/cx16-std.s
+++ b/libsrc/cx16/mou/cx16-std.s
@@ -1,7 +1,7 @@
 ;
 ; Driver for the Commander X16 Kernal's mouse driver.
 ;
-; 2019-11-16, Greg King
+; 2019-12-25, Greg King
 ;
 
         .include        "zeropage.inc"
@@ -66,18 +66,16 @@ SCREEN_HEIGHT   = 480 - 1
 ;----------------------------------------------------------------------------
 ; Global variables.
 
-.bss
-
-XPos            := MOUSEX               ; Current mouse position, X
-YPos            := MOUSEY               ; Current mouse position, Y
+XPos            := ptr3                 ; Current mouse position, X
+YPos            := ptr4                 ; Current mouse position, Y
 
-XMin            := MOUSEL               ; X1 value of bounding box
-XMax            := MOUSER               ; X2 value of bounding box
-YMin            := MOUSET               ; Y1 value of bounding box
-YMax            := MOUSEB               ; Y2 value of bounding box
-Box             := XMin
+.bss
 
-Buttons         := MOUSEBT              ; button status bits
+Box:
+XMin:           .res    2               ; X1 value of bounding box
+XMax:           .res    2               ; X2 value of bounding box
+YMin:           .res    2               ; Y1 value of bounding box
+YMax:           .res    2               ; Y2 value of bounding box
 
 .rodata
 
@@ -121,22 +119,22 @@ INSTALL:
         bpl     @L1
 
         ldx     #$00            ; Don't change sprite's scale
-        lda     #$01            ; Initiate and show sprite
-        jsr     MOUSE
+        lda     #$01            ; Create sprite
+        jsr     MOUSE_CONFIG
 
 ; Be sure the mouse cursor is invisible, and at the default location. We
 ; need to do that here, because the mouse interrupt handler might not set
 ; the mouse position if it hasn't changed.
 
-        sei
         jsr     CHIDE
+.if 0
         lda     XPos
         ldx     XPos+1
         jsr     CMOVEX
         lda     YPos
         ldx     YPos+1
         jsr     CMOVEY
-        cli
+.endif
 
 ; Done, return zero
 
@@ -148,7 +146,10 @@ INSTALL:
 ; UNINSTALL routine -- is called before the driver is removed from memory.
 ; No return code required (the driver is removed from memory on return).
 
-UNINSTALL       := HIDE                 ; Hide cursor on exit
+UNINSTALL:                      ; Disable mouse on exit
+        lda     #$00
+        tax
+        jmp     MOUSE_CONFIG
 
 ;----------------------------------------------------------------------------
 ; HIDE routine -- is called to hide the mouse pointer. The mouse kernel manages
@@ -181,6 +182,7 @@ SETBOX: sta     ptr1
         lda     (ptr1)
         ldy     #$01
 
+        php
         sei
         sta     XMin
         lda     (ptr1),y
@@ -191,10 +193,12 @@ SETBOX: sta     ptr1
         iny
         lda     (ptr1),y
         sta     YMax
-        cli
+        plp
 
         rts
 
+;; Note: SETBOX and GETBOX currently have no effect!
+
 ;----------------------------------------------------------------------------
 ; GETBOX: Return the mouse bounding box. The parameters are passed as they
 ; come from the C program, that is, a pointer to a mouse_box struct in .XA .
@@ -222,7 +226,10 @@ GETBOX: sta     ptr1
 ; No checks are done to see if the new position is valid (within
 ; the bounding box or the screen). No return code required.
 
-MOVE:   sei                             ; No interrupts
+;; Note: This function currently has no effect!
+
+MOVE:   php
+        sei                             ; No interrupts
 
         sta     YPos
         stx     YPos+1                  ; New Y position
@@ -237,14 +244,16 @@ MOVE:   sei                             ; No interrupts
         sta     XPos                    ; New X position
         jsr     CMOVEX                  ; Move the cursor
 
-        cli                             ; Allow interrupts
+        plp                             ; Allow interrupts
         rts
 
 ;----------------------------------------------------------------------------
 ; BUTTONS: Return the CBM 1351 button mask in .XA .
 
 BUTTONS:
-        lda     Buttons
+        ldx     #XPos
+        jsr     MOUSE_GET
+
         and     #%00000111
         tax
         lda     ButtMask,x
@@ -255,9 +264,9 @@ BUTTONS:
 ; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1.
 ; No return code required.
 
-POS:    ldy     #MOUSE_POS::XCOORD      ; Structure offset
+POS:    jsr     BUTTONS
 
-        sei                             ; Disable interrupts
+POS1:   ldy     #MOUSE_POS::XCOORD      ; Structure offset
         lda     XPos                    ; Transfer the position
         sta     (ptr1),y
         lda     XPos+1
@@ -267,8 +276,6 @@ POS:    ldy     #MOUSE_POS::XCOORD      ; Structure offset
         iny
         sta     (ptr1),y
         lda     YPos+1
-        cli                             ; Enable interrupts
-
         iny
         sta     (ptr1),y                ; Store last byte
         rts                             ; Done
@@ -282,20 +289,15 @@ POS:    ldy     #MOUSE_POS::XCOORD      ; Structure offset
 ; call mouse_pos to initialize the struct pointer, and fill the position
 ; fields.
 
-INFO:   jsr     POS
-
-; Fill in the button state
-
-        jsr     BUTTONS                 ; Will not touch ptr1
+INFO:   jsr     BUTTONS                 ; Will not touch ptr1
         ldy     #MOUSE_INFO::BUTTONS
         sta     (ptr1),y
-        rts
+        jmp     POS1
 
 ;----------------------------------------------------------------------------
 ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
 ; specific data in ptr1, and the ioctl code in A.
 ; Must return an error code in .XA .
-;
 
 IOCTL:  lda     #<MOUSE_ERR_INV_IOCTL   ; We don't support ioctls, for now
         ldx     #>MOUSE_ERR_INV_IOCTL
diff --git a/libsrc/cx16/mouse_stat_stddrv.s b/libsrc/cx16/mouse_stat_stddrv.s
index 1ff8ad43..8e0a3ed5 100644
--- a/libsrc/cx16/mouse_stat_stddrv.s
+++ b/libsrc/cx16/mouse_stat_stddrv.s
@@ -1,7 +1,7 @@
 ;
 ; Address of the static standard mouse driver
 ;
-; 2019-11-08,Greg King
+; 2019-11-08, Greg King
 ;
 ; const void mouse_static_stddrv[];
 ;
diff --git a/libsrc/cx16/set_tv.s b/libsrc/cx16/set_tv.s
index 8b802f32..c23568c6 100644
--- a/libsrc/cx16/set_tv.s
+++ b/libsrc/cx16/set_tv.s
@@ -1,5 +1,5 @@
 ;
-; 2019-11-06, Greg King
+; 2019-12-22, Greg King
 ;
 ; void __fastcall__ set_tv (unsigned char);
 ; /* Set the video mode the machine will use. */
@@ -11,9 +11,6 @@
 
 
 .proc   _set_tv
-        php
-        sei                             ; Don't let interrupts interfere
-
         ; Point to the video output register.
 
         stz     VERA::CTRL              ; Use port 0
@@ -25,6 +22,5 @@
         stx     VERA::ADDR+2
 
         sta     VERA::DATA0
-        plp                             ; Re-enable interrupts
         rts
 .endproc
diff --git a/libsrc/cx16/sysuname.s b/libsrc/cx16/sysuname.s
index f8500936..4aefb7cf 100644
--- a/libsrc/cx16/sysuname.s
+++ b/libsrc/cx16/sysuname.s
@@ -9,7 +9,7 @@
 
         .import         utscopy
 
-__sysuname 	:= 	utscopy
+__sysuname      :=      utscopy
 
 ;--------------------------------------------------------------------------
 ; Data. We define a fixed utsname struct here, and just copy it.
diff --git a/libsrc/cx16/tgi_stat_stddrv.s b/libsrc/cx16/tgi_stat_stddrv.s
index 566a3639..e501f4c2 100644
--- a/libsrc/cx16/tgi_stat_stddrv.s
+++ b/libsrc/cx16/tgi_stat_stddrv.s
@@ -1,11 +1,10 @@
 ;
 ; Address of the static standard TGI driver
 ;
-; 2019-11-06, Greg King
+; 2019-12-22, Greg King
 ;
 ; const void tgi_static_stddrv[];
 ;
 
-        .import _cx16_640x4c_tgi
-
-        .export _tgi_static_stddrv := _cx16_640x4c_tgi
+        .import _cx16_320x8b_tgi
+        .export _tgi_static_stddrv := _cx16_320x8b_tgi
diff --git a/libsrc/cx16/tgi_stddrv.s b/libsrc/cx16/tgi_stddrv.s
index 0f77e734..0e46a6cb 100644
--- a/libsrc/cx16/tgi_stddrv.s
+++ b/libsrc/cx16/tgi_stddrv.s
@@ -1,7 +1,7 @@
 ;
 ; Name of the standard TGI driver
 ;
-; 2019-11-06, Greg King
+; 2019-12-22, Greg King
 ;
 ; const char tgi_stddrv[];
 ;
@@ -9,5 +9,4 @@
         .export _tgi_stddrv
 
 .rodata
-
-_tgi_stddrv:    .asciiz "cx16-640x4c.tgi"
+_tgi_stddrv:    .asciiz "cx16-320x8b.tgi"
diff --git a/libsrc/cx16/vset.s b/libsrc/cx16/vaddr0.s
similarity index 60%
rename from libsrc/cx16/vset.s
rename to libsrc/cx16/vaddr0.s
index 9178850e..384bf350 100644
--- a/libsrc/cx16/vset.s
+++ b/libsrc/cx16/vaddr0.s
@@ -1,19 +1,18 @@
 ;
-; 2019-10-22, Greg King
+; 2019-12-22, Greg King
 ;
 ; Set the __far__ address that VERA will use for data access.
 ; This is a support function for the fastcall functions vpeek() and vpoke().
 ;
 
-        .export         vset
+        .export         vaddr0
 
         .importzp       sreg
         .include        "cx16.inc"
 
 
-vset:   ldy     sreg
-        sei                     ; don't let interrupt handlers interfere
-        stz     VERA::CTRL      ; set address for VERA's data port zero
+vaddr0: stz     VERA::CTRL      ; set address for VERA's data port zero
+        ldy     sreg
         sta     VERA::ADDR
         stx     VERA::ADDR+1
         sty     VERA::ADDR+2
diff --git a/libsrc/cx16/vpeek.s b/libsrc/cx16/vpeek.s
index 0c1a9465..80d4d536 100644
--- a/libsrc/cx16/vpeek.s
+++ b/libsrc/cx16/vpeek.s
@@ -1,5 +1,5 @@
 ;
-; 2019-10-22, Greg King
+; 2019-12-22, Greg King
 ;
 ; unsigned char fastcall vpeek (unsigned long addr);
 ; /* Get a byte from a location in VERA's internal address space. */
@@ -7,13 +7,11 @@
 
         .export         _vpeek
 
-        .import         vset
+        .import         vaddr0
         .include        "cx16.inc"
 
 
-_vpeek: php                     ; (vset blocks interrupts)
-        jsr     vset            ; put VERA's address
+_vpeek: jsr     vaddr0          ; put VERA's address
         ldx     #>$0000
         lda     VERA::DATA0     ; read VERA port zero
-        plp
         rts
diff --git a/libsrc/cx16/vpoke.s b/libsrc/cx16/vpoke.s
index 8c21e9b2..2c8497a5 100644
--- a/libsrc/cx16/vpoke.s
+++ b/libsrc/cx16/vpoke.s
@@ -1,5 +1,5 @@
 ;
-; 2019-10-22, Greg King
+; 2019-12-22, Greg King
 ;
 ; void fastcall vpoke (unsigned char data, unsigned long addr);
 ; /* Put a byte into a location in VERA's internal address space.
@@ -9,13 +9,11 @@
 
         .export         _vpoke
 
-        .import         vset, popa
+        .import         vaddr0, popa
         .include        "cx16.inc"
 
 
-_vpoke: php                     ; (vset blocks interrupts)
-        jsr     vset            ; put VERA's address
+_vpoke: jsr     vaddr0          ; put VERA's address
         jsr     popa
         sta     VERA::DATA0     ; write data to VERA port zero
-        plp
         rts
diff --git a/libsrc/cx16/waitvsync.s b/libsrc/cx16/waitvsync.s
index 09d01c6a..e8176916 100644
--- a/libsrc/cx16/waitvsync.s
+++ b/libsrc/cx16/waitvsync.s
@@ -1,9 +1,10 @@
 ;
-; 2019-09-26, Greg King
+; 2019-12-23, Greg King
 ;
 ; void waitvsync (void);
+; /* Wait for the start of the next video field. */
 ;
-; VERA's vertical sync causes IRQs which increment the jiffy clock.
+; VERA's vertical sync causes IRQs which increment the jiffy timer.
 ;
 
         .export         _waitvsync
@@ -11,7 +12,10 @@
         .include        "cx16.inc"
 
 _waitvsync:
-        lda     TIME + 2
-:       cmp     TIME + 2
+        ldx     VIA1::PRA2      ; (TIMER is in RAM bank 0)
+        stz     VIA1::PRA2
+        lda     TIMER + 2
+:       cmp     TIMER + 2
         beq     :-              ; Wait for next jiffy
+        stx     VIA1::PRA2
         rts
diff --git a/src/ca65/struct.c b/src/ca65/struct.c
index 6d279a70..ecbaa2a7 100644
--- a/src/ca65/struct.c
+++ b/src/ca65/struct.c
@@ -87,6 +87,7 @@ static long Member (long AllocSize)
     /* Check the size for a reasonable value */
     if (AllocSize >= 0x1000000) {
         ErrorSkip ("Range error");
+        AllocSize = 1;
     }
 
     /* Return the size */
@@ -193,7 +194,13 @@ static long DoStructInternal (long Offs, unsigned Type)
                 if (CurTok.Tok == TOK_SEP) {
                     ErrorSkip ("Address is missing");
                 } else {
-                    Offs = Member (1);
+                    Offs = ConstExpression ();
+
+                    /* Check the address for a reasonable value */
+                    if (Offs >= 0x1000000) {
+                        ErrorSkip ("Range error");
+                        Offs = 0;
+                    }
                 }
                 break;
 
-- 
2.26.0