Page 1 of 1

Kempston support

Posted: Tue Apr 09, 2024 8:14 pm
by sludge
How do you go about supporting Kempston joystick in games?

I think its IN 31 but I haven't a clue about the up/down/left/right/fire bits.

This is the routine I use for Sinclair (I think it will make sense), how would you adapt it for Kempston?

Code: Select all

Sinclair

		ld a,239
		ld (js1+1),a
		ld (downx+4),a
		ld (upx+4),a
		ld (leftx+4),a
		ld (js2+1),a
	
		ld a,2
		ld (stickup+1),a
		ld a,4
		ld (stickdown+1),a
		ld a,16
		ld (stickleft+1),a
		ld a,8
		ld (stickright+1),a

		ld a,$01
		ld (js3+1),a
		ret

Re: Kempston support

Posted: Tue Apr 09, 2024 8:27 pm
by PROSM
For the Kempston, you read from port 31. The received byte is as follows:

Code: Select all

000FUDLR

(F - fire, U - up, D - down, L - left, R - right)
The Kempston joystick input is active-high, meaning that if the button/direction is activated, the relevant bit will be 1. This is in contrast to the keyboard, which is active-low, where a pressed key will result in the relevant bit being 0.

Bear in mind that the three most significant bits might not necessarily be zero on every hardware setup, so it's best to mask away those bits like you would with the keyboard.

I'm afraid I don't know what's going on with the routine you've posted - there's no IN instructions to actually read the keyboard data, so presumably it's only part of a larger routine.

Re: Kempston support

Posted: Tue Apr 09, 2024 8:29 pm
by TomD
Easiest way to implement is:

Code: Select all

ld bc,0x001f
in a,(c)
then check which bit is set in a

fire is bit 4
up is bit 3
down is bit 2
left is bit 1
right is bit 0

Code: Select all

bit 4,a
jr nz,_thefireroutine
Some joysticks can have a second and even third fire button but they are rare.

TomD

Re: Kempston support

Posted: Tue Apr 09, 2024 8:38 pm
by sludge
Tried this but it wont work, character just keeps moving right.

Code: Select all

kempston

		ld a,31
		ld (js1+1),a
		ld (downx+4),a
		ld (upx+4),a
		ld (leftx+4),a
		ld (js2+1),a
	
		ld a,3
		ld (stickup+1),a
		ld a,2
		ld (stickdown+1),a
		ld a,1
		ld (stickleft+1),a
		ld a,0
		ld (stickright+1),a

		ld a,4
		ld (js3+1),a
		ret


Re: Kempston support

Posted: Tue Apr 09, 2024 8:40 pm
by sludge
Theres also this part:

Code: Select all

js1		ld a,239
		in a, (254)
Perhaps the 254 needs to change?

Re: Kempston support

Posted: Tue Apr 09, 2024 9:08 pm
by sludge
Ah right, I realised why I never bothered with Kempston, if no Kempston is present IN31 automatically reads it as fire being pressed.

That means the game starts automatically with Kempston controls even though no Kempston is connected.

Re: Kempston support

Posted: Tue Apr 09, 2024 9:17 pm
by TomD
sludge wrote: Tue Apr 09, 2024 9:08 pm Ah right, I realised why I never bothered with Kempston, if no Kempston is present IN31 automatically reads it as fire being pressed.

That means the game starts automatically with Kempston controls even though no Kempston is connected.
Following code from JetSet Willy checks if Kempston is connected

Code: Select all

	xor a
	ld (kempston),a	; reset kempston present flag
	ld bc,0x001f
	di
	xor a
loop:
	in e,(c)
	or e
	djnz loop	; check for all b's
	and %00100000	; checks if bit 5 set, will be zero if kempston present
	jr nz,end
	ld a,0x01
	ld (kempston),a	; set kempston present
end:

Re: Kempston support

Posted: Tue Apr 09, 2024 9:33 pm
by sludge
Cheers Tom, I'll have a play around with that routine.

Re: Kempston support

Posted: Tue Apr 09, 2024 10:36 pm
by ketmar
that's how i detect kempston joystick in my code. HL is 0 if no kemprson joystick present, 1 otherwise.

Code: Select all

  ld    hl, # 0
  ;; zero flag
  xor   a
  ;; wait for the interrupt to avoid floating bus issue
  halt
  in    a, () $1F
  ;; $FF? nothing's here
  inc   a
  \ jr    z, # .done
  ret   z
  ;; test for some invalid values
  dec   a
  ld    e, a
  and   # $E0
  \ jr    nz, # .done
  ret   nz
  ld    a, e
  and   # $03
  cp    # $03
  \ jr    z, # .done  ;; left & right pressed simultaneously. ???
  ret   z
  ld    a, e
  and   # $0C
  cp    # $0C
  \ jr    z, # .done  ;; up & down pressed simultaneously. ???
  ret   z
  inc   l           ;; change the flag
  ret
do not forget "HALT" instruction, it is important to not read some ULA garbage here.

Re: Kempston support

Posted: Wed Apr 10, 2024 1:48 am
by sludge
I'm still a bit flummoxed with the bits not working - perhaps the 254 part has something to do with it?

This is what I use on the title screen to load Kempston values into the game code:

Code: Select all

kempston

		ld a,31
		ld (js1+1),a
		ld (downx+4),a
		ld (upx+4),a
		ld (leftx+4),a
		ld (js2+1),a
	
		ld a,3
		ld (stickup+1),a
		ld a,2
		ld (stickdown+1),a
		ld a,1
		ld (stickleft+1),a
		ld a,0
		ld (stickright+1),a

		ld a,4
		ld (js3+1),a
		ret
This is part of the game code which is set up for Sinclair joystick:

Code: Select all

js2		ld a,239
		in a, (254)
js3		and 1
		call z,fire

js1		ld a,239
		in a, (254)

stickdown	
		and 4
		jr nz,downx

Re: Kempston support

Posted: Wed Apr 10, 2024 1:56 am
by ParadigmShifter
You're just loading the same value into several addresses?

Code: Select all

		ld a,31
		ld (js1+1),a
		ld (downx+4),a
		ld (upx+4),a
		ld (leftx+4),a
		ld (js2+1),a
are you thinking each bit is in fact a byte or something? I dunno. Your code is weird sorry!

Re: Kempston support

Posted: Wed Apr 10, 2024 2:05 am
by ParadigmShifter
Right I see you are trying to self modify the code to change IN 254 to IN 31. EDIT: Also reading from the same input port more than once a frame seems a bit pointless really... read it once per frame.

Well that's a bad plan tbh. Just have 2 routines. Remember the logic for keyboard and kempston (pressed = 0 for kbd, pressed = 1 for kempston) is opposite as well.

Only self modify code if it makes it faster or smaller. Your code looks like neither? You'd be better off with a function pointer to jump to a routine to handle keyboard or joystick as appropriate.

Re: Kempston support

Posted: Wed Apr 10, 2024 6:06 am
by sludge
Excuse my coding, it was written over thirty year ago on graph paper in a maths lesson. :-)

I've never got round to modifying that bit of the code although the rest of the game code isnt much better either.

My coding skills are quite shocking, I doubt I know how to use any more than twenty Z80 commands properly.

Re: Kempston support

Posted: Wed Apr 10, 2024 6:11 am
by ketmar
sludge wrote: Wed Apr 10, 2024 6:06 am My coding skills are quite shocking, I doubt I know how to use any more than twenty Z80 commands properly.
more than enough! "LD" alone occupies about 1/3 of the whole non-prefixed instruction set! ;-)

Re: Kempston support

Posted: Wed Apr 10, 2024 6:32 am
by sludge
ketmar wrote: Wed Apr 10, 2024 6:11 am more than enough! "LD" alone occupies about 1/3 of the whole non-prefixed instruction set! ;-)
True.

Re: Kempston support

Posted: Wed Apr 10, 2024 7:12 am
by R-Tape
sludge wrote: Wed Apr 10, 2024 1:48 am This is what I use on the title screen to load Kempston values into the game code:
It might be less confusing to have 3 separate routines rather than all that code poking. So e.g. on the intro page you have a byte that says what control option has been selected, the game code could look something like this:

Code: Select all

....main game loop
call playercontrol
....

playercontrol:
	ld a,(controlbyte)
	cp 0
	jr z,keys
	cp 1
	jr z,sinclair
	cp 2
	jr z,kempston
	
	

Re: Kempston support

Posted: Thu Apr 11, 2024 1:38 am
by ParadigmShifter
For more than a few cases of an IF statement like that I prefer function pointers e.g.

Code: Select all

ld hl, (controlmethod)
jp (hl)
DoneInput:
where controlmethod points to a routine that handles the specific input and ends with a jp DoneInput. jp (hl) is the fastest jump of all (4T!). Of course jp (hl) is a terrible name for the opcode it should be JP HL...

You can call a routine instead by doing this instead

Code: Select all

ld hl, (controlmethod)
call jphl
; will return to here

; elsewhere
jphl: jp (hl)
but that isn't as efficient (not that input matters really since it's a lot faster than drawing graphics etc.). You can even search through the ROM or your own data to find a byte that is same as jp (hl) (#E9 hex) so you don't need to waste a byte in your code :)