DEV-SNIP #1 - Input
DEV-SNIP #1 - Input
All programs need input. All zeddies have a keyboard. Great! With the availability of peripherals with joystick connections then the world of user input is looking richer than ever. With great richness comes great complexity however.
Here is my humble submission in the category of a nice general purpose input routine, where input from a number of devices is focused into a few simple values which can tell you whether an input is:
* just activated
* held
* just released
* not activated
It's currently specialised for ZXpand but it's easily updated to work with, for example, Chroma or (I still don't believe they exist) Kempston
Here is my humble submission in the category of a nice general purpose input routine, where input from a number of devices is focused into a few simple values which can tell you whether an input is:
* just activated
* held
* just released
* not activated
It's currently specialised for ZXpand but it's easily updated to work with, for example, Chroma or (I still don't believe they exist) Kempston
Re: DEV-SNIP #1 - Input
Code for BRASS assembler.
Code: Select all
readinput:
call $1ffe ; get the joystick bits by calling ZXpand ROM function - this will crash with no ZXpand present
; UDLRF---
or %00000111
ld (LAST_J),a
ld de,kbin ; read the keyboard, building a table at (de)
ld c,$fe
ld b,8
-: ld a,c ; read each of the 8 half rows
in a,($fe)
ld (de),a
rlc c
inc de
djnz {-}
; point at first input state block
;
ld hl,inputstates
call updateinputstate ; (up)
call updateinputstate ; (down)
call updateinputstate ; etc.
call updateinputstate ;
call updateinputstate
call updateinputstate
; fall into here for last input - quit
updateinputstate:
ld a,(hl) ; input info table
ld (uibittest),a ; get opcode for j/s bit test
inc hl
ld a,(hl) ; half-row index
inc hl
ld de,kbin ; keyboard bits table pointer - 8 byte aligned
or e
ld e,a ; add offset to table
ld a,(de) ; get key input bits
and (hl) ; result will be a=0 if required key is down
inc hl
jr z,{+} ; skip joystick read if pressed
ld a,(LAST_J)
+: sla (hl) ; (key & 3) = 0 - not pressed, 1 - just pressed, 2 - just released and >3 - held
uibittest = $+1
and 0 ; if a key was already detected a will be 0 so this test succeeds
jr nz,{+} ; otherwise joystick bit is tested - skip if bit = 1 (not pressed)
set 0,(hl) ; signify impulse
+: inc hl ; ready for next input in table
ret
.align 8
kbin:
.byte 0,0,0,0,0,0,0,0 ; storage for keyboard half-rows
LAST_J:
.byte 0 ; storage for last joystick value
; ----- 4 3 2 1 0
;
; $FE - V, C, X, Z, SH 0
; $FD - G, F, D, S, A 1
; $FB - T, R, E, W, Q 2
; $F7 - 5, 4, 3, 2, 1 3
; $EF - 6, 7, 8, 9, 0 4
; $DF - Y, U, I, O, P 5
; $BF - H, J, K, L, NL 6
; $7F - B, N, M, ., SP 7
;
; joystick bit, or $ff/%11111111 for no joy
; key row offset 0-7,
; key mask,
; input impulse
inputstates:
.byte %10000000,2,%00000001,0 ; up (Q)
.byte %01000000,1,%00000001,0 ; down (A)
.byte %00100000,7,%00001000,0 ; left (N)
.byte %00010000,7,%00000100,0 ; right (M)
.byte %00001000,7,%00000001,0 ; fire (SP)
.byte %11111111,3,%00000001,0 ; advance (1)
.byte %11111111,0,$00000101,0 ; quit (SH+X)
; calculate actual input impulse addresses
up = inputstates + 3
down = inputstates + 7
left = inputstates + 11
right = inputstates + 15
fire = inputstates + 19
advance = inputstates + 23
quit = inputstates + 27
Re: DEV-SNIP #1 - Input
How it's used.
From the main program call readinput once per frame. The variables declared at the end of the code snippet point to bytes in memory where the current control state may be read.
If the value is 0, then no control is active.
If the value is 1, then a control associated with the trigger have just activated.
If the value is 3, then the controls associated with the trigger are still activated.
If the value is 2, then the controls associated with the trigger are just deactivated.
How it works.
Each trigger can have a joystick direction and key associated with it. The current input state is represented by bit 0 of the trigger value. The previous state is represented by the value of bit 1.
The state of a key is determined by specifying a half-row index and a bit mask. These correspond to the keyboard matrix and the table of keys and their values are shown in the table in the comment in the code. Columns show the bit number to test in the half-row, which are labelled in the diagram's rows.
The joystick direction is determined by specifying a bit mask used in some self modifying code that tests a bit in the joystick value.
The settings for an input are specified in the 'inputstates' structure like so:
Here is the 'up' trigger. It's associated with bit 7 of the joystick value. It is also available by pressing Q - which appears in half-row 2, at bit 0:
The beauty of setting things up like this is that:
* input is all in one place
* redefining input is fairly simple, change the definition table
* different phases of the input can be detected easily so no external logic for one-shots is required
... and probably other stuff too.
I hope this code is useful.
From the main program call readinput once per frame. The variables declared at the end of the code snippet point to bytes in memory where the current control state may be read.
If the value is 0, then no control is active.
If the value is 1, then a control associated with the trigger have just activated.
If the value is 3, then the controls associated with the trigger are still activated.
If the value is 2, then the controls associated with the trigger are just deactivated.
Code: Select all
; do something if UP pressed
ld a,(up)
or a
jr nz,up
; fire only when fire button first pressed
ld a,(fire)
cp 1
jr z,dofire
Each trigger can have a joystick direction and key associated with it. The current input state is represented by bit 0 of the trigger value. The previous state is represented by the value of bit 1.
The state of a key is determined by specifying a half-row index and a bit mask. These correspond to the keyboard matrix and the table of keys and their values are shown in the table in the comment in the code. Columns show the bit number to test in the half-row, which are labelled in the diagram's rows.
The joystick direction is determined by specifying a bit mask used in some self modifying code that tests a bit in the joystick value.
The settings for an input are specified in the 'inputstates' structure like so:
Code: Select all
.byte %10000000,2,%00000001,0 ; up (Q)
Code: Select all
; ----- 4 3 2 1 0
;
; $FE - V, C, X, Z, SH 0
; $FD - G, F, D, S, A 1
; $FB - T, R, E, W, Q 2
...
* input is all in one place
* redefining input is fairly simple, change the definition table
* different phases of the input can be detected easily so no external logic for one-shots is required
... and probably other stuff too.
I hope this code is useful.
- 1024MAK
- Posts: 5153
- Joined: Mon Sep 26, 2011 10:56 am
- Location: Looking forward to summer in Somerset, UK...
Re: DEV-SNIP #1 - Input
Before finding this forum, I didn't think any users of ZX81's existed anymore....
Let alone that there was new software and hardware being developed
(Maybe I should go looking for some fairies at the bottom of the garden now that the "nights are drawing in"... well, after a few pints...)
Kempston joystick interfaces (or compatible interfaces) is, I presume, what is being referred to. Kempston joystick interfaces that have a ZX81 sized edge-connector and which fit AND work do exist.
It's most likely that they were not made or marketed for the ZX81, but that ZX81 sized edge-connectors were a bit cheaper than ZX Spectrum sized edge-connectors...
Of course, the cheapest joystick "interface",is to wire up a 9 way D-connector to the keyboard matrix via soldering wires to the solder connections on the keyboard sockets...
Mark
ZX81 Variations
ZX81 Chip Pin-outs
ZX81 Video Transistor Buffer Amp
Standby alert
There are four lights!
Step up to red alert. Sir, are you absolutely sure? It does mean changing the bulb
Looking forward to summer later in the year.
ZX81 Chip Pin-outs
ZX81 Video Transistor Buffer Amp
Standby alert
There are four lights!
Step up to red alert. Sir, are you absolutely sure? It does mean changing the bulb
Looking forward to summer later in the year.
Re: DEV-SNIP #1 - Input
Glad to see my trap worked first time Mark
If anyone wants to donate an interface for testing purposes..!
If anyone wants to donate an interface for testing purposes..!
Re: DEV-SNIP #1 - Input
Is this a routine that gets both a joystick direction and a key back?
Can it be used for plain keyboard read, or is it only for joystick read?
Will it work for simple keybord read on hardware that is not ZXpand, or is it ZXpand specific ports?
Re: DEV-SNIP #1 - Input
Cool, very cool...
Cheers Andy
Cheers Andy
what's that Smell.... smells like fresh flux and solder fumes...
Re: DEV-SNIP #1 - Input
Hi Martin. It is for game-style input, where a control/trigger is attached to a particular key and/or joystick direction. It can be used for keys only, or joystick only if desired. Specify $ff/%11111111 for either of the masks. In the example there are 2 keys which don't have a joystick equivalent.
Only the joystick is ZXpand specific. The keyboard reading is Sinclair standard. No specific hardware required
Whaythenkyew
Re: DEV-SNIP #1 - Input
@Charlie
If you genuinely need a j/stk interface I have a pukka Kempston speccy one and a no-name ZX81 interface with ZX81 edge connector, you can have with my blessings.
Never used them so have to guess they are ok.
If you genuinely need a j/stk interface I have a pukka Kempston speccy one and a no-name ZX81 interface with ZX81 edge connector, you can have with my blessings.
Never used them so have to guess they are ok.
Last edited by Moggy on Tue Nov 14, 2017 3:13 pm, edited 3 times in total.
Re: DEV-SNIP #1 - Input
So if I use this routine in my program without ZXpand it will crash because I don't have ZXpand?