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