Jump to content
IGNORED

Driving controllers


Propane13

Recommended Posts

Hi!

 

I am interested in putting some Driving Controller support into a game I'm writing.

But, I don't have much info on how they work.

 

Here's the only thing I could find:

http://videogames.org/html/2600Stuff/DrivingControllers

 

It's an old email, that I guess you have to open in Wordpad, and it seems to be missing some info,

 

What I'm gathering is that the 2 nibbles of SWCHA are impacted.

The left 4 bits are impacted if the driving controller is plugged into port 1.

And the right 4 bits are impacted if the driving controller is plugged into port 2.

 

It sounds like from the article that the bits are impacted as such:

 

Rotating left

1100

1101<--|

1111 |

1110 |

1100----

...

etc

 

Rotating right

1100

1110<--|

1111 |

1101 |

1100----

...

etc

 

This is good, but it brings up some questions:

 

1) If I wanted to "auto-detect" a Driving controller, I'm guessing I could just poll SWCHA each frame. I would assume the user was using a joystick until I came across 1100 in SWCHA's left nibble, which is a "Joystick Impossibility", and if this occurred, I could jump to driving controller mode, correct? I am worried of a potential con where there is noise on the controller lines, and by accident, we get 1100, and then are stuck in driving controller mode, when we really have a joystick plugged in. How high is the probability of something like this happening?

 

2) How often do these values get updated in the hardware? I am guessing it's instantaneous.

If that's the case, how do you get around this situation:

a) Start of frame 1: driving controller in %1100 position

b) Middle of frame 1: user spins driving controller left "really fast". It cycles through 3 states-- from 1101 to 1111 to 1110

c) start of frame 2: driving controller is in 1110 position

d) Character on-screen moves right instead of left (oops)

My guess is is that there's a "number of times per frame" these need to be checked, and that corresponds to the fastest that someone can spin the knob. Does anyone know what that number is?

 

Thanks!

-John

Link to comment
Share on other sites

I am worried of a potential con where there is noise on the controller lines, and by accident, we get 1100, and then are stuck in driving controller mode, when we really have a joystick plugged in. How high is the probability of something like this happening?

 

I don't have any info on the driving controllers (I'd be curious to see some of those answers myself), but regarding "sticking" them in driving controller mode, you could always snap back to joystick mode if you saw a 10nn or 01nn pattern, meaning they'd pushed the joystick left or right. Should be a quick test you can run every few frames as a sanity check... chances are if there was a noise issue where the game thought it was a DC but they had a joystick, the player would probably wiggle it in various directions to get a response.

 

--Will

Edited by e1will
Link to comment
Share on other sites

http://en.wikipedia.org/wiki/Gray_code

 

The idea here is that only one bit changes at a time, making it easy to determine whether or not a state change has occurred.

 

Make a table like the wikipedia shows. It will be 8 entries long, I think.

 

So, take the current value and locate that value in your table. That's where the controller was located at the last valid sample. Your baseline.

 

Now you can figure out where it turned based on the new value in relation to the old one in the table like this:

 

Sample a new value. If it's the same as the old value, do nothing. The controller didn't move, loop back and wait for the next sample.

 

If it's different, look it up in the table, and compute the difference between where the reference old value is, and where the new value is. That will be a number you can use to perform your rotate left and rotate right computations.

 

When done, loop back and store that value as the new reference.

 

This gives you a motion vector with the origin being the last sample, and the direction being the latest one.

 

The key to these is bit changes per second. The code is designed to only change one bit at a time, that's why it's not counting up in straight binary.

 

If you don't sample often enough, the values in the table will "wrap around" giving false data, like an indication that a rotate right occured, when really it was a lot of rotating left. In this scenario, enough time passed to exceed the bit changes per sample, essentially giving random data. This will be seen as the player object moving erratically.

 

If you sample too much, you are wasting time you could be using for other things, or the player will have to really be aggressive on the controller to get anything done.

 

Those controllers are very coarse, only offering 45 degree precision, and that's 8 direction changes per turn. So that's say 000 at top dead center, 001 at 45 degrees clockwise, 011 at 90 degrees clockwise, 010 at 120, etc...

 

To determine sample time, do some math based on anticipated controller input and the resolution of the the thing. Since this controller is coarse, there isn't that much resolution, I'll bet a sample per frame, or maybe two per frame should be plenty, or good for all but the quickest inputs.

 

Joystick input would be different enough to detect, but there would have to be some player motion on the controller for that to happen, like the person above said. Wouldn't the impossibility occur, if the user held the joystick diagonal, with the fire button, or something like that? Maybe tracking a sequence would be better?

 

The trackball is just two of these things, and a 4 bit code instead of a 3 bit one, I think. Been a long time. I once wrote a mouse routine for the 8 bitters using the track ball, and had trouble with fast motion and a one sample per frame... I think the trackball has much greater angular precision. 15 degrees or less, and it had a 4 bit grey code, requiring a faster sample. These are coarse, and have 3 bits, requiring less, I think.

 

Anyway, the key to working with it is to know the precision, which is 45 degrees, and the grey code sequence. From there, you can figure out what the player did, given a sufficient sample rate.

Edited by potatohead
Link to comment
Share on other sites

Thanks, I didn't know that existed.

 

That disassembly (which is bad ass cool to see) confirms the overall path I detailed above. It's simpler actually.

 

INDY 500 does check once per frame, and that game has SPOT ON controls, so that's good to know.

 

The rest is very similar to the overall process above.

 

Tables are used to assign velocity values, based on rotation, which is based on the position of the controller.

 

  jsr ReadDrivingControllers
  jsr DeterminePlayerMotion

 

ReadDrivingControllers
  ldx #1                           ; start with player 2
  lda SWCHB                        ; read the console switches
  sta difficultySwitchValue        ; save to manipulate difficulty settings
  lda SWCHA                        ; read driving controller
  bit gameVariation                ; check for one player (time trial) game
  bvc .readPlayer1Controller
.setDrivingControllerValue
  and #3                           ; keep valid driving controller values
  sta drivingControllerValues,x
  lda INPT4,x                      ; read the joystick button
  bpl .accelerateCar               ; branch if fire button pressed
  lda accelerationRate,x           ; get the player's acceleration rate
  bne .reduceAccelerationRate      ; if not 0 then don't move
  lda playerVelocity,x             ; get the player's velocity
  beq .setPlayerRotation           ; branch if at rest
  dec playerVelocity,x             ; reduce the player's velocity
  lda initDecelerationRate
  sta accelerationRate,x           ; set to show car slowing down
  jsr InitPlayerMotion
  jmp .setPlayerRotation

.accelerateCar
  lda accelerationRate,x           ; don't change player's velocity until
  bne .reduceAccelerationRate      ; acceleration rate reaches 0
  lda maximumVelocity
  bit difficultySwitchValue        ; check the difficulty setting
  bmi .skipSpeedReduction          ; skip speed reduction if EXPERT setting
  sec
  sbc #2                           ; reduce init speed for NOVICE mode
.skipSpeedReduction
  cmp playerVelocity,x
  bcc .setPlayerRotation
  inc playerVelocity,x             ; increase player's velocity
  lda initAccelerationRate         ; reset the acceleration rate
  sta accelerationRate,x
  jsr InitPlayerMotion
.setPlayerRotation
  lda drivingControllerValues,x    ; get driving controller values
  asl                              ; multiply the value by 4 (i.e. shift
  asl                              ; values to D3 and D2)
  ora previousDCValues,x           ; add in the previous DC values
  tay                              ; set for RotationValueTable offset
  lda playerDirections,x           ; get the player's direction
  cmp previousPlayerDirections,x
  bne .readNewDirectionValues
  lda RotationValueTable,y
  sta playerRotation,x
.setPlayerDirections
  clc
  adc playerDirections,x           ; add in direction to manipulate REFLECT
  and #$0F                         ; only keep lower nybbles
  sta playerDirections,x
  tya
  lsr                              ; shift driving controller value back
  lsr                              ; into D1 and D0
  sta previousDCValues,x           ; to save for next frame
  jsr CheckToChangeDirectionPath
.readPlayer1Controller
  asl difficultySwitchValue        ; shift player 1 difficulty setting to D7
  lda SWCHA                        ; read driving controller
  lsr                              ; shift player 1 values to lower nybbles
  lsr
  lsr
  lsr
  dex
  beq .setDrivingControllerValue
  rts

Edited by potatohead
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...