From: Christian Groessler Date: Fri, 3 Jan 2014 22:40:22 +0000 (+0100) Subject: Add "joystick mouse" driver and default mouse callback routine (not X-Git-Tag: V2.15~196^2~16 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=a5dfce7c416b587b456286c11feaf4ac139feb67;p=cc65 Add "joystick mouse" driver and default mouse callback routine (not using P/M graphics). --- diff --git a/libsrc/atari/libref.s b/libsrc/atari/libref.s index 8d96ff62d..e6b9df6a5 100644 --- a/libsrc/atari/libref.s +++ b/libsrc/atari/libref.s @@ -2,12 +2,13 @@ ; Oliver Schmidt, 2013-05-31 ; - .export em_libref, joy_libref, tgi_libref, ser_libref + .export em_libref, joy_libref, tgi_libref, ser_libref, mouse_libref .import _exit .import atari_ser_libref em_libref := _exit joy_libref := _exit +mouse_libref := _exit ser_libref := atari_ser_libref .ifdef __ATARIXL__ .import CIO_handler diff --git a/libsrc/atari/mcbdefault.s b/libsrc/atari/mcbdefault.s new file mode 100644 index 000000000..91e920ac4 --- /dev/null +++ b/libsrc/atari/mcbdefault.s @@ -0,0 +1,114 @@ +; +; Default mouse callbacks for the Ataris +; +; Christian Groessler, 03.01.2014 +; +; derived from Apple2 version by +; Oliver Schmidt, 22.09.2005 +; +; All functions in this module should be interrupt safe, because they may +; be called from an interrupt handler +; + + .export _mouse_def_callbacks + .importzp tmp4 + .import mul40,loc_tmp + + .include "atari.inc" + +; ------------------------------------------------------------------------ + + .bss + +backup: .res 1 +helper: .res 2 + +; ------------------------------------------------------------------------ + + .segment "EXTZP" : zeropage +scrptr: .res 2 + +; ------------------------------------------------------------------------ + + + .rodata + + ; Callback structure +_mouse_def_callbacks: + .addr hide + .addr show + .addr movex + .addr movey + +; ------------------------------------------------------------------------ + + .data + +cursor = 11 ; '+' screen code' + +; setcursor + +getcursor: +column: ldy #$00 ; Patched at runtime + lda (scrptr),y ; Patched at runtime + cmp #cursor + rts + +setcursor: + lda #cursor +setscr: sta (scrptr),y ; Patched at runtime + rts + +; ------------------------------------------------------------------------ + + .code + +done: + rts + +; Hide the mouse cursor. +hide: + jsr getcursor ; Cursor visible at current position? + bne done ; No, we're done + lda backup ; Get character at cursor position + jmp setscr ; Draw character + +; Show the mouse cursor. +show: + jsr getcursor ; Cursor visible at current position? + beq done ; Yes, we're done + sta backup ; Save character at cursor position + jmp setcursor ; Draw cursor + + +; Move the mouse cursor x position to the value in A/X. +movex: + cpx #0 + cpx #1 + ror a + lsr a ; convert to character position + lsr a + sta column+1 + rts + +; Move the mouse cursor y position to the value in A/X. +movey: + tax + ldy tmp4 ; mul40 uses tmp4 + lda loc_tmp ; and this local variable + pha + txa ; get parameter back + lsr a ; convert y position to character line + lsr a + lsr a + jsr mul40 + clc + adc SAVMSC + sta scrptr + txa + adc SAVMSC+1 + sta scrptr+1 + pla + sta loc_tmp + sty tmp4 + rts diff --git a/libsrc/atari/mou/atrjoy.s b/libsrc/atari/mou/atrjoy.s new file mode 100644 index 000000000..1a5afa71a --- /dev/null +++ b/libsrc/atari/mou/atrjoy.s @@ -0,0 +1,443 @@ +; +; Driver for a "joystick mouse". +; +; C128 version: Ullrich von Bassewitz, 2004-04-05, 2009-09-26 +; Adapted to Atari: Christian Groessler, 2014-01-02 +; + + .include "zeropage.inc" + .include "mouse-kernel.inc" + .include "atari.inc" + + .macpack generic + +; ------------------------------------------------------------------------ +; Header. Includes jump table + +.segment "JUMPTABLE" + +HEADER: + +; Driver signature + + .byte $6d, $6f, $75 ; "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 coord +CMOVEY: jmp $0000 ; Move the cursor to Y coord + + +;---------------------------------------------------------------------------- +; Constants + +SCREEN_HEIGHT = 191 +SCREEN_WIDTH = 319 + +.enum JOY + UP = $01 + DOWN = $02 + LEFT = $04 + RIGHT = $08 +.endenum + +;---------------------------------------------------------------------------- +; 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 +; reorder 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 +Buttons: .res 1 ; Button mask + + +Temp: .res 1 ; Temporary value used in the int handler +visible: .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 ; XMax + .word SCREEN_HEIGHT ; YMax + .byte 0 ; Buttons +.endproc + +.code + +;---------------------------------------------------------------------------- +; INSTALL routine. Is called after the driver is loaded into memory. If +; possible, check if the hardware is present. +; Must return an MOUSE_ERR_xx code in a/x. + +INSTALL: + +; Initialize 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 (= MOUSE_ERR_OK) + + ldx #$00 + 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 only called +; if the mouse is currently visible and should get hidden. For most drivers, +; no special action is required besides hiding the mouse cursor. +; No return code required. + +HIDE: dec visible + 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 only called +; if the mouse is currently hidden and should become visible. For most drivers, +; no special action is required besides enabling the mouse cursor. +; No return code required. + +SHOW: inc visible + 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 a/x. +; No checks are done if the mouse is currently inside the box, this 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 a/x. + +GETBOX: sta ptr1 + stx ptr1+1 ; Save data pointer + + ldy #.sizeof (MOUSE_BOX)-1 + sei + +@L1: lda XMin,y + sta (ptr1),y + dey + bpl @L1 + + cli + 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 a/x. 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 + + pha + txa + pha + jsr CHIDE + pla + tax + pla + + 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 + + lda visible + beq @Ret + + jsr CSHOW + +@Ret: cli ; Allow interrupts + rts + +;---------------------------------------------------------------------------- +; BUTTONS: Return the button mask in a/x. + +BUTTONS: + lda Buttons + ldx #$00 + 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 will just +; call _mouse_pos to initialize the struct pointer and fill the position +; fields. + +INFO: jsr POS + +; Fill in the button state + + lda Buttons + 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 a/x. +; + +IOCTL: lda #MOUSE_ERR_INV_IOCTL +hlprts: rts + +;---------------------------------------------------------------------------- +; 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: + +; Check for a pressed button and place the result into Buttons + + ldx #0 + lda TRIG0 ; joystick #0 trigger + bne @L0 ; not pressed + ldx #MOUSE_BTN_LEFT +@L0: stx Buttons + + lda PORTA ; get joystick direction bits + and #15 ; clear joystick #1 bits + eor #15 + sta Temp + clc + beq hlprts ; no movement, do nothing + + jsr CHIDE + +; Check left/right + + lda Temp ; Read joystick #0 + and #(JOY::LEFT | JOY::RIGHT) + beq @SkipX ; + +; We will cheat here and rely on the fact that either the left, OR the right +; bit can be active + + and #JOY::RIGHT ; Check RIGHT bit + bne @Right + lda #$FF + tax + bne @AddX ; Branch always +@Right: lda #$01 + ldx #$00 + +; Calculate the new X coordinate (--> a/y) + +@AddX: add XPos + tay ; Remember low byte + txa + adc XPos+1 + tax + +; Limit the X coordinate 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: sty XPos + stx XPos+1 + +; Move the mouse pointer to the new X pos + + tya + jsr CMOVEX + +; Calculate the Y movement vector + +@SkipX: lda Temp ; Read joystick #0 + and #(JOY::UP | JOY::DOWN) ; Check up/down + beq @SkipY ; + +; We will cheat here and rely on the fact that either the up, OR the down +; bit can be active + + lsr a + bcc @Down + lda #$FF + tax + bne @AddY +@Down: lda #$01 + ldx #$00 + +; Calculate the new Y coordinate (--> a/y) + +@AddY: add YPos + tay ; Remember low byte + txa + adc YPos+1 + tax + +; Limit the Y coordinate 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: sty YPos + stx YPos+1 + +; Move the mouse pointer to the new X pos + + tya + jsr CMOVEY + +; Done + +@SkipY: lda visible + beq @Done + + jsr CSHOW + +@Done: clc ; Interrupt not "handled" + rts + diff --git a/libsrc/atari/mouse_stat_stddrv.s b/libsrc/atari/mouse_stat_stddrv.s new file mode 100644 index 000000000..18ebda9a2 --- /dev/null +++ b/libsrc/atari/mouse_stat_stddrv.s @@ -0,0 +1,22 @@ +; +; Address of the static standard mouse driver +; +; Christian Groessler, 2014-01-02 +; +; const void mouse_static_stddrv[]; +; + + .export _mouse_static_stddrv + .ifdef __ATARIXL__ + .import _atrxjoy_mou + .else + .import _atrjoy_mou + .endif + +.rodata + + .ifdef __ATARIXL__ +_mouse_static_stddrv := _atrxjoy_mou + .else +_mouse_static_stddrv := _atrjoy_mou + .endif diff --git a/libsrc/atari/mouse_stddrv.s b/libsrc/atari/mouse_stddrv.s new file mode 100644 index 000000000..443e53254 --- /dev/null +++ b/libsrc/atari/mouse_stddrv.s @@ -0,0 +1,18 @@ +; +; Name of the standard mouse driver +; +; Christian Groessler, 2014-01-02 +; +; const char mouse_stddrv[]; +; + + .export _mouse_stddrv + +.rodata + +_mouse_stddrv: + .ifdef __ATARIXL__ + .asciiz "ATRXJOY.MOU" + .else + .asciiz "ATRJOY.MOU" + .endif diff --git a/libsrc/atari/mul40.s b/libsrc/atari/mul40.s index b94ab5c52..96235bf6c 100644 --- a/libsrc/atari/mul40.s +++ b/libsrc/atari/mul40.s @@ -6,7 +6,7 @@ ; uses tmp4 .importzp tmp4 - .export mul40 + .export mul40,loc_tmp .proc mul40