home *** CD-ROM | disk | FTP | other *** search
- Emil Gilliam's Guide to Game Port Programming
- Revised 10/30/93
-
- TABLE OF CONTENTS
-
- Section Name
-
- LEGAL INFORMATION
- 0 SUMMARY OF CHANGES FROM 10/22/93 AND 06/10/93 REVISIONS
- 1 INTRODUCTION
- 2 ROM BIOS GAME PORT FUNCTIONS
- 3 ACCESSING THE GAME I/O PORT DIRECTLY
- 4 INTERPRETING THE JOYSTICK X AND Y VALUES
- 5 GRAVIS GAMEPAD
- 6 PADDLES
- 7 DETECTING THE GAME PORT AND CONTROLLERS
- 8 GAME PORT PINOUTS
- 9 HOW TO CONTACT ME
-
- ------------------------------------------------------------------------------
-
- LEGAL INFORMATION
-
- This "Joystick Guide" is (C) Copyright 1993 Emil Gilliam. All rights
- reserved.
-
- THIS DOCUMENT AND THE ACCOMPANYING SOURCE CODE FILE ARE PROVIDED "AS IS"
- WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING ANY WARRANTY OF
- MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. EMIL GILLIAM WILL NOT BE
- HELD LIABLE FOR ANY DAMAGES OR LOSSES OF ANY KIND THAT RESULT FROM THE USE OR
- THE INABILITY TO USE THE INFORMATION PROVIDED IN THIS DOCUMENT OR THIS SOURCE
- CODE FILE, INCLUDING, BUT NOT LIMITED TO, LOSS OF PROPERTY OR INCOME.
-
- This document and its accompanying source code file are freeware, not
- public domain. They may be distributed freely provided that neither file is
- modified, and that they are distributed together along with FILE_ID.DIZ in
- their entirety, including the legal notice, and that:
- If they are distributed by a computer club, no more than $5 U.S. is charged
- for the disk on which the archive containing this document and the
- accompanying source code file is stored; if they are to be distributed by a
- shareware/freeware company (for example, on a CD-ROM collection of files), my
- permission is obtained first.
- This legal information supersedes all previous notices.
-
- ------------------------------------------------------------------------------
-
- 0.0 SUMMARY OF CHANGES FROM 10/22/93 AND 06/10/93 REVISIONS
-
- Changes from 10/22/93 revision:
-
- Improved copyright notice, thanks to:
- Kip Cooley at the Diamond Bar BBS (909) 923-1031 (1:218/101).
- Ian Remmler at the DownTown BBS (210) 625-4479 (1:387/1001).
-
- Bug fix (SI and DI should be saved, ES was saved incorrectly in
- read_2_joysticks) in read_1_joystick and read_2_joysticks. Thanks to
- Kip Cooley (see above).
-
- A little optimization in the detect_game_port procedure, thanks to David
- Kirschbaum, "Toad Hall," at the Federal Post BBS (1:3634/2).
-
- FILE_ID.DIZ file added.
-
- A big thanks to everyone who has made suggestions for this Guide!
-
- Changes from 06/10/93 revision:
-
- More specific about precision and ranges of coordinates in section 4.1.
- Added information about game-port bit in equipment-status word.
- More specific about the joystick port itself (in section 8).
-
- ------------------------------------------------------------------------------
-
- 1.0 INTRODUCTION
-
- 1.1 About the game port
-
- Any machine in the IBM PC family of computers can have a game port, either
- built-in or on an add-on card. As suggested by its name, the game port is
- where you can connect one or two joysticks, or other controllers suitable for
- playing games with, to the computer. This document describes how a program
- accesses the game port, so if you're writing a game or other program that uses
- a joystick or other such controller, you'll know how to get your program to
- get the status of the joystick or whatever is hooked up to the game port.
- As far as I know, three things can be connected to a game port: an analog
- joystick (you can have up to two connected at once), a Gravis GamePad, which
- is a digital joystick (see section 5), or up to four paddles (see section 6).
- By far, analog joysticks are more commonly used for game controllers than the
- other two. (I have never actually seen a paddle for the IBM in my life, nor
- seen a program that uses it; I only know that such a thing exists, but it must
- be extremely rare or old. I only included information on it here for
- completeness.)
- When analog joysticks are connected to the game port, they are referred to
- as joysticks A and B (for player 1 and player 2 in a game, respectively).
- Each analog joystick has two buttons on it. The stick itself is opposed to
- the type of joystick on a Gravis GamePad or to what's used for a Nintendo or
- Sega, or to the joysticks used on many early home computers that have 9-pin
- joystick connectors, all of which are "digital" joysticks. (Usually in this
- document, if I refer to simply the "joystick," I'm talking about the analog
- joystick.)
-
- 1.2 The difference between an analog and a digital joystick
-
- What's the difference between an analog joystick and a digital joystick?
- Inside a digital joystick like the Gravis GamePad, there are simple switches
- which can only detect if the joystick is all the way up, down, left, or right,
- at any of the 4 diagonals, or at the center. The joystick therefore has only
- 9 distinct positions. In an analog joystick, however, the joystick has
- potentiometers inside it that can tell where the stick's position is more
- accurately, so a program doesn't have to know that the joystick is somewhere
- to the left of the center or whatever; it can know just how far it is to the
- left. The joystick gives information to the computer about where the stick's
- coordinates are.
-
- 1.3 Reading the controller values
-
- The game port isn't tied to any interrupts; if you're writing a game or
- some other application that does something whenever a joystick button is
- pressed or whenever the stick is moved (or the paddle is turned), you have to
- program it to "poll" the game port, in other words, read the game port status
- over and over (perhaps many times per second) and see if a button is being
- pressed or the joystick is in a particular position.
- There are two ways for a program to get the status of the game port (and
- thus of whatever controller is connected to it): It can call the ROM BIOS
- functions to do it (see section 2), or it can directly use the I/O ports that
- are connected to the game port (see section 3).
-
- ------------------------------------------------------------------------------
-
- 2.0 ROM BIOS JOYSTICK FUNCTIONS
-
- 2.1 About the functions
-
- Here are the ROM BIOS functions for reading the joystick positions and
- button status. (You can also use them for getting the status of the paddles,
- see section 6.) Beware that some older machines (original PC's and PCjr's,
- and XT's whose BIOSes date back to 11/08/82) don't support these INT 15h
- functions in their ROM BIOSes. (It's ironic that PCjr's don't support these
- functions, because all PCjr's have a game port - I think. XT's with newer
- BIOSes, 01/10/86, do support these functions.)
-
- 2.2 Function to get button status
-
- INT 15h Function 84h - joystick functions
-
- Subfunction 0 - get joystick button status
- DON'T USE THIS UNLESS YOU ABSOLUTELY HAVE TO -- IT'S SLOW!!! See 2.5.
- Call with: AH=84h, DX=0
- Returns:
- On PC's and PCjr's (which don't support this function), AH=80h and
- CF=1, other flags: undefined
-
- On PC XT's whose BIOSes date to 11/08/82 (which also don't support
- this function, AH=86h and CF=1, other flags undefined
-
- On all other machines (which do support this function), CF=0,
- AH: Bits 0-3 - undefined (probably 0 but don't count on it)
- Bit 4 - Joystick A button 1 status (1=button not pressed,
- 0=button being pressed)
- Bit 5 - Joystick A button 2 status (ditto)
- Bit 6 - Joystick B button 1 status (ditto)
- Bit 7 - Joystick B button 2 status (ditto)
- Note: Those are the bit definitions for the analog joystick. See
- the sections on the Gravis GamePad (section 5) and the paddles
- (section 6) for the bit definitions for those controllers.
- DX: Undefined (probably 201h but don't bet your life on it)
- Other flag registers: undefined
-
- Officially, this function will can return CF=1 if there was an
- error reading the joystick button values or there is no game
- adapter. I don't see how that can ever happen; the ROM BIOS code
- can't return CF=1 and never checks to see if a game adapter is
- installed at all, at least in the 01/10/86 XT BIOS.
-
- 2.3 Function to get joystick position
-
- INT 15h Function 84h - joystick functions
-
- Subfunction 1 - get joystick position
- Call with: AH=84h, DX=1
- Returns:
- On PC's, PCjr's, and XT's with 11/08/82 BIOSes (which don't support
- this function), see section 2.2.
-
- On all other machines (which do support this function), CF=0,
- AX = Joystick A x-coordinate (see section 4 about these)
- BX = Joystick A y-coordinate (ditto)
- CX = Joystick B x-coordinate (ditto)
- DX = Joystick B y-coordinate (ditto)
- Note: These are the register definitions for the analog joystick.
- See the sections on the Gravis GamePad (section 5) and the paddles
- (section 6) for the register definitions for those controllers.
- Other flag registers: undefined
-
- Officially, this function can also return CF=1 if there was an
- error, like no adapter card. However, at least in the 01/10/86 XT
- BIOS, this can't ever happen; the code never checks for an adapter
- card. Upon exit, any of the four registers for joystick values
- will be equal to 0 if that joystick isn't connected (or if the 1
- bit in the game port register for that coordinate never turned 0
- within a reasonable amount of time; you'd know what the heck I'm
- talking about if you read section 3.)
-
- 2.4 Advantage to using ROM BIOS functions
-
- Really, there aren't a whole lot of reasons for using the ROM BIOS
- functions for reading the joystick (or other controller) status. I suppose if
- you're doing some quick-and-dirty program, it's easier because you don't have
- to come up with the routine yourself. If there is a joystick emulator of some
- sort installed, it might intercept the joystick calls to interrupt 15h (but it
- would more likely put the processor into V86 mode and trap I/O to port 201h if
- the processor is a 386 or up) and so your program might work with it better.
- This is quite unlikely because I've never seen anything that emulates a
- joystick or other controller.
-
- 2.5 Disadvantages to using the ROM BIOS functions
-
- The big minus to using the ROM BIOS functions for reading the joystick (or
- other controller) status is that they're really SLOW! Considering how many
- things have to trap interrupt 15h (DOS, the XMS driver, and probably other
- things), and how the ROM BIOS has to check the function number and do other
- maintenance garbage, like with the CMOS RAM on some newer ROM BIOSes, the
- system wastes a lot of time just getting to the joystick routines. Also, the
- ROM BIOS routine for reading the joystick position is quite slow because it
- reads the joystick coordinates one at a time instead of all at once (as far as
- I know that's how it's done in all ROM BIOSes). At least, don't call INT 15h
- for getting the joystick button values if you can help it; you can get the
- joystick button status in just two instructions; I'll even give some code for
- doing that if you are a beginner at assembly language or are too lazy to
- figure this one out. (See the routine button_status in JOYSTICK.ASM.)
- The other disadvantage is that some older machines (original PC's, PCjr's,
- and XT's whose BIOSes date back to 11/08/82) don't support these INT 15h
- functions in their ROM BIOSes. (XT's with newer BIOSes, 01/10/86, do support
- these functions.) On the machines that don't support the joystick functions
- in their ROM BIOSes, in order to read the joystick values or get the status of
- the buttons, you have to do it yourself with hardware ports. (See section 3.)
-
- ------------------------------------------------------------------------------
-
- 3.0 ACCESSING THE GAME I/O PORT DIRECTLY
-
- 3.1 How it works
-
- The game port is accessed through a single 8-bit I/O port, 201h.
- (Officially, ports 200h through 20Fh are for the game port; only 201h is used,
- however. The rest of these ports aren't used by the game port but maybe there
- are other things that use them [?].) When you read an 8-bit value from port
- 201h, here's what the bits are (for the analog joystick; see the sections on
- the Gravis GamePad [section 5] and the paddles [section 6] for information on
- those controllers). Be aware that the game port itself has no idea what is
- connected to it; it's the controller that gives it the bits that you get
- through port 201h.
-
- Bit Description
- 0 Joystick A x-coordinate
- 1 Joystick A y-coordinate
- 2 Joystick B x-coordinate
- 3 Joystick B y-coordinate
- 4 Status of joystick A button 1 (1=not pressed, 0=pressed)
- 5 Status of joystick A button 2 (ditto)
- 6 Status of joystick B button 1 (ditto)
- 7 Status of joystick B button 2 (ditto)
-
- Reading the joystick button status is very easy; you simply IN from port
- 201h and the top 4 bits of AL will be the button status. (This takes a
- whopping two instructions; again, see button_status in JOYSTICK.ASM.)
- You're probably wondering how the x and y coordinates of the joysticks can
- fit within single bits, especially for the analog joystick which can detect
- many x and y coordinates. This is the slow part about reading the joystick
- position and it's a pain to write a routine to do that that's very optimized.
- (Look in JOYSTICK.ASM and you'll find routines to do that, already there for
- you to use and modify; they are read_1_joystick and read_2_joysticks. It's
- much better to rely on these than the ROM BIOS routines which can be horribly
- inaccurate.)
- To read the joystick coordinates, first you write a value to the 8-bit port
- 201h. It doesn't matter what the value is, just as long as you write a value.
- This does what's called firing the joystick one-shots. The four bottom bits
- of port 201h will immediately become 1. You read the joystick port over and
- over again and time how long it takes for the bits to turn 0. The bits do not
- become 0 all at once; each one changes from 1 to 0 in an amount of time
- (elapsed time after you wrote the value to port 201h) proportional to the x or
- y coordinate that that bit represents.
- Yes, I know what you're thinking. That's a pain in the gluteus maximus.
- For one thing, that might be slow especially if you're reading the joystick
- positions several times a second, (it takes the same amount of time on every
- computer regardless of speed). It would be nice if there were separate I/O
- ports for each coordinate where you read the port and that's the value right
- there. But this is a lot easier for the hardware engineers.
- The reason the ROM BIOS routine for reading the joystick position is slow
- is because it reads the four joystick coordinate bits one at a time; it will
- fire the joystick one-shots, time how long it takes for bit 0 to change from 1
- to 0, fire the joystick one-shots again, time how long it takes for bit 1 to
- change from 1 to 0, and so on. That's not very efficient; the fastest
- possible routine for reading the joystick position would fire the joystick
- one-shots once and then time all four bits at once. That's kind of hard to do
- considering that even on slow computers you want the timing to be as accurate
- as possible but at the same time the computer has to sort out which bits
- changed when, and which coordinates they would represent. JOYSTICK.ASM,
- included in this archive, has a routine (read_2_joysticks) that will time all
- four joystick coordinate bits at once. It might not be very accurate on
- slower computers, however, because many timer chip counts might pass by on
- each run of the loop while the CPU tries to figure out what to do about the
- bits in the joystick port value that changed. But if you're only going to
- read joystick A, you can use read_1_joystick instead which is more accurate on
- slower computers because the loop size is smaller and uses registers instead
- of memory operands to save the coordinates it's figured out so far.
- Be aware that if a joystick isn't connected, the bits representing that
- joystick will either be 0 and stay 0 or will be 1 and stay 1. If the bits for
- a joystick are 1 and don't become 0 within a reasonable amount of time, assume
- that the joystick isn't connected or that something's wrong with the joystick.
- Just how long is a "reasonable amount of time" ? See section 3.2.2.
- Note: Whenever you fire the joystick one-shots, you have to wait for all
- four 1-bits to turn 0 before you can fire the joystick one-shots again.
-
- 3.2 Timings
-
- In your routine for reading the joystick position, you should use the timer
- chip as a way of finding out the length of time between when you fire the
- joystick one-shots and a bit changes to 1.
-
- 3.2.1 Lengths of time
-
- Have your joystick-reading routine count the number of timer chip clock
- ticks (there are 1193180 ticks per second) that pass between when you fire
- the joystick one-shots and when the bit turns from 1 to 0. Then have it
- divide this value by 16. This will be the value for the coordinate you're
- reading. (Actually you don't have to use 16/1193180's of a second as the
- units; you can use any units you want for the coordinates of the joystick.
- However, these are the units which the values returned by the ROM BIOS
- joystick-reading function are in, they're the units used in this document
- whenever joystick x or y coordinates are given, and they're also the units
- used by the functions in JOYSTICK.ASM.
-
- 3.2.2 How long is too long?
-
- If you fire the joystick one-shots, and the 1 bits don't turn to 0 within a
- normal amount of time (or don't turn to 0 at all), something must be wrong
- with the joystick port or the joystick(s). How long is a reasonable amount of
- time before assuming that something's wrong? The maximum x or y coordinate
- value that you can get back from the ROM BIOS is 1FFh. On my joystick,
- coordinates don't usually go past 100 or 150. I guess 1FF0h clock ticks
- after when you write to the joystick port would be a good time to assume that
- something's wrong.
- Of course, this could also depend on what your program expects the maximum
- possible x or y coordinate to be; it gets this information from whenever it
- calibrates. But the length of time after you fire off the joystick one-shots
- needs to be considerably more than what the program considers to be the
- maximum coordinate before it cries wolf. For example, if during calibration
- (see section 8) the program found out that the maximum x-coordinate returned
- by the joystick was 140, and then during the program the 1 bit hasn't changed
- to 0 by the time 140*16 clock ticks have intervened, don't assume something's
- wrong yet; wait until at least 30*16 more clock ticks, perhaps, and if the 1
- bit changes to 0 within that time, your program can treat this extraordinarily
- high x coordinate to be the same as 140. Remember, the joystick is not very
- exact.
- In the XT ROM BIOS, the ROM BIOS waits for a certain number of runs of a
- loop to happen before it assumes that there's an error; but that's not a good
- way to do it because that's processor-speed specific.
-
- ------------------------------------------------------------------------------
-
- 4.0 INTERPRETING THE JOYSTICK X AND Y VALUES
-
- 4.1 Now for the hard part...
-
- Analog joysticks are not very exact. Their values can "float" around over
- periods of time, and constantly require calibration, both on the joystick and
- by the program. The maximum x-coordinate is about 146 on my joystick (which
- is a Kraft QuickShot), and the maximum y-coordinate is about 154, but the
- routine in my ROM BIOS which reads the joystick values is not very accurate at
- all, and the maximum y-coordinates can jump around all the way from 105 to
- 155! And then, of course, turning the calibration knobs on my joystick could
- change it somewhat, and on a different brand or model of joystick the ranges
- might be very different. According to "Advanced MS-DOS Programming" by Ray
- Duncan, the coordinates should be in the range 0 to 416 for a 250 KOhm
- joystick. I'd appreciate it if people could please give me the values they
- get for their joysticks.
- Maybe the only thing you can be certain of is that higher x-coordinates are
- right and that higher y-coordinates are down, and that the coordinates are
- evenly spaced (i.e. moving the joystick the same amount in a particular
- direction makes the coordinates change the same amount, more or less, no
- matter what position the joystick was in to begin with). If the joystick
- stays in a particular direction, the x- and y-coordinates will probably jump
- around by 1 or 2; you can't expect the joystick values to be precise all the
- way to the least significant bit. This is probably caused by vibration of the
- joystick (or of the hand of the one holding it) and by the simple way in which
- the joystick converts the potentiometer output to timing outputs (not by
- anything fancy like a timing chip with an analog-to-digital converter, unless
- any of the really nice joysticks do this, but probably with a simple capacitor
- circuit of some sort).
-
- 4.2 Calibration
-
- How do we solve this problem? Obviously the joystick cannot be used for
- very precise control (if you need very accurate and precise control like for a
- drawing program, the mouse would be a better input device). However, a way to
- resolve the differences in coordinate ranges is to have a joystick
- calibration routine somewhere in your program.
- If you have played games that use the joystick (and the joystick isn't
- used for much other than games), surely you have seen calibration screens.
- They are usually in the configuration menus of the game (or the game does its
- joystick calibration every time you start the game, but that's a pain for the
- user because that has to be done every time the game is started). Calibration
- is when the game finds out what normal x and y coordinates are for different
- positions on your joystick. That way, during the game, it can know what sort
- of values to interpret as what.
-
- 4.2.1 How to calibrate - the not-so-good way
-
- One way to calibrate the joystick is to ask the user to center the joystick
- and press the button. When the button press is detected, the program reads
- the coordinates of the joystick. Now the program will know that if the
- coordinates of the joystick are ever close to this value, the joystick can be
- regarded as being in the center. This method doesn't require much user
- intervention; as a matter of fact, one game assumes that the joystick is
- centered when you start the game because it just reads the joystick
- coordinates upon startup. However, this method of calibration isn't very good
- because it can't figure out what good coordinates for left, right, up, or down
- would be.
-
- 4.2.2 How to calibrate - a better way
-
- A better way to calibrate asks the user to move the joystick to its upper-
- left hand position and press the joystick button. When the user presses the
- joystick button, the program reads the joystick coordinates and assumes that
- they are good minimum x and y values. Then the program asks the user to move
- the joystick to its lower-right hand position and press the button. When the
- user presses the joystick button, the program reads the joystick coordinates
- and assumes that they are good maximum x and y values.
- Some games that calibrate the joystick this way ask the user to press
- button 1 when the joystick is in its upper-left hand corner, and button 2 when
- the joystick is in its lower-right hand corner. This might be handy in order
- to make sure that the user knows which button is what, and in order to make
- sure that both buttons are responding.
-
- 4.2.3 How to calibrate - digital type joysticks
-
- Some games don't take advantage of the fact that the joystick is analog as
- opposed to digital. If the joystick is to the right, the character runs
- right, but always at the same speed, regardless of how far to the right the
- joystick is; if the joystick is to the left, the character runs left at the
- same speed; if the joystick is near the center, the character doesn't move at
- all. If your application that uses the joystick is going to do this, a better
- way to calibrate might be to ask the user to move the joystick to the upper-
- left hand corner, press the button, move the joystick to the lower-right hand
- corner, press the button, center the joystick, and press the button. This
- way, you'll have a more accurate determination of which direction is the
- center. (You shouldn't do this if you're going to use the joystick as an
- analog joystick, however; this would make it very hard to interpret joystick
- coordinates in that case.)
-
- 4.2.4 When things go wrong...
-
- If the maximum x value from calibration turns out to be less than or equal
- to the minimum x value, or the maximum y value is less than or equal to the
- minimum y value, then something went wrong (either something's wrong with the
- joystick or the port, or the user didn't follow the calibration instructions
- correctly!) In this case, you should just give some sort of error message
- saying that calibration failed.
-
- 4.2.5 Recalibration
-
- Remember that the joystick values might float around even in the middle of
- a program. You might calibrate the joystick at the beginning of a game, and
- ten minutes into the game, you let go of the joystick and let it go to the
- center position, and the character on the screen moves left. The joystick
- requires constant recalibration which can be a real pain. If you're writing a
- game that uses the joystick, however, let there be some way by which the user
- can recalibrate the joystick in the middle of the game, without having to
- start the game over.
-
- 4.2.6 The calibration knobs on the joystick
-
- The calibration knobs on the joystick modify the joystick values to a
- certain extent. When the joystick knobs are adjusted so that the center of
- the joystick has coordinates that are near the maximum or minimum x or y
- coordinates, the joystick cannot detect as many positions because joystick
- positions that go off the edge tend to be "clipped." Therefore, it might be a
- good idea to ask the user to also adjust the calibration knobs on the
- joystick, and you might give some sort of pixel display which shows whatever
- values the joystick is currently returning so that the user can adjust the
- joystick to give x and y coordinates for the center that are as near to the
- center of the pixel display as possible.
-
- 4.3 Interpreting the values
-
- 4.3.1 Analog
-
- Now that your program knows what minimum and maximum x and y coordinates
- are from calibration, whenever the joystick is read during the program, how
- does it know what to interpret the values as? Here you're going to be using
- some linear interpolation. If the x value is halfway between the minimum and
- maximum x values, and the y value is halfway between the minimum and maximum
- y values, you can assume that the joystick is centered. (Don't assume that
- the joystick is exactly halfway between, though; leave a certain range of x
- and y values which are centered.) Likewise, if the x value is 3/4 of the way
- from the minimum x to the maximum x, the joystick is 3/4 of the way to the
- right. If any of the coordinates turn out to be more than the maxima, or less
- than the minima, then just assume them to be equal to the maximum or minimum
- coordinates.
-
- 4.3.2 Digital
-
- If your program is using the joystick as a digital joystick, then your
- program is probably just going to have exact cutoff x and y coordinates for
- determining which position the joystick is in. Here's an illustration (ASCII
- doesn't make it very easy to do this...)
-
- +--------+--------+--------+ <- minimum y value
- | | | |
- | 1 | 2 | 3 |
- | | | |
- +--------+--------+--------+ <- 1/3 of the way from the min y to the max y
- | | | |
- | 4 | 5 | 6 |
- | | | |
- +--------+--------+--------+ <- 2/3 of the way from the min y to the max y
- | | | |
- | 7 | 8 | 9 | 1=upper-left
- | | | | 2=up
- +--------+--------+--------+ <- maximum y value 3=upper-right
- | | 4=left
- | | 2/3 from min | 5=centered
- minimum x | y to max y maximum x value 6=right
- value | 7=lower-left
- | 8=down
- 1/3 from min x to max y 9=lower-right
-
- Of course, the fractions could be anything you wanted them to be.
- If you had calibrated the joystick the way described in 4.2.3, it might be
- more like this:
-
- +--------+--------+--------+ <- minimum y value
- | | | |
- | 1 | 2 | 3 |
- | | | |
- +--------+--------+--------+ <- 2/3 from minimum y to center y
- | | | |
- | 6 | 5 | 4 | <- center y value
- | | | |
- +--------+--------+--------+ <- 1/3 from center y to maximum y
- | | | |
- | 7 | 8 | 9 |
- | | | |
- +--------+--------+--------+ <- maximum y value
- | / | \ |
- minimum x | center x | maximum x
- | |
- 2/3 from min x 1/3 from center x
- to center x to max x
-
- Again, of course, the fractions can be whatever you want them to be!
-
- ------------------------------------------------------------------------------
-
- 5.0 GRAVIS GAMEPAD
-
- 5.1 Description
-
- The Gravis GamePad is a digital controller that connects to the regular
- joystick port. It looks similar to the Super Nintendo pad. It has four
- buttons, which can be used either as four buttons or as two normal buttons and
- two turbo buttons. Whenever you press a "turbo" button, it's like pressing
- the normal button that it corresponds to except that a timer of some sort in
- the joystick rapidly turns the signal for the button on and off, making rapid-
- fire in a game easy. A switch on the GamePad can make it suitable for either
- left-handed or right-handed play; you can hold the joystick the other way,
- and the joystick will invert which pad direction is which and which button is
- which. Note that both the rapid-fire and the left/right-handed switching of
- the joystick controls are invisible to the program; the software does not (and
- can not) find out which modes the GamePad is in, and it doesn't need to invert
- its idea of which button is which or whatever if the joystick is held the
- other way because the joystick does all that. If a turbo button is pressed,
- it only appears to the software as a joystick button being turned on and off.
-
- 5.2 Digital joystick
-
- A Gravis GamePad is not very suitable for playing games which use the
- joystick as an analog joystick, because there is only one up position, only
- one left position, and so on. The GamePad can only detect nine positions of
- the pad--the center, up, down, left, right, and four intermediate positions.
- Probably, the values on a Gravis GamePad don't float around very much, but I'm
- not sure about this because I don't have a Gravis GamePad to try this with.
-
- 5.3 Programming the Gravis GamePad
-
- 5.3.1 Buttons
-
- When the Gravis GamePad is in four-button mode, the third and fourth
- buttons appear to be the first and second buttons of joystick B. This means
- that if you read from I/O port 201h to get the button status (or call the ROM
- BIOS function to do this), bits 4 through 7 will give the status of GamePad
- buttons 1 through 4 in that order (1 means the button is not pressed, 0 means
- the button is pressed). If you connect more than one Gravis GamePad to the
- computer at a time, buttons 3 and 4 of each joystick don't do anything for
- this reason, since there aren't enough bits for all the buttons. (At least,
- that's what I think happens; unless both buttons 3 and 4 on joystick A and
- buttons 1 and 2 on joystick B trigger the same bits, but this would depend on
- the Y-connector that you use to connect the two GamePads to the game port.)
- In two-button mode, buttons 3 and 4 act like turbo buttons for buttons 1 and
- 2, but when a turbo button is pressed, it only appears to the program that the
- button is being pressed and released over and over. Turbo doesn't mean
- anything special from the program's point of view.
-
- 5.3.2 The pad itself
-
- Since the pad is digital and can only detect nine positions, and there are
- no calibration knobs on the Gravis GamePad, the values that you get from
- reading it probably don't "float around" very much. (I'm not sure about this
- because I don't have a Gravis GamePad to test this on; if you have one, please
- let me know about the typical values that you get for each of the nine pad
- positions.) If your program is going to use the joystick as a digital
- joystick, it probably doesn't even have to know whether or not there is a
- Gravis GamePad (unless you plan to use buttons 3 and 4). After all, it
- returns values that are similar to those values that a regular joystick would
- return in those nine positions, so if your program is going to use the
- joystick as a digital joystick, after calibration it can treat all joysticks
- the same way.
-
- ------------------------------------------------------------------------------
-
- 6.0 PADDLES
-
- 6.1 Description
-
- A paddle is another type of controller that can be connected to the game
- port. It is quite different from an analog or digital joystick, in that,
- while joysticks have two axes (x and y), the paddle only has one axis. A
- paddle consists of a knob which you turn left and right, and one button.
- Paddles are suitable for games in which you are only going to move something
- on the screen left and right (or up and down), such as Pong-type games in
- which you move something left and right to catch a ball and bounce it back at
- the other player's paddle on the screen. The paddles that you connect to the
- game port are probably named such because of table-tennis paddles. Up to four
- paddles can be connected to the game port at a time.
-
- 6.2 Programming
-
- 6.2.1 Getting the button status and the coordinates
-
- When you read from I/O port 201h to get the status of the paddles, the bits
- will have the following definitions:
-
- Bit Description
- 0 Paddle A coordinate
- 1 Paddle B coordinate
- 2 Paddle C coordinate
- 3 Paddle D coordinate
- 4 Status of paddle A button (1=not pressed, 0=pressed)
- 5 Status of paddle B button (ditto)
- 6 Status of paddle C button (ditto)
- 7 Status of paddle D button (ditto)
-
- Of course, you can also call the ROM BIOS functions to get the status of
- the paddles. The bits for the buttons will be the same as above, and for the
- function which gives you the joystick coordinates, instead of getting the
- joystick A and B x and y coordinates in AX, BX, CX, and DX, you will get the
- coordinates of the four paddles (with a 0 coordinate for a paddle which isn't
- connected or isn't responding).
- Getting the coordinates of the paddles is very much the same as getting the
- coordinates of the joysticks. You fire the one-shots by writing any 8-bit
- value to port 201h, and then you time how long it takes for the 1 bits in bits
- 0-3 to change to 0 (the bit for a paddle which isn't connected is undefined,
- but will probably be 0 and stay 0 or be 1 and stay 1). The timings are
- probably very much the same as for a joystick. Of course, if you are writing
- a routine to read the coordinate of just paddle A, the routine will probably
- be relatively small and efficient because it only has to look at one bit, as
- opposed to the routine for reading the joystick coordinates which has to time
- at least 2 bits.
-
- 6.2.2 Interpreting the coordinates
-
- Since I don't have a paddle (and I don't know anyone who has one; I only
- know from my reference that they exist), I wouldn't know this for sure, but it
- is most likely that when the paddle is in its rightmost (most clockwise)
- position, the coordinate of that paddle is the highest, and that when the
- paddle is in its leftmost (most counter-clockwise) position, the coordinate
- of that paddle is the lowest.
- I don't know whether or not paddles have calibration knobs, or whether or
- not the lower and upper bounds of the coordinates are very well defined, but
- since I don't know what typical coordinates are, or whether or not coordinates
- are very constant across paddles (probably not), you probably need calibration
- of some sort. Probably the program would ask the user to put the paddle in
- its leftmost position and press the button, and then it would read the paddle
- coordinate; then it would ask the user to put the paddle in its rightmost
- position and press the button, and then it would read the paddle coordinate
- again. Calibration fails, of course, if the upper bound is less than or equal
- to the lower bound. The value halfway between these two values can be assumed
- to be the center.
-
- ------------------------------------------------------------------------------
-
- 7.0 DETECTING THE GAME PORT AND CONTROLLERS
-
- 7.1 Detecting the game port
-
- How do you tell whether or not there's a game port connected to the system?
- One way is to read from I/O port 201h, and if the value is 0F0h, there is a
- game port connected to the system, otherwise there isn't (unless there are
- joysticks connected which are giving different values; if you haven't fired
- the joystick one-shots recently this shouldn't be the case). This is not
- really a good way to do it because some game ports could be nonstandard and
- return different values if the joysticks are not connected. My joystick port
- is this way; if no joysticks are connected and I have the computer read from
- I/O port 201h, the value it gets is 0F3h.
- The computer's equipment status word (which you can get by reading the word
- at 0040h:0010h or by doing an int 11h which returns this word in AX) contains
- a bit that tells (or is supposed to tell) whether or not there is a game card
- (on machines other than PS/2's). If this bit is 1, there is a game card; if
- it's 0, there isn't. This bit is bit 12 of the word. Beware; bit 12 of the
- equipment status word is unused (or used for something else) on PS/2's, so
- this is not really a good way to check for a game port. When the computer is
- booted up, the BIOS checks to see whether or not there is a game port (on
- XT's and probably on most other machines, it uses the same method described
- above, which isn't really the best way), and it sets this bit accordingly.
- A better way to detect whether or not there is a game port is to read the
- port, and if the value is 0FFh (the value you get from any I/O port to which
- no device is connected), there is no game port; otherwise there is. Make sure
- that you haven't fired the joystick one-shots recently when you do this so
- that if there is a game port and joysticks are connected, 0FFh isn't the
- actual value that is being returned. There's already a C-callable function in
- JOYSTICK.ASM which does this (detect_game_port). This may not be 100%
- reliable, however, so be sure to give the user a way to override whether or
- not the program thinks there's a game port.
- In any case, the program will probably not need to know whether or not
- there is a game port, just whether or not the controller is connected.
- So it would probably just be easier to detect whether or not a controller is
- connected in the first place since a game port isn't much use without
- something connected to it.
-
- 7.2 Detecting joysticks
-
- There really isn't any way that the program can tell which type of
- controller is connected to the game port. The program probably has to ask the
- user for this information. If your program is going to use the joystick as a
- digital joystick, it probably won't need to know whether or not there is a
- Gravis GamePad connected (unless it could use buttons 3 and 4 in this case).
- However, there is a way to tell whether or not controllers are connected,
- and if so, how many (assuming that you know whether the controllers are
- paddles or joysticks). Fire the one-shots by writing any value to the 8-bit
- port 201h. Then continue to read from port 201h, and if any of the lower 4
- bits changes values within a "reasonable amount of time" (see section 3.2.2),
- the controller that it goes to is connected. The joystick-reading procedures
- in JOYSTICK.ASM can be used for detecting joysticks because they return 0FFFFh
- for the coordinates of the bits in the joystick port value that never changed.
- One method which you should NOT use to detect joysticks: Call the ROM BIOS
- function to read the joystick values, and if a joystick coordinate that it
- returns is not 0, that joystick is connected. You shouldn't use this method.
- You see, if the bits for a joystick which isn't connected are always 0, the
- ROM BIOS function might realize that these bits are 0 on the first or second
- run of its timing loop and assume that these bits had just turned 0 (when in
- fact they were always 0), and therefore return a really low value like 1 or 2
- but not 0. On my computer, although I only have one joystick connected to the
- game port, the ROM BIOS function for getting the joystick coordinates always
- returns 1 or 2 for the x and y coordinates of joystick 2. You have to
- actually detect a CHANGE in a bit for a controller in order to assume that the
- joystick is there. The joystick routines in JOYSTICK.ASM look for bit
- changes, instead of noticing that a bit is 0 and thinking that it had just
- turned 0. This is probably more reliable than the method for telling whether
- or not a game port is connected to the machine, but you might still want to
- give the user a chance to override what the program thinks.
-
- ------------------------------------------------------------------------------
-
- 8.0 PINOUTS
-
- 8.1 Introduction
-
- For you hardware hackers out there, (no, I'm not one), this section is
- about the pinouts on the game port. The game port is useful for other things
- than connecting joysticks or other controllers; it could be used for
- diagnostic purposes since reading from I/O port 201h simply gives the status
- of certain pins on the game port.
- Here's one thing which I need help on from someone: The list of pins on the
- game connector that I have doesn't say anything about a pin which does
- anything whenever the joystick one-shots are fired. However, the joystick has
- to know somehow whether or not the one-shots are fired so it can start timing
- so that it knows when to turn the coordinate bits from 1 to 0. Help!
- When a joystick button is being pressed, the bit for that button is 0, and
- when the button is not pressed, the bit is 1. You would expect it to be the
- other way around. The reason is probably because the voltages that the
- computer uses for signals are backwards - a higher voltage means a 0 and a
- lower voltage means a 1. (Can anyone give me precise values for the
- voltages? I would expect +5V with respect to ground to be a 0 bit and 0V to
- be a 1 bit; this explains why the buttons return a 0 when pressed and 1 when
- not pressed, since they are normally open buttons. I need to test this with a
- voltmeter some time...)
- Remember, to the game port itself, there is no functional difference
- between the pins that give the joystick position and the pins that give the
- button status; the circuitry within the joystick is what converts the outputs
- from the variable resistors that read the position to high and low signals
- whose timings are based on them. All the game port itself does is take the
- high and low signals given to it on the pins and convert them to 0's and 1's
- when you read port 201h, and fire the joystick one-shots somehow when you
- write to that port.
-
- 8.2 Pinouts
-
- The computer's connector is a female DB-15. I'm not sure which pins are
- which numbers, but a male DB-15 on something that you connect to the game port
- would probably have the numbers of the end pins marked.
-
- Pin number What it does
- ---------- ------------
- 1 +5V DC
- 2 Bit 4 of I/O port 201h
- 3 Bit 0 of I/O port 201h
- 4 Ground
- 5 Ground
- 6 Bit 1 of I/O port 201h
- 7 Bit 5 of I/O port 201h
- 8 +5V DC
- 9 +5V DC
- 10 Bit 6 of I/O port 201h
- 11 Bit 2 of I/O port 201h
- 12 Ground
- 13 Bit 3 of I/O port 201h
- 14 Bit 7 of I/O port 201h
- 15 +5V DC
-
- All signals that come into the game port (the bits of the I/O port) are
- "active high," whatever that means.
-
- ------------------------------------------------------------------------------
-
- 9.0 HOW TO CONTACT ME
-
- Please let me know of anything I left out (I know I'm missing some info
- like the joystick one-shots on the pinouts, and definite voltages for the
- pinouts [high and low] with respect to ground) and anything that's inaccurate
- in this document. Any comments or suggestions are appreciated! I can be
- contacted at:
-
- SnailMail: 713 N.W. 141 St., Edmond, OK, 73013-1920.
-
- FidoNet: Usually I'm on the lookout for any messages addressed to me on the
- 80XXX echo.
-
- InterNet: emil.gilliam@oubbs.telecom.uoknor.edu
-
-
-