Skip to content

Commit

Permalink
added right player joystick
Browse files Browse the repository at this point in the history
using default Stella keys:

    Up	    Y
    Down    H
    Left    G
    Right   J
    Fire    F
  • Loading branch information
JetSetIlly committed Sep 30, 2021
1 parent 87f3bd1 commit e273716
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 30 deletions.
70 changes: 56 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,20 +208,60 @@ Although if want to pass flags to the run mode you'll need to specify it.

## Hand Controllers

Stick, paddle and keypad inputs are supported. Currently, only stick and
paddles for the left player are available but keypad input is available for
both players.
Stick, paddle and keypad inputs are supported.

### Stick

The stick is the most common control method for `Atari 2600` games. The stick
can be operated with the DPad or left thumbstick of a [gamepad](#gamepad) or by
the cursor keys on your computer's keyboard. Fire button is the keyboards space
bar or any of the gamepad's face buttons.
The stick is the most common control method for `Atari 2600` games. The
left-side player is controlled with the following keys.

<table>
<tr>
<th colspan=2>Left-Side Player</th>
</tr>
<tr>
<td align="center">Cursor Keys</td>
<td align="center">Stick Direction</td>
</tr>
<tr>
<td align="center">Space</td>
<td align="center">Fire Button</td>
</tr>
</table>

The right-side player is controlled with the following keys.

<table>
<tr>
<th colspan=2>Right-Side Player</th>
</tr>
<tr>
<td align="center">G</td>
<td align="center">Left</td>
</tr>
<tr>
<td align="center">J</td>
<td align="center">Right</td>
</tr>
<tr>
<td align="center">Y</td>
<td align="center">Up</td>
</tr>
<tr>
<td align="center">H</td>
<td align="center">Down</td>
</tr>
<tr>
<td align="center">F</td>
<td align="center">Fire Button</td>
</tr>
</table>

The stick for the left-side player can also be controlled with a [gamepad](#gamepad).

### Paddle

The paddle can be controlled with the mouse or [gamepad](#gamepad).
The paddle for the left-side player can be controlled with the mouse or a [gamepad](#gamepad).

In the case of the mouse, the mouse must be [captured](#mouse-capture).

Expand All @@ -230,17 +270,19 @@ however and which device is used depends on the game. For some games, the
triggers will suffice but other games will perform better when using the mouse.

`Nightdriver` is an example of a game that plays well with the triggers,
whereas `Circus Tricks` is better played with the mouse.
whereas experience says that `Circus Tricks` is better played with the mouse.

The paddle for the right-side player is not currently supported.

### Keypad

Keypad input for both players is supported.

<table>
<tr>
<th colspan=3>Left Hand Player</th>
<th colspan=3>Left-Side Player</th>
<th></th>
<th colspan=3>Right Hand Player</th>
<th colspan=3>Right-Side Player</th>
</tr>
<tr>
<td align="center">1</td>
Expand Down Expand Up @@ -294,9 +336,9 @@ need.

### Gamepad

For convenience the joystick and paddle can be controlled through a gamepad.
For the joystick, use the left thumbstick or the DPad. Any of the face buttons
will act as the joystick's fire button.
For convenience the joystick and paddle for the left-side player can be
controlled through a gamepad. For the joystick, use the left thumbstick or the
DPad. Any of the face buttons will act as the joystick's fire button.

To control the paddle use the left and right analogue triggers. Note that you
will need to 'waggle' the triggers a couple of times for the emulator to detect
Expand Down
1 change: 0 additions & 1 deletion gui/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,5 @@ const (
// of the controller.
ReqControllerChange FeatureReq = "ReqControllerChange" // plugging.PortID, plugging.PeripheralID


ReqCartridgeEvent FeatureReq = "ReqCartridgeEvent" // mapper.Event
)
3 changes: 1 addition & 2 deletions gui/sdlimgui/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,8 +344,7 @@ func (img *SdlImgui) serviceKeyboard(ev *sdl.KeyboardEvent) {
}
}

// forward keypresses to userinput.Event channel if in playmore or gui is
// in captured state
// forward keypresses to userinput.Event channel
if img.isPlaymode() || img.isCaptured() {
mod := userinput.KeyModNone

Expand Down
1 change: 1 addition & 0 deletions hardware/riot/ports/plugging/plugging.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type PeripheralID string

// List of valid PeripheralID values.
const (
PeriphNone PeripheralID = "None"
PeriphPanel PeripheralID = "Panel"
PeriphStick PeripheralID = "Stick"
PeriphPaddle PeripheralID = "Paddle"
Expand Down
17 changes: 15 additions & 2 deletions hardware/riot/ports/ports.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,7 @@ func (p *Ports) GetPlayback() error {
return nil
}

// HandleEvent forwards the Event and EventData to the device connected to the
// specified PortID.
// HandleEvent implements userinput.HandleInput interface.
func (p *Ports) HandleEvent(id plugging.PortID, ev Event, d EventData) error {
var err error

Expand All @@ -333,6 +332,20 @@ func (p *Ports) HandleEvent(id plugging.PortID, ev Event, d EventData) error {
return nil
}

// PeripheralID implements userinput.HandleInput interface.
func (p *Ports) PeripheralID(id plugging.PortID) plugging.PeripheralID {
switch id {
case plugging.PortPanel:
return p.Panel.ID()
case plugging.PortLeftPlayer:
return p.LeftPlayer.ID()
case plugging.PortRightPlayer:
return p.RightPlayer.ID()
}

return plugging.PeriphNone
}

// WriteSWCHx implements the MemoryAccess interface.
func (p *Ports) WriteSWCHx(id plugging.PortID, data uint8) {
switch id {
Expand Down
80 changes: 69 additions & 11 deletions userinput/controllers.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (c *Controllers) keyboard(ev EventKeyboard, handle HandleInput) error {
case "F5":
err = handle.HandleEvent(plugging.PortPanel, ports.PanelTogglePlayer1Pro, nil)

// joystick
// joystick (left player)
case "Left":
err = handle.HandleEvent(plugging.PortLeftPlayer, ports.Left, ports.DataStickTrue)
case "Right":
Expand All @@ -82,6 +82,11 @@ func (c *Controllers) keyboard(ev EventKeyboard, handle HandleInput) error {
case "Space":
err = handle.HandleEvent(plugging.PortLeftPlayer, ports.Fire, true)

// joystick (right player)
// * keypad and joystick share some keys (see below for other inputs)
case "J":
err = handle.HandleEvent(plugging.PortRightPlayer, ports.Right, ports.DataStickTrue)

// keypad (left player)
case "1", "2", "3":
err = handle.HandleEvent(plugging.PortLeftPlayer, ports.KeypadDown, rune(ev.Key[0]))
Expand All @@ -105,6 +110,7 @@ func (c *Controllers) keyboard(ev EventKeyboard, handle HandleInput) error {
err = handle.HandleEvent(plugging.PortLeftPlayer, ports.KeypadDown, '#')

// keypad (right player)
// * keypad and joystick share some keys (see below for other inputs)
case "4":
err = handle.HandleEvent(plugging.PortRightPlayer, ports.KeypadDown, '1')
case "5":
Expand All @@ -115,20 +121,39 @@ func (c *Controllers) keyboard(ev EventKeyboard, handle HandleInput) error {
err = handle.HandleEvent(plugging.PortRightPlayer, ports.KeypadDown, '4')
case "T":
err = handle.HandleEvent(plugging.PortRightPlayer, ports.KeypadDown, '5')
case "Y":
err = handle.HandleEvent(plugging.PortRightPlayer, ports.KeypadDown, '6')
case "F":
err = handle.HandleEvent(plugging.PortRightPlayer, ports.KeypadDown, '7')
case "G":
err = handle.HandleEvent(plugging.PortRightPlayer, ports.KeypadDown, '8')
case "H":
err = handle.HandleEvent(plugging.PortRightPlayer, ports.KeypadDown, '9')
case "V":
err = handle.HandleEvent(plugging.PortRightPlayer, ports.KeypadDown, '*')
case "B":
err = handle.HandleEvent(plugging.PortRightPlayer, ports.KeypadDown, '0')
case "N":
err = handle.HandleEvent(plugging.PortRightPlayer, ports.KeypadDown, '#')

// keypad (right player) *OR* joystick (right player)
// * keypad and joystick share some keys (see above for other inputs)
case "Y":
if handle.PeripheralID(plugging.PortRightPlayer) == plugging.PeriphKeypad {
err = handle.HandleEvent(plugging.PortRightPlayer, ports.KeypadDown, '6')
} else {
err = handle.HandleEvent(plugging.PortRightPlayer, ports.Up, ports.DataStickTrue)
}
case "F":
if handle.PeripheralID(plugging.PortRightPlayer) == plugging.PeriphKeypad {
err = handle.HandleEvent(plugging.PortRightPlayer, ports.KeypadDown, '7')
} else {
err = handle.HandleEvent(plugging.PortRightPlayer, ports.Fire, true)
}
case "G":
if handle.PeripheralID(plugging.PortRightPlayer) == plugging.PeriphKeypad {
err = handle.HandleEvent(plugging.PortRightPlayer, ports.KeypadDown, '8')
} else {
err = handle.HandleEvent(plugging.PortRightPlayer, ports.Left, ports.DataStickTrue)
}
case "H":
if handle.PeripheralID(plugging.PortRightPlayer) == plugging.PeriphKeypad {
err = handle.HandleEvent(plugging.PortRightPlayer, ports.KeypadDown, '9')
} else {
err = handle.HandleEvent(plugging.PortRightPlayer, ports.Down, ports.DataStickTrue)
}
}
} else {
switch ev.Key {
Expand All @@ -138,7 +163,7 @@ func (c *Controllers) keyboard(ev EventKeyboard, handle HandleInput) error {
case "F2":
err = handle.HandleEvent(plugging.PortPanel, ports.PanelReset, false)

// josytick
// josytick (left player)
case "Left":
err = handle.HandleEvent(plugging.PortLeftPlayer, ports.Left, ports.DataStickFalse)
case "Right":
Expand All @@ -150,13 +175,46 @@ func (c *Controllers) keyboard(ev EventKeyboard, handle HandleInput) error {
case "Space":
err = handle.HandleEvent(plugging.PortLeftPlayer, ports.Fire, false)

// joystick (right player)
// * keypad and joystick share some keys (see below for other inputs)
case "J":
err = handle.HandleEvent(plugging.PortRightPlayer, ports.Right, ports.DataStickFalse)

// keyboard (left player)
case "1", "2", "3", "Q", "W", "E", "A", "S", "D", "Z", "X", "C":
err = handle.HandleEvent(plugging.PortLeftPlayer, ports.KeypadUp, nil)

// keyboard (right player)
case "4", "5", "6", "R", "T", "Y", "F", "G", "H", "V", "B", "N":
// * keypad and joystick share some keys (see below for other inputs)
case "4", "5", "6", "R", "T", "V", "B", "N":
err = handle.HandleEvent(plugging.PortRightPlayer, ports.KeypadUp, nil)

// keypad (right player) *OR* joystick (right player)
// * keypad and joystick share some keys (see above for other inputs)
case "Y":
if handle.PeripheralID(plugging.PortRightPlayer) == plugging.PeriphKeypad {
err = handle.HandleEvent(plugging.PortRightPlayer, ports.KeypadUp, nil)
} else {
err = handle.HandleEvent(plugging.PortRightPlayer, ports.Up, ports.DataStickFalse)
}
case "F":
if handle.PeripheralID(plugging.PortRightPlayer) == plugging.PeriphKeypad {
err = handle.HandleEvent(plugging.PortRightPlayer, ports.KeypadUp, nil)
} else {
err = handle.HandleEvent(plugging.PortRightPlayer, ports.Fire, false)
}
case "G":
if handle.PeripheralID(plugging.PortRightPlayer) == plugging.PeriphKeypad {
err = handle.HandleEvent(plugging.PortRightPlayer, ports.KeypadUp, nil)
} else {
err = handle.HandleEvent(plugging.PortRightPlayer, ports.Left, ports.DataStickFalse)
}
case "H":
if handle.PeripheralID(plugging.PortRightPlayer) == plugging.PeriphKeypad {
err = handle.HandleEvent(plugging.PortRightPlayer, ports.KeypadUp, nil)
} else {
err = handle.HandleEvent(plugging.PortRightPlayer, ports.Down, ports.DataStickFalse)
}
}
}

Expand Down
5 changes: 5 additions & 0 deletions userinput/userinput.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,10 @@ import (

// HandleInput conceptualises data being sent to the console ports.
type HandleInput interface {
// HandleEvent forwards the Event and EventData to the device connected to the
// specified PortID.
HandleEvent(id plugging.PortID, ev ports.Event, d ports.EventData) error

// PeripheralID identifies the device currently attached to the port.
PeripheralID(id plugging.PortID) plugging.PeripheralID
}

0 comments on commit e273716

Please sign in to comment.