To say that adding joystick support was frustrating is an understatement!
There's not a whole lot of information on the net about sampling the joysticks, less still about reading the buttons, and some of the information that is available is, well, wrong. And to confuse matters further, I was having issues in MESS with the 2nd joystick button. Not having a physical 2-button joystick to test on real hardware is fraught with impediments to success.
Still at this point unable to test on real hardware, I at least seem to have sorted out the details and MESS finally behaves as I'd expect, given the Coco 3 schematics. I guess I should have gone to them in the first place, rather than as a last resort.
I thought I'd post my joystick code here on the off chance that someone else has similar issues in the future.
Let's define some useful constants.
PIA0 .equ 0xFF00
PIA1 .equ 0xFF20
DATAA .equ 0x00
DDRA .equ DATAA
CRA .equ 0x01
DATAB .equ 0x02
DDRB .equ DATAB
CRB .equ 0x03
; equates to keyboard rows
; - phantom keys appear accordingly
RJOY_BTN1 .equ (1<<0)
LJOY_BTN1 .equ (1<<1)
RJOY_BTN2 .equ (1<<2)
LJOY_BTN2 .equ (1<<3)
;.define LEFT_JOYSTICK
.ifdef LEFT_JOYSTICK
JOY_BTN1 .equ LJOY_BTN1
JOY_BTN2 .equ LJOY_BTN2
.else
.define RIGHT_JOYSTICK
JOY_BTN1 .equ RJOY_BTN1
JOY_BTN2 .equ RJOY_BTN2
.endif
; high and low thresholds
; for 'digital' operation
JOY_LO_TH .equ 0x64 ; ~40%
JOY_HI_TH .equ 0x98 ; ~60%
First up, the one-off initialisation, which sets all the appropriate PIA data-direction registers. Bear in mind that Knight Lore takes full control of the Coco 3 hardware,
swapping out ROM and disabling all interrupts except a simple (F)ISR
used to emulate the Z80 Refresh register. So the PIA's are immune to any reconfiguration behind-the-scenes.
; configure joystick axis selection as outputs
; and also select left/right joystick
lda PIA0+CRA
ldb PIA0+CRB
ora #(1<<5)|(1<<4) ; CA2 as output
orb #(1<<5)|(1<<4) ; CB2 as output
.ifdef LEFT_JOYSTICK
orb #(1<<3) ; CB2=1 left joystick
.else
andb #~(1<<3) ; CB2=0 right joystick
.endif
sta PIA0+CRA
stb PIA0+CRB
; configure comparator as input
lda PIA0+CRA
anda #~(1<<2) ; select DDRA
sta PIA0+CRA
lda PIA0+DDRA
anda #~(1<<7) ; PA7 as input
sta PIA0+DDRA
lda PIA0+CRA
ora #(1<<2) ; select DATAA
sta PIA0+CRA
; configure sound register as outputs
lda PIA1+CRA
anda #~(1<<2) ; select DDRA
sta PIA1+CRA
lda PIA1+DDRA
ora #0xfc ; PA[7..2] as output
sta PIA1+DDRA
lda PIA1+CRA
ora #(1<<2) ; select DATAA
sta PIA1+CRA
Now the joystick and button sampling. Note that Knight Lore uses a 'digital' joystick so it's only concerned with checking the position on each axis within three zones - left, middle and right.
; select hoizontal axis
lda PIA0+CRA
anda #~(1<<3) ; CA2=0 horizontal
sta PIA0+CRA
; set comparator value to 40%
lda PIA1+DATAA
anda #0x03 ; clear value
ora #JOY_LO_TH ; low threshold
sta PIA1+DATAA
lda PIA0+DATAA ; comparator
bita #(1<<7) ; joystick greater?
bne 1$ ; yes, skip
orb #INP_LEFT ; aka #INP_W
bra 2$
; set comparator value to 60%
1$: lda PIA1+DATAA
anda #3 ; clear value
ora #JOY_HI_TH ; high threshold
sta PIA1+DATAA
lda PIA0+DATAA ; comparator
bita #(1<<7) ; joystick greater?
beq 2$ ; no, skip
orb #INP_RIGHT ; aka #INP_E
; select vertical axis
2$: lda PIA0+CRA
ora #(1<<3) ; CA2=1 vertical
sta PIA0+CRA
; set comparator value to 40%
lda PIA1+DATAA
anda #0x03 ; clear value
ora #JOY_LO_TH ; low threshold
sta PIA1+DATAA
lda PIA0+DATAA ; comparator
bita #(1<<7) ; joystick greater?
bne 3$ ; yes, skip
orb #INP_FORWARD ; aka #INP_N
bra 4$
; set comparator value to 60%
3$: lda PIA1+DATAA
anda #3 ; clear value
ora #JOY_HI_TH ; hi threshold
sta PIA1+DATAA
lda PIA0+DATAA ; comparator
bita #(1<<7) ; joystick greater?
beq 4$ ; no, skip
orb #INP_PICKUP_DROP ; aka #INP_S
; read joystick buttons
4$: lda #0xff ; no keys, only buttons
jsr read_port
bita #JOY_BTN1
beq 5$
orb #INP_JUMP
5$: bita #JOY_BTN2
beq 6$
orb #INP_DIR_PICKUP_DROP
6$: bra finished_input
I haven't done any timing nor studied the BASIC joystick routines but short of hand-picking registers and instructions that minimise clock cycles, I don't think there's much you could do to get a faster sampling routine. Happy to be proven wrong by any astute reader.
Waiting for a 2-button adapter to turn up; hopefully that'll arrive in time for me to test before sending the final version off to John for demonstrating at the CocoFEST. I was going to try to experiment with some optimisation to speed up the rendering, but I think I'll take a short break from Knight Lore - or the 6809 port at least - until after CocoFEST.
I'm already thinking about the next port, which is dangerous before finishing off Knight Lore completely. But I've got a couple of new ideas which I need to investigate further. One is an actual arcade port; not a new game for the Coco (or any platform really) but it would be cool to have the actual arcade code and graphics, effectively, running on the Coco3. And reverse-engineering is already complete, so the port would be relatively quick. We'll see...
No comments:
Post a Comment