Blob Blame History Raw
From 5da525e0ea10987d9dbf1ad2ba5bad9548d23f59 Mon Sep 17 00:00:00 2001
From: Greg King <gregdk@users.sf.net>
Date: Sat, 16 Nov 2019 14:51:24 -0500
Subject: [PATCH 096/170] Added a standard mouse driver to the cx16 library.

---
 doc/cx16.sgml                   |   9 +-
 include/cx16.h                  |   9 +-
 libsrc/cx16/mcbdefault.s        |  65 +++++++
 libsrc/cx16/mou/cx16-std.s      | 310 ++++++++++++++++++++++++++++++++
 libsrc/cx16/mouse_stat_stddrv.s |  11 ++
 libsrc/cx16/mouse_stddrv.s      |  13 ++
 6 files changed, 415 insertions(+), 2 deletions(-)
 create mode 100644 libsrc/cx16/mcbdefault.s
 create mode 100644 libsrc/cx16/mou/cx16-std.s
 create mode 100644 libsrc/cx16/mouse_stat_stddrv.s
 create mode 100644 libsrc/cx16/mouse_stddrv.s

diff --git a/doc/cx16.sgml b/doc/cx16.sgml
index 16e43db9..7189e715 100644
--- a/doc/cx16.sgml
+++ b/doc/cx16.sgml
@@ -236,7 +236,14 @@ point to <tt/cX16-std.joy (cx16_std_joy)/.
 
 <sect1>Mouse drivers<p>
 
-No mouse drivers are available currently for the CX16.
+The default drivers, <tt/mouse_stddrv (mouse_static_stddrv)/,
+point to <tt/cX16-std.mou (cx16_std_mou)/.
+
+<descrip>
+  <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.
+</descrip><p>
 
 
 <sect1>RS232 device drivers<p>
diff --git a/include/cx16.h b/include/cx16.h
index a6f1b78f..b465378a 100644
--- a/include/cx16.h
+++ b/include/cx16.h
@@ -115,7 +115,7 @@
 #define TV_NTSC_MONO    6
 #define TV_RGB2         7
 
-/* Video mode defines */
+/* Video modes */
 #define VIDEOMODE_40x30         0x00
 #define VIDEOMODE_80x60         0x02
 #define VIDEOMODE_40COL         VIDEOMODE_40x30
@@ -123,6 +123,12 @@
 #define VIDEOMODE_320x240       0x80
 #define VIDEOMODE_SWAP          (-1)
 
+/* VERA's interrupt flags */
+#define VERA_IRQ_VSYNC          0b00000001
+#define VERA_IRQ_RASTER         0b00000010
+#define VERA_IRQ_SPR_COLL       0b00000100
+#define VERA_IRQ_UART           0b00001000
+
 
 /* Define hardware */
 
@@ -163,6 +169,7 @@ struct __emul {
 /* The addresses of the static drivers */
 
 extern void cx16_std_joy[];             /* Referred to by joy_static_stddrv[] */
+extern void cx16_std_mou[];             /* Referred to by mouse_static_stddrv[] */
 
 
 
diff --git a/libsrc/cx16/mcbdefault.s b/libsrc/cx16/mcbdefault.s
new file mode 100644
index 00000000..d817b9ae
--- /dev/null
+++ b/libsrc/cx16/mcbdefault.s
@@ -0,0 +1,65 @@
+;
+; Default mouse callbacks for the CX16
+;
+; 2019-11-09, Greg King
+;
+; 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
+
+hide:   ldx     #$00            ; Don't change sprite's scale
+        lda     #$00            ; Disable sprite
+        jmp     MOUSE
+
+; --------------------------------------------------------------------------
+; Show the mouse pointer. Always called with interrupts disabled.
+
+show:   ldx     #$00
+        lda     #<-$01          ; Enable sprite
+        jmp     MOUSE
+
+; --------------------------------------------------------------------------
+; Prepare to move the mouse pointer. Always called with interrupts disabled.
+
+prep:   ; Fall through
+
+; --------------------------------------------------------------------------
+; Draw the mouse pointer. Always called with interrupts disabled.
+
+draw:   ; Fall through
+
+; --------------------------------------------------------------------------
+; Move the mouse pointer X position to the value in .XA .  Always called with
+; interrupts disabled.
+
+movex:                          ; Already set by drivers
+        ; Fall through
+
+; --------------------------------------------------------------------------
+; Move the mouse pointer Y position to the value in .XA .  Always called with
+; interrupts disabled.
+
+movey:  rts                     ; Already set by drivers
+
+; --------------------------------------------------------------------------
+; Callback structure
+
+.rodata
+
+_mouse_def_callbacks:
+        .addr   hide
+        .addr   show
+        .addr   prep
+        .addr   draw
+        .addr   movex
+        .addr   movey
diff --git a/libsrc/cx16/mou/cx16-std.s b/libsrc/cx16/mou/cx16-std.s
new file mode 100644
index 00000000..eb3f8316
--- /dev/null
+++ b/libsrc/cx16/mou/cx16-std.s
@@ -0,0 +1,310 @@
+;
+; Driver for the Commander X16 Kernal's mouse driver.
+;
+; 2019-11-16, Greg King
+;
+
+        .include        "zeropage.inc"
+        .include        "mouse-kernel.inc"
+        .include        "cx16.inc"
+        .include        "cbm_kernal.inc"
+
+        .macpack        module
+
+
+; ------------------------------------------------------------------------
+; Header. Includes jump table
+
+        module_header   _cx16_std_mou
+
+HEADER:
+
+; Driver signature
+
+        .byte   $6d, $6f, $75           ; ASCII "mou"
+        .byte   MOUSE_API_VERSION       ; Mouse driver API version number
+
+; Library reference
+
+        .addr   $0000
+
+; Jump table
+
+        .addr   INSTALL
+        .addr   UNINSTALL
+        .addr   HIDE
+        .addr   SHOW
+        .addr   SETBOX
+        .addr   GETBOX
+        .addr   MOVE
+        .addr   BUTTONS
+        .addr   POS
+        .addr   INFO
+        .addr   IOCTL
+        .addr   IRQ
+
+; Mouse driver flags
+
+        .byte   $00                     ; Don't need interrupts
+
+; Callback table, set by the mouse kernel before INSTALL is called
+
+CHIDE:  jmp     $0000                   ; Hide the cursor
+CSHOW:  jmp     $0000                   ; Show the cursor
+CPREP:  jmp     $0000                   ; Prepare to move the cursor
+CDRAW:  jmp     $0000                   ; Draw the cursor
+CMOVEX: jmp     $0000                   ; Move the cursor to X coord
+CMOVEY: jmp     $0000                   ; Move the cursor to Y coord
+
+
+;----------------------------------------------------------------------------
+; Constants
+
+SCREEN_WIDTH    = 640 - 1               ; (origin is zero)
+SCREEN_HEIGHT   = 480 - 1
+
+;----------------------------------------------------------------------------
+; Global variables.
+
+.bss
+
+XPos            := MOUSEX               ; Current mouse position, X
+YPos            := MOUSEY               ; 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
+
+Buttons         := MOUSEBT              ; button status bits
+
+.rodata
+
+; Default values for above variables
+; (We use ".proc" because we want to define both a label and a scope.)
+
+.proc   DefBox
+        .word   0                       ; XMin
+        .word   SCREEN_WIDTH            ; XMax
+        .word   0                       ; YMin
+        .word   SCREEN_HEIGHT           ; YMax
+.endproc
+
+; These button masks are compatible with the CBM 1351 and the CMD SmartMouse.
+
+ButtMask:
+        .byte   %00000000               ; No buttons
+        .byte   %00010000               ; Left
+        .byte   %00000001               ; Right
+        .byte   %00010001               ; Left, right
+        .byte   %00000010               ; Middle
+        .byte   %00010010               ; Left, middle
+        .byte   %00000011               ; Middle, right
+        .byte   %00010011               ; Left, middle, right
+
+.code
+
+;----------------------------------------------------------------------------
+; INSTALL routine. Is called after the driver is loaded into memory.
+; If possible, check if the hardware is present.
+; Must return a MOUSE_ERR_xx code in .XA .
+
+INSTALL:
+
+; Initialize variables. Just copy the default stuff over.
+
+        ldx     #.sizeof(DefBox) - 1
+@L1:    lda     DefBox,x
+        sta     Box,x
+        dex
+        bpl     @L1
+
+        ldx     #$00            ; Don't change sprite's scale
+        lda     #$01            ; Initiate and show sprite
+        jsr     MOUSE
+
+; 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
+        lda     XPos
+        ldx     XPos+1
+        jsr     CMOVEX
+        lda     YPos
+        ldx     YPos+1
+        jsr     CMOVEY
+        cli
+
+; Done, return zero
+
+        ldx     #>MOUSE_ERR_OK
+        txa
+        rts
+
+;----------------------------------------------------------------------------
+; 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
+
+;----------------------------------------------------------------------------
+; HIDE routine -- is called to hide the mouse pointer. The mouse kernel manages
+; a counter for calls to show/hide, and the driver entry point is called only
+; if the mouse currently is visible, and should get hidden. For most drivers,
+; no special action is required besides disabling the mouse cursor.
+; No return code required.
+
+HIDE:   jmp     CHIDE
+
+;----------------------------------------------------------------------------
+; SHOW routine -- is called to show the mouse pointer. The mouse kernel manages
+; a counter for calls to show/hide, and the driver entry point is called only
+; if the mouse currently is hidden, and should become visible. For most drivers,
+; no special action is required besides enabling the mouse cursor.
+; No return code required.
+
+SHOW:   jmp     CSHOW
+
+;----------------------------------------------------------------------------
+; SETBOX: Set 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 .
+; No checks are done if the mouse is currently inside the box, that is the job
+; of the caller. It is not necessary to validate the parameters, trust the
+; caller, and save some code here. No return code required.
+
+SETBOX: sta     ptr1
+        stx     ptr1+1                  ; Save data pointer
+
+        lda     (ptr1)
+        ldy     #$01
+
+        sei
+        sta     XMin
+        lda     (ptr1),y
+        sta     YMin
+        iny
+        lda     (ptr1),y
+        sta     XMax
+        iny
+        lda     (ptr1),y
+        sta     YMax
+        cli
+
+        rts
+
+;----------------------------------------------------------------------------
+; 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 .
+
+GETBOX: sta     ptr1
+        stx     ptr1+1                  ; Save data pointer
+
+        lda     XMin
+        sta     (ptr1)
+        ldy     #$01
+        lda     YMin
+        sta     (ptr1),y
+        iny
+        lda     XMax
+        sta     (ptr1),y
+        iny
+        lda     YMax
+        sta     (ptr1),y
+        rts
+
+;----------------------------------------------------------------------------
+; MOVE: Put the mouse at a new position. That position is passed as it comes
+; from the C program, that is: X on the stack and Y in .XA .  The C wrapper
+; will remove the parameter from the stack, on return.
+; 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
+
+        sta     YPos
+        stx     YPos+1                  ; New Y position
+        jsr     CMOVEY                  ; Set it
+
+        ldy     #$01
+        lda     (sp),y
+        sta     XPos+1
+        tax
+        dey
+        lda     (sp),y
+        sta     XPos                    ; New X position
+        jsr     CMOVEX                  ; Move the cursor
+
+        cli                             ; Allow interrupts
+        rts
+
+;----------------------------------------------------------------------------
+; BUTTONS: Return the CBM 1351 button mask in .XA .
+
+BUTTONS:
+        lda     Buttons
+        and     #%00000111
+        tax
+        lda     ButtMask,x
+        ldx     #>$0000
+        rts
+
+;----------------------------------------------------------------------------
+; 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
+
+        sei                             ; Disable interrupts
+        lda     XPos                    ; Transfer the position
+        sta     (ptr1),y
+        lda     XPos+1
+        iny
+        sta     (ptr1),y
+        lda     YPos
+        iny
+        sta     (ptr1),y
+        lda     YPos+1
+        cli                             ; Enable interrupts
+
+        iny
+        sta     (ptr1),y                ; Store last byte
+        rts                             ; Done
+
+;----------------------------------------------------------------------------
+; INFO: Returns mouse position and current button mask in the MOUSE_INFO
+; struct pointed to by ptr1. No return code required.
+;
+; We're cheating here to keep the code smaller: The first fields of the
+; mouse_info struct are identical to the mouse_pos struct; so, we just will
+; 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
+        ldy     #MOUSE_INFO::BUTTONS
+        sta     (ptr1),y
+        rts
+
+;----------------------------------------------------------------------------
+; 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
+;       rts                             ; Fall through
+
+;----------------------------------------------------------------------------
+; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context
+; (so be careful). The routine MUST return carry set if the interrupt has been
+; 'handled' -- which means that the interrupt source is gone. Otherwise, it
+; MUST return carry clear.
+
+IRQ:    rts                             ; Kernal ROM does this routine's job
diff --git a/libsrc/cx16/mouse_stat_stddrv.s b/libsrc/cx16/mouse_stat_stddrv.s
new file mode 100644
index 00000000..1ff8ad43
--- /dev/null
+++ b/libsrc/cx16/mouse_stat_stddrv.s
@@ -0,0 +1,11 @@
+;
+; Address of the static standard mouse driver
+;
+; 2019-11-08,Greg King
+;
+; const void mouse_static_stddrv[];
+;
+
+        .import _cx16_std_mou
+
+        .export _mouse_static_stddrv := _cx16_std_mou
diff --git a/libsrc/cx16/mouse_stddrv.s b/libsrc/cx16/mouse_stddrv.s
new file mode 100644
index 00000000..d708bb66
--- /dev/null
+++ b/libsrc/cx16/mouse_stddrv.s
@@ -0,0 +1,13 @@
+;
+; Name of the standard mouse driver
+;
+; 2019-11-08, Greg King
+;
+; const char mouse_stddrv[];
+;
+
+        .export _mouse_stddrv
+
+.rodata
+
+_mouse_stddrv:  .asciiz "cx16-std.mou"
-- 
2.26.0