From 1c83d8232b7999caea5ed04dd5133d69aa81d638 Mon Sep 17 00:00:00 2001 From: Greg King Date: Fri, 23 Aug 2013 03:06:00 -0400 Subject: [PATCH] Added a driver to the CBM510 library that lets a joystick pretend to be a mouse. --- include/cbm510.h | 7 +- libsrc/cbm510/mcbdefault.s | 131 +++++++++ libsrc/cbm510/mou/cbm510-joy.s | 445 ++++++++++++++++++++++++++++++ libsrc/cbm510/mouse_stat_stddrv.s | 13 + libsrc/cbm510/mouse_stddrv.s | 16 ++ libsrc/cbm510/mouseref.s | 23 ++ 6 files changed, 632 insertions(+), 3 deletions(-) create mode 100644 libsrc/cbm510/mcbdefault.s create mode 100644 libsrc/cbm510/mou/cbm510-joy.s create mode 100644 libsrc/cbm510/mouse_stat_stddrv.s create mode 100644 libsrc/cbm510/mouse_stddrv.s create mode 100644 libsrc/cbm510/mouseref.s diff --git a/include/cbm510.h b/include/cbm510.h index 350527c89..797b2c4fa 100644 --- a/include/cbm510.h +++ b/include/cbm510.h @@ -2,11 +2,11 @@ /* */ /* cbm510.h */ /* */ -/* System specific definitions for the CBM5x0 / P500 */ +/* System-specific definitions for the CBM5x0 / P500 */ /* */ /* */ /* */ -/* (C) 2001-2009, Ullrich von Bassewitz */ +/* (C) 2001-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -100,7 +100,7 @@ #define SID (*(struct __sid*)0xDA00) #include <_6526.h> -#define CIA (*(struct __6526*)0xDC00) +#define CIA2 (*(struct __6526*)0xDC00) #include <_6551.h> #define ACIA (*(struct __6551*)0xDD00) @@ -118,6 +118,7 @@ /* The addresses of the static drivers */ +extern void cbm510_joy_mou[]; /* Referred to by mouse_static_stddrv[] */ extern void cbm510_ram_emd[]; extern void cbm510_std_joy[]; /* Referred to by joy_static_stddrv[] */ extern void cbm510_std_ser[]; diff --git a/libsrc/cbm510/mcbdefault.s b/libsrc/cbm510/mcbdefault.s new file mode 100644 index 000000000..a6504ae30 --- /dev/null +++ b/libsrc/cbm510/mcbdefault.s @@ -0,0 +1,131 @@ +; +; Default mouse callbacks for the CBM510 (P128) +; +; 2004-03-20, Ullrich von Bassewitz2 +; 2013-06-25, Greg King +; +; All functions in this module should be interrupt-safe because they might +; be called from an interrupt handler. +; + + .export _mouse_def_callbacks + .import vic:zp + + .include "mouse-kernel.inc" + .include "cbm510.inc" + + .macpack generic + +; Sprite definitions. The first value can be changed to adjust the number +; of the sprite used for the mouse. All others depend on that value. +MOUSE_SPR = 0 ; Sprite used for the mouse +MOUSE_SPR_MASK = $01 .shl MOUSE_SPR ; Positive mask +MOUSE_SPR_NMASK = .lobyte(.not MOUSE_SPR_MASK) ; Negative mask +VIC_SPR_X = (VIC_SPR0_X + 2*MOUSE_SPR) ; Sprite X register +VIC_SPR_Y = (VIC_SPR0_Y + 2*MOUSE_SPR) ; Sprite Y register + +; -------------------------------------------------------------------------- +; Hide the mouse pointer. Always called with interrupts disabled. + +.proc hide + + ldy #15 + sty IndReg + + ldy #VIC_SPR_ENA + lda (vic),y + and #MOUSE_SPR_NMASK + sta (vic),y + + ldy ExecReg + sty IndReg + rts + +.endproc + +; -------------------------------------------------------------------------- +; Show the mouse pointer. Always called with interrupts disabled. + +.proc show + + ldy #15 + sty IndReg + + ldy #VIC_SPR_ENA + lda (vic),y + ora #MOUSE_SPR_MASK + sta (vic),y + + ldy ExecReg + sty IndReg + rts + +.endproc + +; -------------------------------------------------------------------------- +; Move the mouse pointer x position to the value in .XA. Always called with +; interrupts disabled. + +.proc movex + + ldy #15 + sty IndReg + +; Add the x correction; and, set the low byte. That frees .A. + + add #<24 ; x correction + ldy #VIC_SPR_X + sta (vic),y + +; Set the high byte + + ldy #VIC_SPR_HI_X + txa + adc #>24 + bnz @L1 ; Branch if high byte not zero + lda (vic),y ; Get high x bits of all sprites + and #MOUSE_SPR_NMASK ; Clear high bit for sprite + sta (vic),y + +@L0: ldy ExecReg + sty IndReg + rts + +@L1: lda (vic),y ; Get high x bits of all sprites + ora #MOUSE_SPR_MASK ; Set high bit for sprite + sta (vic),y + bnz @L0 ; branch always + +.endproc + +; -------------------------------------------------------------------------- +; Move the mouse pointer y position to the value in .XA. Always called with +; interrupts disabled. + +.proc movey + + ldy #15 + sty IndReg + + add #50 ; y correction (first visible line) + ldy #VIC_SPR_Y + sta (vic),y ; Set y position + + ldy ExecReg + sty IndReg + rts + +.endproc + +; -------------------------------------------------------------------------- +; Callback structure + +.rodata + +_mouse_def_callbacks: + .addr hide + .addr show + .addr movex + .addr movey + + diff --git a/libsrc/cbm510/mou/cbm510-joy.s b/libsrc/cbm510/mou/cbm510-joy.s new file mode 100644 index 000000000..7a98f8d39 --- /dev/null +++ b/libsrc/cbm510/mou/cbm510-joy.s @@ -0,0 +1,445 @@ +; +; Driver for a "joystick mouse". +; +; 2009-09-26, Ullrich von Bassewitz +; 2013-08-22, Greg King +; + + .include "zeropage.inc" + .include "../extzp.inc" + + .include "mouse-kernel.inc" + .include "cbm510.inc" + + .macpack generic + +; ------------------------------------------------------------------------ +; Header. Includes jump table + +.segment "JUMPTABLE" + +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 MOUSE_FLAG_LATE_IRQ + +; Callback table, set by the kernel before INSTALL is called. + +CHIDE: jmp $0000 ; Hide the cursor +CSHOW: jmp $0000 ; Show the cursor +CMOVEX: jmp $0000 ; Move the cursor to x co-ord. +CMOVEY: jmp $0000 ; Move the cursor to y co-ord. + + +;---------------------------------------------------------------------------- +; Constants + +SCREEN_HEIGHT = YSIZE * 8 +SCREEN_WIDTH = XSIZE * 8 + +.scope JOY + UP = %00000001 + DOWN = %00000010 + LEFT = %00000100 + RIGHT = %00001000 + FIRE = %00010000 +.endscope + +;---------------------------------------------------------------------------- +; Global variables. The bounding box values are sorted so that they can be +; written with the least effort in the SETBOX and GETBOX routines; so, don't +; re-order them. + +.bss + +Vars: +YPos: .res 2 ; Current mouse position, y +XPos: .res 2 ; Current mouse position, x +XMin: .res 2 ; X1 value of bounding box +YMin: .res 2 ; Y1 value of bounding box +XMax: .res 2 ; X2 value of bounding box +YMax: .res 2 ; Y2 value of bounding box + +; Temporary value used in the interrupt handler + +Temp: .res 1 + +; Default values for above variables + +.rodata + +.proc DefVars + .word SCREEN_HEIGHT / 2 ; YPos + .word SCREEN_WIDTH / 2 ; XPos + .word 0 ; XMin + .word 0 ; YMin + .word SCREEN_WIDTH - 1 ; XMax + .word SCREEN_HEIGHT - 1 ; YMax +.endproc + +.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: + +; Initiate variables; just copy the default stuff over. + + ldx #.sizeof(DefVars) - 1 +@L1: lda DefVars,x + sta Vars,x + dex + bpl @L1 + +; Be sure the mouse cursor is invisible and at the default location. We +; need to do that here because our mouse interrupt handler doesn't 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 hiding the mouse cursor. +; No return code required. + +HIDE: sei + jsr CHIDE + cli + rts + +;---------------------------------------------------------------------------- +; 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: sei + jsr CSHOW + cli + rts + +;---------------------------------------------------------------------------- +; 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 currently is 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 + + ldy #.sizeof (MOUSE_BOX) - 1 + sei + +@L1: lda (ptr1),y + sta XMin,y + dey + bpl @L1 + + 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 + + ldy #.sizeof (MOUSE_BOX) - 1 + +@L1: lda XMin,y + sta (ptr1),y + dey + bpl @L1 + + rts + +;---------------------------------------------------------------------------- +; MOVE: Move the mouse to a new position. The 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 if the new position is valid (within the bounding box or +; the screen). No return code required. +; + +MOVE: sei ; No interrupts + + jsr MoveY ; Set new y position + + ldy #1 + lda (sp),y + sta XPos+1 + tax + dey + lda (sp),y + jsr MoveX ; Move the pointer + + cli ; Allow interrupts + rts + +;---------------------------------------------------------------------------- +; BUTTONS: Return the button mask in .XA. +; Joystick 2's fire button is the left mouse button. +; Joystick 1's fire button is the right mouse button. + +BUTTONS: + ldx #15 ; Switch to the system bank + stx IndReg + +; Get the fire-button bits + + ldy #CIA::PRA + lda (cia2),y + +; Switch back to the execution bank. + + ldy ExecReg + sty IndReg + +; Joystick 2, fire button is in bit 7. +; Joystick 1, fire button is in bit 6. + + and #%11000000 + rol a ; Move bits 7,6 to bits 1,0 + rol a + rol a + adc #%00001110 ; Move bit 1 to bit 4 + and #MOUSE_BTN_LEFT | MOUSE_BTN_RIGHT + +; Bits go up when buttons go down. + + eor #MOUSE_BTN_LEFT | MOUSE_BTN_RIGHT + ldx #>0 + rts + +;---------------------------------------------------------------------------- +; 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 +; use _mouse_pos to fill the position fields. + +INFO: jsr BUTTONS + +; Fill in the button state. + + ldy #MOUSE_INFO::BUTTONS + sta (ptr1),y + +; jmp POS ; Fall through + +;---------------------------------------------------------------------------- +; 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 + +;---------------------------------------------------------------------------- +; 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 + rts + +;---------------------------------------------------------------------------- +; IRQ: Irq.-handler entry point. Called as a subroutine, but in the 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. +; Reads joystick 2. +; + +IRQ: ldy #15 ; Switch to the system bank + sty IndReg + +; Get the direction bits. + + ldy #CIA::PRB + lda (cia2),y ; Read joystick inputs + +; Switch back to the execution bank. + + ldy ExecReg + sty IndReg + +; Joystick 2, directions in bits 7-4. +; Mask the relevant bits. + + and #$F0 + eor #$F0 ; All bits are inverted + sta Temp + +; Check left/right. + + and #(JOY::LEFT | JOY::RIGHT) << 4 + bze @SkipX + +; We will cheat here, and rely on the fact that either the left OR the right +; bit can be active. + + and #JOY::RIGHT << 4 ; Check RIGHT bit + bnz @Right + lda #<-1 + tax + bnz @AddX ; Branch always +@Right: lda #<1 + ldx #>1 + +; Calculate the new x co-ordinate (--> .YA). + +@AddX: add XPos + tay ; Remember low byte + txa + adc XPos+1 + tax + +; Limit the x co-ordinate to the bounding box. + + cpy XMin + sbc XMin+1 + bpl @L1 + ldy XMin + ldx XMin+1 + jmp @L2 + +@L1: txa + cpy XMax + sbc XMax+1 + bmi @L2 + ldy XMax + ldx XMax+1 +@L2: tya + jsr MoveX + +; Calculate the y movement vector. + +@SkipX: lda Temp ; Get joystick again + and #(JOY::UP | JOY::DOWN) << 4 ; Check up/down + bze @SkipY + +; We will cheat here, and rely on the fact that either the up OR the down +; bit can be active. + + and #JOY::UP << 4 ; Check UP bit + bze @Down + lda #<-1 + tax + bnz @AddY +@Down: lda #<1 + ldx #>1 + +; Calculate the new y co-ordinate (--> .YA). + +@AddY: add YPos + tay ; Remember low byte + txa + adc YPos+1 + tax + +; Limit the y co-ordinate to the bounding box. + + cpy YMin + sbc YMin+1 + bpl @L3 + ldy YMin + ldx YMin+1 + jmp @L4 + +@L3: txa + cpy YMax + sbc YMax+1 + bmi @L4 + ldy YMax + ldx YMax+1 +@L4: tya + jsr MoveY + +; Done + +@SkipY: clc ; Interrupt not handled + rts + +; Move the mouse pointer to the new x pos. + +MoveX: sta XPos + stx XPos+1 + jmp CMOVEX + +; Move the mouse pointer to the new y pos. + +MoveY: sta YPos + stx YPos+1 + jmp CMOVEY diff --git a/libsrc/cbm510/mouse_stat_stddrv.s b/libsrc/cbm510/mouse_stat_stddrv.s new file mode 100644 index 000000000..71eec00ee --- /dev/null +++ b/libsrc/cbm510/mouse_stat_stddrv.s @@ -0,0 +1,13 @@ +; +; Address of the static standard mouse driver +; +; 2012-11-01, Oliver Schmidt +; 2013-08-06, Greg King +; +; const void mouse_static_stddrv[]; +; + + .export _mouse_static_stddrv + .import _cbm510_joy_mou + +_mouse_static_stddrv := _cbm510_joy_mou diff --git a/libsrc/cbm510/mouse_stddrv.s b/libsrc/cbm510/mouse_stddrv.s new file mode 100644 index 000000000..7f6ec42a2 --- /dev/null +++ b/libsrc/cbm510/mouse_stddrv.s @@ -0,0 +1,16 @@ +; +; Name of the standard mouse driver +; +; 2009-09-11, Ullrich von Bassewitz +; 2013-06-25, Greg King +; +; const char mouse_stddrv[]; +; + + .export _mouse_stddrv + +.rodata + +_mouse_stddrv: .asciiz "cbm510-joy.mou" + + diff --git a/libsrc/cbm510/mouseref.s b/libsrc/cbm510/mouseref.s new file mode 100644 index 000000000..90aeedf3a --- /dev/null +++ b/libsrc/cbm510/mouseref.s @@ -0,0 +1,23 @@ +; +; Pointer for library references by device drivers. +; +; 2013-07-25, Greg King +; + + .export mouse_libref, _pen_adjuster + + .data + +mouse_libref: ; generic label for mouse-kernel + +; A program optionally can set this pointer to a function that gives +; a calibration value to a driver. If this pointer isn't NULL, +; then a driver that wants a value can call that function. +; +; The function might read a value from a file; or, it might ask the user +; to help calibrate the driver. +; +; void __fastcall__ (*pen_adjuster)(unsigned char *) = NULL; +; +_pen_adjuster: + .addr $0000 -- 2.39.5