MSX1 mouse control in asm

Por farique

Resident (39)

imagem de farique

17-11-2020, 20:54

Hi,
I've managed to implement Edwin's assembly mouse routine and it works but the sprite I'm controlling keeps randomly jumping 16 pixels in every direction. Can it be a stray bit somewhere?
I've been looking around but MSX1 mouse control in assembly seems to be a very sparse topic.
As GTPAD only seems to work on then MSX2 I'm stuck with Edwin's approach.
I'm using openMXS 0.15.0.

Here is my routine:

	ld    d,0x93 ; mouse number 1
	ld    e,0x10 ; mouse number 1
mouse:
	call gtmous ; the mouse reading routine

	ld a,(pos)
	sub a,h
	ld (pos),a
	ld a,(pos+1)
	sub a,l
	ld (pos+1),a

	ld a,(pos)
	ld hl,6913
	call wrtvrm
	ld hl,0x1800
	call wrtvrm

	ld a,(pos+1)
	ld hl,6912
	call wrtvrm
	ld hl,0x1801
	call wrtvrm

	jp mouse

Yes, I'm more than a little assembly impaired :P

EDIT:
Ok, I've done something very terrible, I've added this

	ld a,15
	cp h
	jp z,mouse

	ld a,240
	cp h
	jp z,mouse

	ld a,15
	cp l
	jp z,mouse

	ld a,240
	cp l
	jp z,mouse

right after call gtmous to filter the 15 bits jumps and it worked but come on, I feel dirty!

Entrar ou registrar-se para comentar

Por Juan Luis

Master (132)

imagem de Juan Luis

18-11-2020, 03:05

You can find a good description how to use mouse in MSX 1 and 2 with assembly examples here, in this web:

https://www.msx.org/wiki/Mouse/Trackball

Both methods of using mouse in MSX are explained.

Por farique

Resident (39)

imagem de farique

18-11-2020, 05:22

Thank you, Juan.
The MXS1 routine is almost the same I was using with some little modifications.
One thing I was suspecting was the interrupt and just adding the DI and EI from there did the trick. My approach seems to be still a tad more stable, however.

Por mzoran

Master (131)

imagem de mzoran

19-11-2020, 09:11

Thanks for bringing up this topic. Made me finally test a mouse with MSX1. But for completeness we should also save button states when reading deltas. So for anyone wishing to experiment in the future, a small MSX1 BASIC mouse test program.
First an assembly routine:

	org 0bff9h

	;.BIN header
	;byte 0   ID byte #FE
	;byte 1+2 start-address
	;byte 3+4 end-address
	;byte 5+6 execution-address
	db 0feh
	dw BLOAD_START_POINT 
	dw BLOAD_END_POINT
	dw BLOAD_EXEC_POINT

BLOAD_START_POINT:

MOUSE_DELTA_Y: DB 0
MOUSE_DELTA_X: DB 0
MOUSE_BUTTONS: DB 0

; Routine to read the mouse by direct accesses (works on MSX1/2/2+/turbo R)
;
; Input: DE = 09310h for mouse in port 1 (D = 10010011b, E = 00010000b)
; 	 DE = 0EC20h for mouse in port 2 (D = 11101100b, E = 00100000b)
; Output: H = X-offset, L = Y-offset (H = L = 255 if no mouse), 
; B = button state, bit 4 = 0 when left button pressed, bit 5 = 0 when right button pressed
 
WAIT1:  equ   10              ; Short delay value
WAIT2:  equ   30              ; Long delay value
 
GTMOUS:
	ld	b,WAIT2	; Long delay for first read
	call	GTOFS2	; Read bits 7-4 of the x-offset
	and	0Fh
	rlca
	rlca
	rlca
	rlca
	ld	c,a
	call	GTOFST	; Read bits 3-0 of the x-offset
	and	0Fh
	or	c
	ld	h,a	; Store combined x-offset
	call	GTOFST	; Read bits 7-4 of the y-offset
	and	0Fh
	rlca
	rlca
	rlca
	rlca
	ld	c,a
	call	GTOFST	; Read bits 3-0 of the y-offset
    ; pokusaj, spremi vrijednost i provijeri kasnije bitove
    ld b,a
	and 0Fh
	or c
	ld l,a		; Store combined y-offset
BLOAD_EXEC_POINT:
	ret
 
GTOFST:	ld b,WAIT1
GTOFS2:	ld a,15		; Read PSG register 15 for mouse
	di		; DI useless if the routine is used during an interrupt
	out (0A0h),a
	ld a,d
	out (0A1h),a
	xor e
	ld d,a
 
	call WAITMS	; Extra delay because the mouse is slow
 
	ld a,14
	out (0A0h),a
	ei		; EI useless if the routine is used during an interrupt
	in a,(0A2h)
	ret
WAITMS:
	ld	a,b
WTTR:
	djnz	WTTR
	db	0EDh,055h	; Back if Z80 (RETN on Z80, NOP on R800)
	rlca
	rlca
	ld	b,a
WTTR2:
	djnz	WTTR2
	ld	b,a	
WTTR3:
	djnz	WTTR3
	ret

READ_MOUSE1:
    ld de,09310h
    jr READ_MOUSE1_L1
READ_MOUSE2:
    ld de, 0EC20h
READ_MOUSE1_L1:
    call GTMOUS
    ld (MOUSE_DELTA_Y),hl
    ld a,b
    ld (MOUSE_BUTTONS),a 
    ret

BLOAD_END_POINT:

and the BASIC part:

10 'mouse test
20 'must bload mouse.bin
30 'to read mouse in port 1 call c04e
40 'to read mouse in port 2 call c053
50 'raw y delta at c000
60 'raw x delta at c001
70 'raw button state at c002
80 DEFUSR0=&HC053:DEFINT A-Z
90 SCREEN 2
100 A$=""
110 FOR I=1 TO 8
120 READ A:A$=A$+CHR$(A)
130 NEXT I
140 SPRITE$(0)=A$
150 A=USR(0)
160 TX=PEEK(&HC001):TY=PEEK(&HC000):T=PEEK(&HC002)
170 IF TX>128 THEN DX=256-TX ELSE DX=-TX
180 IF TY>128 THEN DY=256-TY ELSE DY=-TY
190 IF (T AND 16)>0 THEN LB=0 ELSE LB=1
200 IF (T AND 32)>0 THEN RB=0 ELSE RB=1
210 X=X+DX:Y=Y+DY
220 IF X>256 THEN X=256
230 IF X<0 THEN X=0
240 IF Y>192 THEN Y=192
250 IF Y<0 THEN Y=0
260 PUT SPRITE 0,(X-4,Y-4),15
270 IF RB=1 THEN X1=X:Y1=Y:GOTO 150
280 IF LB=0 GOTO 150
290 LINE (X1,Y1)-(X,Y):X1=X:Y1=Y
300 GOTO 150
310 DATA 16,16,16,238,16,16,16,0