Gopher2600/hardware/peripherals/stick.go
steve 35e31cccb7 o errors
- refined error package
2020-01-05 18:58:28 +00:00

95 lines
2.5 KiB
Go

package peripherals
import (
"gopher2600/errors"
"gopher2600/hardware/memory"
"gopher2600/hardware/memory/vcssymbols"
"github.com/splace/joysticks"
)
// Stick emulaes the digital VCS joystick
type Stick struct {
device *joysticks.HID
err error
}
// NewStick is the preferred method of initialisation for the Stick type
func NewStick(tia memory.PeriphBus, riot memory.PeriphBus, panel *Panel) *Stick {
stick := new(Stick)
// TODO: make all this work with a seconc contoller. for now, initialise
// and asssume that there is just one controller for player 0
riot.PeriphWrite(vcssymbols.SWCHA, 0xff)
tia.PeriphWrite(vcssymbols.INPT4, 0x80)
tia.PeriphWrite(vcssymbols.INPT5, 0x80)
// there is a flaw (either in splace/joysticks or somewehere else lower
// down in the kernel driver) which means that Connect() will not return
// until it recieves some input from the controller. to get around this,
// we've put the main body of the NewStick() function in a go routine.
go func() {
// try connecting to specific controller.
// system assigned index: typically increments on each new controller added.
stick.device = joysticks.Connect(1)
if stick.device == nil {
stick.err = errors.NewGopherError(errors.NoControllersFound, nil)
return
}
// get/assign channels for specific events
stickMove := stick.device.OnMove(1)
buttonPress := stick.device.OnClose(1)
buttonRelease := stick.device.OnOpen(1)
// on xbox controller, button 8 is the start button
resetPress := stick.device.OnClose(8)
resetRelease := stick.device.OnOpen(8)
// on xbox controller, button 9 is the back button
selectPress := stick.device.OnClose(7)
selectRelease := stick.device.OnOpen(7)
// start feeding OS events onto the event channels.
go stick.device.ParcelOutEvents()
// handle event channels
for {
select {
case <-resetPress:
panel.SetGameReset(true)
case <-resetRelease:
panel.SetGameReset(false)
case <-selectPress:
panel.SetGameSelect(true)
case <-selectRelease:
panel.SetGameSelect(false)
case <-buttonPress:
tia.PeriphWrite(vcssymbols.INPT4, 0x00)
case <-buttonRelease:
tia.PeriphWrite(vcssymbols.INPT4, 0x80)
case ev := <-stickMove:
swcha := uint8(0xff)
x := ev.(joysticks.CoordsEvent).X
y := ev.(joysticks.CoordsEvent).Y
if x < -0.5 {
swcha &= 0xbf
} else if x > 0.5 {
swcha &= 0x7f
}
if y < -0.5 {
swcha &= 0xef
} else if y > 0.5 {
swcha &= 0xdf
}
riot.PeriphWrite(vcssymbols.SWCHA, swcha)
}
}
}()
return stick
}