Mouse/Trackball
This page was last modified 22:45, 13 August 2017 by Sd snatcher. Based on work by Flyguille and NYYRIKKI.

The mouse and trackball use a different low-level protocols to communicate with the MSX. But the BIOS abstracts this difference internally, so they are both handled same way when using the BIOS calls.


Contents

MSX-BIOS programmer interface

It's easy to read the mouse using the MSX-BIOS. The programmer just need to use the following functions:

  • GTPAD (00DBh)
    • Function 12 = Fetch the mouse data from joystick port 1. Returns FFh on current implementations.
    • Function 13 = Get touchpad X coordinate
    • Function 14 = Get touchpad Y coordinate
    • Function 15 = Reserved for future use. Always return 0 on current implementations.
    • Function 16 = Fetch the mouse data from joystick port 2. Returns FFh on current implementations.
    • Function 17 = Get touchpad X coordinate
    • Function 18 = Get touchpad Y coordinate
    • Function 19 = Reserved for future use. Always return 0 on current implementations.
  • System variables
    • XSAVE (FAFEh): X coordinate fetched by NEWPAD
    • YSAVE (FB00h): Y coordinate fetched by NEWPAD

Notes:

  • By default, existing MSX1 computers will return 0 for the mouse coordinate fetch functions (meaning that no mouse driver is present), and MSX2/2+/TR will return FFh.
  • GTPAD will internally redirect these functions to the routine NEWPAD (01ADh) in the subROM.
  • XSAVE and YSAVE are caches for used by NEWPAD to fetch coordinates from any devices it handles. They'll be overwritten by every call to a function of NEWPAD that fetches coordinates from the devices.

Example of usage of mouse with BIOS-calls

Please note: This routine does not work on MSX1. (See direct usage of mouse)

        ; BASIC header
 
	DB #FE
	DW BEGIN
	DW END
	DW INIT
	ORG #C000
 
;--------------------------
 
BEGIN:
 
GTPAD:  EQU #DB
SETWRT: EQU #53
LDIRVM: EQU #5C
CHGMOD: EQU #5F
 
SPRATT: EQU #F928
SPRGEN: EQU #F926
FORCLR: EQU #F3E9
HINT:   EQU #FD9F
 
XPOS:   DB 128
YPOS:   DB 96
PORT:   DB 12
BUSY:   DB 0
 
SPRITE:
        DB %0001000
        DB %0001000
        DB %0001000
        DB %1110111
        DB %0001000
        DB %0001000
        DB %0001000
        DB 0
INIT:
        DI
        ;Select mouse port
        CALL SELECTPORT
 
        ; Set colors
        LD HL,FORCLR
        LD (HL),15
        INC HL
        LD (HL),0
        INC HL
        LD (HL),0
 
        ; Change screenmode
        LD A,1
        CALL CHGMOD
 
        ; Copy sprite outlook
 
        LD HL,SPRITE
        LD DE,(SPRGEN)
        LD BC,8
        CALL LDIRVM
 
        ; Setup interrupt hook
        LD HL,HINT
        LD DE,STORE
        LD BC,5
        LDIR
        LD HL,INTERRUPT
        LD DE,HINT
        LD BC,3
        LDIR
        RET
 
SELECTPORT:
        ; Autodetect mouse port
        CALL READMOUSE
        DEC D
        RET NZ
        DEC E
        RET NZ
        LD A,16
        LD (PORT),A
        RET
 
 
 
READMOUSE:
        ; Read mouse position (relative to previous position)
        ; OUT E = X
        ; OUT D = Y
 
        LD A,(PORT)
        PUSH AF
        CALL GTPAD
        POP AF
        ADD A, 2
        PUSH AF
        CALL GTPAD
        POP DE
        PUSH AF
        LD A, D
        DEC A
        CALL GTPAD
        POP DE
        LD E,A
        RET
 
INTERRUPT:
        ; This will be copied to interrupt hook
        JP HANDLER
 
HANDLER:
        ; This is actual interrupt handler routine
        LD A,(BUSY)
        AND A
        RET NZ
        LD A,255
        LD (BUSY),A
 
        CALL READMOUSE
        LD HL,(XPOS)
        CALL CLIPADD
        LD (XPOS),HL
 
        DI
        LD DE,(SPRATT)
        EX DE,HL
        CALL SETWRT
 
        LD A,D
        SUB 4
        OUT (#98),A   ; Sprite Y
        LD A,E
        SUB 4
        LD C,8        ; Color
        JR NC,.NOEC
        ADD A,32
        LD C,8+128    ; Color + EC
.NOEC:
        OUT (#98),A   ; Sprite X
        LD A,0
        OUT (#98),A   ; Sprite number
        LD A,C
        OUT (#98),A   ; Color + [EC]
 
        XOR A
        LD (BUSY),A
 
STORE:
        ; Here is space for old interrupt handler from the interrupt hook
        DB 0,0,0,0,0
        RET
 
 
CLIPADD:
        ; Make sure that mouse pointer stays inside visible screen area
        LD A,L
        LD B,E
        CALL LIMITADD
        LD L,A
        LD A,H
        LD B,D
        CALL LIMITADD
        LD H,A
        CP 191
        RET C
        LD H,191
        RET
 
LIMITADD:
 
; Clip mouse pointer to 0..255
; In:  A = mouse position 0..255
;      B = mouse move -128..+127
; Out: A = new mouse position 0..255
 
 
	SUB	128		; move from range 0..255 to -128..+127
	ADD	B		; add mouse offset, both numbers are signed
	JP	PE,.CLIP	; pe -> previous instruction caused a signed overflow
	ADD	128		; move back to range 0..255
	RET			;
.CLIP:	LD	A,B		; get mouse offset
	CPL			; flip all bits (only bit 7 matters)
	ADD	A,A		; move bit 7 to carry flag
	SBC	A,A		; carry set -> a=255   carry not set -> a=0
	RET			;
 
 
 
END:

Direct usage of mouse

Mouse related BIOS-calls are not available on MSX1, so in this case you need to handle mouse directly. Here is example of how to do that. Note that the trackball uses a different protocol and need a specific routine.

; A routine  to read the mouse:
;
;
;        LD    D,&B10010011     ; Use these values for a mouse in port 1
;        LD    E,&B00010000 
; 
;
;        LD    D,&B11101100     ; Use these values for a mouse in port 2
;        LD    E,&B00100000
;
; Read the mouse.   Input: D/E=.... Output: H=X-offset, L=Y-offset
; Note that the routine will output H=L=255 if no mouse is present!
GTMOUS:
 
        LD    B,WAIT2          ; Long delay for first read
        CALL  GTOFS2          ; Read bit 7-4 of the x-offset
        AND   0FH
        RLCA
        RLCA
        RLCA
        RLCA
        LD    C,A
        CALL  GTOFST          ; Read bit 3-0 of the x-offset
        AND   0FH
        OR    C
        LD    H,A             ; Store combined x-offset
        CALL  GTOFST          ; Read bit 7-4 of the y-offset
        AND   0FH
        RLCA
        RLCA
        RLCA
        RLCA
        LD    C,A
        CALL  GTOFST          ; Read bit 3-0 of the y-offset
        AND   0FH
        OR    C
        LD    L,A             ; Store combined y-offset
        RET
 
WAIT1:  EQU   10              ; Short delay value
WAIT2:  EQU   30              ; Long delay value
 
GTOFST: LD    B,WAIT1
GTOFS2: LD    A,15            ; Read psg register 15 voor mouse
        OUT   (0A0H),A
        LD    A,D
        OUT   (0A1H),A
        XOR   E
        LD    D,A
 
WAIT:   DJNZ  WAIT           ; Extra delay because the mouse is slow.
 
        LD    A,14
        OUT   (0A0H),A
        IN    A,(0A2H)
        RET



Extended mouse protocol (2014)

This protocol is defined by NYYRIKKI & Prodatron in 2014. Currently only SymbOS 2.1 supports this extended protocol. This is MSX-BIOS compatible without need to modify existing software, but to use the extended features, you need to use external driver.

Communication is done 4bits (nibble) at a time using pin 8 as clock. High nibble will be sent always first. This is same way as in original MSX-mouse protocol, but there are two extra bytes added to the end.

Here is description of all the bytes sent by mouse:

Byte 1: X-axis signed delta (Original protocol) Positive value means mouse is moved to Left.

Byte 2: Y-axis signed delta (Original protocol) Positive value means mouse is moved to Up.

Byte 3 high nibble = ID nibble: (bits 7-4) = 0001
	bits 7 & 6 are "00" for MSX-BIOS mouse identification
	bits 5 & 4 are "01 "for Extended mouse protocol identification

Byte 3 low nibble = Button nibble:
	bit 3 : 0 = Unused, reserved for future (to expand ID or to support additional button)
	bit 2 : 5th mouse button: 0=Not pressed, 1=Pressed
	bit 1 : 4th mouse button: 0=Not pressed, 1=Pressed
	bit 0 : 3rd button (wheel button): 0=Not pressed, 1=Pressed

Byte 4: Z-axis signed delta. Positive value means wheel is moved to Up

Please note:

  • If bytes 3/4 are not read within 3 ms (counting starts from reading of 1st byte) mouse will return 1st byte on next read. (This is to improve compatibility with existing software)
  • Minimum time between clocks is 0.18 ms.


Trackball

With pins 1-4 the trackball sends out X when pin 8 is set and Y when pin 8 is reset. The data format is signed nibble. Trackball's corresponding internal counter is reset when pin 8 is toggled. (Detailed explanation needed)